diff --git a/Gopkg.lock b/Gopkg.lock
index 11bcf70..a6e2a98 100644
--- a/Gopkg.lock
+++ b/Gopkg.lock
@@ -2,12 +2,12 @@
[[projects]]
- digest = "1:87c2e02fb01c27060ccc5ba7c5a407cc91147726f8f40b70cceeedbc52b1f3a8"
+ digest = "1:05eebdd5727fea23083fce0d98d307d70c86baed644178e81608aaa9f09ea469"
name = "github.com/Sirupsen/logrus"
packages = ["."]
pruneopts = "UT"
- revision = "e1e72e9de974bd926e5c56f83753fba2df402ce5"
- version = "v1.3.0"
+ revision = "60c74ad9be0d874af0ab0daef6ab07c5c5911f0d"
+ version = "v1.6.0"
[[projects]]
branch = "master"
@@ -22,20 +22,20 @@
revision = "8159197d3770eb6dbf3a9706a6d40462ebb69cec"
[[projects]]
- digest = "1:4fd5ce7844c22e194005b9e12fee8adc70fb5ba0bbba9e1964d2e3d1f301d789"
+ digest = "1:d87c9221a974263e3b369bfd3513707b2a53e27a6cd799d472f94dc6a6157e59"
name = "github.com/bwmarrin/discordgo"
packages = ["."]
pruneopts = "UT"
- revision = "4a33b9bc7c56cfdb9bb244e33e83cb3941fe2bdc"
- version = "v0.18.0"
+ revision = "ed4d6904961d1688b3f5601b3d73e95a71046734"
+ version = "v0.20.3"
[[projects]]
- digest = "1:43dd08a10854b2056e615d1b1d22ac94559d822e1f8b6fcc92c1a1057e85188e"
+ digest = "1:6d29f02f0f01c627c2be40fb7347669a9ff2aa215cb97747294c1d13ffa74bdd"
name = "github.com/gorilla/websocket"
packages = ["."]
pruneopts = "UT"
- revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b"
- version = "v1.2.0"
+ revision = "b65e62901fc1c0d968042419e74789f6af455eb9"
+ version = "v1.4.2"
[[projects]]
branch = "master"
@@ -46,36 +46,37 @@
revision = "2e40e0d508cbac591bab4ae18b231153295f3a0a"
[[projects]]
- digest = "1:0a69a1c0db3591fcefb47f115b224592c8dfa4368b7ba9fae509d5e16cdc95c8"
+ digest = "1:09cb61dc19af93deae01587e2fdb1c081e0bf48f1a5ad5fa24f48750dc57dce8"
name = "github.com/konsorten/go-windows-terminal-sequences"
packages = ["."]
pruneopts = "UT"
- revision = "5c8c8bd35d3832f5d134ae1e1e375b69a4d25242"
- version = "v1.0.1"
+ revision = "edb144dfd453055e1e49a3d8b410a660b5a87613"
+ version = "v1.0.3"
[[projects]]
branch = "master"
- digest = "1:e035fb07be76ce6e4ce005add75491d9f0749403f595f153d6e2823a71c24149"
+ digest = "1:1714bd928fd176237ccdea21695bf72801c1ee5f51bccefb69b87f0fd376a6aa"
name = "golang.org/x/crypto"
packages = [
+ "internal/subtle",
"nacl/secretbox",
"poly1305",
"salsa20/salsa",
- "ssh/terminal",
]
pruneopts = "UT"
- revision = "c4a91bd4f524f10d064139674cf55852e055ad01"
+ revision = "70a84ac30bf957c7df57edd1935d2081871515e1"
[[projects]]
branch = "master"
- digest = "1:43cde116ff48f299eddb7e6515677e6d0a2c915854bb05a333877f07c3bb3033"
+ digest = "1:145abe7dfa46d17ef35e5126ed1cc87b9100e78b9f428c9460deea34bfeabafb"
name = "golang.org/x/sys"
packages = [
+ "cpu",
+ "internal/unsafeheader",
"unix",
- "windows",
]
pruneopts = "UT"
- revision = "11f53e03133963fb11ae0588e08b5e0b85be8be5"
+ revision = "226ff32320da7b90d0b5bc2365f4e359c466fb78"
[solve-meta]
analyzer-name = "dep"
diff --git a/Gopkg.toml b/Gopkg.toml
index e71da66..43dc884 100644
--- a/Gopkg.toml
+++ b/Gopkg.toml
@@ -31,7 +31,7 @@
[[constraint]]
name = "github.com/bwmarrin/discordgo"
- version = "0.18.0"
+ version = "0.20.0"
[prune]
go-tests = true
diff --git a/config.template.json b/config.template.json
index f65fe2d..6af593a 100644
--- a/config.template.json
+++ b/config.template.json
@@ -4,6 +4,7 @@
"RolesToNotify": ["<@&roleid>", "<@userid>"],
"GameStatus": "current playing game",
"PollingInterval": 10,
+ "BotPrefix": "!",
"Servers": [
{
"Name": "Your awesome server",
diff --git a/config/config.go b/config/config.go
index 69be37d..2a1b8ad 100644
--- a/config/config.go
+++ b/config/config.go
@@ -16,16 +16,20 @@ type configStruct struct {
Token string `json:"Token"`
RoomIDList []string `json:"RoomIDList"`
RolesToNotify []string `json:"RolesToNotify"`
- Servers []server `json:"Servers"`
+ Servers []Server `json:"Servers"`
GameStatus string `json:"GameStatus"`
PollingInterval time.Duration `json:"PollingInterval"`
+ BotPrefix string `json:"BotPrefix"`
}
-type server struct {
+type Server struct {
Name string `json:"Name"`
Address string `json:"Address"`
Port int `json:"Port"`
Online bool `json:"Online,omitempty"`
+ // OnlineTimestamp - time of when the server last came online
+ OnlineTimestamp time.Time
+ OfflineTimestamp time.Time
}
func Configure() {
diff --git a/makefile b/makefile
index d582a52..8958b9b 100644
--- a/makefile
+++ b/makefile
@@ -4,7 +4,7 @@ run:
go run ./src/main.go
linux:
- go build -o ./dist/ServerStatus-linux -ldflags="-X main.version=${VERSION}" ./main.go
+ GOOS=linux GOARCH=amd64 go build -o ./dist/ServerStatus-linux -ldflags="-X main.version=${VERSION}" ./main.go
mac:
GOOS=darwin GOARCH=amd64 go build -o ./dist/ServerStatus-mac -ldflags="-X main.version=${VERSION}" ./main.go
diff --git a/readme.md b/readme.md
index 4285d1c..630e9b5 100644
--- a/readme.md
+++ b/readme.md
@@ -43,7 +43,7 @@ services:
## Usage
To get the current status of your servers simply type `!ServerStatus` in chat.
-
+
## Compiling from source
- Make sure Go and Make are installed
@@ -55,5 +55,4 @@ https://github.com/reactiflux/discord-irc/wiki/Creating-a-discord-bot-&-getting-
### How to get your room ID
To get IDs, turn on Developer Mode in the Discord client (User Settings -> Appearance) and then right-click your name/icon anywhere in the client and select Copy ID.
-
-
+
diff --git a/readme_files/screenshot1.png b/readme_files/screenshot1.png
new file mode 100644
index 0000000..0060e1d
Binary files /dev/null and b/readme_files/screenshot1.png differ
diff --git a/readme_files/screenshot2.gif b/readme_files/screenshot2.gif
new file mode 100644
index 0000000..a48072f
Binary files /dev/null and b/readme_files/screenshot2.gif differ
diff --git a/serverstatus/serverstatus.go b/serverstatus/serverstatus.go
index 5ee2be0..1424d3d 100644
--- a/serverstatus/serverstatus.go
+++ b/serverstatus/serverstatus.go
@@ -1,12 +1,14 @@
package serverstatus
import (
+ "fmt"
"log"
"strconv"
"strings"
+ "sync"
"time"
- "github.com/anvie/port-scanner"
+ portscanner "github.com/anvie/port-scanner"
"github.com/bwmarrin/discordgo"
steam "github.com/kidoman/go-steam"
"github.com/mgerb/ServerStatus/bot"
@@ -24,6 +26,8 @@ func Start() {
//set each server status as online to start
for i := range config.Config.Servers {
config.Config.Servers[i].Online = true
+ config.Config.Servers[i].OnlineTimestamp = time.Now()
+ config.Config.Servers[i].OfflineTimestamp = time.Now()
}
err := bot.Session.UpdateStatus(0, config.Config.GameStatus)
@@ -48,49 +52,74 @@ func scanServers() {
for {
- for index, server := range config.Config.Servers {
- prevServerUp := server.Online //set value to previous server status
+ // use waitgroup to scan all servers concurrently
+ var wg sync.WaitGroup
- serverScanner := portscanner.NewPortScanner(server.Address, time.Second*2, 1)
- serverUp := serverScanner.IsOpen(server.Port) //check if the port is open
-
- // if server isn't up check RCON protocol (UDP)
- if !serverUp {
- host := server.Address + ":" + strconv.Itoa(server.Port)
- steamConnection, err := steam.Connect(host)
- if err == nil {
- defer steamConnection.Close()
- _, err := steamConnection.Ping()
- if err == nil {
- serverUp = true
- }
- }
- }
-
- if serverUp && serverUp != prevServerUp {
- sendMessageToRooms(green, server.Name, "Is now online :smiley:", true)
- } else if !serverUp && serverUp != prevServerUp {
- sendMessageToRooms(red, server.Name, "Has gone offline :frowning2:", true)
- }
-
- config.Config.Servers[index].Online = serverUp
+ for index := range config.Config.Servers {
+ wg.Add(1)
+ go worker(index, &config.Config.Servers[index], &wg)
}
+ wg.Wait()
+
time.Sleep(time.Second * config.Config.PollingInterval)
}
}
+func worker(index int, server *config.Server, wg *sync.WaitGroup) {
+ defer wg.Done()
+
+ prevServerUp := server.Online //set value to previous server status
+
+ var serverUp bool
+ retryCounter := 0
+
+ // try reconnecting 5 times if failure persists (every 2 seconds)
+ for {
+ serverScanner := portscanner.NewPortScanner(server.Address, time.Second*2, 1)
+ serverUp = serverScanner.IsOpen(server.Port) //check if the port is open
+ if serverUp || retryCounter >= 5 {
+ break
+ }
+ retryCounter++
+ time.Sleep(time.Second * 2)
+ }
+
+ // if server isn't up check RCON protocol (UDP)
+ if !serverUp {
+ host := server.Address + ":" + strconv.Itoa(server.Port)
+ steamConnection, err := steam.Connect(host)
+ if err == nil {
+ defer steamConnection.Close()
+ _, err := steamConnection.Ping()
+ if err == nil {
+ serverUp = true
+ }
+ }
+ }
+
+ if serverUp && serverUp != prevServerUp {
+ server.OnlineTimestamp = time.Now()
+ sendMessageToRooms(green, server.Name, "Is now online :smiley:", true)
+ } else if !serverUp && serverUp != prevServerUp {
+ server.OfflineTimestamp = time.Now()
+ sendMessageToRooms(red, server.Name, "Has gone offline :frowning2:", true)
+ }
+
+ server.Online = serverUp
+}
+
func sendMessageToRooms(color int, title, description string, mentionRoles bool) {
for _, roomID := range config.Config.RoomIDList {
if mentionRoles {
content := strings.Join(config.Config.RolesToNotify, " ")
bot.Session.ChannelMessageSend(roomID, content)
}
- sendEmbededMessage(roomID, color, title, description)
+ sendEmbeddedMessage(roomID, color, title, description)
}
}
-func sendEmbededMessage(roomID string, color int, title, description string) {
+func sendEmbeddedMessage(roomID string, color int, title, description string) {
embed := &discordgo.MessageEmbed{
Color: color,
@@ -110,13 +139,23 @@ func MessageHandler(s *discordgo.Session, m *discordgo.MessageCreate) {
return
}
- if m.Content == "!ServerStatus" {
+ if m.Content == config.Config.BotPrefix+"ServerStatus" {
for _, server := range config.Config.Servers {
if server.Online {
- sendEmbededMessage(m.ChannelID, green, server.Name, "Online!")
+ sendEmbeddedMessage(m.ChannelID, green, server.Name, "Online!\nUptime: "+fmtDuration(time.Since(server.OnlineTimestamp)))
} else {
- sendEmbededMessage(m.ChannelID, red, server.Name, "Offline!")
+ sendEmbeddedMessage(m.ChannelID, red, server.Name, "Offline!\nDowntime: "+fmtDuration(time.Since(server.OfflineTimestamp)))
}
}
}
}
+
+func fmtDuration(d time.Duration) string {
+
+ days := int(d.Hours()) / 24
+ hours := int(d.Hours()) % 60
+ minutes := int(d.Minutes()) % 60
+ seconds := int(d.Seconds()) % 60
+
+ return fmt.Sprintf("%dd %dh %dm %ds", days, hours, minutes, seconds)
+}