Skip to content

Commit

Permalink
Merge pull request #2 from infiniteloopcloud/dev
Browse files Browse the repository at this point in the history
Issue #1
  • Loading branch information
PumpkinSeed authored May 2, 2022
2 parents 58cb4ff + 9ab48c3 commit 0851bef
Show file tree
Hide file tree
Showing 7 changed files with 252 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@

# Dependency directories (remove the comment below to include it)
# vendor/
go.mod
go.sum

config.json
55 changes: 55 additions & 0 deletions env/env.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package env

import (
"encoding/json"
"io/ioutil"
"log"
"os"
)

var (
configuration *Static
ConfigFlag string = "DOWNDETECTOR_CONFIG"
)

type Static struct {
BotToken string `json:"bot_token"`
BotGuild string `json:"bot_guild"`
Address string `json:"address"`
ChannelName string `json:"channelName"`
Checks []Check
}

type Check struct {
Type string `json:"type"`
Value string `json:"value"`
Interval string `json:"interval"`
Parameters *Parameters `json:"parameters"`
}

type Parameters struct {
StatusCode int `json:"status_code"`
}

func Configuration() *Static {
if configuration == nil {
var path string
if path = os.Getenv(ConfigFlag); path == "" {
path = "./config.json"
}

file, err := ioutil.ReadFile(path)
if err != nil {
log.Printf("[ERROR] %s\n", err.Error())
return nil
}
var s Static
if err := json.Unmarshal(file, &s); err != nil {
log.Printf("[ERROR] unmarshal file: %s", err.Error())
return nil
}
configuration = &s

}
return configuration
}
16 changes: 16 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
github.com/Clinet/discordgo-embed v0.0.0-20220113222025-bafe0c917646 h1:KkKIDMzyOhNnW5ew6KpRvEflciWqo09NmgVGqTZEj3M=
github.com/Clinet/discordgo-embed v0.0.0-20220113222025-bafe0c917646/go.mod h1:0ydUl+01209LCyzJk68BeRtCN1IMrNJgX4IBmwmC1f8=
github.com/bwmarrin/discordgo v0.25.0 h1:NXhdfHRNxtwso6FPdzW2i3uBvvU7UIQTghmV2T4nqAs=
github.com/bwmarrin/discordgo v0.25.0/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/infiniteloopcloud/discord-jira v0.2.0 h1:w3PuND+cojzqfbkk1UinZHSU3c86giqwSF9idFbDBJY=
github.com/infiniteloopcloud/discord-jira v0.2.0/go.mod h1:G3sQnTp4hX9/rcl0qc0dhRSPlJU/R9lbk/xOqc8dy10=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
56 changes: 56 additions & 0 deletions handler/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package handler

import (
"log"
"net/http"
"strconv"

embed "github.com/Clinet/discordgo-embed"
"github.com/bwmarrin/discordgo"
env "github.com/infiniteloopcloud/discord-downdetector/env"
)

const (
warning = 0xD10000
)

var channelName string

// Check is the endpoint alive
func Handle(body env.Check) (string, *discordgo.MessageEmbed, error) {
var statusCode = http.StatusOK
code := checkHealth(body)

if body.Parameters != nil && body.Parameters.StatusCode != 0 {
statusCode = body.Parameters.StatusCode
}
if code != statusCode {
return unreachable(body, code)
} else {
return "", nil, nil
}

}

// Send an embed to the downdetector channel
func unreachable(check env.Check, code int) (string, *discordgo.MessageEmbed, error) {
status := strconv.Itoa(code)
message := embed.NewEmbed().
SetAuthor("Status code: " + status).
SetTitle("[Host unreachable] " + check.Value).
SetColor(warning)

return env.Configuration().ChannelName, message.MessageEmbed, nil
}

// Return the status code of the request
func checkHealth(check env.Check) int {
resp, err := http.Get(check.Type + "://" + check.Value)
if err != nil {
log.Println("[ERROR]", err)
return resp.StatusCode
}
defer resp.Body.Close()

return resp.StatusCode
}
9 changes: 9 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package main

import (
runner "github.com/infiniteloopcloud/discord-downdetector/runner"
)

func main() {
runner.Run()
}
51 changes: 51 additions & 0 deletions runner/runner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package runner

import (
"log"
"time"

"github.com/infiniteloopcloud/discord-downdetector/env"
handler "github.com/infiniteloopcloud/discord-downdetector/handler"
utils "github.com/infiniteloopcloud/discord-downdetector/utils"
)

func check(body env.Check) {
channel, message, err := handler.Handle(body)
if err != nil {
log.Printf("[ERROR] %s", err.Error())
return
}
channelID := utils.GetChannelID(channel)
if channelID == "" {
channelID = utils.GetChannelID("unknown")
}
if channelID != "" && message != nil {
_, err = utils.GetSession().ChannelMessageSendEmbed(channelID, message)
if err != nil {
log.Printf("[ERROR] %s", err.Error())
}
}
}

func Run() {
log.Printf("[RUNNING] Downdetector")

// A loop what runs forever to check is the host reachable
for {
for i := range env.Configuration().Checks {
check(env.Configuration().Checks[i])
}
// Checks only the first object's interval
// Don't wait between objects
interval, unit := utils.GetTime(env.Configuration().Checks[0].Interval)
switch unit {
case "h":
time.Sleep(time.Duration(interval) * time.Hour)
case "m":
time.Sleep(time.Duration(interval) * time.Minute)
case "s":
time.Sleep(time.Duration(interval) * time.Second)
}
}

}
61 changes: 61 additions & 0 deletions utils/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package utils

import (
"encoding/json"
"log"
"strconv"

"github.com/bwmarrin/discordgo"
"github.com/infiniteloopcloud/discord-downdetector/env"
)

var session *discordgo.Session
var channelsCache map[string]string

func GetTime(x string) (int, string) {
i := x[len(x)-1:]
unitVal := x[:len(x)-1]
unit, _ := strconv.Atoi(unitVal)
return unit, i
}

func GetEvent(raw []byte) (string, error) {
var static env.Static
err := json.Unmarshal(raw, &static)
if err != nil {
return "", err
}
return env.Configuration().ChannelName, nil
}

func GetChannelID(name string) string {
if channelsCache == nil {
channelsCache = make(map[string]string)
}
if id, ok := channelsCache[name]; ok {
return id
} else {
channels, err := GetSession().GuildChannels(env.Configuration().BotGuild)
if err != nil {
log.Print(err)
}
for _, channel := range channels {
if name == channel.Name {
channelsCache[channel.Name] = channel.ID
return channel.ID
}
}
}
return ""
}

func GetSession() *discordgo.Session {
if session == nil {
var err error
session, err = discordgo.New("Bot " + env.Configuration().BotToken)
if err != nil {
log.Printf("[ERROR] %s", err.Error())
}
}
return session
}

0 comments on commit 0851bef

Please sign in to comment.