mirror of https://git.sr.ht/~ashkeel/strimertul
Alert templates are precalculate on config load/change
This commit is contained in:
parent
ee8c88b94c
commit
65d6be5ec3
|
@ -247,7 +247,8 @@
|
|||
"variation-header": "Variations",
|
||||
"add-variation": "Add variation",
|
||||
"variation-condition": "Condition",
|
||||
"min-months": "Subscription months (at least)"
|
||||
"min-months": "Subscription months (at least)",
|
||||
"delete-variation": "Delete variation"
|
||||
}
|
||||
},
|
||||
"auth": {
|
||||
|
|
|
@ -133,6 +133,7 @@ export default function TwitchBotAlertsPage(
|
|||
<input
|
||||
type="radio"
|
||||
name={`sub-var-${i}`}
|
||||
checked={variation.is_gifted ?? false}
|
||||
onChange={(ev) =>
|
||||
dispatch(
|
||||
apiReducer.actions.twitchBotAlertsChanged({
|
||||
|
@ -163,6 +164,7 @@ export default function TwitchBotAlertsPage(
|
|||
<label className="radio">
|
||||
<input
|
||||
type="radio"
|
||||
checked={!!variation.min_streak}
|
||||
name={`sub-var-${i}`}
|
||||
onChange={(ev) =>
|
||||
dispatch(
|
||||
|
@ -195,7 +197,34 @@ export default function TwitchBotAlertsPage(
|
|||
</Field>
|
||||
{variation.min_streak ? (
|
||||
<Field name={t('twitch.bot-alerts.min-months')}>
|
||||
<input type="number" className="input" min="1" step="1" />
|
||||
<input
|
||||
type="number"
|
||||
className="input"
|
||||
min="1"
|
||||
step="1"
|
||||
value={variation.min_streak}
|
||||
onChange={(ev) =>
|
||||
dispatch(
|
||||
apiReducer.actions.twitchBotAlertsChanged({
|
||||
...twitchBotAlerts,
|
||||
subscription: {
|
||||
...twitchBotAlerts.subscription,
|
||||
variations:
|
||||
// Replace messages in nth variation
|
||||
twitchBotAlerts?.subscription?.variations.map(
|
||||
(v, j) =>
|
||||
j === i
|
||||
? {
|
||||
...v,
|
||||
min_streak: ev.target.value,
|
||||
}
|
||||
: v,
|
||||
),
|
||||
},
|
||||
}),
|
||||
)
|
||||
}
|
||||
/>
|
||||
</Field>
|
||||
) : null}
|
||||
<Field name={t('twitch.bot-alerts.messages')}>
|
||||
|
@ -218,6 +247,24 @@ export default function TwitchBotAlertsPage(
|
|||
}
|
||||
/>
|
||||
</Field>
|
||||
<button
|
||||
className="button is-small is-danger"
|
||||
onClick={() => {
|
||||
const variations =
|
||||
twitchBotAlerts?.subscription?.variations ?? [];
|
||||
dispatch(
|
||||
apiReducer.actions.twitchBotAlertsChanged({
|
||||
...twitchBotAlerts,
|
||||
subscription: {
|
||||
...twitchBotAlerts.subscription,
|
||||
variations: variations.filter((v, j) => j !== i),
|
||||
},
|
||||
}),
|
||||
);
|
||||
}}
|
||||
>
|
||||
{t('twitch.bot-alerts.delete-variation')}
|
||||
</button>
|
||||
</article>
|
||||
))}
|
||||
<button
|
||||
|
|
2
go.mod
2
go.mod
|
@ -14,3 +14,5 @@ require (
|
|||
github.com/strimertul/kilovolt/v6 v6.1.0
|
||||
github.com/strimertul/stulbe-client-go v0.6.0
|
||||
)
|
||||
|
||||
replace github.com/nicklaw5/helix/v2 => github.com/ashkeel/helix/v2 v2.2.1-0.20211206103917-e677e633538f
|
||||
|
|
4
go.sum
4
go.sum
|
@ -10,6 +10,8 @@ github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFP
|
|||
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/ashkeel/helix/v2 v2.2.1-0.20211206103917-e677e633538f h1:ZpYT5G9ktPZdLbRh5Y9gNpBwK8xis9LfcNaofP5BJpo=
|
||||
github.com/ashkeel/helix/v2 v2.2.1-0.20211206103917-e677e633538f/go.mod h1:0ONzvVi1cH+k3a7EDIFNNqxfW0podhf+CqlmFvuexq8=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
|
@ -101,8 +103,6 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
|
|||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/nicklaw5/helix/v2 v2.2.0 h1:vJQVH9ayABEDWgqLfg+f5tjN1bKy0cFnoHuNiWfu7f4=
|
||||
github.com/nicklaw5/helix/v2 v2.2.0/go.mod h1:0ONzvVi1cH+k3a7EDIFNNqxfW0podhf+CqlmFvuexq8=
|
||||
github.com/orcaman/concurrent-map v0.0.0-20210501183033-44dafcb38ecc h1:Ak86L+yDSOzKFa7WM5bf5itSOo1e3Xh8bm5YCMUXIjQ=
|
||||
github.com/orcaman/concurrent-map v0.0.0-20210501183033-44dafcb38ecc/go.mod h1:Lu3tH6HLW3feq74c2GC+jIMS/K2CFcDWnWD9XkenwhI=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"text/template"
|
||||
|
@ -68,13 +69,16 @@ type BotAlertsConfig struct {
|
|||
type BotAlertsModule struct {
|
||||
Config BotAlertsConfig
|
||||
|
||||
bot *Bot
|
||||
mu sync.Mutex
|
||||
bot *Bot
|
||||
mu sync.Mutex
|
||||
templates map[string]*template.Template
|
||||
}
|
||||
|
||||
func SetupAlerts(bot *Bot) *BotAlertsModule {
|
||||
mod := &BotAlertsModule{
|
||||
bot: bot,
|
||||
bot: bot,
|
||||
mu: sync.Mutex{},
|
||||
templates: make(map[string]*template.Template),
|
||||
}
|
||||
|
||||
// Load config from database
|
||||
|
@ -86,6 +90,8 @@ func SetupAlerts(bot *Bot) *BotAlertsModule {
|
|||
bot.api.db.PutJSON(BotAlertsKey, mod.Config)
|
||||
}
|
||||
|
||||
mod.compileTemplates()
|
||||
|
||||
go bot.api.db.Subscribe(context.Background(), func(changed []database.ModifiedKV) error {
|
||||
for _, kv := range changed {
|
||||
if kv.Key == BotAlertsKey {
|
||||
|
@ -95,6 +101,7 @@ func SetupAlerts(bot *Bot) *BotAlertsModule {
|
|||
} else {
|
||||
bot.logger.Info("reloaded timer config")
|
||||
}
|
||||
mod.compileTemplates()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -117,26 +124,37 @@ func SetupAlerts(bot *Bot) *BotAlertsModule {
|
|||
return
|
||||
}
|
||||
// Assign random message
|
||||
msg := mod.Config.Subscription.Messages[rand.Intn(len(mod.Config.Subscription.Messages))]
|
||||
messageID := rand.Intn(len(mod.Config.Subscription.Messages))
|
||||
tpl, ok := mod.templates[fmt.Sprintf("sub-%d", messageID)]
|
||||
// If template is broken, write it as is (soft fail, plus we raise attention I guess?)
|
||||
if !ok {
|
||||
mod.bot.WriteMessage(mod.Config.Subscription.Messages[messageID])
|
||||
return
|
||||
}
|
||||
// Check for variations, either by streak or gifted
|
||||
if sub.IsGift {
|
||||
for _, variation := range mod.Config.Subscription.Variations {
|
||||
for variationIndex, variation := range mod.Config.Subscription.Variations {
|
||||
if variation.IsGifted != nil && *variation.IsGifted {
|
||||
msg = variation.Messages[rand.Intn(len(variation.Messages))]
|
||||
break
|
||||
// Make sure template is valid
|
||||
if temp, ok := mod.templates[fmt.Sprintf("sub-v%d-%d", variationIndex, messageID)]; ok {
|
||||
tpl = temp
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if sub.DurationMonths > 0 {
|
||||
minMonths := -1
|
||||
for _, variation := range mod.Config.Subscription.Variations {
|
||||
for variationIndex, variation := range mod.Config.Subscription.Variations {
|
||||
if variation.MinStreak != nil && sub.DurationMonths >= *variation.MinStreak && sub.DurationMonths >= minMonths {
|
||||
msg = variation.Messages[rand.Intn(len(variation.Messages))]
|
||||
minMonths = *variation.MinStreak
|
||||
break
|
||||
// Make sure template is valid
|
||||
if temp, ok := mod.templates[fmt.Sprintf("sub-v%d-%d", variationIndex, messageID)]; ok {
|
||||
tpl = temp
|
||||
minMonths = *variation.MinStreak
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
writeTemplate(bot, msg, sub)
|
||||
writeTemplate(bot, tpl, sub)
|
||||
}
|
||||
addPendingSub := func(ev interface{}) {
|
||||
switch ev.(type) {
|
||||
|
@ -173,7 +191,7 @@ func SetupAlerts(bot *Bot) *BotAlertsModule {
|
|||
// Already pending, add extra data
|
||||
ev.StreakMonths = sub.StreakMonths
|
||||
ev.DurationMonths = sub.DurationMonths
|
||||
ev.CumulativeTotal = sub.CumulativeTotal
|
||||
ev.CumulativeMonths = sub.CumulativeMonths
|
||||
ev.Message = sub.Message
|
||||
return
|
||||
}
|
||||
|
@ -187,7 +205,7 @@ func SetupAlerts(bot *Bot) *BotAlertsModule {
|
|||
Tier: sub.Tier,
|
||||
StreakMonths: sub.StreakMonths,
|
||||
DurationMonths: sub.DurationMonths,
|
||||
CumulativeTotal: sub.CumulativeTotal,
|
||||
CumulativeMonths: sub.CumulativeMonths,
|
||||
Message: sub.Message,
|
||||
}
|
||||
go func() {
|
||||
|
@ -221,9 +239,14 @@ func SetupAlerts(bot *Bot) *BotAlertsModule {
|
|||
continue
|
||||
}
|
||||
// Pick a random message
|
||||
msg := mod.Config.Follow.Messages[rand.Intn(len(mod.Config.Follow.Messages))]
|
||||
messageID := rand.Intn(len(mod.Config.Follow.Messages))
|
||||
// Pick compiled template or fallback to plain text
|
||||
if tpl, ok := mod.templates[fmt.Sprintf("follow-%d", messageID)]; ok {
|
||||
writeTemplate(bot, tpl, &followEv)
|
||||
} else {
|
||||
bot.WriteMessage(mod.Config.Follow.Messages[messageID])
|
||||
}
|
||||
// Compile template and send
|
||||
writeTemplate(bot, msg, &followEv)
|
||||
case helix.EventSubTypeChannelRaid:
|
||||
// Only process if we care about raids
|
||||
if !mod.Config.Raid.Enabled {
|
||||
|
@ -237,19 +260,28 @@ func SetupAlerts(bot *Bot) *BotAlertsModule {
|
|||
continue
|
||||
}
|
||||
// Pick a random message from base set
|
||||
msg := mod.Config.Raid.Messages[rand.Intn(len(mod.Config.Raid.Messages))]
|
||||
messageID := rand.Intn(len(mod.Config.Raid.Messages))
|
||||
tpl, ok := mod.templates[fmt.Sprintf("raid-%d", messageID)]
|
||||
if !ok {
|
||||
// Broken template!
|
||||
mod.bot.WriteMessage(mod.Config.Raid.Messages[messageID])
|
||||
continue
|
||||
}
|
||||
// If we have variations, loop through all the available variations and pick the one with the highest minimum viewers that are met
|
||||
if len(mod.Config.Raid.Variations) > 0 {
|
||||
minViewers := -1
|
||||
for _, variation := range mod.Config.Raid.Variations {
|
||||
for variationIndex, variation := range mod.Config.Raid.Variations {
|
||||
if variation.MinViewers != nil && *variation.MinViewers > minViewers && raidEv.Viewers >= *variation.MinViewers {
|
||||
msg = variation.Messages[rand.Intn(len(variation.Messages))]
|
||||
minViewers = *variation.MinViewers
|
||||
// Make sure the template is valid
|
||||
if varTemplate, ok := mod.templates[fmt.Sprintf("raid-v%d-%d", variationIndex, messageID)]; ok {
|
||||
tpl = varTemplate
|
||||
minViewers = *variation.MinViewers
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Compile template and send
|
||||
writeTemplate(bot, msg, &raidEv)
|
||||
writeTemplate(bot, tpl, &raidEv)
|
||||
case helix.EventSubTypeChannelCheer:
|
||||
// Only process if we care about bits
|
||||
if !mod.Config.Cheer.Enabled {
|
||||
|
@ -263,19 +295,28 @@ func SetupAlerts(bot *Bot) *BotAlertsModule {
|
|||
continue
|
||||
}
|
||||
// Pick a random message from base set
|
||||
msg := mod.Config.Cheer.Messages[rand.Intn(len(mod.Config.Cheer.Messages))]
|
||||
messageID := rand.Intn(len(mod.Config.Cheer.Messages))
|
||||
tpl, ok := mod.templates[fmt.Sprintf("cheer-%d", messageID)]
|
||||
if !ok {
|
||||
// Broken template!
|
||||
mod.bot.WriteMessage(mod.Config.Raid.Messages[messageID])
|
||||
continue
|
||||
}
|
||||
// If we have variations, loop through all the available variations and pick the one with the highest minimum amount that is met
|
||||
if len(mod.Config.Cheer.Variations) > 0 {
|
||||
minAmount := -1
|
||||
for _, variation := range mod.Config.Cheer.Variations {
|
||||
for variationIndex, variation := range mod.Config.Cheer.Variations {
|
||||
if variation.MinAmount != nil && *variation.MinAmount > minAmount && cheerEv.Bits >= *variation.MinAmount {
|
||||
msg = variation.Messages[rand.Intn(len(variation.Messages))]
|
||||
minAmount = *variation.MinAmount
|
||||
// Make sure the template is valid
|
||||
if varTemplate, ok := mod.templates[fmt.Sprintf("cheer-v%d-%d", variationIndex, messageID)]; ok {
|
||||
tpl = varTemplate
|
||||
minAmount = *variation.MinAmount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Compile template and send
|
||||
writeTemplate(bot, msg, &cheerEv)
|
||||
writeTemplate(bot, tpl, &cheerEv)
|
||||
case helix.EventSubTypeChannelSubscription:
|
||||
// Only process if we care about subscriptions
|
||||
if !mod.Config.Subscription.Enabled {
|
||||
|
@ -315,28 +356,40 @@ func SetupAlerts(bot *Bot) *BotAlertsModule {
|
|||
continue
|
||||
}
|
||||
// Pick a random message from base set
|
||||
msg := mod.Config.GiftSub.Messages[rand.Intn(len(mod.Config.GiftSub.Messages))]
|
||||
messageID := rand.Intn(len(mod.Config.GiftSub.Messages))
|
||||
tpl, ok := mod.templates[fmt.Sprintf("gift-%d", messageID)]
|
||||
if !ok {
|
||||
// Broken template!
|
||||
mod.bot.WriteMessage(mod.Config.GiftSub.Messages[messageID])
|
||||
continue
|
||||
}
|
||||
// If we have variations, loop through all the available variations and pick the one with the highest minimum cumulative total that are met
|
||||
if len(mod.Config.GiftSub.Variations) > 0 {
|
||||
if giftEv.IsAnonymous {
|
||||
for _, variation := range mod.Config.GiftSub.Variations {
|
||||
for variationIndex, variation := range mod.Config.GiftSub.Variations {
|
||||
if variation.IsAnonymous != nil && *variation.IsAnonymous {
|
||||
msg = variation.Messages[rand.Intn(len(variation.Messages))]
|
||||
break
|
||||
// Make sure template is valid
|
||||
if temp, ok := mod.templates[fmt.Sprintf("gift-v%d-%d", variationIndex, messageID)]; ok {
|
||||
tpl = temp
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if giftEv.CumulativeTotal > 0 {
|
||||
minCumulative := -1
|
||||
for _, variation := range mod.Config.GiftSub.Variations {
|
||||
for variationIndex, variation := range mod.Config.GiftSub.Variations {
|
||||
if variation.MinCumulative != nil && *variation.MinCumulative > minCumulative && giftEv.CumulativeTotal >= *variation.MinCumulative {
|
||||
msg = variation.Messages[rand.Intn(len(variation.Messages))]
|
||||
minCumulative = *variation.MinCumulative
|
||||
// Make sure template is valid
|
||||
if temp, ok := mod.templates[fmt.Sprintf("gift-v%d-%d", variationIndex, messageID)]; ok {
|
||||
tpl = temp
|
||||
minCumulative = *variation.MinCumulative
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Compile template and send
|
||||
writeTemplate(bot, msg, &giftEv)
|
||||
writeTemplate(bot, tpl, &giftEv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -348,14 +401,57 @@ func SetupAlerts(bot *Bot) *BotAlertsModule {
|
|||
return mod
|
||||
}
|
||||
|
||||
func writeTemplate(bot *Bot, msg string, data interface{}) {
|
||||
func (m *BotAlertsModule) compileTemplates() {
|
||||
m.templates = make(map[string]*template.Template)
|
||||
for index, msg := range m.Config.Follow.Messages {
|
||||
m.addTemplate(fmt.Sprintf("follow-%d", index), msg)
|
||||
}
|
||||
for index, msg := range m.Config.Subscription.Messages {
|
||||
m.addTemplate(fmt.Sprintf("sub-%d", index), msg)
|
||||
}
|
||||
for varIndex, variation := range m.Config.Subscription.Variations {
|
||||
for index, msg := range variation.Messages {
|
||||
m.addTemplate(fmt.Sprintf("sub-v%d-%d", varIndex, index), msg)
|
||||
}
|
||||
}
|
||||
for index, msg := range m.Config.Raid.Messages {
|
||||
m.addTemplate(fmt.Sprintf("raid-%d", index), msg)
|
||||
}
|
||||
for varIndex, variation := range m.Config.Raid.Variations {
|
||||
for index, msg := range variation.Messages {
|
||||
m.addTemplate(fmt.Sprintf("raid-v%d-%d", varIndex, index), msg)
|
||||
}
|
||||
}
|
||||
for index, msg := range m.Config.Cheer.Messages {
|
||||
m.addTemplate(fmt.Sprintf("cheer-%d", index), msg)
|
||||
}
|
||||
for varIndex, variation := range m.Config.Cheer.Variations {
|
||||
for index, msg := range variation.Messages {
|
||||
m.addTemplate(fmt.Sprintf("cheer-v%d-%d", varIndex, index), msg)
|
||||
}
|
||||
}
|
||||
for index, msg := range m.Config.GiftSub.Messages {
|
||||
m.addTemplate(fmt.Sprintf("gift-%d", index), msg)
|
||||
}
|
||||
for varIndex, variation := range m.Config.GiftSub.Variations {
|
||||
for index, msg := range variation.Messages {
|
||||
m.addTemplate(fmt.Sprintf("gift-v%d-%d", varIndex, index), msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *BotAlertsModule) addTemplate(id string, msg string) {
|
||||
tpl, err := template.New("").Funcs(sprig.TxtFuncMap()).Parse(msg)
|
||||
if err != nil {
|
||||
bot.logger.WithError(err).Error("error parsing template for alert")
|
||||
m.bot.logger.WithError(err).Error("error compiling template")
|
||||
return
|
||||
}
|
||||
m.templates[id] = tpl
|
||||
}
|
||||
|
||||
func writeTemplate(bot *Bot, tpl *template.Template, data interface{}) {
|
||||
var buf bytes.Buffer
|
||||
err = tpl.Execute(&buf, data)
|
||||
err := tpl.Execute(&buf, data)
|
||||
if err != nil {
|
||||
bot.logger.WithError(err).Error("error executing template for alert")
|
||||
return
|
||||
|
@ -372,7 +468,7 @@ type subMixedEvent struct {
|
|||
BroadcasterUserName string
|
||||
Tier string
|
||||
IsGift bool
|
||||
CumulativeTotal int
|
||||
CumulativeMonths int
|
||||
StreakMonths int
|
||||
DurationMonths int
|
||||
Message helix.EventSubMessage
|
||||
|
|
Loading…
Reference in New Issue