package main import ( "fmt" "log" "strings" "sync" "time" "github.com/bwmarrin/discordgo" ) type StatusMonitor struct { mu sync.Mutex session *discordgo.Session channelID string host string port int interval time.Duration messageID string onlineSince time.Time } func NewStatusMonitor(s *discordgo.Session, cfg *Config) *StatusMonitor { return &StatusMonitor{ session: s, channelID: cfg.ChannelID, host: cfg.ServerHost, port: cfg.ServerPort, interval: time.Duration(cfg.UpdateInterval) * time.Second, } } func (m *StatusMonitor) Start() { m.updateStatus() m.findExistingMessage() ticker := time.NewTicker(m.interval) go func() { for range ticker.C { m.updateStatus() } }() } func (m *StatusMonitor) findExistingMessage() { msgs, err := m.session.ChannelMessages(m.channelID, 50, "", "", "") if err != nil { log.Printf("Error fetching messages: %v", err) return } for _, msg := range msgs { if msg.Author.ID == m.session.State.User.ID { m.mu.Lock() m.messageID = msg.ID m.mu.Unlock() return } } } func (m *StatusMonitor) buildEmbed(status *ServerStatus) *discordgo.MessageEmbed { embed := &discordgo.MessageEmbed{ Color: 0x808080, Title: "NikoCraft", URL: "https://mc.n1ko.dev", } if !status.Online { embed.Description = "**Сервер оффлайн** 🔴" embed.Color = 0xFF0000 return embed } var b strings.Builder b.WriteString("**Игроки:**\n```\n") if len(status.Players) == 0 { b.WriteString("Никого нет") } else { for i, name := range status.Players { if i > 0 { b.WriteString("\n") } b.WriteString(name) } } b.WriteString("```") embed.Description = b.String() uptime := time.Since(m.onlineSince) var uptimeStr string hours := uptime.Hours() if hours < 1 { uptimeStr = fmt.Sprintf("%.0f мин.", uptime.Minutes()) } else { uptimeStr = fmt.Sprintf("%.1f ч.", hours) } embed.Fields = []*discordgo.MessageEmbedField{ { Name: ":busts_in_silhouette: Игроков", Value: fmt.Sprintf("%d/%d", status.OnlineCount, status.MaxPlayers), Inline: true, }, { Name: ":repeat: Аптайм", Value: uptimeStr, Inline: true, }, } return embed } func (m *StatusMonitor) updateStatus() { status, err := queryServer(m.host, m.port) m.mu.Lock() defer m.mu.Unlock() if err != nil { log.Printf("Server query failed: %v", err) m.onlineSince = time.Time{} status = &ServerStatus{Online: false} } else { if m.onlineSince.IsZero() { m.onlineSince = time.Now() } } embed := m.buildEmbed(status) if m.messageID != "" { _, err := m.session.ChannelMessageEditComplex(&discordgo.MessageEdit{ Channel: m.channelID, ID: m.messageID, Embeds: &[]*discordgo.MessageEmbed{embed}, }) if err != nil { log.Printf("Error editing embed (will create new): %v", err) m.messageID = "" } } if m.messageID == "" { msg, err := m.session.ChannelMessageSendEmbed(m.channelID, embed) if err != nil { log.Printf("Error sending embed: %v", err) return } m.messageID = msg.ID } }