package platforms import ( "fmt" "stream-bot/internal/db" "stream-bot/internal/logger" "sync" "strings" "github.com/gempir/go-twitch-irc/v4" "stream-bot/internal/twitchapi" ) type TwitchPlatform struct { client *twitch.Client manager *Manager channel string botLogin string connected bool mu sync.RWMutex eventSub *TwitchEventSub twitchAPI *twitchapi.TwitchAPI } func NewTwitchPlatform(mgr *Manager) *TwitchPlatform { return &TwitchPlatform{ manager: mgr, twitchAPI: twitchapi.New(), } } func (t *TwitchPlatform) GetName() string { return "twitch" } func (t *TwitchPlatform) Connect() error { tokens, err := db.GetPlatformTokens("twitch") if err != nil || tokens == nil || tokens.BotToken == "" { logger.Warn("Twitch bot token not set, skipping connection") return fmt.Errorf("no bot token") } t.botLogin = tokens.BotLogin if t.botLogin == "" { t.botLogin = "justinfan123" } t.channel = tokens.UserLogin if t.channel == "" { logger.Warn("Twitch user login not set, cannot join channel") return fmt.Errorf("no channel name") } t.client = twitch.NewClient(t.botLogin, "oauth:"+tokens.BotToken) t.client.OnPrivateMessage(func(msg twitch.PrivateMessage) { // Извлекаем значки badges := msg.Tags["badges"] isMod := strings.Contains(badges, "moderator/1") isVip := strings.Contains(badges, "vip/1") isSubscriber := strings.Contains(badges, "subscriber/") isBroadcaster := strings.Contains(badges, "broadcaster/1") t.manager.OnChatMessage("twitch", msg.Channel, msg.User.Name, msg.Message, isMod, isBroadcaster, isVip, isSubscriber) }) t.client.Join(t.channel) go t.client.Connect() t.mu.Lock() t.connected = true t.mu.Unlock() t.twitchAPI = twitchapi.New() t.eventSub = NewTwitchEventSub(t.manager, t.twitchAPI) if err := t.eventSub.Start(); err != nil { logger.Warn("Failed to start EventSub: %v", err) } return nil } func (t *TwitchPlatform) Disconnect() { t.mu.Lock() defer t.mu.Unlock() if t.eventSub != nil { t.eventSub.Stop() } if t.client != nil { t.client.Disconnect() } t.connected = false } func (t *TwitchPlatform) IsConnected() bool { t.mu.RLock() defer t.mu.RUnlock() return t.connected } func (t *TwitchPlatform) SendMessage(text string) error { if t.client == nil { return fmt.Errorf("not connected") } t.client.Say(t.channel, text) return nil } func (t *TwitchPlatform) TimeoutUser(username string, seconds int) { t.client.Say(t.channel, fmt.Sprintf("/timeout %s %d", username, seconds)) } func (t *TwitchPlatform) BanUser(username string) { t.client.Say(t.channel, fmt.Sprintf("/ban %s", username)) } func (t *TwitchPlatform) UnbanUser(username string) { t.client.Say(t.channel, fmt.Sprintf("/unban %s", username)) } func (t *TwitchPlatform) AddVip(username string) { t.client.Say(t.channel, fmt.Sprintf("/vip %s", username)) } func (t *TwitchPlatform) RemoveVip(username string) { t.client.Say(t.channel, fmt.Sprintf("/unvip %s", username)) } func (t *TwitchPlatform) AddMod(username string) { t.client.Say(t.channel, fmt.Sprintf("/mod %s", username)) } func (t *TwitchPlatform) RemoveMod(username string) { t.client.Say(t.channel, fmt.Sprintf("/unmod %s", username)) } func GetClientID() string { tokens, _ := db.GetPlatformTokens("twitch") if tokens != nil && tokens.ClientID != "" { return tokens.ClientID } return "0xc6mhgsuxpkvze0gi70ywjno6l2jw" } func (t *TwitchPlatform) EventSubStatus() (connected bool, subscriptions []string) { if t.eventSub == nil { return false, nil } return t.eventSub.IsConnected(), t.eventSub.GetSubscriptions() }