package core import ( "context" "encoding/json" "log" "time" "gitea.mrixs.me/minecraft-platform/backend/internal/database" "gitea.mrixs.me/minecraft-platform/backend/internal/models" "github.com/Tnze/go-mc/bot/basic" "github.com/Tnze/go-mc/net" ) type ServerPoller struct { Repo *database.ServerRepository } func (p *ServerPoller) Start(ctx context.Context) { log.Println("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(): log.Println("Stopping server poller...") return } } } func (p *ServerPoller) pollAllServers(ctx context.Context) { servers, err := p.Repo.GetAllEnabledServers(ctx) if err != nil { log.Printf("Poller: failed to get servers: %v", err) return } for _, s := range servers { go p.pollServer(ctx, s) } } func (p *ServerPoller) pollServer(ctx context.Context, server *models.GameServer) { resp, delay, err := net.PingAndListTimeout(server.Address, 5*time.Second) if err != nil { log.Printf("Poller: failed to ping %s (%s): %v", server.Name, server.Address, err) return } var status basic.ServerList if err := json.Unmarshal(resp, &status); err != nil { log.Printf("Poller: failed to unmarshal status for %s: %v", server.Name, err) return } // MOTD может быть сложным объектом, извлекаем текст var motdText string if s, ok := status.Description.(string); ok { motdText = s } else { if m, ok := status.Description.(map[string]interface{}); ok { if t, ok := m["text"].(string); ok { motdText = t } } } 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 { log.Printf("Poller: failed to update status for %s: %v", server.Name, err) } else { log.Printf("Poller: successfully polled %s", server.Name) } }