Files
tf2stats/main.go

138 lines
3.2 KiB
Go
Raw Permalink Normal View History

2024-04-21 14:18:13 +02:00
package main
import (
"encoding/json"
"flag"
"fmt"
2024-04-21 23:47:18 +02:00
"hash/fnv"
2024-05-01 14:13:36 +02:00
"io"
"net/http"
2024-04-21 14:18:13 +02:00
"os/exec"
"strings"
2024-04-21 21:52:13 +02:00
"time"
2024-04-22 23:01:48 +02:00
"unicode"
2024-05-01 14:13:36 +02:00
"github.com/influxdata/line-protocol/v2/lineprotocol"
log "github.com/sirupsen/logrus"
2024-04-21 14:18:13 +02:00
)
2024-05-01 14:13:36 +02:00
type SteamAPIResponse struct {
Response struct {
PlayerCount int `json:"player_count"`
Result int `json:"result"`
} `json:"response"`
}
2024-04-21 14:18:13 +02:00
type TF2Stat struct {
Name string `json:"name"`
Map string `json:"map"`
Password bool `json:"password"`
MaxPlayers int `json:"maxplayers"`
NumPlayers int `json:"numplayers"`
QueryPort int `json:"queryPort"`
Ping int `json:"ping"`
Error *string `json:"error,omitempty"`
}
type TF2Server string
var (
2024-04-22 00:06:28 +02:00
server = flag.String("server", "", "comma-separated list of addresses to query")
hashes = flag.String("translate", "", "comma-separated list of maps to hash")
2024-04-21 14:18:13 +02:00
)
func main() {
flag.Parse()
2024-04-22 00:06:28 +02:00
if *hashes != "" {
maps := strings.Split(*hashes, ",")
for _, tf2map := range maps {
h := fnv.New32a()
h.Write([]byte(tf2map))
mHash := h.Sum32()
fmt.Printf("%d\t%s\n", mHash, tf2map)
}
return
}
2024-04-21 14:18:13 +02:00
servers := strings.Split(*server, ",")
var tServer []TF2Server
for _, srv := range servers {
tServer = append(tServer, TF2Server(strings.TrimSpace(srv)))
}
2024-05-01 14:13:36 +02:00
totalStat := new(SteamAPIResponse)
resp, err := http.Get("https://api.steampowered.com/ISteamUserStats/GetNumberOfCurrentPlayers/v1?appid=440")
if err != nil {
log.Debugf("error retrieving tf2 player count: %v", err)
}
defer resp.Body.Close()
bResp, err := io.ReadAll(resp.Body)
if err != nil {
log.Debugf("error reading tf2 player count response: %v", err)
}
err = json.Unmarshal(bResp, &totalStat)
if err != nil {
log.Debugf("error parsing tf2 player count response: %v", err)
}
if totalStat != nil {
var globalEnc lineprotocol.Encoder
globalEnc.StartLine("tf2stats")
globalEnc.AddField("players", lineprotocol.IntValue(int64(totalStat.Response.PlayerCount)))
globalEnc.EndLine(time.Now())
fmt.Print(string(globalEnc.Bytes()))
}
2024-04-21 14:18:13 +02:00
for _, ip := range tServer {
tStat, err := ip.Stats()
if err != nil {
2024-04-21 15:09:35 +02:00
log.Debugf("error retrieving stats for %s: %v", ip, err)
2024-04-21 14:18:13 +02:00
continue
}
2024-04-22 23:01:48 +02:00
cleanName := strings.Map(func(r rune) rune {
if unicode.IsPrint(r) {
return r
}
return -1
}, tStat.Name)
2024-04-21 21:52:13 +02:00
2024-04-22 23:01:48 +02:00
var enc lineprotocol.Encoder
2024-04-21 21:52:13 +02:00
enc.StartLine("tf2server")
enc.AddTag("address", string(ip))
2024-04-22 23:01:48 +02:00
enc.AddTag("name", cleanName)
2024-04-21 21:52:13 +02:00
enc.AddField("player", lineprotocol.IntValue(int64(tStat.NumPlayers)))
enc.AddField("maxplayer", lineprotocol.IntValue(int64(tStat.MaxPlayers)))
enc.AddField("ping", lineprotocol.IntValue(int64(tStat.Ping)))
2024-04-21 23:47:18 +02:00
// hash map to convert it to int
h := fnv.New32a()
2024-05-01 14:13:36 +02:00
_, _ = h.Write([]byte(tStat.Map))
2024-04-21 23:47:18 +02:00
enc.AddField("map", lineprotocol.UintValue(uint64(h.Sum32())))
2024-04-21 21:52:13 +02:00
enc.EndLine(time.Now())
fmt.Print(string(enc.Bytes()))
2024-04-21 14:18:13 +02:00
}
}
func (ip TF2Server) Stats() (*TF2Stat, error) {
2024-05-01 14:13:36 +02:00
cmd := exec.Command("gamedig", "--type", "teamfortress2", string(ip)) //nolint:gosec
2024-04-21 14:18:13 +02:00
bOut, err := cmd.CombinedOutput()
if err != nil {
return nil, err
}
nStat := new(TF2Stat)
if err = json.Unmarshal(bOut, &nStat); err != nil {
return nil, err
}
if nStat.Error != nil {
2024-04-21 14:56:36 +02:00
return nil, fmt.Errorf("gamedig returned error: %v", *nStat.Error)
2024-04-21 14:18:13 +02:00
}
return nStat, nil
}