170 lines
6.3 KiB
Go
170 lines
6.3 KiB
Go
package events
|
||
|
||
import (
|
||
"bytes"
|
||
"encoding/json"
|
||
"fmt"
|
||
"net/http"
|
||
"strings"
|
||
"stream-bot/internal/audio"
|
||
"stream-bot/internal/db"
|
||
"stream-bot/internal/hotkey"
|
||
"stream-bot/internal/logger"
|
||
"stream-bot/internal/webservices"
|
||
)
|
||
|
||
type Processor struct {
|
||
sendMessageFunc func(platform, text string) error
|
||
webSrvMgr *webservices.Manager
|
||
}
|
||
|
||
// NewProcessor создаёт обработчик событий с функцией отправки сообщений и менеджером веб-сервисов
|
||
func NewProcessor(sendMessageFunc func(platform, text string) error, webSrvMgr *webservices.Manager) *Processor {
|
||
return &Processor{
|
||
sendMessageFunc: sendMessageFunc,
|
||
webSrvMgr: webSrvMgr,
|
||
}
|
||
}
|
||
|
||
func (p *Processor) ProcessEvent(platform, eventName string, params map[string]string) {
|
||
// 1. Выполняем действия, сохранённые в БД (send_message, play_sound, press_hotkey)
|
||
actions, err := db.GetEventActions(platform, eventName)
|
||
if err != nil {
|
||
logger.Error("Failed to get event actions: %v", err)
|
||
} else {
|
||
for _, action := range actions {
|
||
switch action.Type {
|
||
case "send_message":
|
||
if p.sendMessageFunc == nil {
|
||
logger.Error("sendMessageFunc is nil, cannot send message")
|
||
continue
|
||
}
|
||
text := action.Text
|
||
for k, v := range params {
|
||
placeholder := "{{" + k + "}}"
|
||
text = strings.ReplaceAll(text, placeholder, v)
|
||
}
|
||
if err := p.sendMessageFunc(platform, text); err != nil {
|
||
logger.Error("Send message error: %v", err)
|
||
}
|
||
case "play_sound":
|
||
if err := audio.PlaySound(action.SoundFile); err != nil {
|
||
logger.Error("Play sound error: %v", err)
|
||
}
|
||
case "press_hotkey":
|
||
if err := hotkey.PressCombination(action.Keys); err != nil {
|
||
logger.Error("Hotkey error: %v", err)
|
||
}
|
||
case "http_request":
|
||
logger.Info("[Event] HTTP request to %s", action.URL)
|
||
}
|
||
}
|
||
}
|
||
|
||
// 2. Отправляем уведомление во все запущенные alert-сервисы (если есть)
|
||
if p.webSrvMgr == nil {
|
||
return
|
||
}
|
||
|
||
// Формируем заголовок и текст уведомления на основе типа события
|
||
title, text := p.formatEventNotification(eventName, params)
|
||
if title == "" && text == "" {
|
||
// Если событие не требует уведомления, не отправляем
|
||
return
|
||
}
|
||
|
||
// Получаем звук для события (можно настроить позже, пока используем стандартные)
|
||
soundFile := p.getSoundForEvent(eventName)
|
||
|
||
payload := map[string]interface{}{
|
||
"title": title,
|
||
"text": text,
|
||
"duration": 5,
|
||
"image": "",
|
||
"sound": soundFile,
|
||
}
|
||
|
||
// Отправляем во все alert-сервисы
|
||
services := p.webSrvMgr.GetAllServices()
|
||
for _, srv := range services {
|
||
if srv.GetType() != "alert" {
|
||
continue
|
||
}
|
||
port := srv.GetPort()
|
||
url := fmt.Sprintf("http://localhost:%d/notify", port)
|
||
body, _ := json.Marshal(payload)
|
||
go func(url string, body []byte) {
|
||
resp, err := http.Post(url, "application/json", bytes.NewReader(body))
|
||
if err != nil {
|
||
logger.Error("Failed to send alert to service %s: %v", url, err)
|
||
} else {
|
||
resp.Body.Close()
|
||
}
|
||
}(url, body)
|
||
}
|
||
}
|
||
|
||
// formatEventNotification формирует заголовок и текст уведомления для события
|
||
func (p *Processor) formatEventNotification(eventName string, params map[string]string) (title, text string) {
|
||
switch eventName {
|
||
case "follow":
|
||
username := params["username"]
|
||
title = "Новый фолловер!"
|
||
text = username + " теперь с нами"
|
||
case "subscribe":
|
||
username := params["username"]
|
||
tier := params["tier"]
|
||
tierName := ""
|
||
switch tier {
|
||
case "1000":
|
||
tierName = "1 уровень"
|
||
case "2000":
|
||
tierName = "2 уровень"
|
||
case "3000":
|
||
tierName = "3 уровень"
|
||
default:
|
||
tierName = tier
|
||
}
|
||
title = "Спасибо за подписку!"
|
||
text = username + " подписался на " + tierName
|
||
case "gift_sub":
|
||
gifter := params["gifter"]
|
||
recipient := params["recipient"]
|
||
total := params["cumulative_total"]
|
||
title = "Подарочная подписка!"
|
||
if recipient != "" {
|
||
text = gifter + " подарил подписку для " + recipient
|
||
} else {
|
||
text = gifter + " подарил " + total + " подписок"
|
||
}
|
||
case "raid":
|
||
from := params["from"]
|
||
viewers := params["viewers"]
|
||
title = "Рейд!"
|
||
text = from + " привёл " + viewers + " зрителей"
|
||
case "reward_redemption":
|
||
username := params["username"]
|
||
reward := params["reward_title"]
|
||
title = "Активирована награда!"
|
||
text = username + " активировал " + reward
|
||
default:
|
||
return "", ""
|
||
}
|
||
return title, text
|
||
}
|
||
|
||
// getSoundForEvent возвращает путь к звуковому файлу для события (можно вынести в настройки)
|
||
func (p *Processor) getSoundForEvent(eventName string) string {
|
||
// Здесь можно читать настройки из БД, пока используем заглушку
|
||
sounds := map[string]string{
|
||
"follow": "/sounds/follow.mp3",
|
||
"subscribe": "/sounds/sub.mp3",
|
||
"gift_sub": "/sounds/gift.mp3",
|
||
"raid": "/sounds/raid.mp3",
|
||
"reward_redemption": "/sounds/reward.mp3",
|
||
}
|
||
if s, ok := sounds[eventName]; ok {
|
||
return s
|
||
}
|
||
return "/sounds/default.mp3"
|
||
} |