135 lines
3.8 KiB
Go
135 lines
3.8 KiB
Go
package events
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
"strconv"
|
|
"time"
|
|
|
|
"velox-bot/internal/db/services"
|
|
|
|
"github.com/bwmarrin/discordgo"
|
|
)
|
|
|
|
// StartTwitchLiveLoop periodically checks configured Twitch streamers and
|
|
// sends live notifications to the configured channel.
|
|
func StartTwitchLiveLoop(s *discordgo.Session, svc *services.Services) {
|
|
if svc == nil || svc.Twitch == nil || s == nil {
|
|
return
|
|
}
|
|
|
|
const (
|
|
interval = 30 * time.Second
|
|
initialDelay = 10 * time.Second
|
|
)
|
|
|
|
go func() {
|
|
time.Sleep(initialDelay)
|
|
|
|
log.Printf("twitch: starting live notification loop (interval=%s)", interval)
|
|
|
|
ticker := time.NewTicker(interval)
|
|
defer ticker.Stop()
|
|
|
|
for range ticker.C {
|
|
ctx := context.Background()
|
|
|
|
guildIDs, err := svc.Twitch.ListGuilds(ctx)
|
|
if err != nil {
|
|
log.Printf("twitch: failed to list guilds: %v", err)
|
|
continue
|
|
}
|
|
|
|
if len(guildIDs) == 0 {
|
|
log.Printf("twitch: no guilds with configured streamers")
|
|
}
|
|
|
|
for _, guildID := range guildIDs {
|
|
log.Printf("twitch: processing guild %d", guildID)
|
|
|
|
channelID, ok, err := svc.Twitch.GetNotificationChannel(ctx, guildID)
|
|
if err != nil {
|
|
log.Printf("twitch: failed to get channel for guild %d: %v", guildID, err)
|
|
continue
|
|
}
|
|
if !ok || channelID == 0 {
|
|
log.Printf("twitch: no notification channel configured for guild %d", guildID)
|
|
continue
|
|
}
|
|
|
|
users, err := svc.Twitch.ListUsersForGuild(ctx, guildID)
|
|
if err != nil {
|
|
log.Printf("twitch: failed to list users for guild %d: %v", guildID, err)
|
|
continue
|
|
}
|
|
|
|
if len(users) == 0 {
|
|
log.Printf("twitch: no streamers configured for guild %d", guildID)
|
|
continue
|
|
}
|
|
|
|
chIDStr := strconv.FormatInt(channelID, 10)
|
|
|
|
for _, username := range users {
|
|
log.Printf("twitch: checking live status for guild %d, user %s", guildID, username)
|
|
|
|
isLive, err := svc.Twitch.IsUserStreaming(ctx, username)
|
|
if err != nil {
|
|
log.Printf("twitch: failed to check stream for %s: %v", username, err)
|
|
continue
|
|
}
|
|
|
|
status, ok, err := svc.Twitch.GetStatus(ctx, guildID, username)
|
|
if err != nil {
|
|
log.Printf("twitch: failed to get status for %s: %v", username, err)
|
|
continue
|
|
}
|
|
if !ok {
|
|
status = "not live"
|
|
}
|
|
|
|
if isLive {
|
|
if status == "not live" {
|
|
log.Printf("twitch: %s went live in guild %d, sending notification to channel %s", username, guildID, chIDStr)
|
|
|
|
liveURL := "https://www.twitch.tv/" + username
|
|
content := "@everyone"
|
|
|
|
previewURL := "https://static-cdn.jtvnw.net/previews-ttv/live_user_" + username + "-640x360.jpg"
|
|
|
|
embed := &discordgo.MessageEmbed{
|
|
Title: ":red_circle: " + username + " is now LIVE on Twitch!",
|
|
Description: "Click the link below to watch the stream.",
|
|
URL: liveURL,
|
|
Color: 0x9146FF, // Twitch purple
|
|
Image: &discordgo.MessageEmbedImage{
|
|
URL: previewURL,
|
|
},
|
|
}
|
|
|
|
if _, err := s.ChannelMessageSendComplex(chIDStr, &discordgo.MessageSend{
|
|
Content: content,
|
|
Embed: embed,
|
|
}); err != nil {
|
|
log.Printf("twitch: failed to send notification for %s: %v", username, err)
|
|
continue
|
|
}
|
|
if err := svc.Twitch.UpdateStatus(ctx, guildID, username, "live"); err != nil {
|
|
log.Printf("twitch: failed to update status to live for %s in guild %d: %v", username, guildID, err)
|
|
}
|
|
}
|
|
} else {
|
|
if status != "not live" {
|
|
log.Printf("twitch: %s is no longer live in guild %d, updating status", username, guildID)
|
|
if err := svc.Twitch.UpdateStatus(ctx, guildID, username, "not live"); err != nil {
|
|
log.Printf("twitch: failed to update status to not live for %s in guild %d: %v", username, guildID, err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
}
|
|
|