mirror of
https://github.com/Luzifer/twitch-bot.git
synced 2024-09-07 20:39:07 +00:00
[core] Switch to go_helpers FieldCollection
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
262742603c
commit
30482591a7
@ -10,6 +10,7 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
@ -49,7 +50,7 @@ func init() {
|
||||
type ActorScript struct{}
|
||||
|
||||
// Execute implements actor interface
|
||||
func (ActorScript) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (ActorScript) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
command, err := attrs.StringSlice("command")
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "getting command")
|
||||
@ -130,7 +131,7 @@ func (ActorScript) IsAsync() bool { return false }
|
||||
func (ActorScript) Name() string { return "script" }
|
||||
|
||||
// Validate implements actor interface
|
||||
func (ActorScript) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
func (ActorScript) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
cmd, err := attrs.StringSlice("command")
|
||||
if err != nil || len(cmd) == 0 {
|
||||
return errors.New("command must be slice of strings with length > 0")
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
@ -41,7 +42,7 @@ func registerAction(name string, acf plugins.ActorCreationFunc) {
|
||||
availableActions[name] = acf
|
||||
}
|
||||
|
||||
func triggerAction(c *irc.Client, m *irc.Message, rule *plugins.Rule, ra *plugins.RuleAction, eventData *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func triggerAction(c *irc.Client, m *irc.Message, rule *plugins.Rule, ra *plugins.RuleAction, eventData *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
availableActionsLock.RLock()
|
||||
defer availableActionsLock.RUnlock()
|
||||
|
||||
@ -65,7 +66,7 @@ func triggerAction(c *irc.Client, m *irc.Message, rule *plugins.Rule, ra *plugin
|
||||
return apc, errors.Wrap(err, "execute action")
|
||||
}
|
||||
|
||||
func handleMessage(c *irc.Client, m *irc.Message, event *string, eventData *plugins.FieldCollection) {
|
||||
func handleMessage(c *irc.Client, m *irc.Message, event *string, eventData *fieldcollection.FieldCollection) {
|
||||
// Send events to registered handlers
|
||||
if event != nil {
|
||||
go notifyEventHandlers(*event, eventData)
|
||||
@ -77,9 +78,9 @@ func handleMessage(c *irc.Client, m *irc.Message, event *string, eventData *plug
|
||||
}
|
||||
}
|
||||
|
||||
func handleMessageRuleExecution(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection) {
|
||||
func handleMessageRuleExecution(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection) {
|
||||
var (
|
||||
ruleEventData = plugins.NewFieldCollection()
|
||||
ruleEventData = fieldcollection.NewFieldCollection()
|
||||
preventCooldown bool
|
||||
)
|
||||
|
||||
|
@ -13,8 +13,8 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/go_helpers/v2/str"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
var cronParser = cron.NewParser(cron.SecondOptional | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor)
|
||||
@ -174,7 +174,7 @@ func (a *autoMessage) allowExecuteDisableOnTemplate() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
fields := plugins.NewFieldCollection()
|
||||
fields := fieldcollection.NewFieldCollection()
|
||||
fields.Set("channel", a.Channel)
|
||||
|
||||
res, err := formatMessage(*a.DisableOnTemplate, nil, nil, fields)
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
"gopkg.in/irc.v4"
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/go_helpers/v2/str"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
@ -303,7 +304,7 @@ func (c *configFile) CloseRawMessageWriter() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c configFile) GetMatchingRules(m *irc.Message, event *string, eventData *plugins.FieldCollection) []*plugins.Rule {
|
||||
func (c configFile) GetMatchingRules(m *irc.Message, event *string, eventData *fieldcollection.FieldCollection) []*plugins.Rule {
|
||||
configLock.RLock()
|
||||
defer configLock.RUnlock()
|
||||
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
@ -93,7 +94,7 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func notifyEventHandlers(event string, eventData *plugins.FieldCollection) {
|
||||
func notifyEventHandlers(event string, eventData *fieldcollection.FieldCollection) {
|
||||
registeredEventHandlersLock.Lock()
|
||||
defer registeredEventHandlersLock.Unlock()
|
||||
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/go_helpers/v2/str"
|
||||
korvike "github.com/Luzifer/korvike/functions"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
@ -37,7 +38,7 @@ func newTemplateFuncProvider() *templateFuncProvider {
|
||||
return out
|
||||
}
|
||||
|
||||
func (t *templateFuncProvider) GetFuncMap(m *irc.Message, r *plugins.Rule, fields *plugins.FieldCollection) template.FuncMap {
|
||||
func (t *templateFuncProvider) GetFuncMap(m *irc.Message, r *plugins.Rule, fields *fieldcollection.FieldCollection) template.FuncMap {
|
||||
t.lock.RLock()
|
||||
defer t.lock.RUnlock()
|
||||
|
||||
|
@ -6,12 +6,13 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
func init() {
|
||||
tplFuncs.Register("arg", func(m *irc.Message, _ *plugins.Rule, _ *plugins.FieldCollection) interface{} {
|
||||
tplFuncs.Register("arg", func(m *irc.Message, _ *plugins.Rule, _ *fieldcollection.FieldCollection) interface{} {
|
||||
return func(arg int) (string, error) {
|
||||
msgParts := strings.Split(m.Trailing(), " ")
|
||||
if len(msgParts) <= arg {
|
||||
@ -30,7 +31,7 @@ func init() {
|
||||
},
|
||||
})
|
||||
|
||||
tplFuncs.Register("chatterHasBadge", func(m *irc.Message, _ *plugins.Rule, _ *plugins.FieldCollection) interface{} {
|
||||
tplFuncs.Register("chatterHasBadge", func(m *irc.Message, _ *plugins.Rule, _ *fieldcollection.FieldCollection) interface{} {
|
||||
return func(badge string) bool {
|
||||
badges := twitch.ParseBadgeLevels(m)
|
||||
return badges.Has(badge)
|
||||
@ -57,7 +58,7 @@ func init() {
|
||||
},
|
||||
)
|
||||
|
||||
tplFuncs.Register("group", func(m *irc.Message, r *plugins.Rule, _ *plugins.FieldCollection) interface{} {
|
||||
tplFuncs.Register("group", func(m *irc.Message, r *plugins.Rule, _ *fieldcollection.FieldCollection) interface{} {
|
||||
return func(idx int, fallback ...string) (string, error) {
|
||||
fields := r.GetMatchMessage().FindStringSubmatch(m.Trailing())
|
||||
if len(fields) <= idx {
|
||||
@ -94,7 +95,7 @@ func init() {
|
||||
},
|
||||
)
|
||||
|
||||
tplFuncs.Register("tag", func(m *irc.Message, _ *plugins.Rule, _ *plugins.FieldCollection) interface{} {
|
||||
tplFuncs.Register("tag", func(m *irc.Message, _ *plugins.Rule, _ *fieldcollection.FieldCollection) interface{} {
|
||||
return func(tag string) string { return m.Tags[tag] }
|
||||
}, plugins.TemplateFuncDocumentation{
|
||||
Description: "Takes the message sent to the channel, returns the value of the tag specified",
|
||||
|
12
go.mod
12
go.mod
@ -4,19 +4,19 @@ go 1.21
|
||||
|
||||
require (
|
||||
github.com/Luzifer/go-openssl/v4 v4.2.2
|
||||
github.com/Luzifer/go_helpers/v2 v2.23.0
|
||||
github.com/Luzifer/go_helpers/v2 v2.24.0
|
||||
github.com/Luzifer/korvike/functions v0.11.0
|
||||
github.com/Luzifer/rconfig/v2 v2.5.0
|
||||
github.com/Masterminds/sprig/v3 v3.2.3
|
||||
github.com/getsentry/sentry-go v0.27.0
|
||||
github.com/glebarez/sqlite v1.11.0
|
||||
github.com/go-git/go-git/v5 v5.11.0
|
||||
github.com/go-git/go-git/v5 v5.12.0
|
||||
github.com/go-sql-driver/mysql v1.8.1
|
||||
github.com/gofrs/uuid v4.4.0+incompatible
|
||||
github.com/gofrs/uuid/v3 v3.1.2
|
||||
github.com/gorilla/mux v1.8.1
|
||||
github.com/gorilla/websocket v1.5.1
|
||||
github.com/itchyny/gojq v0.12.14
|
||||
github.com/itchyny/gojq v0.12.15
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2
|
||||
github.com/orandin/sentrus v1.0.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
@ -31,7 +31,7 @@ require (
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gorm.io/driver/mysql v1.5.6
|
||||
gorm.io/driver/postgres v1.5.7
|
||||
gorm.io/gorm v1.25.8
|
||||
gorm.io/gorm v1.25.9
|
||||
)
|
||||
|
||||
require (
|
||||
@ -87,7 +87,7 @@ require (
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/ryanuber/go-glob v1.0.0 // indirect
|
||||
github.com/sergi/go-diff v1.3.1 // indirect
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/skeema/knownhosts v1.2.2 // indirect
|
||||
github.com/spf13/cast v1.6.0 // indirect
|
||||
@ -105,6 +105,6 @@ require (
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
modernc.org/libc v1.49.0 // indirect
|
||||
modernc.org/mathutil v1.6.0 // indirect
|
||||
modernc.org/memory v1.7.2 // indirect
|
||||
modernc.org/memory v1.8.0 // indirect
|
||||
modernc.org/sqlite v1.29.5 // indirect
|
||||
)
|
||||
|
28
go.sum
28
go.sum
@ -6,8 +6,8 @@ filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Luzifer/go-openssl/v4 v4.2.2 h1:wKF/GhSKGJtHFQYTkN61wXig7mPvDj/oPpW6MmnBpjc=
|
||||
github.com/Luzifer/go-openssl/v4 v4.2.2/go.mod h1:+kAwI4NpyYXoWil85gKSCEJNoCQlMeFikEMn2f+5ffc=
|
||||
github.com/Luzifer/go_helpers/v2 v2.23.0 h1:VowDwOCl6nOt+GVqKUX/do6a94pEeqNTRHb29MsoGX4=
|
||||
github.com/Luzifer/go_helpers/v2 v2.23.0/go.mod h1:BSGkJ/dxqs7AxsfZt8zjJb4R6YB5dONS+/ad7foLUrk=
|
||||
github.com/Luzifer/go_helpers/v2 v2.24.0 h1:abACOhsn6a6c6X22jq42mZM1wuOM0Ihfa6yzssrjrOg=
|
||||
github.com/Luzifer/go_helpers/v2 v2.24.0/go.mod h1:KSVUdAJAav5cWGyB5oKGxmC27HrKULVTOxwPS/Kr+pc=
|
||||
github.com/Luzifer/korvike/functions v0.11.0 h1:2hr3nnt9hy8Esu1W3h50+RggcLRXvrw92kVQLvxzd2Q=
|
||||
github.com/Luzifer/korvike/functions v0.11.0/go.mod h1:osumwH64mWgbwZIfE7rE0BB7Y5HXxrzyO4JfO7fhduU=
|
||||
github.com/Luzifer/rconfig/v2 v2.5.0 h1:zx5lfQbNX3za4VegID97IeY+M+BmfgHxWJTYA94sxok=
|
||||
@ -62,8 +62,8 @@ github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec
|
||||
github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc=
|
||||
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
|
||||
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
|
||||
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
|
||||
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
|
||||
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
|
||||
github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
|
||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||
@ -72,8 +72,8 @@ github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+
|
||||
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||
github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4=
|
||||
github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY=
|
||||
github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys=
|
||||
github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY=
|
||||
github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k=
|
||||
github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
|
||||
github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc=
|
||||
@ -161,8 +161,8 @@ github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq
|
||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/itchyny/gojq v0.12.14 h1:6k8vVtsrhQSYgSGg827AD+PVVaB1NLXEdX+dda2oZCc=
|
||||
github.com/itchyny/gojq v0.12.14/go.mod h1:y1G7oO7XkcR1LPZO59KyoCRy08T3j9vDYRV0GgYSS+s=
|
||||
github.com/itchyny/gojq v0.12.15 h1:WC1Nxbx4Ifw5U2oQWACYz32JK8G9qxNtHzrvW4KEcqI=
|
||||
github.com/itchyny/gojq v0.12.15/go.mod h1:uWAHCbCIla1jiNxmeT5/B5mOjSdfkCq6p8vxWg+BM10=
|
||||
github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE=
|
||||
github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
@ -245,8 +245,8 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
|
||||
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
|
||||
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
|
||||
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
@ -422,8 +422,8 @@ gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkD
|
||||
gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM=
|
||||
gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA=
|
||||
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
gorm.io/gorm v1.25.8 h1:WAGEZ/aEcznN4D03laj8DKnehe1e9gYQAjW8xyPRdeo=
|
||||
gorm.io/gorm v1.25.8/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
gorm.io/gorm v1.25.9 h1:wct0gxZIELDk8+ZqF/MVnHLkA1rvYlBWUMv2EdsK1g8=
|
||||
gorm.io/gorm v1.25.9/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
modernc.org/cc/v4 v4.19.5 h1:QlsZyQ1zf78DGeqnQ9ILi9hXyMdoC5e1qoGNUyBjHQw=
|
||||
@ -438,8 +438,8 @@ modernc.org/libc v1.49.0 h1:/kkNBuCXvlTbOGwrQdgR67eK1Y9+kR+fhdBd89C64VM=
|
||||
modernc.org/libc v1.49.0/go.mod h1:DNz0lgQgT6FPIPm8rHtjFj0FL5/YOr/NYFXWYBcSxMw=
|
||||
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
||||
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
||||
modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E=
|
||||
modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E=
|
||||
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
|
||||
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
|
||||
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
|
||||
|
@ -11,6 +11,8 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
@ -87,7 +89,7 @@ func Register(args plugins.RegistrationArguments) (err error) {
|
||||
|
||||
type actor struct{}
|
||||
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
ptrStringEmpty := func(v string) *string { return &v }("")
|
||||
|
||||
reason, err := formatMessage(attrs.MustString("reason", ptrStringEmpty), m, r, eventData)
|
||||
@ -110,14 +112,13 @@ func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *
|
||||
func (actor) IsAsync() bool { return false }
|
||||
func (actor) Name() string { return actorName }
|
||||
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
reasonTemplate, err := attrs.String("reason")
|
||||
if err != nil || reasonTemplate == "" {
|
||||
return errors.New("reason must be non-empty string")
|
||||
}
|
||||
|
||||
if err = tplValidator(reasonTemplate); err != nil {
|
||||
return errors.Wrap(err, "validating reason template")
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "reason", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
fieldcollection.MustHaveNoUnknowFields,
|
||||
helpers.SchemaValidateTemplateField(tplValidator, "reason"),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -9,6 +9,8 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
@ -19,9 +21,6 @@ var (
|
||||
formatMessage plugins.MsgFormatter
|
||||
hasPerm plugins.ChannelPermissionCheckFunc
|
||||
tcGetter func(string) (*twitch.Client, error)
|
||||
|
||||
ptrBoolFalse = func(v bool) *bool { return &v }(false)
|
||||
ptrStringEmpty = func(s string) *string { return &s }("")
|
||||
)
|
||||
|
||||
// Register provides the plugins.RegisterFunc
|
||||
@ -71,7 +70,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||
|
||||
type actor struct{}
|
||||
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
channel := plugins.DeriveChannel(m, eventData)
|
||||
if channel, err = formatMessage(attrs.MustString("channel", &channel), m, r, eventData); err != nil {
|
||||
return false, errors.Wrap(err, "parsing channel")
|
||||
@ -96,7 +95,7 @@ func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *
|
||||
return false, errors.Wrapf(err, "getting Twitch client for %q", creator)
|
||||
}
|
||||
|
||||
clipInfo, err := tc.CreateClip(context.TODO(), channel, attrs.MustBool("add_delay", ptrBoolFalse))
|
||||
clipInfo, err := tc.CreateClip(context.TODO(), channel, attrs.MustBool("add_delay", helpers.Ptr(false)))
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "creating clip")
|
||||
}
|
||||
@ -110,11 +109,13 @@ func (actor) IsAsync() bool { return false }
|
||||
|
||||
func (actor) Name() string { return actorName }
|
||||
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
for _, field := range []string{"channel", "creator"} {
|
||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
||||
return errors.Wrapf(err, "validating %s template", field)
|
||||
}
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "channel", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "creator", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
helpers.SchemaValidateTemplateField(tplValidator, "channel", "creator"),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/actors/linkdetector"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
@ -40,7 +41,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||
type Actor struct{}
|
||||
|
||||
// Execute implements the actor interface
|
||||
func (Actor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (Actor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
if eventData.HasAll("clips") {
|
||||
// We already detected clips, lets not do it again
|
||||
return false, nil
|
||||
@ -82,4 +83,6 @@ func (Actor) IsAsync() bool { return false }
|
||||
func (Actor) Name() string { return actorName }
|
||||
|
||||
// Validate implements the actor interface
|
||||
func (Actor) Validate(plugins.TemplateValidatorFunc, *plugins.FieldCollection) error { return nil }
|
||||
func (Actor) Validate(plugins.TemplateValidatorFunc, *fieldcollection.FieldCollection) error {
|
||||
return nil
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package commercial
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -10,6 +11,8 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
@ -61,7 +64,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||
|
||||
type actor struct{}
|
||||
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
ptrStringEmpty := func(v string) *string { return &v }("")
|
||||
|
||||
durationStr, err := formatMessage(attrs.MustString("duration", ptrStringEmpty), m, r, eventData)
|
||||
@ -75,14 +78,12 @@ func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *
|
||||
func (actor) IsAsync() bool { return false }
|
||||
func (actor) Name() string { return actorName }
|
||||
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
durationTemplate, err := attrs.String("duration")
|
||||
if err != nil || durationTemplate == "" {
|
||||
return errors.New("duration must be non-empty string")
|
||||
}
|
||||
|
||||
if err = tplValidator(durationTemplate); err != nil {
|
||||
return errors.Wrap(err, "validating duration template")
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "duration", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
helpers.SchemaValidateTemplateField(tplValidator, "duration"),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -13,6 +13,8 @@ import (
|
||||
"gopkg.in/irc.v4"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
@ -20,8 +22,6 @@ import (
|
||||
var (
|
||||
db database.Connector
|
||||
formatMessage plugins.MsgFormatter
|
||||
|
||||
ptrStringEmpty = func(s string) *string { return &s }("")
|
||||
)
|
||||
|
||||
// Register provides the plugins.RegisterFunc
|
||||
@ -135,7 +135,7 @@ func Register(args plugins.RegistrationArguments) (err error) {
|
||||
return fmt.Errorf("registering API route: %w", err)
|
||||
}
|
||||
|
||||
args.RegisterTemplateFunction("channelCounter", func(_ *irc.Message, _ *plugins.Rule, fields *plugins.FieldCollection) interface{} {
|
||||
args.RegisterTemplateFunction("channelCounter", func(_ *irc.Message, _ *plugins.Rule, fields *fieldcollection.FieldCollection) interface{} {
|
||||
return func(name string) (string, error) {
|
||||
channel, err := fields.String("channel")
|
||||
if err != nil {
|
||||
@ -212,13 +212,13 @@ func Register(args plugins.RegistrationArguments) (err error) {
|
||||
|
||||
type actorCounter struct{}
|
||||
|
||||
func (actorCounter) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (actorCounter) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
counterName, err := formatMessage(attrs.MustString("counter", nil), m, r, eventData)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "preparing response")
|
||||
}
|
||||
|
||||
if counterSet := attrs.MustString("counter_set", ptrStringEmpty); counterSet != "" {
|
||||
if counterSet := attrs.MustString("counter_set", helpers.Ptr("")); counterSet != "" {
|
||||
parseValue, err := formatMessage(counterSet, m, r, eventData)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "execute counter value template")
|
||||
@ -236,7 +236,7 @@ func (actorCounter) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, even
|
||||
}
|
||||
|
||||
var counterStep int64 = 1
|
||||
if s := attrs.MustString("counter_step", ptrStringEmpty); s != "" {
|
||||
if s := attrs.MustString("counter_step", helpers.Ptr("")); s != "" {
|
||||
parseStep, err := formatMessage(s, m, r, eventData)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "execute counter step template")
|
||||
@ -257,15 +257,14 @@ func (actorCounter) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, even
|
||||
func (actorCounter) IsAsync() bool { return false }
|
||||
func (actorCounter) Name() string { return "counter" }
|
||||
|
||||
func (actorCounter) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if cn, err := attrs.String("counter"); err != nil || cn == "" {
|
||||
return errors.New("counter name must be non-empty string")
|
||||
}
|
||||
|
||||
for _, field := range []string{"counter", "counter_step", "counter_set"} {
|
||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
||||
return errors.Wrapf(err, "validating %s template", field)
|
||||
}
|
||||
func (actorCounter) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "counter", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
fieldcollection.CanHaveField(fieldcollection.SchemaField{Name: "counter_step", Type: fieldcollection.SchemaFieldTypeString}),
|
||||
fieldcollection.CanHaveField(fieldcollection.SchemaField{Name: "counter_set", Type: fieldcollection.SchemaFieldTypeString}),
|
||||
helpers.SchemaValidateTemplateField(tplValidator, "counter", "counter_step", "counter_set"),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -7,6 +7,8 @@ import (
|
||||
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
@ -48,11 +50,10 @@ func Register(args plugins.RegistrationArguments) error {
|
||||
|
||||
type actor struct{}
|
||||
|
||||
func (actor) Execute(_ *irc.Client, _ *irc.Message, _ *plugins.Rule, _ *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (actor) Execute(_ *irc.Client, _ *irc.Message, _ *plugins.Rule, _ *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
var (
|
||||
ptrZeroDuration = func(v time.Duration) *time.Duration { return &v }(0)
|
||||
delay = attrs.MustDuration("delay", ptrZeroDuration)
|
||||
jitter = attrs.MustDuration("jitter", ptrZeroDuration)
|
||||
delay = attrs.MustDuration("delay", helpers.Ptr(time.Duration(0)))
|
||||
jitter = attrs.MustDuration("jitter", helpers.Ptr(time.Duration(0)))
|
||||
)
|
||||
|
||||
if delay == 0 && jitter == 0 {
|
||||
@ -71,6 +72,6 @@ func (actor) Execute(_ *irc.Client, _ *irc.Message, _ *plugins.Rule, _ *plugins.
|
||||
func (actor) IsAsync() bool { return false }
|
||||
func (actor) Name() string { return actorName }
|
||||
|
||||
func (actor) Validate(plugins.TemplateValidatorFunc, *plugins.FieldCollection) (err error) {
|
||||
func (actor) Validate(plugins.TemplateValidatorFunc, *fieldcollection.FieldCollection) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
@ -32,7 +33,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||
|
||||
type actor struct{}
|
||||
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, _ *plugins.Rule, eventData *plugins.FieldCollection, _ *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, _ *plugins.Rule, eventData *fieldcollection.FieldCollection, _ *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
msgID, ok := m.Tags["id"]
|
||||
if !ok || msgID == "" {
|
||||
return false, nil
|
||||
@ -51,6 +52,6 @@ func (actor) Execute(_ *irc.Client, m *irc.Message, _ *plugins.Rule, eventData *
|
||||
func (actor) IsAsync() bool { return false }
|
||||
func (actor) Name() string { return actorName }
|
||||
|
||||
func (actor) Validate(plugins.TemplateValidatorFunc, *plugins.FieldCollection) (err error) {
|
||||
func (actor) Validate(plugins.TemplateValidatorFunc, *fieldcollection.FieldCollection) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
@ -4,10 +4,13 @@ package eventmod
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
@ -44,7 +47,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||
|
||||
type actor struct{}
|
||||
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
ptrStringEmpty := func(v string) *string { return &v }("")
|
||||
|
||||
fd, err := formatMessage(attrs.MustString("fields", ptrStringEmpty), m, r, eventData)
|
||||
@ -69,14 +72,12 @@ func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *
|
||||
func (actor) IsAsync() bool { return false }
|
||||
func (actor) Name() string { return actorName }
|
||||
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
fieldsTemplate, err := attrs.String("fields")
|
||||
if err != nil || fieldsTemplate == "" {
|
||||
return errors.New("fields must be non-empty string")
|
||||
}
|
||||
|
||||
if err = tplValidator(fieldsTemplate); err != nil {
|
||||
return errors.Wrap(err, "validating fields template")
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "fields", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
helpers.SchemaValidateTemplateField(tplValidator, "fields"),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -5,6 +5,7 @@ package filesay
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
@ -13,6 +14,8 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
@ -57,7 +60,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||
|
||||
type actor struct{}
|
||||
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
ptrStringEmpty := func(v string) *string { return &v }("")
|
||||
|
||||
source, err := formatMessage(attrs.MustString("source", ptrStringEmpty), m, r, eventData)
|
||||
@ -114,14 +117,12 @@ func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *
|
||||
func (actor) IsAsync() bool { return true }
|
||||
func (actor) Name() string { return actorName }
|
||||
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) error {
|
||||
sourceTpl, err := attrs.String("source")
|
||||
if err != nil || sourceTpl == "" {
|
||||
return errors.New("source is expected to be non-empty string")
|
||||
}
|
||||
|
||||
if err = tplValidator(sourceTpl); err != nil {
|
||||
return errors.Wrap(err, "validating source template")
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "source", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
helpers.SchemaValidateTemplateField(tplValidator, "source"),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -5,14 +5,14 @@ package linkdetector
|
||||
import (
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/linkcheck"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
const actorName = "linkdetector"
|
||||
|
||||
var ptrFalse = func(v bool) *bool { return &v }(false)
|
||||
|
||||
// Register provides the plugins.RegisterFunc
|
||||
func Register(args plugins.RegistrationArguments) error {
|
||||
args.RegisterActor(actorName, func() plugins.Actor { return &Actor{} })
|
||||
@ -42,13 +42,13 @@ func Register(args plugins.RegistrationArguments) error {
|
||||
type Actor struct{}
|
||||
|
||||
// Execute implements the actor interface
|
||||
func (Actor) Execute(_ *irc.Client, m *irc.Message, _ *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (Actor) Execute(_ *irc.Client, m *irc.Message, _ *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
if eventData.HasAll("links") {
|
||||
// We already detected links, lets not do it again
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if attrs.MustBool("heuristic", ptrFalse) {
|
||||
if attrs.MustBool("heuristic", helpers.Ptr(false)) {
|
||||
eventData.Set("links", linkcheck.New().HeuristicScanForLinks(m.Trailing()))
|
||||
} else {
|
||||
eventData.Set("links", linkcheck.New().ScanForLinks(m.Trailing()))
|
||||
@ -64,4 +64,6 @@ func (Actor) IsAsync() bool { return false }
|
||||
func (Actor) Name() string { return actorName }
|
||||
|
||||
// Validate implements the actor interface
|
||||
func (Actor) Validate(plugins.TemplateValidatorFunc, *plugins.FieldCollection) error { return nil }
|
||||
func (Actor) Validate(plugins.TemplateValidatorFunc, *fieldcollection.FieldCollection) error {
|
||||
return nil
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ package linkprotect
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
@ -11,7 +12,9 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/actors/clipdetector"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
@ -21,8 +24,6 @@ const actorName = "linkprotect"
|
||||
var (
|
||||
botTwitchClient *twitch.Client
|
||||
clipLink = regexp.MustCompile(`.*(?:clips\.twitch\.tv|www\.twitch\.tv/[^/]*/clip)/.*`)
|
||||
ptrBoolFalse = func(v bool) *bool { return &v }(false)
|
||||
ptrStringEmpty = func(v string) *string { return &v }("")
|
||||
)
|
||||
|
||||
// Register provides the plugins.RegisterFunc
|
||||
@ -127,7 +128,7 @@ const (
|
||||
)
|
||||
|
||||
//nolint:gocyclo // Minimum over the limit, makes no sense to split
|
||||
func (a actor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (a actor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
// In case the clip detector did not run before, lets run it now
|
||||
if preventCooldown, err = (clipdetector.Actor{}).Execute(c, m, r, eventData, attrs); err != nil {
|
||||
return preventCooldown, errors.Wrap(err, "detecting links / clips")
|
||||
@ -141,13 +142,13 @@ func (a actor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData
|
||||
if len(links) == 0 {
|
||||
// If there are no links there is nothing to protect and there
|
||||
// are also no clips as they are parsed from the links
|
||||
if attrs.MustBool("stop_on_no_action", ptrBoolFalse) {
|
||||
if attrs.MustBool("stop_on_no_action", helpers.Ptr(false)) {
|
||||
return false, plugins.ErrStopRuleExecution
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
clipsInterface, err := eventData.Any("clips")
|
||||
clipsInterface, err := eventData.Get("clips")
|
||||
if err != nil {
|
||||
return preventCooldown, errors.Wrap(err, "getting clips from event")
|
||||
}
|
||||
@ -157,21 +158,21 @@ func (a actor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData
|
||||
}
|
||||
|
||||
if a.check(links, clips, attrs) == verdictAllFine {
|
||||
if attrs.MustBool("stop_on_no_action", ptrBoolFalse) {
|
||||
if attrs.MustBool("stop_on_no_action", helpers.Ptr(false)) {
|
||||
return false, plugins.ErrStopRuleExecution
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// That message misbehaved so we need to punish them
|
||||
switch lt := attrs.MustString("action", ptrStringEmpty); lt {
|
||||
switch lt := attrs.MustString("action", helpers.Ptr("")); lt {
|
||||
case "ban":
|
||||
if err = botTwitchClient.BanUser(
|
||||
context.Background(),
|
||||
plugins.DeriveChannel(m, eventData),
|
||||
strings.TrimLeft(plugins.DeriveUser(m, eventData), "@"),
|
||||
0,
|
||||
attrs.MustString("reason", ptrStringEmpty),
|
||||
attrs.MustString("reason", helpers.Ptr("")),
|
||||
); err != nil {
|
||||
return false, errors.Wrap(err, "executing user ban")
|
||||
}
|
||||
@ -201,13 +202,13 @@ func (a actor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData
|
||||
plugins.DeriveChannel(m, eventData),
|
||||
strings.TrimLeft(plugins.DeriveUser(m, eventData), "@"),
|
||||
to,
|
||||
attrs.MustString("reason", ptrStringEmpty),
|
||||
attrs.MustString("reason", helpers.Ptr("")),
|
||||
); err != nil {
|
||||
return false, errors.Wrap(err, "executing user ban")
|
||||
}
|
||||
}
|
||||
|
||||
if attrs.MustBool("stop_on_action", ptrBoolFalse) {
|
||||
if attrs.MustBool("stop_on_action", helpers.Ptr(false)) {
|
||||
return false, plugins.ErrStopRuleExecution
|
||||
}
|
||||
|
||||
@ -218,41 +219,42 @@ func (actor) IsAsync() bool { return false }
|
||||
|
||||
func (actor) Name() string { return actorName }
|
||||
|
||||
func (actor) Validate(_ plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) error {
|
||||
if v, err := attrs.String("action"); err != nil || v == "" {
|
||||
return errors.New("action must be non-empty string")
|
||||
}
|
||||
|
||||
if v, err := attrs.String("reason"); err != nil || v == "" {
|
||||
return errors.New("reason must be non-empty string")
|
||||
}
|
||||
|
||||
if len(attrs.MustStringSlice("allowed_links"))+
|
||||
len(attrs.MustStringSlice("disallowed_links"))+
|
||||
len(attrs.MustStringSlice("allowed_clip_channels"))+
|
||||
len(attrs.MustStringSlice("disallowed_clip_channels")) == 0 {
|
||||
return errors.New("no conditions are provided")
|
||||
func (actor) Validate(_ plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "action", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "reason", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
func(attrs, _ *fieldcollection.FieldCollection) error {
|
||||
if len(attrs.MustStringSlice("allowed_links", helpers.Ptr([]string{})))+
|
||||
len(attrs.MustStringSlice("disallowed_links", helpers.Ptr([]string{})))+
|
||||
len(attrs.MustStringSlice("allowed_clip_channels", helpers.Ptr([]string{})))+
|
||||
len(attrs.MustStringSlice("disallowed_clip_channels", helpers.Ptr([]string{}))) == 0 {
|
||||
return errors.New("no conditions are provided")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a actor) check(links []string, clips []twitch.ClipInfo, attrs *plugins.FieldCollection) (v verdict) {
|
||||
hasClipDefinition := len(attrs.MustStringSlice("allowed_clip_channels"))+len(attrs.MustStringSlice("disallowed_clip_channels")) > 0
|
||||
func (a actor) check(links []string, clips []twitch.ClipInfo, attrs *fieldcollection.FieldCollection) (v verdict) {
|
||||
hasClipDefinition := len(attrs.MustStringSlice("allowed_clip_channels", helpers.Ptr([]string{})))+len(attrs.MustStringSlice("disallowed_clip_channels", helpers.Ptr([]string{}))) > 0
|
||||
|
||||
if v = a.checkLinkDenied(attrs.MustStringSlice("disallowed_links"), links, hasClipDefinition); v == verdictMisbehave {
|
||||
if v = a.checkLinkDenied(attrs.MustStringSlice("disallowed_links", helpers.Ptr([]string{})), links, hasClipDefinition); v == verdictMisbehave {
|
||||
return verdictMisbehave
|
||||
}
|
||||
|
||||
if v = a.checkAllLinksAllowed(attrs.MustStringSlice("allowed_links"), links, hasClipDefinition); v == verdictMisbehave {
|
||||
if v = a.checkAllLinksAllowed(attrs.MustStringSlice("allowed_links", helpers.Ptr([]string{})), links, hasClipDefinition); v == verdictMisbehave {
|
||||
return verdictMisbehave
|
||||
}
|
||||
|
||||
if v = a.checkClipChannelDenied(attrs.MustStringSlice("disallowed_clip_channels"), clips); v == verdictMisbehave {
|
||||
if v = a.checkClipChannelDenied(attrs.MustStringSlice("disallowed_clip_channels", helpers.Ptr([]string{})), clips); v == verdictMisbehave {
|
||||
return verdictMisbehave
|
||||
}
|
||||
|
||||
if v = a.checkAllClipChannelsAllowed(attrs.MustStringSlice("allowed_clip_channels"), clips); v == verdictMisbehave {
|
||||
if v = a.checkAllClipChannelsAllowed(attrs.MustStringSlice("allowed_clip_channels", helpers.Ptr([]string{})), clips); v == verdictMisbehave {
|
||||
return verdictMisbehave
|
||||
}
|
||||
|
||||
|
@ -2,18 +2,19 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
var (
|
||||
formatMessage plugins.MsgFormatter
|
||||
ptrStringEmpty = func(v string) *string { return &v }("")
|
||||
)
|
||||
var formatMessage plugins.MsgFormatter
|
||||
|
||||
// Register provides the plugins.RegisterFunc
|
||||
func Register(args plugins.RegistrationArguments) error {
|
||||
@ -44,8 +45,8 @@ func Register(args plugins.RegistrationArguments) error {
|
||||
|
||||
type actor struct{}
|
||||
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
message, err := formatMessage(attrs.MustString("message", ptrStringEmpty), m, r, eventData)
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
message, err := formatMessage(attrs.MustString("message", helpers.Ptr("")), m, r, eventData)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "executing message template")
|
||||
}
|
||||
@ -61,13 +62,12 @@ func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *
|
||||
func (actor) IsAsync() bool { return true }
|
||||
func (actor) Name() string { return "log" }
|
||||
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if v, err := attrs.String("message"); err != nil || v == "" {
|
||||
return errors.New("message must be non-empty string")
|
||||
}
|
||||
|
||||
if err = tplValidator(attrs.MustString("message", ptrStringEmpty)); err != nil {
|
||||
return errors.Wrap(err, "validating message template")
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "message", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
helpers.SchemaValidateTemplateField(tplValidator, "message"),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -20,12 +20,7 @@ const (
|
||||
postTimeout = 5 * time.Second
|
||||
)
|
||||
|
||||
var (
|
||||
formatMessage plugins.MsgFormatter
|
||||
|
||||
ptrBoolFalse = func(v bool) *bool { return &v }(false)
|
||||
ptrStringEmpty = func(s string) *string { return &s }("")
|
||||
)
|
||||
var formatMessage plugins.MsgFormatter
|
||||
|
||||
// Register provides the plugins.RegisterFunc
|
||||
func Register(args plugins.RegistrationArguments) error {
|
||||
|
@ -7,6 +7,8 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
@ -50,18 +52,18 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
func (d discordActor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (d discordActor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
var payload discordPayload
|
||||
|
||||
if payload.Content, err = formatMessage(attrs.MustString("content", ptrStringEmpty), m, r, eventData); err != nil {
|
||||
if payload.Content, err = formatMessage(attrs.MustString("content", helpers.Ptr("")), m, r, eventData); err != nil {
|
||||
return false, errors.Wrap(err, "parsing content")
|
||||
}
|
||||
|
||||
if payload.Username, err = formatMessage(attrs.MustString("username", ptrStringEmpty), m, r, eventData); err != nil {
|
||||
if payload.Username, err = formatMessage(attrs.MustString("username", helpers.Ptr("")), m, r, eventData); err != nil {
|
||||
return false, errors.Wrap(err, "parsing username")
|
||||
}
|
||||
|
||||
if payload.AvatarURL, err = formatMessage(attrs.MustString("avatar_url", ptrStringEmpty), m, r, eventData); err != nil {
|
||||
if payload.AvatarURL, err = formatMessage(attrs.MustString("avatar_url", helpers.Ptr("")), m, r, eventData); err != nil {
|
||||
return false, errors.Wrap(err, "parsing avatar_url")
|
||||
}
|
||||
|
||||
@ -69,14 +71,14 @@ func (d discordActor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, ev
|
||||
return false, err
|
||||
}
|
||||
|
||||
return sendPayload(attrs.MustString("hook_url", ptrStringEmpty), payload, http.StatusNoContent)
|
||||
return sendPayload(attrs.MustString("hook_url", helpers.Ptr("")), payload, http.StatusNoContent)
|
||||
}
|
||||
|
||||
func (discordActor) IsAsync() bool { return false }
|
||||
|
||||
func (discordActor) Name() string { return "discordhook" }
|
||||
|
||||
func (d discordActor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
func (d discordActor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = d.ValidateRequireNonEmpty(attrs, "hook_url"); err != nil {
|
||||
return err //nolint:wrapcheck
|
||||
}
|
||||
@ -89,7 +91,7 @@ func (d discordActor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs
|
||||
return err //nolint:wrapcheck
|
||||
}
|
||||
|
||||
if !attrs.MustBool("add_embed", ptrBoolFalse) {
|
||||
if !attrs.MustBool("add_embed", helpers.Ptr(false)) {
|
||||
// We're not validating the rest if embeds are disabled but in
|
||||
// this case the content is mandatory
|
||||
return d.ValidateRequireNonEmpty(attrs, "content") //nolint:wrapcheck
|
||||
@ -111,8 +113,8 @@ func (d discordActor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs
|
||||
}
|
||||
|
||||
//nolint:gocyclo // It's complex but just a bunch of converters
|
||||
func (discordActor) addEmbed(payload *discordPayload, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (err error) {
|
||||
if !attrs.MustBool("add_embed", ptrBoolFalse) {
|
||||
func (discordActor) addEmbed(payload *discordPayload, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if !attrs.MustBool("add_embed", helpers.Ptr(false)) {
|
||||
// No embed? No problem!
|
||||
return nil
|
||||
}
|
||||
@ -122,45 +124,45 @@ func (discordActor) addEmbed(payload *discordPayload, m *irc.Message, r *plugins
|
||||
sv string
|
||||
)
|
||||
|
||||
if embed.Title, err = formatMessage(attrs.MustString("embed_title", ptrStringEmpty), m, r, eventData); err != nil {
|
||||
if embed.Title, err = formatMessage(attrs.MustString("embed_title", helpers.Ptr("")), m, r, eventData); err != nil {
|
||||
return errors.Wrap(err, "parsing embed_title")
|
||||
}
|
||||
|
||||
if embed.Description, err = formatMessage(attrs.MustString("embed_description", ptrStringEmpty), m, r, eventData); err != nil {
|
||||
if embed.Description, err = formatMessage(attrs.MustString("embed_description", helpers.Ptr("")), m, r, eventData); err != nil {
|
||||
return errors.Wrap(err, "parsing embed_description")
|
||||
}
|
||||
|
||||
if embed.URL, err = formatMessage(attrs.MustString("embed_url", ptrStringEmpty), m, r, eventData); err != nil {
|
||||
if embed.URL, err = formatMessage(attrs.MustString("embed_url", helpers.Ptr("")), m, r, eventData); err != nil {
|
||||
return errors.Wrap(err, "parsing embed_url")
|
||||
}
|
||||
|
||||
if sv, err = formatMessage(attrs.MustString("embed_image", ptrStringEmpty), m, r, eventData); err != nil {
|
||||
if sv, err = formatMessage(attrs.MustString("embed_image", helpers.Ptr("")), m, r, eventData); err != nil {
|
||||
return errors.Wrap(err, "parsing embed_image")
|
||||
} else if sv != "" {
|
||||
embed.Image = &discordPayloadEmbedImage{URL: sv}
|
||||
}
|
||||
|
||||
if sv, err = formatMessage(attrs.MustString("embed_thumbnail", ptrStringEmpty), m, r, eventData); err != nil {
|
||||
if sv, err = formatMessage(attrs.MustString("embed_thumbnail", helpers.Ptr("")), m, r, eventData); err != nil {
|
||||
return errors.Wrap(err, "parsing embed_thumbnail")
|
||||
} else if sv != "" {
|
||||
embed.Thumbnail = &discordPayloadEmbedImage{URL: sv}
|
||||
}
|
||||
|
||||
if sv, err = formatMessage(attrs.MustString("embed_author_name", ptrStringEmpty), m, r, eventData); err != nil {
|
||||
if sv, err = formatMessage(attrs.MustString("embed_author_name", helpers.Ptr("")), m, r, eventData); err != nil {
|
||||
return errors.Wrap(err, "parsing embed_author_name")
|
||||
} else if sv != "" {
|
||||
embed.Author = &discordPayloadEmbedAuthor{Name: sv}
|
||||
|
||||
if embed.Author.URL, err = formatMessage(attrs.MustString("embed_author_url", ptrStringEmpty), m, r, eventData); err != nil {
|
||||
if embed.Author.URL, err = formatMessage(attrs.MustString("embed_author_url", helpers.Ptr("")), m, r, eventData); err != nil {
|
||||
return errors.Wrap(err, "parsing embed_author_url")
|
||||
}
|
||||
|
||||
if embed.Author.IconURL, err = formatMessage(attrs.MustString("embed_author_icon_url", ptrStringEmpty), m, r, eventData); err != nil {
|
||||
if embed.Author.IconURL, err = formatMessage(attrs.MustString("embed_author_icon_url", helpers.Ptr("")), m, r, eventData); err != nil {
|
||||
return errors.Wrap(err, "parsing embed_author_icon_url")
|
||||
}
|
||||
}
|
||||
|
||||
if sv, err = formatMessage(attrs.MustString("embed_fields", ptrStringEmpty), m, r, eventData); err != nil {
|
||||
if sv, err = formatMessage(attrs.MustString("embed_fields", helpers.Ptr("")), m, r, eventData); err != nil {
|
||||
return errors.Wrap(err, "parsing embed_fields")
|
||||
} else if sv != "" {
|
||||
var flds []discordPayloadEmbedField
|
||||
|
@ -7,6 +7,8 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
@ -14,14 +16,14 @@ type slackCompatibleActor struct {
|
||||
plugins.ActorKit
|
||||
}
|
||||
|
||||
func (s slackCompatibleActor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (s slackCompatibleActor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
text, err := formatMessage(attrs.MustString("text", nil), m, r, eventData)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "parsing text")
|
||||
}
|
||||
|
||||
return sendPayload(
|
||||
s.fixHookURL(attrs.MustString("hook_url", ptrStringEmpty)),
|
||||
s.fixHookURL(attrs.MustString("hook_url", helpers.Ptr(""))),
|
||||
map[string]string{
|
||||
"text": text,
|
||||
},
|
||||
@ -33,7 +35,7 @@ func (slackCompatibleActor) IsAsync() bool { return false }
|
||||
|
||||
func (slackCompatibleActor) Name() string { return "slackhook" }
|
||||
|
||||
func (s slackCompatibleActor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
func (s slackCompatibleActor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = s.ValidateRequireNonEmpty(attrs, "hook_url", "text"); err != nil {
|
||||
return err //nolint:wrapcheck
|
||||
}
|
||||
|
@ -4,11 +4,14 @@ package modchannel
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
@ -18,8 +21,6 @@ const actorName = "modchannel"
|
||||
var (
|
||||
formatMessage plugins.MsgFormatter
|
||||
tcGetter func(string) (*twitch.Client, error)
|
||||
|
||||
ptrStringEmpty = func(s string) *string { return &s }("")
|
||||
)
|
||||
|
||||
// Register provides the plugins.RegisterFunc
|
||||
@ -70,10 +71,10 @@ func Register(args plugins.RegistrationArguments) error {
|
||||
|
||||
type actor struct{}
|
||||
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
var (
|
||||
game = attrs.MustString("game", ptrStringEmpty)
|
||||
title = attrs.MustString("title", ptrStringEmpty)
|
||||
game = attrs.MustString("game", helpers.Ptr(""))
|
||||
title = attrs.MustString("title", helpers.Ptr(""))
|
||||
)
|
||||
|
||||
if game == "" && title == "" {
|
||||
@ -119,15 +120,14 @@ func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *
|
||||
func (actor) IsAsync() bool { return false }
|
||||
func (actor) Name() string { return actorName }
|
||||
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if v, err := attrs.String("channel"); err != nil || v == "" {
|
||||
return errors.New("channel must be non-empty string")
|
||||
}
|
||||
|
||||
for _, field := range []string{"channel", "game", "title"} {
|
||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
||||
return errors.Wrapf(err, "validating %s template", field)
|
||||
}
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "channel", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
fieldcollection.CanHaveField(fieldcollection.SchemaField{Name: "game", Type: fieldcollection.SchemaFieldTypeString}),
|
||||
fieldcollection.CanHaveField(fieldcollection.SchemaField{Name: "title", Type: fieldcollection.SchemaFieldTypeString}),
|
||||
helpers.SchemaValidateTemplateField(tplValidator, "channel", "game", "title"),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -4,6 +4,7 @@
|
||||
package nuke
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
@ -13,7 +14,9 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/go_helpers/v2/str"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
@ -29,10 +32,6 @@ var (
|
||||
|
||||
messageStore = map[string][]*storedMessage{}
|
||||
messageStoreLock sync.RWMutex
|
||||
|
||||
ptrStringDelete = func(v string) *string { return &v }("delete")
|
||||
ptrStringEmpty = func(s string) *string { return &s }("")
|
||||
ptrString10m = func(v string) *string { return &v }("10m")
|
||||
)
|
||||
|
||||
// Register provides the plugins.RegisterFunc
|
||||
@ -150,14 +149,14 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
rawMatch, err := formatMessage(attrs.MustString("match", nil), m, r, eventData)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "formatting match")
|
||||
}
|
||||
match := regexp.MustCompile(rawMatch)
|
||||
|
||||
rawScan, err := formatMessage(attrs.MustString("scan", ptrString10m), m, r, eventData)
|
||||
rawScan, err := formatMessage(attrs.MustString("scan", helpers.Ptr("10m")), m, r, eventData)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "formatting scan duration")
|
||||
}
|
||||
@ -171,7 +170,7 @@ func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *
|
||||
action actionFn
|
||||
actionName string
|
||||
)
|
||||
rawAction, err := formatMessage(attrs.MustString("action", ptrStringDelete), m, r, eventData)
|
||||
rawAction, err := formatMessage(attrs.MustString("action", helpers.Ptr("delete")), m, r, eventData)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "formatting action")
|
||||
}
|
||||
@ -235,15 +234,14 @@ func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *
|
||||
func (actor) IsAsync() bool { return false }
|
||||
func (actor) Name() string { return actorName }
|
||||
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if v, err := attrs.String("match"); err != nil || v == "" {
|
||||
return errors.New("match must be non-empty string")
|
||||
}
|
||||
|
||||
for _, field := range []string{"scan", "action", "match"} {
|
||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
||||
return errors.Wrapf(err, "validating %s template", field)
|
||||
}
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "match", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
fieldcollection.CanHaveField(fieldcollection.SchemaField{Name: "action", Type: fieldcollection.SchemaFieldTypeString}),
|
||||
fieldcollection.CanHaveField(fieldcollection.SchemaField{Name: "scan", Type: fieldcollection.SchemaFieldTypeString}),
|
||||
helpers.SchemaValidateTemplateField(tplValidator, "scan", "action", "match"),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -4,6 +4,7 @@ package punish
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"time"
|
||||
@ -12,6 +13,8 @@ import (
|
||||
"gopkg.in/irc.v4"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
@ -25,11 +28,9 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
botTwitchClient *twitch.Client
|
||||
db database.Connector
|
||||
formatMessage plugins.MsgFormatter
|
||||
ptrDefaultCooldown = func(v time.Duration) *time.Duration { return &v }(oneWeek)
|
||||
ptrStringEmpty = func(v string) *string { return &v }("")
|
||||
botTwitchClient *twitch.Client
|
||||
db database.Connector
|
||||
formatMessage plugins.MsgFormatter
|
||||
)
|
||||
|
||||
// Register provides the plugins.RegisterFunc
|
||||
@ -146,12 +147,12 @@ type (
|
||||
|
||||
// Punish
|
||||
|
||||
func (actorPunish) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (actorPunish) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
var (
|
||||
cooldown = attrs.MustDuration("cooldown", ptrDefaultCooldown)
|
||||
reason = attrs.MustString("reason", ptrStringEmpty)
|
||||
cooldown = attrs.MustDuration("cooldown", helpers.Ptr(oneWeek))
|
||||
reason = attrs.MustString("reason", helpers.Ptr(""))
|
||||
user = attrs.MustString("user", nil)
|
||||
uuid = attrs.MustString("uuid", ptrStringEmpty)
|
||||
uuid = attrs.MustString("uuid", helpers.Ptr(""))
|
||||
)
|
||||
|
||||
levels, err := attrs.StringSlice("levels")
|
||||
@ -225,17 +226,16 @@ func (actorPunish) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, event
|
||||
func (actorPunish) IsAsync() bool { return false }
|
||||
func (actorPunish) Name() string { return actorNamePunish }
|
||||
|
||||
func (actorPunish) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if v, err := attrs.String("user"); err != nil || v == "" {
|
||||
return errors.New("user must be non-empty string")
|
||||
}
|
||||
|
||||
if v, err := attrs.StringSlice("levels"); err != nil || len(v) == 0 {
|
||||
return errors.New("levels must be slice of strings with length > 0")
|
||||
}
|
||||
|
||||
if err = tplValidator(attrs.MustString("user", ptrStringEmpty)); err != nil {
|
||||
return errors.Wrap(err, "validating user template")
|
||||
func (actorPunish) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "levels", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeStringSlice}),
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "user", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
fieldcollection.CanHaveField(fieldcollection.SchemaField{Name: "cooldown", Type: fieldcollection.SchemaFieldTypeDuration}),
|
||||
fieldcollection.CanHaveField(fieldcollection.SchemaField{Name: "reason", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
fieldcollection.CanHaveField(fieldcollection.SchemaField{Name: "uuid", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
helpers.SchemaValidateTemplateField(tplValidator, "user"),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -243,10 +243,10 @@ func (actorPunish) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *p
|
||||
|
||||
// Reset
|
||||
|
||||
func (actorResetPunish) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (actorResetPunish) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
var (
|
||||
user = attrs.MustString("user", nil)
|
||||
uuid = attrs.MustString("uuid", ptrStringEmpty)
|
||||
uuid = attrs.MustString("uuid", helpers.Ptr(""))
|
||||
)
|
||||
|
||||
if user, err = formatMessage(user, m, r, eventData); err != nil {
|
||||
@ -262,13 +262,13 @@ func (actorResetPunish) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule,
|
||||
func (actorResetPunish) IsAsync() bool { return false }
|
||||
func (actorResetPunish) Name() string { return actorNameResetPunish }
|
||||
|
||||
func (actorResetPunish) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if v, err := attrs.String("user"); err != nil || v == "" {
|
||||
return errors.New("user must be non-empty string")
|
||||
}
|
||||
|
||||
if err = tplValidator(attrs.MustString("user", ptrStringEmpty)); err != nil {
|
||||
return errors.Wrap(err, "validating user template")
|
||||
func (actorResetPunish) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "user", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
fieldcollection.CanHaveField(fieldcollection.SchemaField{Name: "uuid", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
helpers.SchemaValidateTemplateField(tplValidator, "user"),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -10,6 +10,8 @@ import (
|
||||
"gopkg.in/irc.v4"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
@ -23,9 +25,9 @@ var (
|
||||
formatMessage plugins.MsgFormatter
|
||||
send plugins.SendMessageFunc
|
||||
|
||||
ptrStringEmpty = func(v string) *string { return &v }("")
|
||||
ptrStringOutFormat = func(v string) *string { return &v }("Quote #{{ .index }}: {{ .quote }}")
|
||||
ptrStringZero = func(v string) *string { return &v }("0")
|
||||
// ptrStringEmpty = func(v string) *string { return &v }("")
|
||||
// ptrStringOutFormat = func(v string) *string { return &v }("Quote #{{ .index }}: {{ .quote }}")
|
||||
// ptrStringZero = func(v string) *string { return &v }("0")
|
||||
)
|
||||
|
||||
// Register provides the plugins.RegisterFunc
|
||||
@ -93,7 +95,7 @@ func Register(args plugins.RegistrationArguments) (err error) {
|
||||
return fmt.Errorf("registering API: %w", err)
|
||||
}
|
||||
|
||||
args.RegisterTemplateFunction("lastQuoteIndex", func(m *irc.Message, _ *plugins.Rule, _ *plugins.FieldCollection) interface{} {
|
||||
args.RegisterTemplateFunction("lastQuoteIndex", func(m *irc.Message, _ *plugins.Rule, _ *fieldcollection.FieldCollection) interface{} {
|
||||
return func() (int, error) {
|
||||
return getMaxQuoteIdx(db, plugins.DeriveChannel(m, nil))
|
||||
}
|
||||
@ -113,11 +115,11 @@ type (
|
||||
actor struct{}
|
||||
)
|
||||
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
var (
|
||||
action = attrs.MustString("action", ptrStringEmpty)
|
||||
indexStr = attrs.MustString("index", ptrStringZero)
|
||||
quote = attrs.MustString("quote", ptrStringEmpty)
|
||||
action = attrs.MustString("action", helpers.Ptr(""))
|
||||
indexStr = attrs.MustString("index", helpers.Ptr("0"))
|
||||
quote = attrs.MustString("quote", helpers.Ptr(""))
|
||||
)
|
||||
|
||||
if indexStr == "" {
|
||||
@ -166,7 +168,7 @@ func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *
|
||||
fields.Set("index", idx)
|
||||
fields.Set("quote", quote)
|
||||
|
||||
format := attrs.MustString("format", ptrStringOutFormat)
|
||||
format := attrs.MustString("format", helpers.Ptr("Quote #{{ .index }}: {{ .quote }}"))
|
||||
msg, err := formatMessage(format, m, r, fields)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "formatting output message")
|
||||
@ -190,31 +192,35 @@ func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *
|
||||
func (actor) IsAsync() bool { return false }
|
||||
func (actor) Name() string { return actorName }
|
||||
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
action := attrs.MustString("action", ptrStringEmpty)
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "action", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
fieldcollection.CanHaveField(fieldcollection.SchemaField{Name: "quote", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
fieldcollection.CanHaveField(fieldcollection.SchemaField{Name: "index", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
fieldcollection.CanHaveField(fieldcollection.SchemaField{Name: "format", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
helpers.SchemaValidateTemplateField(tplValidator, "index", "quote", "format"),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
action := attrs.MustString("action", helpers.Ptr(""))
|
||||
|
||||
switch action {
|
||||
case "add":
|
||||
if v, err := attrs.String("quote"); err != nil || v == "" {
|
||||
return errors.New("quote must be non-empty string for action add")
|
||||
return fmt.Errorf("quote must be non-empty string for action add")
|
||||
}
|
||||
|
||||
case "del":
|
||||
if v, err := attrs.String("index"); err != nil || v == "" {
|
||||
return errors.New("index must be non-empty string for adction del")
|
||||
return fmt.Errorf("index must be non-empty string for adction del")
|
||||
}
|
||||
|
||||
case "get":
|
||||
// No requirements
|
||||
|
||||
default:
|
||||
return errors.New("action must be one of add, del or get")
|
||||
}
|
||||
|
||||
for _, field := range []string{"index", "quote", "format"} {
|
||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
||||
return errors.Wrapf(err, "validating %s template", field)
|
||||
}
|
||||
return fmt.Errorf("action must be one of add, del or get")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -2,9 +2,13 @@
|
||||
package raw
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
@ -13,8 +17,6 @@ const actorName = "raw"
|
||||
var (
|
||||
formatMessage plugins.MsgFormatter
|
||||
send plugins.SendMessageFunc
|
||||
|
||||
ptrStringEmpty = func(s string) *string { return &s }("")
|
||||
)
|
||||
|
||||
// Register provides the plugins.RegisterFunc
|
||||
@ -47,7 +49,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||
|
||||
type actor struct{}
|
||||
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
rawMsg, err := formatMessage(attrs.MustString("message", nil), m, r, eventData)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "preparing raw message")
|
||||
@ -67,13 +69,12 @@ func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *
|
||||
func (actor) IsAsync() bool { return false }
|
||||
func (actor) Name() string { return actorName }
|
||||
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if v, err := attrs.String("message"); err != nil || v == "" {
|
||||
return errors.New("message must be non-empty string")
|
||||
}
|
||||
|
||||
if err = tplValidator(attrs.MustString("message", ptrStringEmpty)); err != nil {
|
||||
return errors.Wrap(err, "validating message template")
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "message", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
helpers.SchemaValidateTemplateField(tplValidator, "message"),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -12,6 +12,8 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
@ -20,9 +22,6 @@ const actorName = "respond"
|
||||
var (
|
||||
formatMessage plugins.MsgFormatter
|
||||
send plugins.SendMessageFunc
|
||||
|
||||
ptrBoolFalse = func(v bool) *bool { return &v }(false)
|
||||
ptrStringEmpty = func(s string) *string { return &s }("")
|
||||
)
|
||||
|
||||
// Register provides the plugins.RegisterFunc
|
||||
@ -102,7 +101,7 @@ func Register(args plugins.RegistrationArguments) (err error) {
|
||||
|
||||
type actor struct{}
|
||||
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
msg, err := formatMessage(attrs.MustString("message", nil), m, r, eventData)
|
||||
if err != nil {
|
||||
if !attrs.CanString("fallback") || attrs.MustString("fallback", nil) == "" {
|
||||
@ -127,7 +126,7 @@ func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *
|
||||
},
|
||||
}
|
||||
|
||||
if attrs.MustBool("as_reply", ptrBoolFalse) {
|
||||
if attrs.MustBool("as_reply", helpers.Ptr(false)) {
|
||||
id, ok := m.Tags["id"]
|
||||
if ok {
|
||||
if ircMessage.Tags == nil {
|
||||
@ -146,15 +145,15 @@ func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *
|
||||
func (actor) IsAsync() bool { return false }
|
||||
func (actor) Name() string { return actorName }
|
||||
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if v, err := attrs.String("message"); err != nil || v == "" {
|
||||
return errors.New("message must be non-empty string")
|
||||
}
|
||||
|
||||
for _, field := range []string{"message", "fallback"} {
|
||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
||||
return errors.Wrapf(err, "validating %s template", field)
|
||||
}
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "message", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
fieldcollection.CanHaveField(fieldcollection.SchemaField{Name: "fallback", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
fieldcollection.CanHaveField(fieldcollection.SchemaField{Name: "as_reply", Type: fieldcollection.SchemaFieldTypeBool}),
|
||||
fieldcollection.CanHaveField(fieldcollection.SchemaField{Name: "to_channel", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
helpers.SchemaValidateTemplateField(tplValidator, "message", "fallback"),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -4,10 +4,13 @@ package shield
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
@ -45,14 +48,12 @@ func Register(args plugins.RegistrationArguments) error {
|
||||
|
||||
type actor struct{}
|
||||
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, _ *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
ptrBoolFalse := func(v bool) *bool { return &v }(false)
|
||||
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, _ *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
return false, errors.Wrap(
|
||||
botTwitchClient.UpdateShieldMode(
|
||||
context.Background(),
|
||||
plugins.DeriveChannel(m, eventData),
|
||||
attrs.MustBool("enable", ptrBoolFalse),
|
||||
attrs.MustBool("enable", helpers.Ptr(false)),
|
||||
),
|
||||
"configuring shield mode",
|
||||
)
|
||||
@ -61,9 +62,11 @@ func (actor) Execute(_ *irc.Client, m *irc.Message, _ *plugins.Rule, eventData *
|
||||
func (actor) IsAsync() bool { return false }
|
||||
func (actor) Name() string { return actorName }
|
||||
|
||||
func (actor) Validate(_ plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if _, err = attrs.Bool("enable"); err != nil {
|
||||
return errors.New("enable must be boolean")
|
||||
func (actor) Validate(_ plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "enable", Type: fieldcollection.SchemaFieldTypeBool}),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -4,11 +4,14 @@ package shoutout
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
@ -55,7 +58,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||
|
||||
type actor struct{}
|
||||
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
user, err := formatMessage(attrs.MustString("user", ptrStringEmpty), m, r, eventData)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "executing user template")
|
||||
@ -74,13 +77,12 @@ func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *
|
||||
func (actor) IsAsync() bool { return false }
|
||||
func (actor) Name() string { return actorName }
|
||||
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if v, err := attrs.String("user"); err != nil || v == "" {
|
||||
return errors.New("user must be non-empty string")
|
||||
}
|
||||
|
||||
if err = tplValidator(attrs.MustString("user", ptrStringEmpty)); err != nil {
|
||||
return errors.Wrap(err, "validating user template")
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "user", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
helpers.SchemaValidateTemplateField(tplValidator, "user"),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -3,9 +3,13 @@
|
||||
package stopexec
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
@ -42,10 +46,8 @@ func Register(args plugins.RegistrationArguments) error {
|
||||
|
||||
type actor struct{}
|
||||
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
ptrStringEmpty := func(v string) *string { return &v }("")
|
||||
|
||||
when, err := formatMessage(attrs.MustString("when", ptrStringEmpty), m, r, eventData)
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
when, err := formatMessage(attrs.MustString("when", helpers.Ptr("")), m, r, eventData)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "executing when template")
|
||||
}
|
||||
@ -60,14 +62,12 @@ func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *
|
||||
func (actor) IsAsync() bool { return false }
|
||||
func (actor) Name() string { return actorName }
|
||||
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
whenTemplate, err := attrs.String("when")
|
||||
if err != nil || whenTemplate == "" {
|
||||
return errors.New("when must be non-empty string")
|
||||
}
|
||||
|
||||
if err = tplValidator(whenTemplate); err != nil {
|
||||
return errors.Wrap(err, "validating when template")
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "when", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
helpers.SchemaValidateTemplateField(tplValidator, "when"),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -3,6 +3,7 @@ package timeout
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
@ -10,6 +11,8 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
@ -65,7 +68,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||
|
||||
type actor struct{}
|
||||
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
reason, err := formatMessage(attrs.MustString("reason", ptrStringEmpty), m, r, eventData)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "executing reason template")
|
||||
@ -86,17 +89,17 @@ func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *
|
||||
func (actor) IsAsync() bool { return false }
|
||||
func (actor) Name() string { return actorName }
|
||||
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if v, err := attrs.Duration("duration"); err != nil || v < time.Second {
|
||||
return errors.New("duration must be of type duration greater or equal one second")
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "duration", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeDuration}),
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "reason", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
helpers.SchemaValidateTemplateField(tplValidator, "reason"),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
if v, err := attrs.String("reason"); err != nil || v == "" {
|
||||
return errors.New("reason must be non-empty string")
|
||||
}
|
||||
|
||||
if err = tplValidator(attrs.MustString("reason", ptrStringEmpty)); err != nil {
|
||||
return errors.Wrap(err, "validating reason template")
|
||||
if attrs.MustDuration("duration", nil) < time.Second {
|
||||
return errors.New("duration must be greater or equal one second")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -11,6 +11,8 @@ import (
|
||||
"gopkg.in/irc.v4"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
@ -144,7 +146,7 @@ func Register(args plugins.RegistrationArguments) (err error) {
|
||||
|
||||
type actorSetVariable struct{}
|
||||
|
||||
func (actorSetVariable) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (actorSetVariable) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
varName, err := formatMessage(attrs.MustString("variable", nil), m, r, eventData)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "preparing variable name")
|
||||
@ -171,15 +173,14 @@ func (actorSetVariable) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule,
|
||||
func (actorSetVariable) IsAsync() bool { return false }
|
||||
func (actorSetVariable) Name() string { return "setvariable" }
|
||||
|
||||
func (actorSetVariable) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if v, err := attrs.String("variable"); err != nil || v == "" {
|
||||
return errors.New("variable name must be non-empty string")
|
||||
}
|
||||
|
||||
for _, field := range []string{"set", "variable"} {
|
||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
||||
return errors.Wrapf(err, "validating %s template", field)
|
||||
}
|
||||
func (actorSetVariable) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "variable", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
fieldcollection.CanHaveField(fieldcollection.SchemaField{Name: "clear", Type: fieldcollection.SchemaFieldTypeBool}),
|
||||
fieldcollection.CanHaveField(fieldcollection.SchemaField{Name: "set", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
helpers.SchemaValidateTemplateField(tplValidator, "set", "variable"),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -3,11 +3,14 @@ package vip
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
@ -16,8 +19,6 @@ var (
|
||||
formatMessage plugins.MsgFormatter
|
||||
permCheckFn plugins.ChannelPermissionCheckFunc
|
||||
tcGetter func(string) (*twitch.Client, error)
|
||||
|
||||
ptrStringEmpty = func(s string) *string { return &s }("")
|
||||
)
|
||||
|
||||
// Register provides the plugins.RegisterFunc
|
||||
@ -98,21 +99,19 @@ type (
|
||||
)
|
||||
|
||||
func (actor) IsAsync() bool { return false }
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
for _, field := range []string{"channel", "user"} {
|
||||
if v, err := attrs.String(field); err != nil || v == "" {
|
||||
return errors.Errorf("%s must be non-empty string", field)
|
||||
}
|
||||
|
||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
||||
return errors.Wrapf(err, "validating %s template", field)
|
||||
}
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "channel", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "user", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
helpers.SchemaValidateTemplateField(tplValidator, "channel", "user"),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (actor) getParams(m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (channel, user string, err error) {
|
||||
func (actor) getParams(m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (channel, user string, err error) {
|
||||
if channel, err = formatMessage(attrs.MustString("channel", nil), m, r, eventData); err != nil {
|
||||
return "", "", errors.Wrap(err, "parsing channel")
|
||||
}
|
||||
@ -124,7 +123,7 @@ func (actor) getParams(m *irc.Message, r *plugins.Rule, eventData *plugins.Field
|
||||
return strings.TrimLeft(channel, "#"), user, nil
|
||||
}
|
||||
|
||||
func (u unvipActor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (u unvipActor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
channel, user, err := u.getParams(m, r, eventData, attrs)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "getting parameters")
|
||||
@ -140,7 +139,7 @@ func (u unvipActor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, even
|
||||
|
||||
func (unvipActor) Name() string { return "unvip" }
|
||||
|
||||
func (v vipActor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (v vipActor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
channel, user, err := v.getParams(m, r, eventData, attrs)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "getting parameters")
|
||||
|
@ -3,10 +3,13 @@ package whisper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
@ -16,8 +19,6 @@ const actorName = "whisper"
|
||||
var (
|
||||
botTwitchClient *twitch.Client
|
||||
formatMessage plugins.MsgFormatter
|
||||
|
||||
ptrStringEmpty = func(s string) *string { return &s }("")
|
||||
)
|
||||
|
||||
// Register provides the plugins.RegisterFunc
|
||||
@ -28,7 +29,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||
args.RegisterActor(actorName, func() plugins.Actor { return &actor{} })
|
||||
|
||||
args.RegisterActorDocumentation(plugins.ActionDocumentation{
|
||||
Description: "Send a whisper (requires a verified bot!)",
|
||||
Description: "Send a whisper",
|
||||
Name: "Send Whisper",
|
||||
Type: "whisper",
|
||||
|
||||
@ -59,7 +60,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||
|
||||
type actor struct{}
|
||||
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
to, err := formatMessage(attrs.MustString("to", nil), m, r, eventData)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "preparing whisper receiver")
|
||||
@ -79,19 +80,13 @@ func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *
|
||||
func (actor) IsAsync() bool { return false }
|
||||
func (actor) Name() string { return actorName }
|
||||
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if v, err := attrs.String("to"); err != nil || v == "" {
|
||||
return errors.New("to must be non-empty string")
|
||||
}
|
||||
|
||||
if v, err := attrs.String("message"); err != nil || v == "" {
|
||||
return errors.New("message must be non-empty string")
|
||||
}
|
||||
|
||||
for _, field := range []string{"message", "to"} {
|
||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
||||
return errors.Wrapf(err, "validating %s template", field)
|
||||
}
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "message", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "to", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
helpers.SchemaValidateTemplateField(tplValidator, "message", "to"),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -1,17 +1,20 @@
|
||||
package customevent
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
type actor struct{}
|
||||
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
fd, err := formatMessage(attrs.MustString("fields", ptrStringEmpty), m, r, eventData)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "executing fields template")
|
||||
@ -35,15 +38,13 @@ func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *
|
||||
func (actor) IsAsync() bool { return false }
|
||||
func (actor) Name() string { return actorName }
|
||||
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if v, err := attrs.String("fields"); err != nil || v == "" {
|
||||
return errors.New("fields is expected to be non-empty string")
|
||||
}
|
||||
|
||||
for _, field := range []string{"fields", "schedule_in"} {
|
||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
||||
return errors.Wrapf(err, "validating %s template", field)
|
||||
}
|
||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "fields", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
fieldcollection.CanHaveField(fieldcollection.SchemaField{Name: "schedule_in", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
helpers.SchemaValidateTemplateField(tplValidator, "fields", "schedule_in"),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
@ -130,14 +131,14 @@ func handleCreateEvent(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func parseEvent(channel string, fieldData io.Reader) (*plugins.FieldCollection, error) {
|
||||
func parseEvent(channel string, fieldData io.Reader) (*fieldcollection.FieldCollection, error) {
|
||||
payload := make(map[string]any)
|
||||
|
||||
if err := json.NewDecoder(fieldData).Decode(&payload); err != nil {
|
||||
return nil, errors.Wrap(err, "parsing event payload")
|
||||
}
|
||||
|
||||
fields := plugins.FieldCollectionFromData(payload)
|
||||
fields := fieldcollection.FieldCollectionFromData(payload)
|
||||
fields.Set("channel", "#"+strings.TrimLeft(channel, "#"))
|
||||
|
||||
return fields, nil
|
||||
|
@ -9,9 +9,9 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
const cleanupTimeout = 15 * time.Minute
|
||||
@ -48,7 +48,7 @@ func getFutureEvents(db database.Connector) (out []storedCustomEvent, err error)
|
||||
)
|
||||
}
|
||||
|
||||
func storeEvent(db database.Connector, scheduleAt time.Time, channel string, fields *plugins.FieldCollection) error {
|
||||
func storeEvent(db database.Connector, scheduleAt time.Time, channel string, fields *fieldcollection.FieldCollection) error {
|
||||
fieldBuf := new(bytes.Buffer)
|
||||
if err := json.NewEncoder(fieldBuf).Encode(fields); err != nil {
|
||||
return errors.Wrap(err, "marshalling fields")
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -87,7 +88,7 @@ func handleKoFiPost(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
fields := plugins.NewFieldCollection()
|
||||
fields := fieldcollection.NewFieldCollection()
|
||||
fields.Set("channel", "#"+strings.TrimLeft(channel, "#"))
|
||||
|
||||
switch payload.Type {
|
||||
|
@ -10,9 +10,9 @@ import (
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/backoff"
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
type (
|
||||
@ -86,7 +86,7 @@ func getEventByID(db database.Connector, eventID uint64) (socketMessage, error)
|
||||
}
|
||||
|
||||
func (o overlaysEvent) ToSocketMessage() (socketMessage, error) {
|
||||
fields := new(plugins.FieldCollection)
|
||||
fields := new(fieldcollection.FieldCollection)
|
||||
if err := json.NewDecoder(strings.NewReader(o.Fields)).Decode(fields); err != nil {
|
||||
return socketMessage{}, errors.Wrap(err, "decoding fields")
|
||||
}
|
||||
|
@ -7,8 +7,8 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
func TestEventDatabaseRoundtrip(t *testing.T) {
|
||||
@ -30,7 +30,7 @@ func TestEventDatabaseRoundtrip(t *testing.T) {
|
||||
IsLive: true,
|
||||
Time: tEvent2,
|
||||
Type: "event 2",
|
||||
Fields: plugins.FieldCollectionFromData(map[string]any{"foo": "bar"}),
|
||||
Fields: fieldcollection.FieldCollectionFromData(map[string]any{"foo": "bar"}),
|
||||
})
|
||||
assert.Equal(t, uint64(1), evtID)
|
||||
assert.NoError(t, err, "adding second event")
|
||||
@ -39,7 +39,7 @@ func TestEventDatabaseRoundtrip(t *testing.T) {
|
||||
IsLive: true,
|
||||
Time: tEvent1,
|
||||
Type: "event 1",
|
||||
Fields: plugins.FieldCollectionFromData(map[string]any{"foo": "bar"}),
|
||||
Fields: fieldcollection.FieldCollectionFromData(map[string]any{"foo": "bar"}),
|
||||
})
|
||||
assert.Equal(t, uint64(2), evtID)
|
||||
assert.NoError(t, err, "adding first event")
|
||||
@ -48,7 +48,7 @@ func TestEventDatabaseRoundtrip(t *testing.T) {
|
||||
IsLive: true,
|
||||
Time: tEvent1,
|
||||
Type: "event",
|
||||
Fields: plugins.FieldCollectionFromData(map[string]any{"foo": "bar"}),
|
||||
Fields: fieldcollection.FieldCollectionFromData(map[string]any{"foo": "bar"}),
|
||||
})
|
||||
assert.Equal(t, uint64(3), evtID)
|
||||
assert.NoError(t, err, "adding other channel event")
|
||||
@ -66,6 +66,6 @@ func TestEventDatabaseRoundtrip(t *testing.T) {
|
||||
IsLive: false,
|
||||
Time: tEvent1,
|
||||
Type: "event 1",
|
||||
Fields: plugins.FieldCollectionFromData(map[string]any{"foo": "bar"}),
|
||||
Fields: fieldcollection.FieldCollectionFromData(map[string]any{"foo": "bar"}),
|
||||
}, evt)
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/go_helpers/v2/str"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
@ -41,12 +42,12 @@ type (
|
||||
|
||||
// socketMessage represents the message overlay sockets will receive
|
||||
socketMessage struct {
|
||||
EventID uint64 `json:"event_id"`
|
||||
IsLive bool `json:"is_live"`
|
||||
Reason sendReason `json:"reason"`
|
||||
Time time.Time `json:"time"`
|
||||
Type string `json:"type"`
|
||||
Fields *plugins.FieldCollection `json:"fields"`
|
||||
EventID uint64 `json:"event_id"`
|
||||
IsLive bool `json:"is_live"`
|
||||
Reason sendReason `json:"reason"`
|
||||
Time time.Time `json:"time"`
|
||||
Type string `json:"type"`
|
||||
Fields *fieldcollection.FieldCollection `json:"fields"`
|
||||
}
|
||||
)
|
||||
|
||||
@ -180,7 +181,7 @@ func Register(args plugins.RegistrationArguments) (err error) {
|
||||
return fmt.Errorf("registering API route: %w", err)
|
||||
}
|
||||
|
||||
if err = args.RegisterEventHandler(func(event string, eventData *plugins.FieldCollection) (err error) {
|
||||
if err = args.RegisterEventHandler(func(event string, eventData *fieldcollection.FieldCollection) (err error) {
|
||||
subscribersLock.RLock()
|
||||
defer subscribersLock.RUnlock()
|
||||
|
||||
|
@ -1,8 +1,10 @@
|
||||
package raffle
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -17,7 +19,7 @@ var ptrStrEmpty = ptrStr("")
|
||||
|
||||
func ptrStr(v string) *string { return &v }
|
||||
|
||||
func (enterRaffleActor) Execute(_ *irc.Client, m *irc.Message, _ *plugins.Rule, evtData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
func (enterRaffleActor) Execute(_ *irc.Client, m *irc.Message, _ *plugins.Rule, evtData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error) {
|
||||
if m != nil || evtData.MustString("reward_id", ptrStrEmpty) == "" {
|
||||
return false, errors.New("enter-raffle actor is only supposed to act on channelpoint redeems")
|
||||
}
|
||||
@ -43,7 +45,7 @@ func (enterRaffleActor) Execute(_ *irc.Client, m *irc.Message, _ *plugins.Rule,
|
||||
EnteredAt: time.Now().UTC(),
|
||||
}
|
||||
|
||||
raffleEventFields := plugins.FieldCollectionFromData(map[string]any{
|
||||
raffleEventFields := fieldcollection.FieldCollectionFromData(map[string]any{
|
||||
"user_id": re.UserID,
|
||||
"user": re.UserLogin,
|
||||
})
|
||||
@ -70,10 +72,11 @@ func (enterRaffleActor) Execute(_ *irc.Client, m *irc.Message, _ *plugins.Rule,
|
||||
func (enterRaffleActor) IsAsync() bool { return false }
|
||||
func (enterRaffleActor) Name() string { return "enter-raffle" }
|
||||
|
||||
func (enterRaffleActor) Validate(_ plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
keyword, err := attrs.String("keyword")
|
||||
if err != nil || keyword == "" {
|
||||
return errors.New("keyword must be non-empty string")
|
||||
func (enterRaffleActor) Validate(_ plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||
if err = attrs.ValidateSchema(
|
||||
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "keyword", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||
); err != nil {
|
||||
return fmt.Errorf("validating attributes: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -9,9 +9,9 @@ import (
|
||||
"gopkg.in/irc.v4"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -374,7 +374,7 @@ func (d *dbClient) PickWinner(raffleID uint64) error {
|
||||
d.speakUp[strings.Join([]string{r.Channel, winner.UserLogin}, ":")] = &speakUpWait{RaffleEntryID: winner.ID, Until: speakUpUntil}
|
||||
d.lock.Unlock()
|
||||
|
||||
fields := plugins.FieldCollectionFromData(map[string]any{
|
||||
fields := fieldcollection.FieldCollectionFromData(map[string]any{
|
||||
"user_id": winner.UserID,
|
||||
"user": winner.UserLogin,
|
||||
"winner": winner,
|
||||
@ -636,9 +636,9 @@ func (d *dbClient) Update(r raffle) error {
|
||||
|
||||
// SendEvent processes the text template and sends the message if
|
||||
// enabled given through the event
|
||||
func (r raffle) SendEvent(evt raffleMessageEvent, fields *plugins.FieldCollection) (err error) {
|
||||
func (r raffle) SendEvent(evt raffleMessageEvent, fields *fieldcollection.FieldCollection) (err error) {
|
||||
if fields == nil {
|
||||
fields = plugins.NewFieldCollection()
|
||||
fields = fieldcollection.NewFieldCollection()
|
||||
}
|
||||
|
||||
fields.Set("raffle", r) // Make raffle available to templating
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
@ -95,7 +96,7 @@ func handleRaffleEntry(m *irc.Message, channel, user string) error {
|
||||
re.UserDisplayName = re.UserLogin
|
||||
}
|
||||
|
||||
raffleEventFields := plugins.FieldCollectionFromData(map[string]any{
|
||||
raffleEventFields := fieldcollection.FieldCollectionFromData(map[string]any{
|
||||
"user_id": m.Tags["user-id"],
|
||||
"user": user,
|
||||
})
|
||||
|
4
internal/helpers/ptr.go
Normal file
4
internal/helpers/ptr.go
Normal file
@ -0,0 +1,4 @@
|
||||
package helpers
|
||||
|
||||
// Ptr creates a pointer to any given type
|
||||
func Ptr[T any](v T) *T { return &v }
|
21
internal/helpers/validateHelper.go
Normal file
21
internal/helpers/validateHelper.go
Normal file
@ -0,0 +1,21 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
)
|
||||
|
||||
// SchemaValidateTemplateField contains a ValidateOpt for the
|
||||
// fieldcollection schema validator to validate template fields
|
||||
func SchemaValidateTemplateField(tplValidator func(string) error, fields ...string) fieldcollection.ValidateOpt {
|
||||
return func(f, _ *fieldcollection.FieldCollection) (err error) {
|
||||
for _, field := range fields {
|
||||
if err = tplValidator(f.MustString(field, Ptr(""))); err != nil {
|
||||
return fmt.Errorf("validating %s: %w", field, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
package userstate
|
||||
|
||||
import (
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
@ -16,7 +17,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||
return errors.Wrap(err, "registering raw message handler")
|
||||
}
|
||||
|
||||
args.RegisterTemplateFunction("botHasBadge", func(m *irc.Message, _ *plugins.Rule, fields *plugins.FieldCollection) interface{} {
|
||||
args.RegisterTemplateFunction("botHasBadge", func(m *irc.Message, _ *plugins.Rule, fields *fieldcollection.FieldCollection) interface{} {
|
||||
return func(badge string) bool {
|
||||
state := userState.Get(plugins.DeriveChannel(m, fields))
|
||||
if state == nil {
|
||||
|
15
irc.go
15
irc.go
@ -13,6 +13,7 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
@ -226,7 +227,7 @@ func (i ircHandler) handleClearChat(m *irc.Message) {
|
||||
|
||||
var (
|
||||
evt *string
|
||||
fields = plugins.NewFieldCollection()
|
||||
fields = fieldcollection.NewFieldCollection()
|
||||
)
|
||||
|
||||
fields.Set(eventFieldChannel, i.getChannel(m)) // Compatibility to plugins.DeriveChannel
|
||||
@ -258,7 +259,7 @@ func (i ircHandler) handleClearChat(m *irc.Message) {
|
||||
}
|
||||
|
||||
func (i ircHandler) handleClearMessage(m *irc.Message) {
|
||||
fields := plugins.FieldCollectionFromData(map[string]interface{}{
|
||||
fields := fieldcollection.FieldCollectionFromData(map[string]interface{}{
|
||||
eventFieldChannel: i.getChannel(m), // Compatibility to plugins.DeriveChannel
|
||||
"message_id": m.Tags["target-msg-id"],
|
||||
"target_name": m.Tags["login"],
|
||||
@ -270,7 +271,7 @@ func (i ircHandler) handleClearMessage(m *irc.Message) {
|
||||
}
|
||||
|
||||
func (i ircHandler) handleJoin(m *irc.Message) {
|
||||
fields := plugins.FieldCollectionFromData(map[string]interface{}{
|
||||
fields := fieldcollection.FieldCollectionFromData(map[string]interface{}{
|
||||
eventFieldChannel: i.getChannel(m), // Compatibility to plugins.DeriveChannel
|
||||
eventFieldUserName: m.User, // Compatibility to plugins.DeriveUser
|
||||
})
|
||||
@ -278,7 +279,7 @@ func (i ircHandler) handleJoin(m *irc.Message) {
|
||||
}
|
||||
|
||||
func (i ircHandler) handlePart(m *irc.Message) {
|
||||
fields := plugins.FieldCollectionFromData(map[string]interface{}{
|
||||
fields := fieldcollection.FieldCollectionFromData(map[string]interface{}{
|
||||
eventFieldChannel: i.getChannel(m), // Compatibility to plugins.DeriveChannel
|
||||
eventFieldUserName: m.User, // Compatibility to plugins.DeriveUser
|
||||
})
|
||||
@ -299,7 +300,7 @@ func (i ircHandler) handlePermit(m *irc.Message) {
|
||||
|
||||
username := msgParts[1]
|
||||
|
||||
fields := plugins.FieldCollectionFromData(map[string]interface{}{
|
||||
fields := fieldcollection.FieldCollectionFromData(map[string]interface{}{
|
||||
eventFieldChannel: i.getChannel(m), // Compatibility to plugins.DeriveChannel
|
||||
eventFieldUserName: m.User, // Compatibility to plugins.DeriveUser
|
||||
eventFieldUserID: m.Tags["user-id"],
|
||||
@ -356,7 +357,7 @@ func (i ircHandler) handleTwitchPrivmsg(m *irc.Message) {
|
||||
}
|
||||
|
||||
if bits := i.tagToNumeric(m, "bits", 0); bits > 0 {
|
||||
fields := plugins.FieldCollectionFromData(map[string]interface{}{
|
||||
fields := fieldcollection.FieldCollectionFromData(map[string]interface{}{
|
||||
"bits": bits,
|
||||
eventFieldChannel: i.getChannel(m), // Compatibility to plugins.DeriveChannel
|
||||
"message": m.Trailing(),
|
||||
@ -380,7 +381,7 @@ func (i ircHandler) handleTwitchUsernotice(m *irc.Message) {
|
||||
"trailing": m.Trailing(),
|
||||
}).Trace("IRC USERNOTICE event")
|
||||
|
||||
evtData := plugins.FieldCollectionFromData(map[string]any{
|
||||
evtData := fieldcollection.FieldCollectionFromData(map[string]any{
|
||||
eventFieldChannel: i.getChannel(m), // Compatibility to plugins.DeriveChannel
|
||||
eventFieldUserName: m.Tags["login"], // Compatibility to plugins.DeriveUser
|
||||
eventFieldUserID: m.Tags["user-id"],
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
@ -19,7 +20,7 @@ var (
|
||||
|
||||
stripNewline = regexp.MustCompile(`(?m)\s*\n\s*`)
|
||||
|
||||
formatMessageFieldSetters = []func(compiledFields *plugins.FieldCollection, m *irc.Message, fields *plugins.FieldCollection){
|
||||
formatMessageFieldSetters = []func(compiledFields *fieldcollection.FieldCollection, m *irc.Message, fields *fieldcollection.FieldCollection){
|
||||
formatMessageFieldChannel,
|
||||
formatMessageFieldMessage,
|
||||
formatMessageFieldUserID,
|
||||
@ -27,8 +28,8 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func formatMessage(tplString string, m *irc.Message, r *plugins.Rule, fields *plugins.FieldCollection) (string, error) {
|
||||
compiledFields := plugins.NewFieldCollection()
|
||||
func formatMessage(tplString string, m *irc.Message, r *plugins.Rule, fields *fieldcollection.FieldCollection) (string, error) {
|
||||
compiledFields := fieldcollection.NewFieldCollection()
|
||||
|
||||
if config != nil {
|
||||
configLock.RLock()
|
||||
@ -61,11 +62,11 @@ func formatMessage(tplString string, m *irc.Message, r *plugins.Rule, fields *pl
|
||||
return strings.TrimSpace(buf.String()), errors.Wrap(err, "execute template")
|
||||
}
|
||||
|
||||
func formatMessageFieldChannel(compiledFields *plugins.FieldCollection, m *irc.Message, fields *plugins.FieldCollection) {
|
||||
func formatMessageFieldChannel(compiledFields *fieldcollection.FieldCollection, m *irc.Message, fields *fieldcollection.FieldCollection) {
|
||||
compiledFields.Set(eventFieldChannel, plugins.DeriveChannel(m, fields))
|
||||
}
|
||||
|
||||
func formatMessageFieldMessage(compiledFields *plugins.FieldCollection, m *irc.Message, _ *plugins.FieldCollection) {
|
||||
func formatMessageFieldMessage(compiledFields *fieldcollection.FieldCollection, m *irc.Message, _ *fieldcollection.FieldCollection) {
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
@ -73,7 +74,7 @@ func formatMessageFieldMessage(compiledFields *plugins.FieldCollection, m *irc.M
|
||||
compiledFields.Set("msg", m)
|
||||
}
|
||||
|
||||
func formatMessageFieldUserID(compiledFields *plugins.FieldCollection, m *irc.Message, _ *plugins.FieldCollection) {
|
||||
func formatMessageFieldUserID(compiledFields *fieldcollection.FieldCollection, m *irc.Message, _ *fieldcollection.FieldCollection) {
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
@ -83,7 +84,7 @@ func formatMessageFieldUserID(compiledFields *plugins.FieldCollection, m *irc.Me
|
||||
}
|
||||
}
|
||||
|
||||
func formatMessageFieldUsername(compiledFields *plugins.FieldCollection, m *irc.Message, fields *plugins.FieldCollection) {
|
||||
func formatMessageFieldUsername(compiledFields *fieldcollection.FieldCollection, m *irc.Message, fields *fieldcollection.FieldCollection) {
|
||||
compiledFields.Set("username", plugins.DeriveUser(m, fields))
|
||||
}
|
||||
|
||||
@ -93,7 +94,7 @@ func validateTemplate(tplString string) error {
|
||||
|
||||
_, err := template.
|
||||
New(tplString).
|
||||
Funcs(tplFuncs.GetFuncMap(nil, nil, plugins.NewFieldCollection())).
|
||||
Funcs(tplFuncs.GetFuncMap(nil, nil, fieldcollection.NewFieldCollection())).
|
||||
Parse(tplString)
|
||||
return errors.Wrap(err, "parsing template")
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package plugins
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@ -16,9 +17,9 @@ type (
|
||||
// (not returning ErrValueNotSet) and does not contain zero value
|
||||
// recognized by reflect (to just check whether the field is set
|
||||
// but allow zero values use HasAll on the FieldCollection)
|
||||
func (ActorKit) ValidateRequireNonEmpty(attrs *FieldCollection, fields ...string) error {
|
||||
func (ActorKit) ValidateRequireNonEmpty(attrs *fieldcollection.FieldCollection, fields ...string) error {
|
||||
for _, field := range fields {
|
||||
v, err := attrs.Any(field)
|
||||
v, err := attrs.Get(field)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "getting field %s", field)
|
||||
}
|
||||
@ -34,7 +35,7 @@ func (ActorKit) ValidateRequireNonEmpty(attrs *FieldCollection, fields ...string
|
||||
// ValidateRequireValidTemplate checks whether fields are gettable
|
||||
// as strings and do have a template which validates (this does not
|
||||
// check for empty strings as an empty template is indeed valid)
|
||||
func (ActorKit) ValidateRequireValidTemplate(tplValidator TemplateValidatorFunc, attrs *FieldCollection, fields ...string) error {
|
||||
func (ActorKit) ValidateRequireValidTemplate(tplValidator TemplateValidatorFunc, attrs *fieldcollection.FieldCollection, fields ...string) error {
|
||||
for _, field := range fields {
|
||||
v, err := attrs.String(field)
|
||||
if err != nil {
|
||||
@ -52,11 +53,11 @@ func (ActorKit) ValidateRequireValidTemplate(tplValidator TemplateValidatorFunc,
|
||||
// ValidateRequireValidTemplateIfSet checks whether the field is
|
||||
// either not set or a valid template (this does not
|
||||
// check for empty strings as an empty template is indeed valid)
|
||||
func (ActorKit) ValidateRequireValidTemplateIfSet(tplValidator TemplateValidatorFunc, attrs *FieldCollection, fields ...string) error {
|
||||
func (ActorKit) ValidateRequireValidTemplateIfSet(tplValidator TemplateValidatorFunc, attrs *fieldcollection.FieldCollection, fields ...string) error {
|
||||
for _, field := range fields {
|
||||
v, err := attrs.String(field)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrValueNotSet) {
|
||||
if errors.Is(err, fieldcollection.ErrValueNotSet) {
|
||||
continue
|
||||
}
|
||||
return errors.Wrapf(err, "getting string field %s", field)
|
||||
|
@ -4,11 +4,12 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestValidateRequireNonEmpty(t *testing.T) {
|
||||
attrs := FieldCollectionFromData(map[string]any{
|
||||
attrs := fieldcollection.FieldCollectionFromData(map[string]any{
|
||||
"str": "",
|
||||
"str_v": "valid",
|
||||
"int": 0,
|
||||
|
@ -1,407 +0,0 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrValueNotSet is used to notify the value is not available in the FieldCollection
|
||||
ErrValueNotSet = errors.New("specified value not found")
|
||||
// ErrValueMismatch is used to notify the value does not match the requested type
|
||||
ErrValueMismatch = errors.New("specified value has different format")
|
||||
)
|
||||
|
||||
// FieldCollection holds an map[string]any with conversion functions attached
|
||||
type FieldCollection struct {
|
||||
data map[string]any
|
||||
lock sync.RWMutex
|
||||
}
|
||||
|
||||
// NewFieldCollection creates a new FieldCollection with empty data store
|
||||
func NewFieldCollection() *FieldCollection {
|
||||
return &FieldCollection{data: make(map[string]any)}
|
||||
}
|
||||
|
||||
// FieldCollectionFromData is a wrapper around NewFieldCollection and SetFromData
|
||||
func FieldCollectionFromData(data map[string]any) *FieldCollection {
|
||||
o := NewFieldCollection()
|
||||
o.SetFromData(data)
|
||||
return o
|
||||
}
|
||||
|
||||
// CanBool tries to read key name as bool and checks whether error is nil
|
||||
func (f *FieldCollection) CanBool(name string) bool {
|
||||
_, err := f.Bool(name)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// CanDuration tries to read key name as time.Duration and checks whether error is nil
|
||||
func (f *FieldCollection) CanDuration(name string) bool {
|
||||
_, err := f.Duration(name)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// CanInt64 tries to read key name as int64 and checks whether error is nil
|
||||
func (f *FieldCollection) CanInt64(name string) bool {
|
||||
_, err := f.Int64(name)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// CanString tries to read key name as string and checks whether error is nil
|
||||
func (f *FieldCollection) CanString(name string) bool {
|
||||
_, err := f.String(name)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// Clone is a wrapper around n.SetFromData(o.Data())
|
||||
func (f *FieldCollection) Clone() *FieldCollection {
|
||||
out := new(FieldCollection)
|
||||
out.SetFromData(f.Data())
|
||||
return out
|
||||
}
|
||||
|
||||
// Data creates a map-copy of the data stored inside the FieldCollection
|
||||
func (f *FieldCollection) Data() map[string]any {
|
||||
if f == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
f.lock.RLock()
|
||||
defer f.lock.RUnlock()
|
||||
|
||||
out := make(map[string]any)
|
||||
for k := range f.data {
|
||||
out[k] = f.data[k]
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// Expect takes a list of keys and returns an error with all non-found names
|
||||
func (f *FieldCollection) Expect(keys ...string) error {
|
||||
if len(keys) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if f == nil || f.data == nil {
|
||||
return errors.New("uninitialized field collection")
|
||||
}
|
||||
|
||||
f.lock.RLock()
|
||||
defer f.lock.RUnlock()
|
||||
|
||||
var missing []string
|
||||
|
||||
for _, k := range keys {
|
||||
if _, ok := f.data[k]; !ok {
|
||||
missing = append(missing, k)
|
||||
}
|
||||
}
|
||||
|
||||
if len(missing) > 0 {
|
||||
return errors.Errorf("missing key(s) %s", strings.Join(missing, ", "))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// HasAll takes a list of keys and returns whether all of them exist inside the FieldCollection
|
||||
func (f *FieldCollection) HasAll(keys ...string) bool {
|
||||
return f.Expect(keys...) == nil
|
||||
}
|
||||
|
||||
// MustBool is a wrapper around Bool and panics if an error was returned
|
||||
func (f *FieldCollection) MustBool(name string, defVal *bool) bool {
|
||||
v, err := f.Bool(name)
|
||||
if err != nil {
|
||||
if defVal != nil {
|
||||
return *defVal
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// MustDuration is a wrapper around Duration and panics if an error was returned
|
||||
func (f *FieldCollection) MustDuration(name string, defVal *time.Duration) time.Duration {
|
||||
v, err := f.Duration(name)
|
||||
if err != nil {
|
||||
if defVal != nil {
|
||||
return *defVal
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// MustInt64 is a wrapper around Int64 and panics if an error was returned
|
||||
func (f *FieldCollection) MustInt64(name string, defVal *int64) int64 {
|
||||
v, err := f.Int64(name)
|
||||
if err != nil {
|
||||
if defVal != nil {
|
||||
return *defVal
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// MustString is a wrapper around String and panics if an error was returned
|
||||
func (f *FieldCollection) MustString(name string, defVal *string) string {
|
||||
v, err := f.String(name)
|
||||
if err != nil {
|
||||
if defVal != nil {
|
||||
return *defVal
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// MustStringSlice is a wrapper around StringSlice and returns nil in case name is not set
|
||||
func (f *FieldCollection) MustStringSlice(name string) []string {
|
||||
v, err := f.StringSlice(name)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Any tries to read key name as any-type (interface)
|
||||
func (f *FieldCollection) Any(name string) (any, error) {
|
||||
if f == nil || f.data == nil {
|
||||
return false, errors.New("uninitialized field collection")
|
||||
}
|
||||
|
||||
f.lock.RLock()
|
||||
defer f.lock.RUnlock()
|
||||
|
||||
v, ok := f.data[name]
|
||||
if !ok {
|
||||
return false, ErrValueNotSet
|
||||
}
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// Bool tries to read key name as bool
|
||||
func (f *FieldCollection) Bool(name string) (bool, error) {
|
||||
if f == nil || f.data == nil {
|
||||
return false, errors.New("uninitialized field collection")
|
||||
}
|
||||
|
||||
f.lock.RLock()
|
||||
defer f.lock.RUnlock()
|
||||
|
||||
v, ok := f.data[name]
|
||||
if !ok {
|
||||
return false, ErrValueNotSet
|
||||
}
|
||||
|
||||
switch v := v.(type) {
|
||||
case bool:
|
||||
return v, nil
|
||||
case string:
|
||||
bv, err := strconv.ParseBool(v)
|
||||
return bv, errors.Wrap(err, "parsing string to bool")
|
||||
}
|
||||
|
||||
return false, ErrValueMismatch
|
||||
}
|
||||
|
||||
// Duration tries to read key name as time.Duration
|
||||
func (f *FieldCollection) Duration(name string) (time.Duration, error) {
|
||||
if f == nil || f.data == nil {
|
||||
return 0, errors.New("uninitialized field collection")
|
||||
}
|
||||
|
||||
f.lock.RLock()
|
||||
defer f.lock.RUnlock()
|
||||
|
||||
v, err := f.String(name)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "getting string value")
|
||||
}
|
||||
|
||||
d, err := time.ParseDuration(v)
|
||||
return d, errors.Wrap(err, "parsing value")
|
||||
}
|
||||
|
||||
// Int64 tries to read key name as int64
|
||||
func (f *FieldCollection) Int64(name string) (int64, error) {
|
||||
if f == nil || f.data == nil {
|
||||
return 0, errors.New("uninitialized field collection")
|
||||
}
|
||||
|
||||
f.lock.RLock()
|
||||
defer f.lock.RUnlock()
|
||||
|
||||
v, ok := f.data[name]
|
||||
if !ok {
|
||||
return 0, ErrValueNotSet
|
||||
}
|
||||
|
||||
switch v := v.(type) {
|
||||
case float64:
|
||||
return int64(v), nil
|
||||
case int:
|
||||
return int64(v), nil
|
||||
case int16:
|
||||
return int64(v), nil
|
||||
case int32:
|
||||
return int64(v), nil
|
||||
case int64:
|
||||
return v, nil
|
||||
}
|
||||
|
||||
return 0, ErrValueMismatch
|
||||
}
|
||||
|
||||
// Set sets a single key to specified value
|
||||
func (f *FieldCollection) Set(key string, value any) {
|
||||
if f == nil {
|
||||
f = NewFieldCollection()
|
||||
}
|
||||
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
if f.data == nil {
|
||||
f.data = make(map[string]any)
|
||||
}
|
||||
|
||||
f.data[key] = value
|
||||
}
|
||||
|
||||
// SetFromData takes a map of data and copies all data into the FieldCollection
|
||||
func (f *FieldCollection) SetFromData(data map[string]any) {
|
||||
if f == nil {
|
||||
f = NewFieldCollection()
|
||||
}
|
||||
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
if f.data == nil {
|
||||
f.data = make(map[string]any)
|
||||
}
|
||||
|
||||
for key, value := range data {
|
||||
f.data[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
// String tries to read key name as string
|
||||
func (f *FieldCollection) String(name string) (string, error) {
|
||||
if f == nil || f.data == nil {
|
||||
return "", errors.New("uninitialized field collection")
|
||||
}
|
||||
|
||||
f.lock.RLock()
|
||||
defer f.lock.RUnlock()
|
||||
|
||||
v, ok := f.data[name]
|
||||
if !ok {
|
||||
return "", ErrValueNotSet
|
||||
}
|
||||
|
||||
if sv, ok := v.(string); ok {
|
||||
return sv, nil
|
||||
}
|
||||
|
||||
if iv, ok := v.(fmt.Stringer); ok {
|
||||
return iv.String(), nil
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%v", v), nil
|
||||
}
|
||||
|
||||
// StringSlice tries to read key name as []string
|
||||
func (f *FieldCollection) StringSlice(name string) ([]string, error) {
|
||||
if f == nil || f.data == nil {
|
||||
return nil, errors.New("uninitialized field collection")
|
||||
}
|
||||
|
||||
f.lock.RLock()
|
||||
defer f.lock.RUnlock()
|
||||
|
||||
v, ok := f.data[name]
|
||||
if !ok {
|
||||
return nil, ErrValueNotSet
|
||||
}
|
||||
|
||||
switch v := v.(type) {
|
||||
case []string:
|
||||
return v, nil
|
||||
|
||||
case []any:
|
||||
var out []string
|
||||
|
||||
for _, iv := range v {
|
||||
sv, ok := iv.(string)
|
||||
if !ok {
|
||||
return nil, errors.New("value in slice was not string")
|
||||
}
|
||||
out = append(out, sv)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
return nil, ErrValueMismatch
|
||||
}
|
||||
|
||||
// Implement JSON marshalling to plain underlying map[string]any
|
||||
|
||||
// MarshalJSON implements the json.Marshaller interface
|
||||
func (f *FieldCollection) MarshalJSON() ([]byte, error) {
|
||||
if f == nil || f.data == nil {
|
||||
return []byte("{}"), nil
|
||||
}
|
||||
|
||||
f.lock.RLock()
|
||||
defer f.lock.RUnlock()
|
||||
|
||||
data, err := json.Marshal(f.data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("marshalling data to json: %w", err)
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the json.Unmarshaller interface
|
||||
func (f *FieldCollection) UnmarshalJSON(raw []byte) error {
|
||||
data := make(map[string]any)
|
||||
if err := json.Unmarshal(raw, &data); err != nil {
|
||||
return errors.Wrap(err, "unmarshalling from JSON")
|
||||
}
|
||||
|
||||
f.SetFromData(data)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Implement YAML marshalling to plain underlying map[string]any
|
||||
|
||||
// MarshalYAML implements the yaml.Marshaller interface
|
||||
func (f *FieldCollection) MarshalYAML() (any, error) {
|
||||
return f.Data(), nil
|
||||
}
|
||||
|
||||
// UnmarshalYAML implements the yaml.Unmarshaller interface
|
||||
func (f *FieldCollection) UnmarshalYAML(unmarshal func(any) error) error {
|
||||
data := make(map[string]any)
|
||||
if err := unmarshal(&data); err != nil {
|
||||
return errors.Wrap(err, "unmarshalling from YAML")
|
||||
}
|
||||
|
||||
f.SetFromData(data)
|
||||
return nil
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func TestFieldCollectionJSONMarshal(t *testing.T) {
|
||||
var (
|
||||
buf = new(bytes.Buffer)
|
||||
raw = `{"key1":"test1","key2":"test2"}`
|
||||
f = NewFieldCollection()
|
||||
)
|
||||
|
||||
if err := json.NewDecoder(strings.NewReader(raw)).Decode(f); err != nil {
|
||||
t.Fatalf("Unable to unmarshal: %s", err)
|
||||
}
|
||||
|
||||
if err := json.NewEncoder(buf).Encode(f); err != nil {
|
||||
t.Fatalf("Unable to marshal: %s", err)
|
||||
}
|
||||
|
||||
if raw != strings.TrimSpace(buf.String()) {
|
||||
t.Errorf("Marshalled JSON does not match expectation: res=%s exp=%s", buf.String(), raw)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFieldCollectionYAMLMarshal(t *testing.T) {
|
||||
var (
|
||||
buf = new(bytes.Buffer)
|
||||
raw = "key1: test1\nkey2: test2"
|
||||
f = NewFieldCollection()
|
||||
)
|
||||
|
||||
if err := yaml.NewDecoder(strings.NewReader(raw)).Decode(f); err != nil {
|
||||
t.Fatalf("Unable to unmarshal: %s", err)
|
||||
}
|
||||
|
||||
if err := yaml.NewEncoder(buf).Encode(f); err != nil {
|
||||
t.Fatalf("Unable to marshal: %s", err)
|
||||
}
|
||||
|
||||
if raw != strings.TrimSpace(buf.String()) {
|
||||
t.Errorf("Marshalled YAML does not match expectation: res=%s exp=%s", buf.String(), raw)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFieldCollectionNilModify(_ *testing.T) {
|
||||
var f *FieldCollection
|
||||
|
||||
f.Set("foo", "bar")
|
||||
|
||||
f = nil
|
||||
f.SetFromData(map[string]interface{}{"foo": "bar"})
|
||||
}
|
||||
|
||||
func TestFieldCollectionNilClone(_ *testing.T) {
|
||||
var f *FieldCollection
|
||||
|
||||
f.Clone()
|
||||
}
|
||||
|
||||
func TestFieldCollectionNilDataGet(t *testing.T) {
|
||||
var f *FieldCollection
|
||||
|
||||
for name, fn := range map[string]func(name string) bool{
|
||||
"bool": f.CanBool,
|
||||
"duration": f.CanDuration,
|
||||
"int64": f.CanInt64,
|
||||
"string": f.CanString,
|
||||
} {
|
||||
if fn("foo") {
|
||||
t.Errorf("%s key is available", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFieldCollectionIntToString(t *testing.T) {
|
||||
val := 123
|
||||
fc := FieldCollectionFromData(map[string]interface{}{"test": val})
|
||||
|
||||
if !fc.CanString("test") {
|
||||
t.Fatalf("cannot convert %T to string", val)
|
||||
}
|
||||
|
||||
if v := fc.MustString("test", nil); v != "123" {
|
||||
t.Errorf("unexpected value: 123 != %s", v)
|
||||
}
|
||||
}
|
@ -4,12 +4,13 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"gopkg.in/irc.v4"
|
||||
)
|
||||
|
||||
// DeriveChannel takes an irc.Message and a FieldCollection and tries
|
||||
// to extract from them the channel the event / message has taken place
|
||||
func DeriveChannel(m *irc.Message, evtData *FieldCollection) string {
|
||||
func DeriveChannel(m *irc.Message, evtData *fieldcollection.FieldCollection) string {
|
||||
if m != nil && len(m.Params) > 0 && strings.HasPrefix(m.Params[0], "#") {
|
||||
return m.Params[0]
|
||||
}
|
||||
@ -23,7 +24,7 @@ func DeriveChannel(m *irc.Message, evtData *FieldCollection) string {
|
||||
|
||||
// DeriveUser takes an irc.Message and a FieldCollection and tries
|
||||
// to extract from them the user causing the event / message
|
||||
func DeriveUser(m *irc.Message, evtData *FieldCollection) string {
|
||||
func DeriveUser(m *irc.Message, evtData *fieldcollection.FieldCollection) string {
|
||||
if m != nil && m.User != "" {
|
||||
return m.User
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"gopkg.in/irc.v4"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
)
|
||||
@ -15,7 +16,7 @@ type (
|
||||
// Actor defines an interface to implement in the plugin for actors
|
||||
Actor interface {
|
||||
// Execute will be called after the config was read into the Actor
|
||||
Execute(c *irc.Client, m *irc.Message, r *Rule, evtData *FieldCollection, attrs *FieldCollection) (preventCooldown bool, err error)
|
||||
Execute(c *irc.Client, m *irc.Message, r *Rule, evtData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (preventCooldown bool, err error)
|
||||
// IsAsync may return true if the Execute function is to be executed
|
||||
// in a Go routine as of long runtime. Normally it should return false
|
||||
// except in very specific cases
|
||||
@ -26,7 +27,7 @@ type (
|
||||
// Validate will be called to validate the loaded configuration. It should
|
||||
// return an error if required keys are missing from the AttributeStore
|
||||
// or if keys contain broken configs
|
||||
Validate(TemplateValidatorFunc, *FieldCollection) error
|
||||
Validate(TemplateValidatorFunc, *fieldcollection.FieldCollection) error
|
||||
}
|
||||
|
||||
// ActorCreationFunc is a function to return a new instance of the
|
||||
@ -62,7 +63,7 @@ type (
|
||||
|
||||
// EventHandlerFunc defines the type of function required to listen
|
||||
// for events
|
||||
EventHandlerFunc func(evt string, eventData *FieldCollection) error
|
||||
EventHandlerFunc func(evt string, eventData *fieldcollection.FieldCollection) error
|
||||
// EventHandlerRegisterFunc is passed from the bot to the
|
||||
// plugins RegisterFunc to register a new event handler function
|
||||
// which is then fed with all events occurring in the bot
|
||||
@ -76,12 +77,12 @@ type (
|
||||
// ModuleConfigGetterFunc is passed from the bot to the
|
||||
// plugins RegisterFunc to fetch module generic or channel specific
|
||||
// configuration from the module configuration
|
||||
ModuleConfigGetterFunc func(module, channel string) *FieldCollection
|
||||
ModuleConfigGetterFunc func(module, channel string) *fieldcollection.FieldCollection
|
||||
|
||||
// MsgFormatter is passed from the bot to the
|
||||
// plugins RegisterFunc to format messages using all registered and
|
||||
// available template functions
|
||||
MsgFormatter func(tplString string, m *irc.Message, r *Rule, fields *FieldCollection) (string, error)
|
||||
MsgFormatter func(tplString string, m *irc.Message, r *Rule, fields *fieldcollection.FieldCollection) (string, error)
|
||||
|
||||
// MsgModificationFunc can be used to modify messages between the
|
||||
// plugins generating them and the bot sending them to the Twitch
|
||||
@ -160,7 +161,7 @@ type (
|
||||
|
||||
// TemplateFuncGetter is the type of function to implement in the
|
||||
// plugin to create a new template function on request of the bot
|
||||
TemplateFuncGetter func(*irc.Message, *Rule, *FieldCollection) any
|
||||
TemplateFuncGetter func(*irc.Message, *Rule, *fieldcollection.FieldCollection) any
|
||||
// TemplateFuncRegister is passed from the bot to the
|
||||
// plugins RegisterFunc to register a new TemplateFuncGetter
|
||||
TemplateFuncRegister func(name string, fg TemplateFuncGetter, doc ...TemplateFuncDocumentation)
|
||||
@ -184,5 +185,5 @@ var ErrSkipSendingMessage = errors.New("skip sending message")
|
||||
// requiring access to the irc.Message, Rule or FieldCollection to
|
||||
// satisfy the TemplateFuncGetter interface
|
||||
func GenericTemplateFunctionGetter(f any) TemplateFuncGetter {
|
||||
return func(*irc.Message, *Rule, *FieldCollection) any { return f }
|
||||
return func(*irc.Message, *Rule, *fieldcollection.FieldCollection) any { return f }
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
package plugins
|
||||
|
||||
import "strings"
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
)
|
||||
|
||||
// DefaultConfigName is the name the default configuration must have
|
||||
// when defined
|
||||
@ -9,16 +13,16 @@ const DefaultConfigName = "default"
|
||||
type (
|
||||
// ModuleConfig represents a mapping of configurations per channel
|
||||
// and module
|
||||
ModuleConfig map[string]map[string]*FieldCollection
|
||||
ModuleConfig map[string]map[string]*fieldcollection.FieldCollection
|
||||
)
|
||||
|
||||
// GetChannelConfig reads the channel specific configuration for the
|
||||
// given module. This is created by taking an empty FieldCollection,
|
||||
// merging in the default configuration and finally overwriting all
|
||||
// existing channel configurations.
|
||||
func (m ModuleConfig) GetChannelConfig(module, channel string) *FieldCollection {
|
||||
func (m ModuleConfig) GetChannelConfig(module, channel string) *fieldcollection.FieldCollection {
|
||||
channel = strings.TrimLeft(channel, "#@")
|
||||
composed := NewFieldCollection()
|
||||
composed := fieldcollection.NewFieldCollection()
|
||||
|
||||
for _, i := range []string{DefaultConfigName, channel} {
|
||||
f := m[module][i]
|
||||
|
@ -3,6 +3,7 @@ package plugins
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@ -10,12 +11,12 @@ import (
|
||||
func TestModuleConfigGet(t *testing.T) {
|
||||
strPtrEmpty := func(v string) *string { return &v }("")
|
||||
m := ModuleConfig{
|
||||
"test": map[string]*FieldCollection{
|
||||
DefaultConfigName: FieldCollectionFromData(map[string]any{
|
||||
"test": map[string]*fieldcollection.FieldCollection{
|
||||
DefaultConfigName: fieldcollection.FieldCollectionFromData(map[string]any{
|
||||
"setindefault": DefaultConfigName,
|
||||
"setinboth": DefaultConfigName,
|
||||
}),
|
||||
"test": FieldCollectionFromData(map[string]any{
|
||||
"test": fieldcollection.FieldCollectionFromData(map[string]any{
|
||||
"setinchannel": "channel",
|
||||
"setinboth": "channel",
|
||||
}),
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
"gopkg.in/irc.v4"
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/go_helpers/v2/str"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
)
|
||||
@ -73,8 +74,8 @@ type (
|
||||
|
||||
// RuleAction represents an action to be executed when running a Rule
|
||||
RuleAction struct {
|
||||
Type string `json:"type" yaml:"type,omitempty"`
|
||||
Attributes *FieldCollection `json:"attributes" yaml:"attributes,omitempty"`
|
||||
Type string `json:"type" yaml:"type,omitempty"`
|
||||
Attributes *fieldcollection.FieldCollection `json:"attributes" yaml:"attributes,omitempty"`
|
||||
}
|
||||
)
|
||||
|
||||
@ -89,7 +90,7 @@ func (r Rule) MatcherID() string {
|
||||
}
|
||||
|
||||
// Matches checks whether the Rule should be executed for the given parameters
|
||||
func (r *Rule) Matches(m *irc.Message, event *string, timerStore TimerStore, msgFormatter MsgFormatter, twitchClient *twitch.Client, eventData *FieldCollection) bool {
|
||||
func (r *Rule) Matches(m *irc.Message, event *string, timerStore TimerStore, msgFormatter MsgFormatter, twitchClient *twitch.Client, eventData *fieldcollection.FieldCollection) bool {
|
||||
r.msgFormatter = msgFormatter
|
||||
r.timerStore = timerStore
|
||||
r.twitchClient = twitchClient
|
||||
@ -102,7 +103,7 @@ func (r *Rule) Matches(m *irc.Message, event *string, timerStore TimerStore, msg
|
||||
})
|
||||
)
|
||||
|
||||
for _, matcher := range []func(*logrus.Entry, *irc.Message, *string, twitch.BadgeCollection, *FieldCollection) bool{
|
||||
for _, matcher := range []func(*logrus.Entry, *irc.Message, *string, twitch.BadgeCollection, *fieldcollection.FieldCollection) bool{
|
||||
r.allowExecuteDisable,
|
||||
r.allowExecuteChannelWhitelist,
|
||||
r.allowExecuteUserWhitelist,
|
||||
@ -144,7 +145,7 @@ func (r *Rule) GetMatchMessage() *regexp.Regexp {
|
||||
|
||||
// SetCooldown uses the given TimerStore to set the cooldowns for the
|
||||
// Rule after execution
|
||||
func (r *Rule) SetCooldown(timerStore TimerStore, m *irc.Message, evtData *FieldCollection) {
|
||||
func (r *Rule) SetCooldown(timerStore TimerStore, m *irc.Message, evtData *fieldcollection.FieldCollection) {
|
||||
var err error
|
||||
|
||||
if r.Cooldown != nil {
|
||||
@ -250,7 +251,7 @@ func (r Rule) Validate(tplValidate TemplateValidatorFunc) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Rule) allowExecuteBadgeBlacklist(logger *logrus.Entry, _ *irc.Message, _ *string, badges twitch.BadgeCollection, _ *FieldCollection) bool {
|
||||
func (r *Rule) allowExecuteBadgeBlacklist(logger *logrus.Entry, _ *irc.Message, _ *string, badges twitch.BadgeCollection, _ *fieldcollection.FieldCollection) bool {
|
||||
for _, b := range r.DisableOn {
|
||||
if badges.Has(b) {
|
||||
logger.Tracef("Non-Match: Disable-Badge %s", b)
|
||||
@ -261,7 +262,7 @@ func (r *Rule) allowExecuteBadgeBlacklist(logger *logrus.Entry, _ *irc.Message,
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *Rule) allowExecuteBadgeWhitelist(_ *logrus.Entry, _ *irc.Message, _ *string, badges twitch.BadgeCollection, _ *FieldCollection) bool {
|
||||
func (r *Rule) allowExecuteBadgeWhitelist(_ *logrus.Entry, _ *irc.Message, _ *string, badges twitch.BadgeCollection, _ *fieldcollection.FieldCollection) bool {
|
||||
if len(r.EnableOn) == 0 {
|
||||
// No match criteria set, does not speak against matching
|
||||
return true
|
||||
@ -276,7 +277,7 @@ func (r *Rule) allowExecuteBadgeWhitelist(_ *logrus.Entry, _ *irc.Message, _ *st
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *Rule) allowExecuteChannelCooldown(logger *logrus.Entry, m *irc.Message, _ *string, badges twitch.BadgeCollection, evtData *FieldCollection) bool {
|
||||
func (r *Rule) allowExecuteChannelCooldown(logger *logrus.Entry, m *irc.Message, _ *string, badges twitch.BadgeCollection, evtData *fieldcollection.FieldCollection) bool {
|
||||
if r.ChannelCooldown == nil || DeriveChannel(m, evtData) == "" {
|
||||
// No match criteria set, does not speak against matching
|
||||
return true
|
||||
@ -301,7 +302,7 @@ func (r *Rule) allowExecuteChannelCooldown(logger *logrus.Entry, m *irc.Message,
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *Rule) allowExecuteChannelWhitelist(logger *logrus.Entry, m *irc.Message, _ *string, _ twitch.BadgeCollection, evtData *FieldCollection) bool {
|
||||
func (r *Rule) allowExecuteChannelWhitelist(logger *logrus.Entry, m *irc.Message, _ *string, _ twitch.BadgeCollection, evtData *fieldcollection.FieldCollection) bool {
|
||||
if len(r.MatchChannels) == 0 {
|
||||
// No match criteria set, does not speak against matching
|
||||
return true
|
||||
@ -315,7 +316,7 @@ func (r *Rule) allowExecuteChannelWhitelist(logger *logrus.Entry, m *irc.Message
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *Rule) allowExecuteDisable(logger *logrus.Entry, _ *irc.Message, _ *string, _ twitch.BadgeCollection, _ *FieldCollection) bool {
|
||||
func (r *Rule) allowExecuteDisable(logger *logrus.Entry, _ *irc.Message, _ *string, _ twitch.BadgeCollection, _ *fieldcollection.FieldCollection) bool {
|
||||
if r.Disable == nil {
|
||||
// No match criteria set, does not speak against matching
|
||||
return true
|
||||
@ -329,7 +330,7 @@ func (r *Rule) allowExecuteDisable(logger *logrus.Entry, _ *irc.Message, _ *stri
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *Rule) allowExecuteDisableOnOffline(logger *logrus.Entry, m *irc.Message, _ *string, _ twitch.BadgeCollection, evtData *FieldCollection) bool {
|
||||
func (r *Rule) allowExecuteDisableOnOffline(logger *logrus.Entry, m *irc.Message, _ *string, _ twitch.BadgeCollection, evtData *fieldcollection.FieldCollection) bool {
|
||||
if r.DisableOnOffline == nil || !*r.DisableOnOffline || DeriveChannel(m, evtData) == "" {
|
||||
// No match criteria set, does not speak against matching
|
||||
return true
|
||||
@ -348,7 +349,7 @@ func (r *Rule) allowExecuteDisableOnOffline(logger *logrus.Entry, m *irc.Message
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *Rule) allowExecuteDisableOnPermit(logger *logrus.Entry, m *irc.Message, _ *string, _ twitch.BadgeCollection, evtData *FieldCollection) bool {
|
||||
func (r *Rule) allowExecuteDisableOnPermit(logger *logrus.Entry, m *irc.Message, _ *string, _ twitch.BadgeCollection, evtData *fieldcollection.FieldCollection) bool {
|
||||
hasPermit, err := r.timerStore.HasPermit(DeriveChannel(m, evtData), DeriveUser(m, evtData))
|
||||
if err != nil {
|
||||
logger.WithError(err).Error("checking permit")
|
||||
@ -363,7 +364,7 @@ func (r *Rule) allowExecuteDisableOnPermit(logger *logrus.Entry, m *irc.Message,
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *Rule) allowExecuteDisableOnTemplate(logger *logrus.Entry, m *irc.Message, _ *string, _ twitch.BadgeCollection, evtData *FieldCollection) bool {
|
||||
func (r *Rule) allowExecuteDisableOnTemplate(logger *logrus.Entry, m *irc.Message, _ *string, _ twitch.BadgeCollection, evtData *fieldcollection.FieldCollection) bool {
|
||||
if r.DisableOnTemplate == nil || *r.DisableOnTemplate == "" {
|
||||
// No match criteria set, does not speak against matching
|
||||
return true
|
||||
@ -384,7 +385,7 @@ func (r *Rule) allowExecuteDisableOnTemplate(logger *logrus.Entry, m *irc.Messag
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *Rule) allowExecuteEventMatch(logger *logrus.Entry, _ *irc.Message, event *string, _ twitch.BadgeCollection, _ *FieldCollection) bool {
|
||||
func (r *Rule) allowExecuteEventMatch(logger *logrus.Entry, _ *irc.Message, event *string, _ twitch.BadgeCollection, _ *fieldcollection.FieldCollection) bool {
|
||||
// The user defines either no event to match or they define an
|
||||
// event to match. We now need to ensure this match is valid for
|
||||
// the current execution:
|
||||
@ -430,7 +431,7 @@ func (r *Rule) allowExecuteEventMatch(logger *logrus.Entry, _ *irc.Message, even
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *Rule) allowExecuteMessageMatcherBlacklist(logger *logrus.Entry, m *irc.Message, _ *string, _ twitch.BadgeCollection, _ *FieldCollection) bool {
|
||||
func (r *Rule) allowExecuteMessageMatcherBlacklist(logger *logrus.Entry, m *irc.Message, _ *string, _ twitch.BadgeCollection, _ *fieldcollection.FieldCollection) bool {
|
||||
if len(r.DisableOnMatchMessages) == 0 {
|
||||
// No match criteria set, does not speak against matching
|
||||
return true
|
||||
@ -459,7 +460,7 @@ func (r *Rule) allowExecuteMessageMatcherBlacklist(logger *logrus.Entry, m *irc.
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *Rule) allowExecuteMessageMatcherWhitelist(logger *logrus.Entry, m *irc.Message, _ *string, _ twitch.BadgeCollection, _ *FieldCollection) bool {
|
||||
func (r *Rule) allowExecuteMessageMatcherWhitelist(logger *logrus.Entry, m *irc.Message, _ *string, _ twitch.BadgeCollection, _ *fieldcollection.FieldCollection) bool {
|
||||
if r.MatchMessage == nil {
|
||||
// No match criteria set, does not speak against matching
|
||||
return true
|
||||
@ -484,7 +485,7 @@ func (r *Rule) allowExecuteMessageMatcherWhitelist(logger *logrus.Entry, m *irc.
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *Rule) allowExecuteRuleCooldown(logger *logrus.Entry, _ *irc.Message, _ *string, badges twitch.BadgeCollection, _ *FieldCollection) bool {
|
||||
func (r *Rule) allowExecuteRuleCooldown(logger *logrus.Entry, _ *irc.Message, _ *string, badges twitch.BadgeCollection, _ *fieldcollection.FieldCollection) bool {
|
||||
if r.Cooldown == nil {
|
||||
// No match criteria set, does not speak against matching
|
||||
return true
|
||||
@ -509,7 +510,7 @@ func (r *Rule) allowExecuteRuleCooldown(logger *logrus.Entry, _ *irc.Message, _
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *Rule) allowExecuteUserCooldown(logger *logrus.Entry, m *irc.Message, _ *string, badges twitch.BadgeCollection, evtData *FieldCollection) bool {
|
||||
func (r *Rule) allowExecuteUserCooldown(logger *logrus.Entry, m *irc.Message, _ *string, badges twitch.BadgeCollection, evtData *fieldcollection.FieldCollection) bool {
|
||||
if r.UserCooldown == nil {
|
||||
// No match criteria set, does not speak against matching
|
||||
return true
|
||||
@ -534,7 +535,7 @@ func (r *Rule) allowExecuteUserCooldown(logger *logrus.Entry, m *irc.Message, _
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *Rule) allowExecuteUserWhitelist(logger *logrus.Entry, m *irc.Message, _ *string, _ twitch.BadgeCollection, evtData *FieldCollection) bool {
|
||||
func (r *Rule) allowExecuteUserWhitelist(logger *logrus.Entry, m *irc.Message, _ *string, _ twitch.BadgeCollection, evtData *fieldcollection.FieldCollection) bool {
|
||||
if len(r.MatchUsers) == 0 {
|
||||
// No match criteria set, does not speak against matching
|
||||
return true
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
)
|
||||
|
||||
@ -141,7 +142,7 @@ func TestAllowExecuteDisableOnTemplate(t *testing.T) {
|
||||
} {
|
||||
// We don't test the message formatter here but only the disable functionality
|
||||
// so we fake the result of the evaluation
|
||||
r.msgFormatter = func(string, *irc.Message, *Rule, *FieldCollection) (string, error) {
|
||||
r.msgFormatter = func(string, *irc.Message, *Rule, *fieldcollection.FieldCollection) (string, error) {
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/backoff"
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/go_helpers/v2/str"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/actors/announce"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/actors/ban"
|
||||
@ -181,12 +182,12 @@ func getRegistrationArguments() plugins.RegistrationArguments {
|
||||
SendMessage: sendMessage,
|
||||
ValidateToken: authService.ValidateTokenFor,
|
||||
|
||||
CreateEvent: func(evt string, eventData *plugins.FieldCollection) error {
|
||||
CreateEvent: func(evt string, eventData *fieldcollection.FieldCollection) error {
|
||||
handleMessage(ircHdl.Client(), nil, &evt, eventData)
|
||||
return nil
|
||||
},
|
||||
|
||||
GetModuleConfigForChannel: func(module, channel string) *plugins.FieldCollection {
|
||||
GetModuleConfigForChannel: func(module, channel string) *fieldcollection.FieldCollection {
|
||||
return config.ModuleConfig.GetChannelConfig(module, channel)
|
||||
},
|
||||
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
@ -88,7 +89,7 @@ func generateTplDocsRender(e *plugins.TemplateFuncDocumentationExample) (string,
|
||||
rule.MatchMessage = &e.MatchMessage
|
||||
}
|
||||
|
||||
return formatMessage(e.Template, msg, rule, plugins.FieldCollectionFromData(map[string]any{
|
||||
return formatMessage(e.Template, msg, rule, fieldcollection.FieldCollectionFromData(map[string]any{
|
||||
"testDuration": 5*time.Hour + 33*time.Minute + 12*time.Second,
|
||||
}))
|
||||
}
|
||||
|
@ -8,10 +8,10 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/service/access"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
type (
|
||||
@ -241,7 +241,7 @@ func (*twitchWatcher) handleEventSubChannelAdBreakBegin(m json.RawMessage) error
|
||||
return errors.Wrap(err, "unmarshalling event")
|
||||
}
|
||||
|
||||
fields := plugins.FieldCollectionFromData(map[string]any{
|
||||
fields := fieldcollection.FieldCollectionFromData(map[string]any{
|
||||
"channel": "#" + payload.BroadcasterUserLogin,
|
||||
"duration": payload.Duration,
|
||||
"is_automatic": payload.IsAutomatic,
|
||||
@ -260,7 +260,7 @@ func (*twitchWatcher) handleEventSubChannelFollow(m json.RawMessage) error {
|
||||
return errors.Wrap(err, "unmarshalling event")
|
||||
}
|
||||
|
||||
fields := plugins.FieldCollectionFromData(map[string]interface{}{
|
||||
fields := fieldcollection.FieldCollectionFromData(map[string]interface{}{
|
||||
"channel": "#" + payload.BroadcasterUserLogin,
|
||||
"followed_at": payload.FollowedAt,
|
||||
"user_id": payload.UserID,
|
||||
@ -279,7 +279,7 @@ func (*twitchWatcher) handleEventSubChannelPointCustomRewardRedemptionAdd(m json
|
||||
return errors.Wrap(err, "unmarshalling event")
|
||||
}
|
||||
|
||||
fields := plugins.FieldCollectionFromData(map[string]interface{}{
|
||||
fields := fieldcollection.FieldCollectionFromData(map[string]interface{}{
|
||||
"channel": "#" + payload.BroadcasterUserLogin,
|
||||
"reward_cost": payload.Reward.Cost,
|
||||
"reward_id": payload.Reward.ID,
|
||||
@ -302,7 +302,7 @@ func (*twitchWatcher) handleEventSubChannelOutboundRaid(m json.RawMessage) error
|
||||
return errors.Wrap(err, "unmarshalling event")
|
||||
}
|
||||
|
||||
fields := plugins.FieldCollectionFromData(map[string]interface{}{
|
||||
fields := fieldcollection.FieldCollectionFromData(map[string]interface{}{
|
||||
"channel": "#" + payload.FromBroadcasterUserLogin,
|
||||
"to_id": payload.ToBroadcasterUserID,
|
||||
"to": payload.ToBroadcasterUserLogin,
|
||||
@ -333,7 +333,7 @@ func (*twitchWatcher) handleEventSubChannelPollChange(event *string) func(json.R
|
||||
return errors.Wrap(err, "unmarshalling event")
|
||||
}
|
||||
|
||||
fields := plugins.FieldCollectionFromData(map[string]any{
|
||||
fields := fieldcollection.FieldCollectionFromData(map[string]any{
|
||||
"channel": "#" + payload.BroadcasterUserLogin,
|
||||
"hasChannelPointVoting": payload.ChannelPointsVoting.IsEnabled,
|
||||
"title": payload.Title,
|
||||
@ -370,7 +370,7 @@ func (*twitchWatcher) handleEventSubHypetrainEvent(eventType *string) func(json.
|
||||
return errors.Wrap(err, "unmarshalling event")
|
||||
}
|
||||
|
||||
fields := plugins.FieldCollectionFromData(map[string]any{
|
||||
fields := fieldcollection.FieldCollectionFromData(map[string]any{
|
||||
"channel": "#" + payload.BroadcasterUserLogin,
|
||||
"level": payload.Level,
|
||||
})
|
||||
@ -394,7 +394,7 @@ func (*twitchWatcher) handleEventSubShoutoutCreated(m json.RawMessage) error {
|
||||
return errors.Wrap(err, "unmarshalling event")
|
||||
}
|
||||
|
||||
fields := plugins.FieldCollectionFromData(map[string]any{
|
||||
fields := fieldcollection.FieldCollectionFromData(map[string]any{
|
||||
"channel": "#" + payload.BroadcasterUserLogin,
|
||||
"to_id": payload.ToBroadcasterUserID,
|
||||
"to": payload.ToBroadcasterUserLogin,
|
||||
@ -413,7 +413,7 @@ func (*twitchWatcher) handleEventSubShoutoutReceived(m json.RawMessage) error {
|
||||
return errors.Wrap(err, "unmarshalling event")
|
||||
}
|
||||
|
||||
fields := plugins.FieldCollectionFromData(map[string]any{
|
||||
fields := fieldcollection.FieldCollectionFromData(map[string]any{
|
||||
"channel": "#" + payload.BroadcasterUserLogin,
|
||||
"from_id": payload.FromBroadcasterUserID,
|
||||
"from": payload.FromBroadcasterUserLogin,
|
||||
@ -570,7 +570,7 @@ func (t *twitchWatcher) triggerUpdate(channel string, title, category *string, o
|
||||
"channel": channel,
|
||||
"category": *category,
|
||||
}).Info("Category updated")
|
||||
go handleMessage(ircHdl.Client(), nil, eventTypeTwitchCategoryUpdate, plugins.FieldCollectionFromData(map[string]interface{}{
|
||||
go handleMessage(ircHdl.Client(), nil, eventTypeTwitchCategoryUpdate, fieldcollection.FieldCollectionFromData(map[string]interface{}{
|
||||
"channel": "#" + channel,
|
||||
"category": *category,
|
||||
}))
|
||||
@ -582,7 +582,7 @@ func (t *twitchWatcher) triggerUpdate(channel string, title, category *string, o
|
||||
"channel": channel,
|
||||
"title": *title,
|
||||
}).Info("Title updated")
|
||||
go handleMessage(ircHdl.Client(), nil, eventTypeTwitchTitleUpdate, plugins.FieldCollectionFromData(map[string]interface{}{
|
||||
go handleMessage(ircHdl.Client(), nil, eventTypeTwitchTitleUpdate, fieldcollection.FieldCollectionFromData(map[string]interface{}{
|
||||
"channel": "#" + channel,
|
||||
"title": *title,
|
||||
}))
|
||||
@ -600,7 +600,7 @@ func (t *twitchWatcher) triggerUpdate(channel string, title, category *string, o
|
||||
evt = eventTypeTwitchStreamOffline
|
||||
}
|
||||
|
||||
go handleMessage(ircHdl.Client(), nil, evt, plugins.FieldCollectionFromData(map[string]interface{}{
|
||||
go handleMessage(ircHdl.Client(), nil, evt, fieldcollection.FieldCollectionFromData(map[string]interface{}{
|
||||
"channel": "#" + channel,
|
||||
}))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user