1
0
mirror of https://github.com/mgerb/ServerStatus synced 2026-01-12 04:02:48 +00:00

1 Commits

Author SHA1 Message Date
242f840180 added embedded messages 2018-03-15 21:03:47 -05:00
15 changed files with 51 additions and 223 deletions

View File

@@ -1,2 +0,0 @@
/vendor
/dist

View File

@@ -1,17 +0,0 @@
FROM golang:1.11.1-alpine
WORKDIR /go/src/github.com/mgerb/ServerStatus
ADD . .
RUN apk add --no-cache git alpine-sdk
RUN go get -u github.com/golang/dep/cmd/dep
RUN dep ensure
RUN make linux
FROM alpine:3.8
RUN apk update && apk add ca-certificates && rm -rf /var/cache/apk/*
WORKDIR /server-status
COPY --from=0 /go/src/github.com/mgerb/ServerStatus/dist/ServerStatus-linux .
ENTRYPOINT ./ServerStatus-linux

65
Gopkg.lock generated
View File

@@ -1,90 +1,41 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
digest = "1:05eebdd5727fea23083fce0d98d307d70c86baed644178e81608aaa9f09ea469"
name = "github.com/Sirupsen/logrus"
packages = ["."]
pruneopts = "UT"
revision = "60c74ad9be0d874af0ab0daef6ab07c5c5911f0d"
version = "v1.6.0"
[[projects]]
branch = "master"
digest = "1:b7e05c8da029b985907b15e126cde5f42f2814b08211a184dac436eeec6fe780"
name = "github.com/anvie/port-scanner"
packages = [
".",
"predictors",
"predictors/webserver",
"predictors/webserver"
]
pruneopts = "UT"
revision = "8159197d3770eb6dbf3a9706a6d40462ebb69cec"
[[projects]]
digest = "1:d87c9221a974263e3b369bfd3513707b2a53e27a6cd799d472f94dc6a6157e59"
name = "github.com/bwmarrin/discordgo"
packages = ["."]
pruneopts = "UT"
revision = "ed4d6904961d1688b3f5601b3d73e95a71046734"
version = "v0.20.3"
revision = "4a33b9bc7c56cfdb9bb244e33e83cb3941fe2bdc"
version = "v0.18.0"
[[projects]]
digest = "1:6d29f02f0f01c627c2be40fb7347669a9ff2aa215cb97747294c1d13ffa74bdd"
name = "github.com/gorilla/websocket"
packages = ["."]
pruneopts = "UT"
revision = "b65e62901fc1c0d968042419e74789f6af455eb9"
version = "v1.4.2"
revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b"
version = "v1.2.0"
[[projects]]
branch = "master"
digest = "1:50993a8fbb3042b88dfecb8f4473a42f13ac70d6fd86f64df525a28b357c2d5b"
name = "github.com/kidoman/go-steam"
packages = ["."]
pruneopts = "UT"
revision = "2e40e0d508cbac591bab4ae18b231153295f3a0a"
[[projects]]
digest = "1:09cb61dc19af93deae01587e2fdb1c081e0bf48f1a5ad5fa24f48750dc57dce8"
name = "github.com/konsorten/go-windows-terminal-sequences"
packages = ["."]
pruneopts = "UT"
revision = "edb144dfd453055e1e49a3d8b410a660b5a87613"
version = "v1.0.3"
[[projects]]
branch = "master"
digest = "1:1714bd928fd176237ccdea21695bf72801c1ee5f51bccefb69b87f0fd376a6aa"
name = "golang.org/x/crypto"
packages = [
"internal/subtle",
"nacl/secretbox",
"poly1305",
"salsa20/salsa",
"salsa20/salsa"
]
pruneopts = "UT"
revision = "70a84ac30bf957c7df57edd1935d2081871515e1"
[[projects]]
branch = "master"
digest = "1:145abe7dfa46d17ef35e5126ed1cc87b9100e78b9f428c9460deea34bfeabafb"
name = "golang.org/x/sys"
packages = [
"cpu",
"internal/unsafeheader",
"unix",
]
pruneopts = "UT"
revision = "226ff32320da7b90d0b5bc2365f4e359c466fb78"
revision = "c4a91bd4f524f10d064139674cf55852e055ad01"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
input-imports = [
"github.com/anvie/port-scanner",
"github.com/bwmarrin/discordgo",
"github.com/kidoman/go-steam",
]
inputs-digest = "0832269100c492c595c4fe5f02e10d70889b9fa4d6a869c3ad59584cda0c5d31"
solver-name = "gps-cdcl"
solver-version = 1

View File

@@ -31,12 +31,8 @@
[[constraint]]
name = "github.com/bwmarrin/discordgo"
version = "0.20.0"
version = "0.18.0"
[prune]
go-tests = true
unused-packages = true
[[constraint]]
branch = "master"
name = "github.com/kidoman/go-steam"

View File

@@ -3,8 +3,6 @@
"RoomIDList":["room id list goes here"],
"RolesToNotify": ["<@&roleid>", "<@userid>"],
"GameStatus": "current playing game",
"PollingInterval": 10,
"BotPrefix": "!",
"Servers": [
{
"Name": "Your awesome server",

View File

@@ -6,30 +6,24 @@ import (
"io/ioutil"
"log"
"os"
"time"
)
// Variables used for command line parameters
var Config configStruct
type configStruct struct {
Token string `json:"Token"`
RoomIDList []string `json:"RoomIDList"`
RolesToNotify []string `json:"RolesToNotify"`
Servers []Server `json:"Servers"`
GameStatus string `json:"GameStatus"`
PollingInterval time.Duration `json:"PollingInterval"`
BotPrefix string `json:"BotPrefix"`
Token string `json:"Token"`
RoomIDList []string `json:"RoomIDList"`
RolesToNotify []string `json:"RolesToNotify"`
Servers []server `json:"Servers"`
GameStatus string `json:"GameStatus"`
}
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() {
@@ -49,8 +43,4 @@ func Configure() {
log.Println(err)
}
if Config.PollingInterval == 0 {
log.Fatal("Please set your PollingInterval > 0 in your config file.")
}
}

View File

@@ -1,5 +0,0 @@
version=$(git describe --tags)
docker build -t mgerb/server-status:latest .
docker tag mgerb/server-status:latest mgerb/server-status:$version

View File

@@ -1,7 +0,0 @@
version: "2"
services:
server-status:
image: mgerb/server-status:latest
volumes:
- ./config.json:/server-status/config.json

View File

@@ -1,5 +0,0 @@
version=$(git describe --tags)
docker push mgerb/server-status:latest;
docker push mgerb/server-status:$version;

View File

@@ -8,6 +8,11 @@ import (
"github.com/mgerb/ServerStatus/serverstatus"
)
// Variables used for command line parameters
var (
BotID string
)
var version = "undefined"
func init() {

View File

@@ -4,7 +4,7 @@ run:
go run ./src/main.go
linux:
GOOS=linux GOARCH=amd64 go build -o ./dist/ServerStatus-linux -ldflags="-X main.version=${VERSION}" ./main.go
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

View File

@@ -1,49 +1,26 @@
# Server Status
Monitors a list of servers and sends a chat notification when a server goes on or offline.
Scans a list of TCP servers checking checking which are currently online.
This bot will send a chat notification when the status of a server changes (goes on or offline).
- **TCP** - should work with all servers
- **UDP** - [Source RCON Protocol](https://developer.valvesoftware.com/wiki/Source_RCON_Protocol) is supported
I originally made this bot to check if private World of Warcraft servers were up or not.
It's actually much more useful than that and can be used for most servers.
NOTE: This bot currently does not work for UDP servers.
## Configuration
- Download the latest release [here](https://github.com/mgerb/ServerStatus/releases)
- Add your bot token as well as other configurations to **config.json**
- Add your bot token as well as other configurations to config.json
- Execute the OS specific binary!
### Mentioning Roles/Users
- list of user/role ID's must be in the following format (see below for obtaining ID's)
- `<@userid>`
- `<@&roleid>`
### Polling Interval
The polling interval is how often the bot will try to ping the servers.
A good interval is 10 seconds, but this may need some adjustment if
it happens to be spamming notifications.
- time in seconds
- configurable in **config.json**
## With Docker
```
docker run -it -v /path/to/your/config.json:/server-status/config.json:ro mgerb/server-status
```
### Docker Compose
```
version: "2"
services:
server-status:
image: mgerb/server-status:latest
volumes:
- /path/to/your/config.json:/server-status/config.json
```
- you must first get your role/user id
- for user `<@userid>`
- for role `<@&roleid>`
## Usage
To get the current status of your servers simply type `!ServerStatus` in chat.
![Server Status](./readme_files/screenshot1.png)
![Server Status](https://i.imgur.com/ZzQSBJp.png)
## Compiling from source
- Make sure Go and Make are installed
@@ -55,4 +32,5 @@ 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.
<img src="./readme_files/screenshot2.gif"/>
<img src="https://camo.githubusercontent.com/9f759ec8b45a6e9dd2242bc64c82897c74f84a25/687474703a2f2f692e696d6775722e636f6d2f47684b70424d512e676966"/>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 838 KiB

View File

@@ -1,16 +1,12 @@
package serverstatus
import (
"fmt"
"log"
"strconv"
"strings"
"sync"
"time"
portscanner "github.com/anvie/port-scanner"
"github.com/anvie/port-scanner"
"github.com/bwmarrin/discordgo"
steam "github.com/kidoman/go-steam"
"github.com/mgerb/ServerStatus/bot"
"github.com/mgerb/ServerStatus/config"
)
@@ -26,8 +22,6 @@ 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)
@@ -52,61 +46,23 @@ func scanServers() {
for {
// use waitgroup to scan all servers concurrently
var wg sync.WaitGroup
for index, server := range config.Config.Servers {
prevServerUp := server.Online //set value to previous server status
for index := range config.Config.Servers {
wg.Add(1)
go worker(index, &config.Config.Servers[index], &wg)
}
serverScanner := portscanner.NewPortScanner(server.Address, time.Second*2, 1)
serverUp := serverScanner.IsOpen(server.Port) //check if the port is open
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 {
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
}
}
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)
time.Sleep(time.Second * 5)
}
server.Online = serverUp
}
func sendMessageToRooms(color int, title, description string, mentionRoles bool) {
@@ -115,11 +71,11 @@ func sendMessageToRooms(color int, title, description string, mentionRoles bool)
content := strings.Join(config.Config.RolesToNotify, " ")
bot.Session.ChannelMessageSend(roomID, content)
}
sendEmbeddedMessage(roomID, color, title, description)
sendEmbededMessage(roomID, color, title, description)
}
}
func sendEmbeddedMessage(roomID string, color int, title, description string) {
func sendEmbededMessage(roomID string, color int, title, description string) {
embed := &discordgo.MessageEmbed{
Color: color,
@@ -139,23 +95,13 @@ func MessageHandler(s *discordgo.Session, m *discordgo.MessageCreate) {
return
}
if m.Content == config.Config.BotPrefix+"ServerStatus" {
if m.Content == "!ServerStatus" {
for _, server := range config.Config.Servers {
if server.Online {
sendEmbeddedMessage(m.ChannelID, green, server.Name, "Online!\nUptime: "+fmtDuration(time.Since(server.OnlineTimestamp)))
sendEmbededMessage(m.ChannelID, green, server.Name, "Online!")
} else {
sendEmbeddedMessage(m.ChannelID, red, server.Name, "Offline!\nDowntime: "+fmtDuration(time.Since(server.OfflineTimestamp)))
sendEmbededMessage(m.ChannelID, red, server.Name, "Offline!")
}
}
}
}
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)
}