91 lines
2.1 KiB
Go
91 lines
2.1 KiB
Go
package core
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"log/slog"
|
|
"time"
|
|
|
|
"gitea.mrixs.me/minecraft-platform/backend/internal/database"
|
|
"gitea.mrixs.me/minecraft-platform/backend/internal/models"
|
|
"github.com/Tnze/go-mc/bot"
|
|
"github.com/Tnze/go-mc/chat"
|
|
)
|
|
|
|
type pingResponse struct {
|
|
Description chat.Message `json:"description"`
|
|
Players struct {
|
|
Max int `json:"max"`
|
|
Online int `json:"online"`
|
|
} `json:"players"`
|
|
Version struct {
|
|
Name string `json:"name"`
|
|
Protocol int `json:"protocol"`
|
|
} `json:"version"`
|
|
}
|
|
|
|
type ServerPoller struct {
|
|
Repo *database.ServerRepository
|
|
}
|
|
|
|
func (p *ServerPoller) Start(ctx context.Context) {
|
|
slog.Info("Starting server poller...")
|
|
ticker := time.NewTicker(60 * time.Second)
|
|
defer ticker.Stop()
|
|
|
|
p.pollAllServers(ctx)
|
|
|
|
for {
|
|
select {
|
|
case <-ticker.C:
|
|
p.pollAllServers(ctx)
|
|
case <-ctx.Done():
|
|
slog.Info("Stopping server poller...")
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func (p *ServerPoller) pollAllServers(ctx context.Context) {
|
|
servers, err := p.Repo.GetAllEnabledServers(ctx)
|
|
if err != nil {
|
|
slog.Error("Poller: failed to get servers", "error", err)
|
|
return
|
|
}
|
|
|
|
for _, s := range servers {
|
|
go p.pollServer(ctx, s)
|
|
}
|
|
}
|
|
|
|
func (p *ServerPoller) pollServer(ctx context.Context, server *models.GameServer) {
|
|
resp, delay, err := bot.PingAndList(server.Address)
|
|
if err != nil {
|
|
slog.Warn("Poller: failed to ping server", "server", server.Name, "address", server.Address, "error", err)
|
|
return
|
|
}
|
|
|
|
var status pingResponse
|
|
if err := json.Unmarshal(resp, &status); err != nil {
|
|
slog.Error("Poller: failed to unmarshal status", "server", server.Name, "error", err)
|
|
return
|
|
}
|
|
|
|
motdText := status.Description.String()
|
|
|
|
updateData := &models.ServerStatus{
|
|
StatusJSON: string(resp),
|
|
Motd: motdText,
|
|
PlayerCount: status.Players.Online,
|
|
MaxPlayers: status.Players.Max,
|
|
VersionName: status.Version.Name,
|
|
Ping: delay.Milliseconds(),
|
|
}
|
|
|
|
if err := p.Repo.UpdateServerStatus(ctx, server.ID, updateData); err != nil {
|
|
slog.Error("Poller: failed to update status", "server", server.Name, "error", err)
|
|
} else {
|
|
slog.Info("Poller: successfully polled server", "server", server.Name)
|
|
}
|
|
}
|