[core] Switch to go_helpers FieldCollection
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
262742603c
commit
30482591a7
65 changed files with 548 additions and 974 deletions
action_script.goactions.goautomessage.goconfig.goevents.gofunctions.gofunctions_irc.gogo.modgo.sumirc.gomsgformatter.go
internal
actors
ban
clip
clipdetector
commercial
counter
delay
delete
eventmod
filesay
linkdetector
linkprotect
log
messagehook
modchannel
nuke
punish
quotedb
raw
respond
shield
shoutout
stopexec
timeout
variables
vip
whisper
apimodules
customevent
kofi
overlays
raffle
helpers
template/userstate
plugins
actorkit.goactorkit_test.gofieldcollection.gofieldcollection_test.gohelpers.gointerface.gomoduleConfig.gomoduleConfig_test.gorule.gorule_test.go
plugins_core.gotplDocs.gotwitchWatcher.go
|
@ -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…
Add table
Reference in a new issue