mcstatus/monitor.go

130 lines
2.6 KiB
Go

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) formatMessage(status *ServerStatus) string {
if !status.Online {
return "**Сервер оффлайн** 🔴"
}
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("```\n")
fmt.Fprintf(&b, ":busts_in_silhouette: Кол-во игроков: %d\n", status.OnlineCount)
uptime := time.Since(m.onlineSince)
hours := uptime.Hours()
if hours < 1 {
fmt.Fprintf(&b, ":repeat: Аптайм сервера: %.0f мин.", uptime.Minutes())
} else {
fmt.Fprintf(&b, ":repeat: Аптайм сервера: %.1f ч.", hours)
}
return b.String()
}
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()
}
}
content := m.formatMessage(status)
if m.messageID != "" {
_, err := m.session.ChannelMessageEdit(m.channelID, m.messageID, content)
if err != nil {
log.Printf("Error editing message (will create new): %v", err)
m.messageID = ""
}
}
if m.messageID == "" {
msg, err := m.session.ChannelMessageSend(m.channelID, content)
if err != nil {
log.Printf("Error sending message: %v", err)
return
}
m.messageID = msg.ID
}
}