strimertul/twitch/alerts/mixed.go

136 lines
4.1 KiB
Go

package alerts
import (
"math/rand"
"time"
"github.com/nicklaw5/helix/v2"
"git.sr.ht/~ashkeel/strimertul/twitch/chat"
)
type subMixedEvent struct {
UserID string
UserLogin string
UserName string
BroadcasterUserID string
BroadcasterUserLogin string
BroadcasterUserName string
Tier string
IsGift bool
CumulativeMonths int
StreakMonths int
DurationMonths int
Message helix.EventSubMessage
}
// Subscriptions are handled with a slight delay as info come from different events and must be aggregated
func (m *Module) addMixedEvent(event any) {
switch sub := event.(type) {
case helix.EventSubChannelSubscribeEvent:
m.pendingMux.Lock()
defer m.pendingMux.Unlock()
if ev, ok := m.pendingSubs[sub.UserID]; ok {
// Already pending, add extra data
ev.IsGift = sub.IsGift
m.pendingSubs[sub.UserID] = ev
return
}
m.pendingSubs[sub.UserID] = subMixedEvent{
UserID: sub.UserID,
UserLogin: sub.UserLogin,
UserName: sub.UserName,
BroadcasterUserID: sub.BroadcasterUserID,
BroadcasterUserLogin: sub.BroadcasterUserLogin,
BroadcasterUserName: sub.BroadcasterUserName,
Tier: sub.Tier,
IsGift: sub.IsGift,
}
go func() {
// Wait a bit to make sure we aggregate all events
time.Sleep(time.Second * 3)
m.processPendingSub(sub.UserID)
}()
case helix.EventSubChannelSubscriptionMessageEvent:
m.pendingMux.Lock()
defer m.pendingMux.Unlock()
if ev, ok := m.pendingSubs[sub.UserID]; ok {
// Already pending, add extra data
ev.StreakMonths = sub.StreakMonths
ev.DurationMonths = sub.DurationMonths
ev.CumulativeMonths = sub.CumulativeMonths
ev.Message = sub.Message
return
}
m.pendingSubs[sub.UserID] = subMixedEvent{
UserID: sub.UserID,
UserLogin: sub.UserLogin,
UserName: sub.UserName,
BroadcasterUserID: sub.BroadcasterUserID,
BroadcasterUserLogin: sub.BroadcasterUserLogin,
BroadcasterUserName: sub.BroadcasterUserName,
Tier: sub.Tier,
StreakMonths: sub.StreakMonths,
DurationMonths: sub.DurationMonths,
CumulativeMonths: sub.CumulativeMonths,
Message: sub.Message,
}
go func() {
// Wait a bit to make sure we aggregate all events
time.Sleep(time.Second * 3)
m.processPendingSub(sub.UserID)
}()
}
}
func (m *Module) processPendingSub(user string) {
m.pendingMux.Lock()
defer m.pendingMux.Unlock()
sub, ok := m.pendingSubs[user]
defer delete(m.pendingSubs, user)
if !ok {
// Somehow it's gone? Return early
return
}
// One last check in case config changed
if !m.Config.Subscription.Enabled {
return
}
// Assign random message
messageID := rand.Intn(len(m.Config.Subscription.Messages))
tpl, ok := m.templates[templateTypeSubscription][m.Config.Subscription.Messages[messageID]]
// If template is broken, write it as is (soft fail, plus we raise attention I guess?)
if !ok {
// Broken template!
chat.WriteMessage(m.db, m.logger, chat.WriteMessageRequest{
Message: m.Config.Subscription.Messages[messageID],
Announce: m.Config.Subscription.Announce,
})
return
}
// Check for variations, either by streak or gifted
if sub.IsGift {
variation := getBestValidVariation(m.Config.Subscription.Variations, func(variation subscriptionVariation) int {
if variation.IsGifted != nil && *variation.IsGifted {
return 1
}
return 0
})
tpl = m.replaceWithVariation(tpl, templateTypeSubscription, variation.Messages)
} else if sub.DurationMonths > 0 {
// Get variation with the highest minimum streak that's met
variation := getBestValidVariation(m.Config.Subscription.Variations, func(variation subscriptionVariation) int {
if variation.MinStreak != nil && sub.DurationMonths >= *variation.MinStreak {
return sub.DurationMonths
}
return 0
})
tpl = m.replaceWithVariation(tpl, templateTypeSubscription, variation.Messages)
}
m.writeTemplate(tpl, sub, m.Config.Subscription.Announce)
}