216 lines
6.3 KiB
Go
216 lines
6.3 KiB
Go
package platforms
|
||
|
||
import (
|
||
"strings"
|
||
"sync"
|
||
"time"
|
||
"fmt"
|
||
"stream-bot/internal/commands"
|
||
"stream-bot/internal/events"
|
||
"stream-bot/internal/logger"
|
||
"stream-bot/internal/userstats"
|
||
"stream-bot/internal/db"
|
||
"stream-bot/internal/notifications"
|
||
"stream-bot/internal/webservices"
|
||
|
||
|
||
|
||
)
|
||
|
||
type Platform interface {
|
||
Connect() error
|
||
Disconnect()
|
||
SendMessage(text string) error
|
||
GetName() string
|
||
}
|
||
|
||
type Manager struct {
|
||
platforms map[string]Platform
|
||
cmdProc *commands.Processor
|
||
eventProc *events.Processor
|
||
mu sync.RWMutex
|
||
userStats *userstats.Store
|
||
notifMgr *notifications.Manager
|
||
webServices *webservices.Manager
|
||
}
|
||
|
||
func NewManager(cmdProc *commands.Processor, eventProc *events.Processor, notifMgr *notifications.Manager, webSrv *webservices.Manager) *Manager {
|
||
m := &Manager{
|
||
platforms: make(map[string]Platform),
|
||
cmdProc: cmdProc,
|
||
eventProc: eventProc,
|
||
userStats: userstats.NewStore(),
|
||
notifMgr: notifMgr,
|
||
webServices: webSrv,
|
||
}
|
||
m.platforms["twitch"] = NewTwitchPlatform(m)
|
||
return m
|
||
}
|
||
|
||
func (m *Manager) ConnectAll() {
|
||
for name, p := range m.platforms {
|
||
if err := p.Connect(); err != nil {
|
||
logger.Error("Failed to connect %s: %v", name, err)
|
||
}
|
||
}
|
||
}
|
||
|
||
func (m *Manager) StopAll() {
|
||
for _, p := range m.platforms {
|
||
p.Disconnect()
|
||
}
|
||
}
|
||
|
||
func (m *Manager) GetPlatform(name string) Platform {
|
||
m.mu.RLock()
|
||
defer m.mu.RUnlock()
|
||
return m.platforms[name]
|
||
}
|
||
|
||
func (m *Manager) OnChatMessage(platform, channel, username, message string, isMod, isBroadcaster, isVip, isSubscriber bool) {
|
||
// Обновляем статистику пользователя
|
||
m.userStats.Update(username, func(u *userstats.UserStats) {
|
||
u.MessageCount++
|
||
u.LastActive = time.Now()
|
||
u.IsMod = isMod
|
||
u.IsVip = isVip
|
||
u.IsSubscriber = isSubscriber
|
||
})
|
||
if m.notifMgr != nil {
|
||
m.notifMgr.PlayEvent("new_message")
|
||
}
|
||
m.webServices.SendChatMessage(webservices.ChatMessage{
|
||
Username: username,
|
||
Message: message,
|
||
IsMod: isMod,
|
||
IsVip: isVip,
|
||
IsSub: isSubscriber,
|
||
Timestamp: time.Now().Unix(),
|
||
})
|
||
// Обработка команды
|
||
if len(message) == 0 || message[0] != '!' {
|
||
// Проверка на отметку: если пользователь отмечен и это его первое сообщение за стрим (сегодня)
|
||
m.checkAndSendMarkNotification(username, platform, channel)
|
||
return
|
||
}
|
||
|
||
parts := strings.SplitN(message, " ", 2)
|
||
trigger := strings.TrimPrefix(parts[0], "!")
|
||
args := ""
|
||
if len(parts) > 1 {
|
||
args = parts[1]
|
||
}
|
||
resp, _, err := m.cmdProc.ProcessCommand(trigger, username, platform, isMod, isBroadcaster, args)
|
||
if err != nil {
|
||
logger.Error("Command error: %v", err)
|
||
return
|
||
}
|
||
if resp != "" {
|
||
if p := m.GetPlatform(platform); p != nil {
|
||
p.SendMessage(resp)
|
||
}
|
||
}
|
||
// После команды тоже проверяем отметку (можно вынести в общее место)
|
||
m.checkAndSendMarkNotification(username, platform, channel)
|
||
}
|
||
|
||
// checkAndSendMarkNotification отправляет сообщение, если пользователь отмечен и сегодня ещё не отмечали
|
||
func (m *Manager) checkAndSendMarkNotification(username, platform, channel string) {
|
||
marked, lastDate, err := db.IsUserMarked(username, platform)
|
||
if err != nil {
|
||
logger.Error("Failed to check marked user: %v", err)
|
||
return
|
||
}
|
||
if !marked {
|
||
return
|
||
}
|
||
today := time.Now().Format("2006-01-02")
|
||
if lastDate == today {
|
||
return
|
||
}
|
||
// Отправляем сообщение с упоминанием пользователя, а не канала
|
||
msg := fmt.Sprintf("Время кое-кого отметить! Отмечен @%s", username)
|
||
if p := m.GetPlatform(platform); p != nil {
|
||
p.SendMessage(msg)
|
||
}
|
||
db.UpdateMarkedUserDate(username, platform, time.Now())
|
||
}
|
||
|
||
func (m *Manager) OnEvent(platform, eventName string, params map[string]string) {
|
||
m.eventProc.ProcessEvent(platform, eventName, params)
|
||
if m.webServices != nil {
|
||
// Преобразуем map[string]string в map[string]interface{}
|
||
data := make(map[string]interface{})
|
||
for k, v := range params {
|
||
data[k] = v
|
||
}
|
||
// Исправленный вызов:
|
||
m.webServices.SendAlertEvent(webservices.AlertEvent{
|
||
Type: eventName,
|
||
Data: data,
|
||
})
|
||
}
|
||
}
|
||
|
||
func (m *Manager) IsConnected(platform string) bool {
|
||
m.mu.RLock()
|
||
defer m.mu.RUnlock()
|
||
if p, ok := m.platforms[platform]; ok {
|
||
if tw, ok := p.(*TwitchPlatform); ok {
|
||
return tw.IsConnected()
|
||
}
|
||
// для других платформ можно добавить аналогично
|
||
}
|
||
return false
|
||
}
|
||
|
||
func (m *Manager) GetAllUsers() []*userstats.UserStats {
|
||
return m.userStats.GetAll()
|
||
}
|
||
|
||
func (m *Manager) UpdateUserFlags(username string, isVip, isMod, isSubscriber bool) {
|
||
m.userStats.Update(username, func(u *userstats.UserStats) {
|
||
if isVip {
|
||
u.IsVip = isVip
|
||
}
|
||
if isMod {
|
||
u.IsMod = isMod
|
||
}
|
||
if isSubscriber {
|
||
u.IsSubscriber = isSubscriber
|
||
}
|
||
})
|
||
}
|
||
|
||
func (m *Manager) UpdateUserMarked(username string, marked bool) {
|
||
m.userStats.Update(username, func(u *userstats.UserStats) {
|
||
u.IsMarked = marked
|
||
})
|
||
}
|
||
|
||
func (m *Manager) SetVip(username string, isVip bool) {
|
||
m.userStats.Update(username, func(u *userstats.UserStats) {
|
||
u.IsVip = isVip
|
||
})
|
||
}
|
||
|
||
func (m *Manager) SetMod(username string, isMod bool) {
|
||
m.userStats.Update(username, func(u *userstats.UserStats) {
|
||
u.IsMod = isMod
|
||
})
|
||
}
|
||
|
||
func (m *Manager) SetMarked(username string, isMarked bool) {
|
||
m.userStats.Update(username, func(u *userstats.UserStats) {
|
||
u.IsMarked = isMarked
|
||
})
|
||
}
|
||
|
||
func (m *Manager) GetTwitchEventSubStatus() (connected bool, subscriptions []string, err error) {
|
||
tw, ok := m.platforms["twitch"].(*TwitchPlatform)
|
||
if !ok {
|
||
return false, nil, fmt.Errorf("twitch platform not available")
|
||
}
|
||
connected, subscriptions = tw.EventSubStatus()
|
||
return connected, subscriptions, nil
|
||
} |