Last active
February 17, 2024 18:15
-
-
Save cstewart90/b11974b1589fcce137f35573a632b0ea to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"errors" | |
"net/http" | |
"strings" | |
"sync" | |
"time" | |
"github.com/labstack/echo/v4" | |
"github.com/labstack/echo/v4/middleware" | |
"github.com/rumblefrog/go-a2s" | |
) | |
const ( | |
ServerTimeout = time.Second * 1 | |
MinimumServerLength = 4 | |
MaximumServers = 40 | |
LimitPerSecond = 3 | |
) | |
type serverInfo struct { | |
Server string `json:"server"` | |
Error string `json:"error"` | |
Name string `json:"name"` | |
Map string `json:"map"` | |
Folder string `json:"folder"` | |
Game string `json:"game"` | |
ID uint16 `json:"app_id"` | |
GameID uint64 `json:"game_id"` | |
Players uint8 `json:"players"` | |
MaxPlayers uint8 `json:"max_players"` | |
Bots uint8 `json:"bots"` | |
ServerType string `json:"server_type"` | |
ServerOS string `json:"server_os"` | |
Visibility bool `json:"password"` | |
VAC bool `json:"vac"` | |
Version string `json:"version"` | |
} | |
type infoResponse struct { | |
Error string `json:"error"` | |
Servers []serverInfo `json:"servers"` | |
} | |
func main() { | |
e := echo.New() | |
e.Use(middleware.Logger()) | |
e.Use(middleware.Recover()) | |
e.Use(middleware.RateLimiter(middleware.NewRateLimiterMemoryStore(LimitPerSecond))) | |
e.GET("/info", info) | |
e.Logger.Fatal(e.Start(":9090")) | |
} | |
func info(c echo.Context) error { | |
servers, err := getServers(c.QueryParam("servers")) | |
response := infoResponse{} | |
if err != nil { | |
response.Error = err.Error() | |
return c.JSON(http.StatusBadRequest, response) | |
} | |
var wg sync.WaitGroup | |
infos := make([]serverInfo, len(servers)) | |
for i, server := range servers { | |
wg.Add(1) | |
go func(i int, server string) { | |
defer wg.Done() | |
infos[i] = getInfo(server) | |
}(i, server) | |
} | |
wg.Wait() | |
response.Servers = infos | |
return c.JSON(http.StatusOK, response) | |
} | |
func getServers(s string) ([]string, error) { | |
if len(s) == 0 { | |
return []string{}, errors.New("no servers provided") | |
} | |
s = strings.ReplaceAll(s, " ", "") | |
servers := strings.Split(s, ",") | |
servers = removeBlankServers(servers) | |
if len(servers) > MaximumServers { | |
return []string{}, errors.New("too many servers, max is 40") | |
} | |
return servers, nil | |
} | |
func removeBlankServers(servers []string) []string { | |
var newServers []string | |
for _, server := range servers { | |
if len(server) >= MinimumServerLength { | |
newServers = append(newServers, server) | |
} | |
} | |
return newServers | |
} | |
func getInfo(server string) serverInfo { | |
client, err := a2s.NewClient(server, a2s.TimeoutOption(ServerTimeout)) | |
if err != nil { | |
return serverInfo{Server: server, Error: err.Error()} | |
} | |
defer client.Close() | |
info, err := client.QueryInfo() | |
if err != nil { | |
return serverInfo{Server: server, Error: err.Error()} | |
} | |
return serverInfo{ | |
Server: server, | |
Error: "", | |
Name: info.Name, | |
Map: info.Map, | |
Folder: info.Folder, | |
Game: info.Game, | |
ID: info.ID, | |
GameID: info.ExtendedServerInfo.GameID, | |
Players: info.Players, | |
MaxPlayers: info.MaxPlayers, | |
Bots: info.Bots, | |
ServerType: info.ServerType.String(), | |
ServerOS: info.ServerOS.String(), | |
Visibility: info.Visibility, | |
VAC: info.VAC, | |
Version: info.Version, | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module a2s-json | |
go 1.22 | |
require ( | |
github.com/labstack/echo/v4 v4.11.4 | |
github.com/rumblefrog/go-a2s v1.0.2 | |
) | |
require ( | |
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect | |
github.com/labstack/gommon v0.4.2 // indirect | |
github.com/mattn/go-colorable v0.1.13 // indirect | |
github.com/mattn/go-isatty v0.0.20 // indirect | |
github.com/valyala/bytebufferpool v1.0.0 // indirect | |
github.com/valyala/fasttemplate v1.2.2 // indirect | |
golang.org/x/crypto v0.19.0 // indirect | |
golang.org/x/net v0.21.0 // indirect | |
golang.org/x/sys v0.17.0 // indirect | |
golang.org/x/text v0.14.0 // indirect | |
golang.org/x/time v0.5.0 // indirect | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment