mirror of
https://github.com/Luzifer/twitch-bot.git
synced 2025-01-01 17:31:16 +00:00
[core] Switch to go_helpers FieldCollection
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
262742603c
commit
30482591a7
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"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"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/pkg/twitch"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
@ -49,7 +50,7 @@ func init() {
|
||||||
type ActorScript struct{}
|
type ActorScript struct{}
|
||||||
|
|
||||||
// Execute implements actor interface
|
// 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")
|
command, err := attrs.StringSlice("command")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "getting command")
|
return false, errors.Wrap(err, "getting command")
|
||||||
|
@ -130,7 +131,7 @@ func (ActorScript) IsAsync() bool { return false }
|
||||||
func (ActorScript) Name() string { return "script" }
|
func (ActorScript) Name() string { return "script" }
|
||||||
|
|
||||||
// Validate implements actor interface
|
// 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")
|
cmd, err := attrs.StringSlice("command")
|
||||||
if err != nil || len(cmd) == 0 {
|
if err != nil || len(cmd) == 0 {
|
||||||
return errors.New("command must be slice of strings with length > 0")
|
return errors.New("command must be slice of strings with length > 0")
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"gopkg.in/irc.v4"
|
"gopkg.in/irc.v4"
|
||||||
|
|
||||||
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ func registerAction(name string, acf plugins.ActorCreationFunc) {
|
||||||
availableActions[name] = acf
|
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()
|
availableActionsLock.RLock()
|
||||||
defer availableActionsLock.RUnlock()
|
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")
|
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
|
// Send events to registered handlers
|
||||||
if event != nil {
|
if event != nil {
|
||||||
go notifyEventHandlers(*event, eventData)
|
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 (
|
var (
|
||||||
ruleEventData = plugins.NewFieldCollection()
|
ruleEventData = fieldcollection.NewFieldCollection()
|
||||||
preventCooldown bool
|
preventCooldown bool
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,8 @@ import (
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"gopkg.in/irc.v4"
|
"gopkg.in/irc.v4"
|
||||||
|
|
||||||
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||||
"github.com/Luzifer/go_helpers/v2/str"
|
"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)
|
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
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fields := plugins.NewFieldCollection()
|
fields := fieldcollection.NewFieldCollection()
|
||||||
fields.Set("channel", a.Channel)
|
fields.Set("channel", a.Channel)
|
||||||
|
|
||||||
res, err := formatMessage(*a.DisableOnTemplate, nil, nil, fields)
|
res, err := formatMessage(*a.DisableOnTemplate, nil, nil, fields)
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"gopkg.in/irc.v4"
|
"gopkg.in/irc.v4"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||||
"github.com/Luzifer/go_helpers/v2/str"
|
"github.com/Luzifer/go_helpers/v2/str"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
@ -303,7 +304,7 @@ func (c *configFile) CloseRawMessageWriter() (err error) {
|
||||||
return nil
|
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()
|
configLock.RLock()
|
||||||
defer configLock.RUnlock()
|
defer configLock.RUnlock()
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"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()
|
registeredEventHandlersLock.Lock()
|
||||||
defer registeredEventHandlersLock.Unlock()
|
defer registeredEventHandlersLock.Unlock()
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"gopkg.in/irc.v4"
|
"gopkg.in/irc.v4"
|
||||||
|
|
||||||
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||||
"github.com/Luzifer/go_helpers/v2/str"
|
"github.com/Luzifer/go_helpers/v2/str"
|
||||||
korvike "github.com/Luzifer/korvike/functions"
|
korvike "github.com/Luzifer/korvike/functions"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
|
@ -37,7 +38,7 @@ func newTemplateFuncProvider() *templateFuncProvider {
|
||||||
return out
|
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()
|
t.lock.RLock()
|
||||||
defer t.lock.RUnlock()
|
defer t.lock.RUnlock()
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,13 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"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/pkg/twitch"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
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) {
|
return func(arg int) (string, error) {
|
||||||
msgParts := strings.Split(m.Trailing(), " ")
|
msgParts := strings.Split(m.Trailing(), " ")
|
||||||
if len(msgParts) <= arg {
|
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 {
|
return func(badge string) bool {
|
||||||
badges := twitch.ParseBadgeLevels(m)
|
badges := twitch.ParseBadgeLevels(m)
|
||||||
return badges.Has(badge)
|
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) {
|
return func(idx int, fallback ...string) (string, error) {
|
||||||
fields := r.GetMatchMessage().FindStringSubmatch(m.Trailing())
|
fields := r.GetMatchMessage().FindStringSubmatch(m.Trailing())
|
||||||
if len(fields) <= idx {
|
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] }
|
return func(tag string) string { return m.Tags[tag] }
|
||||||
}, plugins.TemplateFuncDocumentation{
|
}, plugins.TemplateFuncDocumentation{
|
||||||
Description: "Takes the message sent to the channel, returns the value of the tag specified",
|
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 (
|
require (
|
||||||
github.com/Luzifer/go-openssl/v4 v4.2.2
|
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/korvike/functions v0.11.0
|
||||||
github.com/Luzifer/rconfig/v2 v2.5.0
|
github.com/Luzifer/rconfig/v2 v2.5.0
|
||||||
github.com/Masterminds/sprig/v3 v3.2.3
|
github.com/Masterminds/sprig/v3 v3.2.3
|
||||||
github.com/getsentry/sentry-go v0.27.0
|
github.com/getsentry/sentry-go v0.27.0
|
||||||
github.com/glebarez/sqlite v1.11.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/go-sql-driver/mysql v1.8.1
|
||||||
github.com/gofrs/uuid v4.4.0+incompatible
|
github.com/gofrs/uuid v4.4.0+incompatible
|
||||||
github.com/gofrs/uuid/v3 v3.1.2
|
github.com/gofrs/uuid/v3 v3.1.2
|
||||||
github.com/gorilla/mux v1.8.1
|
github.com/gorilla/mux v1.8.1
|
||||||
github.com/gorilla/websocket v1.5.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/mitchellh/hashstructure/v2 v2.0.2
|
||||||
github.com/orandin/sentrus v1.0.0
|
github.com/orandin/sentrus v1.0.0
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
|
@ -31,7 +31,7 @@ require (
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
gorm.io/driver/mysql v1.5.6
|
gorm.io/driver/mysql v1.5.6
|
||||||
gorm.io/driver/postgres v1.5.7
|
gorm.io/driver/postgres v1.5.7
|
||||||
gorm.io/gorm v1.25.8
|
gorm.io/gorm v1.25.9
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
@ -87,7 +87,7 @@ require (
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/ryanuber/go-glob v1.0.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/shopspring/decimal v1.3.1 // indirect
|
||||||
github.com/skeema/knownhosts v1.2.2 // indirect
|
github.com/skeema/knownhosts v1.2.2 // indirect
|
||||||
github.com/spf13/cast v1.6.0 // indirect
|
github.com/spf13/cast v1.6.0 // indirect
|
||||||
|
@ -105,6 +105,6 @@ require (
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
modernc.org/libc v1.49.0 // indirect
|
modernc.org/libc v1.49.0 // indirect
|
||||||
modernc.org/mathutil v1.6.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
|
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/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 h1:wKF/GhSKGJtHFQYTkN61wXig7mPvDj/oPpW6MmnBpjc=
|
||||||
github.com/Luzifer/go-openssl/v4 v4.2.2/go.mod h1:+kAwI4NpyYXoWil85gKSCEJNoCQlMeFikEMn2f+5ffc=
|
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.24.0 h1:abACOhsn6a6c6X22jq42mZM1wuOM0Ihfa6yzssrjrOg=
|
||||||
github.com/Luzifer/go_helpers/v2 v2.23.0/go.mod h1:BSGkJ/dxqs7AxsfZt8zjJb4R6YB5dONS+/ad7foLUrk=
|
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 h1:2hr3nnt9hy8Esu1W3h50+RggcLRXvrw92kVQLvxzd2Q=
|
||||||
github.com/Luzifer/korvike/functions v0.11.0/go.mod h1:osumwH64mWgbwZIfE7rE0BB7Y5HXxrzyO4JfO7fhduU=
|
github.com/Luzifer/korvike/functions v0.11.0/go.mod h1:osumwH64mWgbwZIfE7rE0BB7Y5HXxrzyO4JfO7fhduU=
|
||||||
github.com/Luzifer/rconfig/v2 v2.5.0 h1:zx5lfQbNX3za4VegID97IeY+M+BmfgHxWJTYA94sxok=
|
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/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 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
|
||||||
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
|
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.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
|
||||||
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
|
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 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||||
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
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=
|
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-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 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-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.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys=
|
||||||
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/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 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-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=
|
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.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
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/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.15 h1:WC1Nxbx4Ifw5U2oQWACYz32JK8G9qxNtHzrvW4KEcqI=
|
||||||
github.com/itchyny/gojq v0.12.14/go.mod h1:y1G7oO7XkcR1LPZO59KyoCRy08T3j9vDYRV0GgYSS+s=
|
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 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE=
|
||||||
github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8=
|
github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8=
|
||||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
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/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 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
|
||||||
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
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.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
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.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 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
|
||||||
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
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 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM=
|
||||||
gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA=
|
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.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||||
gorm.io/gorm v1.25.8 h1:WAGEZ/aEcznN4D03laj8DKnehe1e9gYQAjW8xyPRdeo=
|
gorm.io/gorm v1.25.9 h1:wct0gxZIELDk8+ZqF/MVnHLkA1rvYlBWUMv2EdsK1g8=
|
||||||
gorm.io/gorm v1.25.8/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
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-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/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=
|
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/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 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
||||||
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
||||||
modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E=
|
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
|
||||||
modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E=
|
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 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
||||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||||
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
|
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
|
||||||
|
|
|
@ -11,6 +11,8 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"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/pkg/twitch"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
@ -87,7 +89,7 @@ func Register(args plugins.RegistrationArguments) (err error) {
|
||||||
|
|
||||||
type actor struct{}
|
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 }("")
|
ptrStringEmpty := func(v string) *string { return &v }("")
|
||||||
|
|
||||||
reason, err := formatMessage(attrs.MustString("reason", ptrStringEmpty), m, r, eventData)
|
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) IsAsync() bool { return false }
|
||||||
func (actor) Name() string { return actorName }
|
func (actor) Name() string { return actorName }
|
||||||
|
|
||||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
reasonTemplate, err := attrs.String("reason")
|
if err = attrs.ValidateSchema(
|
||||||
if err != nil || reasonTemplate == "" {
|
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "reason", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||||
return errors.New("reason must be non-empty string")
|
fieldcollection.MustHaveNoUnknowFields,
|
||||||
}
|
helpers.SchemaValidateTemplateField(tplValidator, "reason"),
|
||||||
|
); err != nil {
|
||||||
if err = tplValidator(reasonTemplate); err != nil {
|
return fmt.Errorf("validating attributes: %w", err)
|
||||||
return errors.Wrap(err, "validating reason template")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -9,6 +9,8 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"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/pkg/twitch"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
@ -19,9 +21,6 @@ var (
|
||||||
formatMessage plugins.MsgFormatter
|
formatMessage plugins.MsgFormatter
|
||||||
hasPerm plugins.ChannelPermissionCheckFunc
|
hasPerm plugins.ChannelPermissionCheckFunc
|
||||||
tcGetter func(string) (*twitch.Client, error)
|
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
|
// Register provides the plugins.RegisterFunc
|
||||||
|
@ -71,7 +70,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||||
|
|
||||||
type actor struct{}
|
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)
|
channel := plugins.DeriveChannel(m, eventData)
|
||||||
if channel, err = formatMessage(attrs.MustString("channel", &channel), m, r, eventData); err != nil {
|
if channel, err = formatMessage(attrs.MustString("channel", &channel), m, r, eventData); err != nil {
|
||||||
return false, errors.Wrap(err, "parsing channel")
|
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)
|
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 {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "creating clip")
|
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) Name() string { return actorName }
|
||||||
|
|
||||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
for _, field := range []string{"channel", "creator"} {
|
if err = attrs.ValidateSchema(
|
||||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "channel", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||||
return errors.Wrapf(err, "validating %s template", field)
|
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
|
return nil
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"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/internal/actors/linkdetector"
|
||||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
|
@ -40,7 +41,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||||
type Actor struct{}
|
type Actor struct{}
|
||||||
|
|
||||||
// Execute implements the actor interface
|
// 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") {
|
if eventData.HasAll("clips") {
|
||||||
// We already detected clips, lets not do it again
|
// We already detected clips, lets not do it again
|
||||||
return false, nil
|
return false, nil
|
||||||
|
@ -82,4 +83,6 @@ func (Actor) IsAsync() bool { return false }
|
||||||
func (Actor) Name() string { return actorName }
|
func (Actor) Name() string { return actorName }
|
||||||
|
|
||||||
// Validate implements the actor interface
|
// 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 (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -10,6 +11,8 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"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/pkg/twitch"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
@ -61,7 +64,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||||
|
|
||||||
type actor struct{}
|
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 }("")
|
ptrStringEmpty := func(v string) *string { return &v }("")
|
||||||
|
|
||||||
durationStr, err := formatMessage(attrs.MustString("duration", ptrStringEmpty), m, r, eventData)
|
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) IsAsync() bool { return false }
|
||||||
func (actor) Name() string { return actorName }
|
func (actor) Name() string { return actorName }
|
||||||
|
|
||||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
durationTemplate, err := attrs.String("duration")
|
if err = attrs.ValidateSchema(
|
||||||
if err != nil || durationTemplate == "" {
|
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "duration", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||||
return errors.New("duration must be non-empty string")
|
helpers.SchemaValidateTemplateField(tplValidator, "duration"),
|
||||||
}
|
); err != nil {
|
||||||
|
return fmt.Errorf("validating attributes: %w", err)
|
||||||
if err = tplValidator(durationTemplate); err != nil {
|
|
||||||
return errors.Wrap(err, "validating duration template")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -13,6 +13,8 @@ import (
|
||||||
"gopkg.in/irc.v4"
|
"gopkg.in/irc.v4"
|
||||||
"gorm.io/gorm"
|
"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/database"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
@ -20,8 +22,6 @@ import (
|
||||||
var (
|
var (
|
||||||
db database.Connector
|
db database.Connector
|
||||||
formatMessage plugins.MsgFormatter
|
formatMessage plugins.MsgFormatter
|
||||||
|
|
||||||
ptrStringEmpty = func(s string) *string { return &s }("")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Register provides the plugins.RegisterFunc
|
// Register provides the plugins.RegisterFunc
|
||||||
|
@ -135,7 +135,7 @@ func Register(args plugins.RegistrationArguments) (err error) {
|
||||||
return fmt.Errorf("registering API route: %w", err)
|
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) {
|
return func(name string) (string, error) {
|
||||||
channel, err := fields.String("channel")
|
channel, err := fields.String("channel")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -212,13 +212,13 @@ func Register(args plugins.RegistrationArguments) (err error) {
|
||||||
|
|
||||||
type actorCounter struct{}
|
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)
|
counterName, err := formatMessage(attrs.MustString("counter", nil), m, r, eventData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "preparing response")
|
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)
|
parseValue, err := formatMessage(counterSet, m, r, eventData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "execute counter value template")
|
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
|
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)
|
parseStep, err := formatMessage(s, m, r, eventData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "execute counter step template")
|
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) IsAsync() bool { return false }
|
||||||
func (actorCounter) Name() string { return "counter" }
|
func (actorCounter) Name() string { return "counter" }
|
||||||
|
|
||||||
func (actorCounter) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
func (actorCounter) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
if cn, err := attrs.String("counter"); err != nil || cn == "" {
|
if err = attrs.ValidateSchema(
|
||||||
return errors.New("counter name must be non-empty string")
|
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}),
|
||||||
for _, field := range []string{"counter", "counter_step", "counter_set"} {
|
helpers.SchemaValidateTemplateField(tplValidator, "counter", "counter_step", "counter_set"),
|
||||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
); err != nil {
|
||||||
return errors.Wrapf(err, "validating %s template", field)
|
return fmt.Errorf("validating attributes: %w", err)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -7,6 +7,8 @@ import (
|
||||||
|
|
||||||
"gopkg.in/irc.v4"
|
"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"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -48,11 +50,10 @@ func Register(args plugins.RegistrationArguments) error {
|
||||||
|
|
||||||
type actor struct{}
|
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 (
|
var (
|
||||||
ptrZeroDuration = func(v time.Duration) *time.Duration { return &v }(0)
|
delay = attrs.MustDuration("delay", helpers.Ptr(time.Duration(0)))
|
||||||
delay = attrs.MustDuration("delay", ptrZeroDuration)
|
jitter = attrs.MustDuration("jitter", helpers.Ptr(time.Duration(0)))
|
||||||
jitter = attrs.MustDuration("jitter", ptrZeroDuration)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if delay == 0 && jitter == 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) IsAsync() bool { return false }
|
||||||
func (actor) Name() string { return actorName }
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"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/pkg/twitch"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
@ -32,7 +33,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||||
|
|
||||||
type actor struct{}
|
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"]
|
msgID, ok := m.Tags["id"]
|
||||||
if !ok || msgID == "" {
|
if !ok || msgID == "" {
|
||||||
return false, nil
|
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) IsAsync() bool { return false }
|
||||||
func (actor) Name() string { return actorName }
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,13 @@ package eventmod
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"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"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -44,7 +47,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||||
|
|
||||||
type actor struct{}
|
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 }("")
|
ptrStringEmpty := func(v string) *string { return &v }("")
|
||||||
|
|
||||||
fd, err := formatMessage(attrs.MustString("fields", ptrStringEmpty), m, r, eventData)
|
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) IsAsync() bool { return false }
|
||||||
func (actor) Name() string { return actorName }
|
func (actor) Name() string { return actorName }
|
||||||
|
|
||||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
fieldsTemplate, err := attrs.String("fields")
|
if err = attrs.ValidateSchema(
|
||||||
if err != nil || fieldsTemplate == "" {
|
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "fields", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||||
return errors.New("fields must be non-empty string")
|
helpers.SchemaValidateTemplateField(tplValidator, "fields"),
|
||||||
}
|
); err != nil {
|
||||||
|
return fmt.Errorf("validating attributes: %w", err)
|
||||||
if err = tplValidator(fieldsTemplate); err != nil {
|
|
||||||
return errors.Wrap(err, "validating fields template")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -5,6 +5,7 @@ package filesay
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
|
@ -13,6 +14,8 @@ import (
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"gopkg.in/irc.v4"
|
"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"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -57,7 +60,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||||
|
|
||||||
type actor struct{}
|
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 }("")
|
ptrStringEmpty := func(v string) *string { return &v }("")
|
||||||
|
|
||||||
source, err := formatMessage(attrs.MustString("source", ptrStringEmpty), m, r, eventData)
|
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) IsAsync() bool { return true }
|
||||||
func (actor) Name() string { return actorName }
|
func (actor) Name() string { return actorName }
|
||||||
|
|
||||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) error {
|
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
sourceTpl, err := attrs.String("source")
|
if err = attrs.ValidateSchema(
|
||||||
if err != nil || sourceTpl == "" {
|
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "source", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||||
return errors.New("source is expected to be non-empty string")
|
helpers.SchemaValidateTemplateField(tplValidator, "source"),
|
||||||
}
|
); err != nil {
|
||||||
|
return fmt.Errorf("validating attributes: %w", err)
|
||||||
if err = tplValidator(sourceTpl); err != nil {
|
|
||||||
return errors.Wrap(err, "validating source template")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -5,14 +5,14 @@ package linkdetector
|
||||||
import (
|
import (
|
||||||
"gopkg.in/irc.v4"
|
"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/internal/linkcheck"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
const actorName = "linkdetector"
|
const actorName = "linkdetector"
|
||||||
|
|
||||||
var ptrFalse = func(v bool) *bool { return &v }(false)
|
|
||||||
|
|
||||||
// Register provides the plugins.RegisterFunc
|
// Register provides the plugins.RegisterFunc
|
||||||
func Register(args plugins.RegistrationArguments) error {
|
func Register(args plugins.RegistrationArguments) error {
|
||||||
args.RegisterActor(actorName, func() plugins.Actor { return &Actor{} })
|
args.RegisterActor(actorName, func() plugins.Actor { return &Actor{} })
|
||||||
|
@ -42,13 +42,13 @@ func Register(args plugins.RegistrationArguments) error {
|
||||||
type Actor struct{}
|
type Actor struct{}
|
||||||
|
|
||||||
// Execute implements the actor interface
|
// 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") {
|
if eventData.HasAll("links") {
|
||||||
// We already detected links, lets not do it again
|
// We already detected links, lets not do it again
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if attrs.MustBool("heuristic", ptrFalse) {
|
if attrs.MustBool("heuristic", helpers.Ptr(false)) {
|
||||||
eventData.Set("links", linkcheck.New().HeuristicScanForLinks(m.Trailing()))
|
eventData.Set("links", linkcheck.New().HeuristicScanForLinks(m.Trailing()))
|
||||||
} else {
|
} else {
|
||||||
eventData.Set("links", linkcheck.New().ScanForLinks(m.Trailing()))
|
eventData.Set("links", linkcheck.New().ScanForLinks(m.Trailing()))
|
||||||
|
@ -64,4 +64,6 @@ func (Actor) IsAsync() bool { return false }
|
||||||
func (Actor) Name() string { return actorName }
|
func (Actor) Name() string { return actorName }
|
||||||
|
|
||||||
// Validate implements the actor interface
|
// 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 (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -11,7 +12,9 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"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/actors/clipdetector"
|
||||||
|
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
@ -21,8 +24,6 @@ const actorName = "linkprotect"
|
||||||
var (
|
var (
|
||||||
botTwitchClient *twitch.Client
|
botTwitchClient *twitch.Client
|
||||||
clipLink = regexp.MustCompile(`.*(?:clips\.twitch\.tv|www\.twitch\.tv/[^/]*/clip)/.*`)
|
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
|
// Register provides the plugins.RegisterFunc
|
||||||
|
@ -127,7 +128,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
//nolint:gocyclo // Minimum over the limit, makes no sense to split
|
//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
|
// 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 {
|
if preventCooldown, err = (clipdetector.Actor{}).Execute(c, m, r, eventData, attrs); err != nil {
|
||||||
return preventCooldown, errors.Wrap(err, "detecting links / clips")
|
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 len(links) == 0 {
|
||||||
// If there are no links there is nothing to protect and there
|
// If there are no links there is nothing to protect and there
|
||||||
// are also no clips as they are parsed from the links
|
// 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, plugins.ErrStopRuleExecution
|
||||||
}
|
}
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
clipsInterface, err := eventData.Any("clips")
|
clipsInterface, err := eventData.Get("clips")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return preventCooldown, errors.Wrap(err, "getting clips from event")
|
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 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, plugins.ErrStopRuleExecution
|
||||||
}
|
}
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// That message misbehaved so we need to punish them
|
// 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":
|
case "ban":
|
||||||
if err = botTwitchClient.BanUser(
|
if err = botTwitchClient.BanUser(
|
||||||
context.Background(),
|
context.Background(),
|
||||||
plugins.DeriveChannel(m, eventData),
|
plugins.DeriveChannel(m, eventData),
|
||||||
strings.TrimLeft(plugins.DeriveUser(m, eventData), "@"),
|
strings.TrimLeft(plugins.DeriveUser(m, eventData), "@"),
|
||||||
0,
|
0,
|
||||||
attrs.MustString("reason", ptrStringEmpty),
|
attrs.MustString("reason", helpers.Ptr("")),
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return false, errors.Wrap(err, "executing user ban")
|
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),
|
plugins.DeriveChannel(m, eventData),
|
||||||
strings.TrimLeft(plugins.DeriveUser(m, eventData), "@"),
|
strings.TrimLeft(plugins.DeriveUser(m, eventData), "@"),
|
||||||
to,
|
to,
|
||||||
attrs.MustString("reason", ptrStringEmpty),
|
attrs.MustString("reason", helpers.Ptr("")),
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return false, errors.Wrap(err, "executing user ban")
|
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
|
return false, plugins.ErrStopRuleExecution
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,41 +219,42 @@ func (actor) IsAsync() bool { return false }
|
||||||
|
|
||||||
func (actor) Name() string { return actorName }
|
func (actor) Name() string { return actorName }
|
||||||
|
|
||||||
func (actor) Validate(_ plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) error {
|
func (actor) Validate(_ plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
if v, err := attrs.String("action"); err != nil || v == "" {
|
if err = attrs.ValidateSchema(
|
||||||
return errors.New("action must be non-empty string")
|
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 v, err := attrs.String("reason"); err != nil || v == "" {
|
if len(attrs.MustStringSlice("allowed_links", helpers.Ptr([]string{})))+
|
||||||
return errors.New("reason must be non-empty 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 {
|
||||||
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")
|
return errors.New("no conditions are provided")
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
); err != nil {
|
||||||
|
return fmt.Errorf("validating attributes: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a actor) check(links []string, clips []twitch.ClipInfo, attrs *plugins.FieldCollection) (v verdict) {
|
func (a actor) check(links []string, clips []twitch.ClipInfo, attrs *fieldcollection.FieldCollection) (v verdict) {
|
||||||
hasClipDefinition := len(attrs.MustStringSlice("allowed_clip_channels"))+len(attrs.MustStringSlice("disallowed_clip_channels")) > 0
|
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
|
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
|
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
|
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
|
return verdictMisbehave
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,18 +2,19 @@
|
||||||
package log
|
package log
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"gopkg.in/irc.v4"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"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"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var formatMessage plugins.MsgFormatter
|
||||||
formatMessage plugins.MsgFormatter
|
|
||||||
ptrStringEmpty = func(v string) *string { return &v }("")
|
|
||||||
)
|
|
||||||
|
|
||||||
// Register provides the plugins.RegisterFunc
|
// Register provides the plugins.RegisterFunc
|
||||||
func Register(args plugins.RegistrationArguments) error {
|
func Register(args plugins.RegistrationArguments) error {
|
||||||
|
@ -44,8 +45,8 @@ func Register(args plugins.RegistrationArguments) error {
|
||||||
|
|
||||||
type actor struct{}
|
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) {
|
||||||
message, err := formatMessage(attrs.MustString("message", ptrStringEmpty), m, r, eventData)
|
message, err := formatMessage(attrs.MustString("message", helpers.Ptr("")), m, r, eventData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "executing message template")
|
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) IsAsync() bool { return true }
|
||||||
func (actor) Name() string { return "log" }
|
func (actor) Name() string { return "log" }
|
||||||
|
|
||||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
if v, err := attrs.String("message"); err != nil || v == "" {
|
if err = attrs.ValidateSchema(
|
||||||
return errors.New("message must be non-empty string")
|
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "message", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||||
}
|
helpers.SchemaValidateTemplateField(tplValidator, "message"),
|
||||||
|
); err != nil {
|
||||||
if err = tplValidator(attrs.MustString("message", ptrStringEmpty)); err != nil {
|
return fmt.Errorf("validating attributes: %w", err)
|
||||||
return errors.Wrap(err, "validating message template")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -20,12 +20,7 @@ const (
|
||||||
postTimeout = 5 * time.Second
|
postTimeout = 5 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var formatMessage plugins.MsgFormatter
|
||||||
formatMessage plugins.MsgFormatter
|
|
||||||
|
|
||||||
ptrBoolFalse = func(v bool) *bool { return &v }(false)
|
|
||||||
ptrStringEmpty = func(s string) *string { return &s }("")
|
|
||||||
)
|
|
||||||
|
|
||||||
// Register provides the plugins.RegisterFunc
|
// Register provides the plugins.RegisterFunc
|
||||||
func Register(args plugins.RegistrationArguments) error {
|
func Register(args plugins.RegistrationArguments) error {
|
||||||
|
|
|
@ -7,6 +7,8 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"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"
|
"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
|
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")
|
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")
|
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")
|
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 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) IsAsync() bool { return false }
|
||||||
|
|
||||||
func (discordActor) Name() string { return "discordhook" }
|
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 {
|
if err = d.ValidateRequireNonEmpty(attrs, "hook_url"); err != nil {
|
||||||
return err //nolint:wrapcheck
|
return err //nolint:wrapcheck
|
||||||
}
|
}
|
||||||
|
@ -89,7 +91,7 @@ func (d discordActor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs
|
||||||
return err //nolint:wrapcheck
|
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
|
// We're not validating the rest if embeds are disabled but in
|
||||||
// this case the content is mandatory
|
// this case the content is mandatory
|
||||||
return d.ValidateRequireNonEmpty(attrs, "content") //nolint:wrapcheck
|
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
|
//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) {
|
func (discordActor) addEmbed(payload *discordPayload, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
if !attrs.MustBool("add_embed", ptrBoolFalse) {
|
if !attrs.MustBool("add_embed", helpers.Ptr(false)) {
|
||||||
// No embed? No problem!
|
// No embed? No problem!
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -122,45 +124,45 @@ func (discordActor) addEmbed(payload *discordPayload, m *irc.Message, r *plugins
|
||||||
sv string
|
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")
|
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")
|
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")
|
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")
|
return errors.Wrap(err, "parsing embed_image")
|
||||||
} else if sv != "" {
|
} else if sv != "" {
|
||||||
embed.Image = &discordPayloadEmbedImage{URL: 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")
|
return errors.Wrap(err, "parsing embed_thumbnail")
|
||||||
} else if sv != "" {
|
} else if sv != "" {
|
||||||
embed.Thumbnail = &discordPayloadEmbedImage{URL: 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")
|
return errors.Wrap(err, "parsing embed_author_name")
|
||||||
} else if sv != "" {
|
} else if sv != "" {
|
||||||
embed.Author = &discordPayloadEmbedAuthor{Name: 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")
|
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")
|
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")
|
return errors.Wrap(err, "parsing embed_fields")
|
||||||
} else if sv != "" {
|
} else if sv != "" {
|
||||||
var flds []discordPayloadEmbedField
|
var flds []discordPayloadEmbedField
|
||||||
|
|
|
@ -7,6 +7,8 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"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"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -14,14 +16,14 @@ type slackCompatibleActor struct {
|
||||||
plugins.ActorKit
|
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)
|
text, err := formatMessage(attrs.MustString("text", nil), m, r, eventData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "parsing text")
|
return false, errors.Wrap(err, "parsing text")
|
||||||
}
|
}
|
||||||
|
|
||||||
return sendPayload(
|
return sendPayload(
|
||||||
s.fixHookURL(attrs.MustString("hook_url", ptrStringEmpty)),
|
s.fixHookURL(attrs.MustString("hook_url", helpers.Ptr(""))),
|
||||||
map[string]string{
|
map[string]string{
|
||||||
"text": text,
|
"text": text,
|
||||||
},
|
},
|
||||||
|
@ -33,7 +35,7 @@ func (slackCompatibleActor) IsAsync() bool { return false }
|
||||||
|
|
||||||
func (slackCompatibleActor) Name() string { return "slackhook" }
|
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 {
|
if err = s.ValidateRequireNonEmpty(attrs, "hook_url", "text"); err != nil {
|
||||||
return err //nolint:wrapcheck
|
return err //nolint:wrapcheck
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,14 @@ package modchannel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"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/pkg/twitch"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
@ -18,8 +21,6 @@ const actorName = "modchannel"
|
||||||
var (
|
var (
|
||||||
formatMessage plugins.MsgFormatter
|
formatMessage plugins.MsgFormatter
|
||||||
tcGetter func(string) (*twitch.Client, error)
|
tcGetter func(string) (*twitch.Client, error)
|
||||||
|
|
||||||
ptrStringEmpty = func(s string) *string { return &s }("")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Register provides the plugins.RegisterFunc
|
// Register provides the plugins.RegisterFunc
|
||||||
|
@ -70,10 +71,10 @@ func Register(args plugins.RegistrationArguments) error {
|
||||||
|
|
||||||
type actor struct{}
|
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 (
|
var (
|
||||||
game = attrs.MustString("game", ptrStringEmpty)
|
game = attrs.MustString("game", helpers.Ptr(""))
|
||||||
title = attrs.MustString("title", ptrStringEmpty)
|
title = attrs.MustString("title", helpers.Ptr(""))
|
||||||
)
|
)
|
||||||
|
|
||||||
if game == "" && title == "" {
|
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) IsAsync() bool { return false }
|
||||||
func (actor) Name() string { return actorName }
|
func (actor) Name() string { return actorName }
|
||||||
|
|
||||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
if v, err := attrs.String("channel"); err != nil || v == "" {
|
if err = attrs.ValidateSchema(
|
||||||
return errors.New("channel must be non-empty string")
|
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}),
|
||||||
for _, field := range []string{"channel", "game", "title"} {
|
helpers.SchemaValidateTemplateField(tplValidator, "channel", "game", "title"),
|
||||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
); err != nil {
|
||||||
return errors.Wrapf(err, "validating %s template", field)
|
return fmt.Errorf("validating attributes: %w", err)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
package nuke
|
package nuke
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -13,7 +14,9 @@ import (
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"gopkg.in/irc.v4"
|
"gopkg.in/irc.v4"
|
||||||
|
|
||||||
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||||
"github.com/Luzifer/go_helpers/v2/str"
|
"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/pkg/twitch"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
@ -29,10 +32,6 @@ var (
|
||||||
|
|
||||||
messageStore = map[string][]*storedMessage{}
|
messageStore = map[string][]*storedMessage{}
|
||||||
messageStoreLock sync.RWMutex
|
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
|
// 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)
|
rawMatch, err := formatMessage(attrs.MustString("match", nil), m, r, eventData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "formatting match")
|
return false, errors.Wrap(err, "formatting match")
|
||||||
}
|
}
|
||||||
match := regexp.MustCompile(rawMatch)
|
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 {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "formatting scan duration")
|
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
|
action actionFn
|
||||||
actionName string
|
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 {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "formatting action")
|
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) IsAsync() bool { return false }
|
||||||
func (actor) Name() string { return actorName }
|
func (actor) Name() string { return actorName }
|
||||||
|
|
||||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
if v, err := attrs.String("match"); err != nil || v == "" {
|
if err = attrs.ValidateSchema(
|
||||||
return errors.New("match must be non-empty string")
|
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}),
|
||||||
for _, field := range []string{"scan", "action", "match"} {
|
helpers.SchemaValidateTemplateField(tplValidator, "scan", "action", "match"),
|
||||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
); err != nil {
|
||||||
return errors.Wrapf(err, "validating %s template", field)
|
return fmt.Errorf("validating attributes: %w", err)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -4,6 +4,7 @@ package punish
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -12,6 +13,8 @@ import (
|
||||||
"gopkg.in/irc.v4"
|
"gopkg.in/irc.v4"
|
||||||
"gorm.io/gorm"
|
"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/database"
|
||||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
|
@ -28,8 +31,6 @@ var (
|
||||||
botTwitchClient *twitch.Client
|
botTwitchClient *twitch.Client
|
||||||
db database.Connector
|
db database.Connector
|
||||||
formatMessage plugins.MsgFormatter
|
formatMessage plugins.MsgFormatter
|
||||||
ptrDefaultCooldown = func(v time.Duration) *time.Duration { return &v }(oneWeek)
|
|
||||||
ptrStringEmpty = func(v string) *string { return &v }("")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Register provides the plugins.RegisterFunc
|
// Register provides the plugins.RegisterFunc
|
||||||
|
@ -146,12 +147,12 @@ type (
|
||||||
|
|
||||||
// Punish
|
// 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 (
|
var (
|
||||||
cooldown = attrs.MustDuration("cooldown", ptrDefaultCooldown)
|
cooldown = attrs.MustDuration("cooldown", helpers.Ptr(oneWeek))
|
||||||
reason = attrs.MustString("reason", ptrStringEmpty)
|
reason = attrs.MustString("reason", helpers.Ptr(""))
|
||||||
user = attrs.MustString("user", nil)
|
user = attrs.MustString("user", nil)
|
||||||
uuid = attrs.MustString("uuid", ptrStringEmpty)
|
uuid = attrs.MustString("uuid", helpers.Ptr(""))
|
||||||
)
|
)
|
||||||
|
|
||||||
levels, err := attrs.StringSlice("levels")
|
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) IsAsync() bool { return false }
|
||||||
func (actorPunish) Name() string { return actorNamePunish }
|
func (actorPunish) Name() string { return actorNamePunish }
|
||||||
|
|
||||||
func (actorPunish) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
func (actorPunish) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
if v, err := attrs.String("user"); err != nil || v == "" {
|
if err = attrs.ValidateSchema(
|
||||||
return errors.New("user must be non-empty string")
|
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}),
|
||||||
if v, err := attrs.StringSlice("levels"); err != nil || len(v) == 0 {
|
fieldcollection.CanHaveField(fieldcollection.SchemaField{Name: "reason", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||||
return errors.New("levels must be slice of strings with length > 0")
|
fieldcollection.CanHaveField(fieldcollection.SchemaField{Name: "uuid", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||||
}
|
helpers.SchemaValidateTemplateField(tplValidator, "user"),
|
||||||
|
); err != nil {
|
||||||
if err = tplValidator(attrs.MustString("user", ptrStringEmpty)); err != nil {
|
return fmt.Errorf("validating attributes: %w", err)
|
||||||
return errors.Wrap(err, "validating user template")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -243,10 +243,10 @@ func (actorPunish) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *p
|
||||||
|
|
||||||
// Reset
|
// 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 (
|
var (
|
||||||
user = attrs.MustString("user", nil)
|
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 {
|
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) IsAsync() bool { return false }
|
||||||
func (actorResetPunish) Name() string { return actorNameResetPunish }
|
func (actorResetPunish) Name() string { return actorNameResetPunish }
|
||||||
|
|
||||||
func (actorResetPunish) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
func (actorResetPunish) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
if v, err := attrs.String("user"); err != nil || v == "" {
|
if err = attrs.ValidateSchema(
|
||||||
return errors.New("user must be non-empty string")
|
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"),
|
||||||
if err = tplValidator(attrs.MustString("user", ptrStringEmpty)); err != nil {
|
); err != nil {
|
||||||
return errors.Wrap(err, "validating user template")
|
return fmt.Errorf("validating attributes: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -10,6 +10,8 @@ import (
|
||||||
"gopkg.in/irc.v4"
|
"gopkg.in/irc.v4"
|
||||||
"gorm.io/gorm"
|
"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/database"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
@ -23,9 +25,9 @@ var (
|
||||||
formatMessage plugins.MsgFormatter
|
formatMessage plugins.MsgFormatter
|
||||||
send plugins.SendMessageFunc
|
send plugins.SendMessageFunc
|
||||||
|
|
||||||
ptrStringEmpty = func(v string) *string { return &v }("")
|
// ptrStringEmpty = func(v string) *string { return &v }("")
|
||||||
ptrStringOutFormat = func(v string) *string { return &v }("Quote #{{ .index }}: {{ .quote }}")
|
// ptrStringOutFormat = func(v string) *string { return &v }("Quote #{{ .index }}: {{ .quote }}")
|
||||||
ptrStringZero = func(v string) *string { return &v }("0")
|
// ptrStringZero = func(v string) *string { return &v }("0")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Register provides the plugins.RegisterFunc
|
// Register provides the plugins.RegisterFunc
|
||||||
|
@ -93,7 +95,7 @@ func Register(args plugins.RegistrationArguments) (err error) {
|
||||||
return fmt.Errorf("registering API: %w", err)
|
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 func() (int, error) {
|
||||||
return getMaxQuoteIdx(db, plugins.DeriveChannel(m, nil))
|
return getMaxQuoteIdx(db, plugins.DeriveChannel(m, nil))
|
||||||
}
|
}
|
||||||
|
@ -113,11 +115,11 @@ type (
|
||||||
actor struct{}
|
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 (
|
var (
|
||||||
action = attrs.MustString("action", ptrStringEmpty)
|
action = attrs.MustString("action", helpers.Ptr(""))
|
||||||
indexStr = attrs.MustString("index", ptrStringZero)
|
indexStr = attrs.MustString("index", helpers.Ptr("0"))
|
||||||
quote = attrs.MustString("quote", ptrStringEmpty)
|
quote = attrs.MustString("quote", helpers.Ptr(""))
|
||||||
)
|
)
|
||||||
|
|
||||||
if indexStr == "" {
|
if indexStr == "" {
|
||||||
|
@ -166,7 +168,7 @@ func (actor) Execute(_ *irc.Client, m *irc.Message, r *plugins.Rule, eventData *
|
||||||
fields.Set("index", idx)
|
fields.Set("index", idx)
|
||||||
fields.Set("quote", quote)
|
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)
|
msg, err := formatMessage(format, m, r, fields)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "formatting output message")
|
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) IsAsync() bool { return false }
|
||||||
func (actor) Name() string { return actorName }
|
func (actor) Name() string { return actorName }
|
||||||
|
|
||||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
action := attrs.MustString("action", ptrStringEmpty)
|
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 {
|
switch action {
|
||||||
case "add":
|
case "add":
|
||||||
if v, err := attrs.String("quote"); err != nil || v == "" {
|
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":
|
case "del":
|
||||||
if v, err := attrs.String("index"); err != nil || v == "" {
|
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":
|
case "get":
|
||||||
// No requirements
|
// No requirements
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return errors.New("action must be one of add, del or get")
|
return fmt.Errorf("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 nil
|
return nil
|
||||||
|
|
|
@ -2,9 +2,13 @@
|
||||||
package raw
|
package raw
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"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"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -13,8 +17,6 @@ const actorName = "raw"
|
||||||
var (
|
var (
|
||||||
formatMessage plugins.MsgFormatter
|
formatMessage plugins.MsgFormatter
|
||||||
send plugins.SendMessageFunc
|
send plugins.SendMessageFunc
|
||||||
|
|
||||||
ptrStringEmpty = func(s string) *string { return &s }("")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Register provides the plugins.RegisterFunc
|
// Register provides the plugins.RegisterFunc
|
||||||
|
@ -47,7 +49,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||||
|
|
||||||
type actor struct{}
|
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)
|
rawMsg, err := formatMessage(attrs.MustString("message", nil), m, r, eventData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "preparing raw message")
|
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) IsAsync() bool { return false }
|
||||||
func (actor) Name() string { return actorName }
|
func (actor) Name() string { return actorName }
|
||||||
|
|
||||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
if v, err := attrs.String("message"); err != nil || v == "" {
|
if err = attrs.ValidateSchema(
|
||||||
return errors.New("message must be non-empty string")
|
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "message", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||||
}
|
helpers.SchemaValidateTemplateField(tplValidator, "message"),
|
||||||
|
); err != nil {
|
||||||
if err = tplValidator(attrs.MustString("message", ptrStringEmpty)); err != nil {
|
return fmt.Errorf("validating attributes: %w", err)
|
||||||
return errors.Wrap(err, "validating message template")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -12,6 +12,8 @@ import (
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"gopkg.in/irc.v4"
|
"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"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,9 +22,6 @@ const actorName = "respond"
|
||||||
var (
|
var (
|
||||||
formatMessage plugins.MsgFormatter
|
formatMessage plugins.MsgFormatter
|
||||||
send plugins.SendMessageFunc
|
send plugins.SendMessageFunc
|
||||||
|
|
||||||
ptrBoolFalse = func(v bool) *bool { return &v }(false)
|
|
||||||
ptrStringEmpty = func(s string) *string { return &s }("")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Register provides the plugins.RegisterFunc
|
// Register provides the plugins.RegisterFunc
|
||||||
|
@ -102,7 +101,7 @@ func Register(args plugins.RegistrationArguments) (err error) {
|
||||||
|
|
||||||
type actor struct{}
|
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)
|
msg, err := formatMessage(attrs.MustString("message", nil), m, r, eventData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !attrs.CanString("fallback") || attrs.MustString("fallback", 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"]
|
id, ok := m.Tags["id"]
|
||||||
if ok {
|
if ok {
|
||||||
if ircMessage.Tags == nil {
|
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) IsAsync() bool { return false }
|
||||||
func (actor) Name() string { return actorName }
|
func (actor) Name() string { return actorName }
|
||||||
|
|
||||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
if v, err := attrs.String("message"); err != nil || v == "" {
|
if err = attrs.ValidateSchema(
|
||||||
return errors.New("message must be non-empty string")
|
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}),
|
||||||
for _, field := range []string{"message", "fallback"} {
|
fieldcollection.CanHaveField(fieldcollection.SchemaField{Name: "to_channel", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
helpers.SchemaValidateTemplateField(tplValidator, "message", "fallback"),
|
||||||
return errors.Wrapf(err, "validating %s template", field)
|
); err != nil {
|
||||||
}
|
return fmt.Errorf("validating attributes: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -4,10 +4,13 @@ package shield
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"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/pkg/twitch"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
@ -45,14 +48,12 @@ func Register(args plugins.RegistrationArguments) error {
|
||||||
|
|
||||||
type actor struct{}
|
type actor struct{}
|
||||||
|
|
||||||
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) {
|
||||||
ptrBoolFalse := func(v bool) *bool { return &v }(false)
|
|
||||||
|
|
||||||
return false, errors.Wrap(
|
return false, errors.Wrap(
|
||||||
botTwitchClient.UpdateShieldMode(
|
botTwitchClient.UpdateShieldMode(
|
||||||
context.Background(),
|
context.Background(),
|
||||||
plugins.DeriveChannel(m, eventData),
|
plugins.DeriveChannel(m, eventData),
|
||||||
attrs.MustBool("enable", ptrBoolFalse),
|
attrs.MustBool("enable", helpers.Ptr(false)),
|
||||||
),
|
),
|
||||||
"configuring shield mode",
|
"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) IsAsync() bool { return false }
|
||||||
func (actor) Name() string { return actorName }
|
func (actor) Name() string { return actorName }
|
||||||
|
|
||||||
func (actor) Validate(_ plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
func (actor) Validate(_ plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
if _, err = attrs.Bool("enable"); err != nil {
|
if err = attrs.ValidateSchema(
|
||||||
return errors.New("enable must be boolean")
|
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "enable", Type: fieldcollection.SchemaFieldTypeBool}),
|
||||||
|
); err != nil {
|
||||||
|
return fmt.Errorf("validating attributes: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -4,11 +4,14 @@ package shoutout
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"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/pkg/twitch"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
@ -55,7 +58,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||||
|
|
||||||
type actor struct{}
|
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)
|
user, err := formatMessage(attrs.MustString("user", ptrStringEmpty), m, r, eventData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "executing user template")
|
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) IsAsync() bool { return false }
|
||||||
func (actor) Name() string { return actorName }
|
func (actor) Name() string { return actorName }
|
||||||
|
|
||||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
if v, err := attrs.String("user"); err != nil || v == "" {
|
if err = attrs.ValidateSchema(
|
||||||
return errors.New("user must be non-empty string")
|
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "user", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||||
}
|
helpers.SchemaValidateTemplateField(tplValidator, "user"),
|
||||||
|
); err != nil {
|
||||||
if err = tplValidator(attrs.MustString("user", ptrStringEmpty)); err != nil {
|
return fmt.Errorf("validating attributes: %w", err)
|
||||||
return errors.Wrap(err, "validating user template")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -3,9 +3,13 @@
|
||||||
package stopexec
|
package stopexec
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"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"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -42,10 +46,8 @@ func Register(args plugins.RegistrationArguments) error {
|
||||||
|
|
||||||
type actor struct{}
|
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 }("")
|
when, err := formatMessage(attrs.MustString("when", helpers.Ptr("")), m, r, eventData)
|
||||||
|
|
||||||
when, err := formatMessage(attrs.MustString("when", ptrStringEmpty), m, r, eventData)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "executing when template")
|
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) IsAsync() bool { return false }
|
||||||
func (actor) Name() string { return actorName }
|
func (actor) Name() string { return actorName }
|
||||||
|
|
||||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
whenTemplate, err := attrs.String("when")
|
if err = attrs.ValidateSchema(
|
||||||
if err != nil || whenTemplate == "" {
|
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "when", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||||
return errors.New("when must be non-empty string")
|
helpers.SchemaValidateTemplateField(tplValidator, "when"),
|
||||||
}
|
); err != nil {
|
||||||
|
return fmt.Errorf("validating attributes: %w", err)
|
||||||
if err = tplValidator(whenTemplate); err != nil {
|
|
||||||
return errors.Wrap(err, "validating when template")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -3,6 +3,7 @@ package timeout
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
@ -10,6 +11,8 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"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/pkg/twitch"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
@ -65,7 +68,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||||
|
|
||||||
type actor struct{}
|
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)
|
reason, err := formatMessage(attrs.MustString("reason", ptrStringEmpty), m, r, eventData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "executing reason template")
|
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) IsAsync() bool { return false }
|
||||||
func (actor) Name() string { return actorName }
|
func (actor) Name() string { return actorName }
|
||||||
|
|
||||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
if v, err := attrs.Duration("duration"); err != nil || v < time.Second {
|
if err = attrs.ValidateSchema(
|
||||||
return errors.New("duration must be of type duration greater or equal one second")
|
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 == "" {
|
if attrs.MustDuration("duration", nil) < time.Second {
|
||||||
return errors.New("reason must be non-empty string")
|
return errors.New("duration must be greater or equal one second")
|
||||||
}
|
|
||||||
|
|
||||||
if err = tplValidator(attrs.MustString("reason", ptrStringEmpty)); err != nil {
|
|
||||||
return errors.Wrap(err, "validating reason template")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -11,6 +11,8 @@ import (
|
||||||
"gopkg.in/irc.v4"
|
"gopkg.in/irc.v4"
|
||||||
"gorm.io/gorm"
|
"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/database"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
@ -144,7 +146,7 @@ func Register(args plugins.RegistrationArguments) (err error) {
|
||||||
|
|
||||||
type actorSetVariable struct{}
|
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)
|
varName, err := formatMessage(attrs.MustString("variable", nil), m, r, eventData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "preparing variable name")
|
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) IsAsync() bool { return false }
|
||||||
func (actorSetVariable) Name() string { return "setvariable" }
|
func (actorSetVariable) Name() string { return "setvariable" }
|
||||||
|
|
||||||
func (actorSetVariable) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
func (actorSetVariable) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
if v, err := attrs.String("variable"); err != nil || v == "" {
|
if err = attrs.ValidateSchema(
|
||||||
return errors.New("variable name must be non-empty string")
|
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}),
|
||||||
for _, field := range []string{"set", "variable"} {
|
helpers.SchemaValidateTemplateField(tplValidator, "set", "variable"),
|
||||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
); err != nil {
|
||||||
return errors.Wrapf(err, "validating %s template", field)
|
return fmt.Errorf("validating attributes: %w", err)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -3,11 +3,14 @@ package vip
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"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/pkg/twitch"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
@ -16,8 +19,6 @@ var (
|
||||||
formatMessage plugins.MsgFormatter
|
formatMessage plugins.MsgFormatter
|
||||||
permCheckFn plugins.ChannelPermissionCheckFunc
|
permCheckFn plugins.ChannelPermissionCheckFunc
|
||||||
tcGetter func(string) (*twitch.Client, error)
|
tcGetter func(string) (*twitch.Client, error)
|
||||||
|
|
||||||
ptrStringEmpty = func(s string) *string { return &s }("")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Register provides the plugins.RegisterFunc
|
// Register provides the plugins.RegisterFunc
|
||||||
|
@ -98,21 +99,19 @@ type (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (actor) IsAsync() bool { return false }
|
func (actor) IsAsync() bool { return false }
|
||||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
for _, field := range []string{"channel", "user"} {
|
if err = attrs.ValidateSchema(
|
||||||
if v, err := attrs.String(field); err != nil || v == "" {
|
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "channel", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||||
return errors.Errorf("%s must be non-empty string", field)
|
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "user", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||||
}
|
helpers.SchemaValidateTemplateField(tplValidator, "channel", "user"),
|
||||||
|
); err != nil {
|
||||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
return fmt.Errorf("validating attributes: %w", err)
|
||||||
return errors.Wrapf(err, "validating %s template", field)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
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 {
|
if channel, err = formatMessage(attrs.MustString("channel", nil), m, r, eventData); err != nil {
|
||||||
return "", "", errors.Wrap(err, "parsing channel")
|
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
|
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)
|
channel, user, err := u.getParams(m, r, eventData, attrs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "getting parameters")
|
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 (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)
|
channel, user, err := v.getParams(m, r, eventData, attrs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "getting parameters")
|
return false, errors.Wrap(err, "getting parameters")
|
||||||
|
|
|
@ -3,10 +3,13 @@ package whisper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"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/pkg/twitch"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
@ -16,8 +19,6 @@ const actorName = "whisper"
|
||||||
var (
|
var (
|
||||||
botTwitchClient *twitch.Client
|
botTwitchClient *twitch.Client
|
||||||
formatMessage plugins.MsgFormatter
|
formatMessage plugins.MsgFormatter
|
||||||
|
|
||||||
ptrStringEmpty = func(s string) *string { return &s }("")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Register provides the plugins.RegisterFunc
|
// Register provides the plugins.RegisterFunc
|
||||||
|
@ -28,7 +29,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||||
args.RegisterActor(actorName, func() plugins.Actor { return &actor{} })
|
args.RegisterActor(actorName, func() plugins.Actor { return &actor{} })
|
||||||
|
|
||||||
args.RegisterActorDocumentation(plugins.ActionDocumentation{
|
args.RegisterActorDocumentation(plugins.ActionDocumentation{
|
||||||
Description: "Send a whisper (requires a verified bot!)",
|
Description: "Send a whisper",
|
||||||
Name: "Send Whisper",
|
Name: "Send Whisper",
|
||||||
Type: "whisper",
|
Type: "whisper",
|
||||||
|
|
||||||
|
@ -59,7 +60,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||||
|
|
||||||
type actor struct{}
|
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)
|
to, err := formatMessage(attrs.MustString("to", nil), m, r, eventData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "preparing whisper receiver")
|
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) IsAsync() bool { return false }
|
||||||
func (actor) Name() string { return actorName }
|
func (actor) Name() string { return actorName }
|
||||||
|
|
||||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
if v, err := attrs.String("to"); err != nil || v == "" {
|
if err = attrs.ValidateSchema(
|
||||||
return errors.New("to must be non-empty string")
|
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"),
|
||||||
if v, err := attrs.String("message"); err != nil || v == "" {
|
); err != nil {
|
||||||
return errors.New("message must be non-empty string")
|
return fmt.Errorf("validating attributes: %w", err)
|
||||||
}
|
|
||||||
|
|
||||||
for _, field := range []string{"message", "to"} {
|
|
||||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
|
||||||
return errors.Wrapf(err, "validating %s template", field)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -1,17 +1,20 @@
|
||||||
package customevent
|
package customevent
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"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"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
type actor struct{}
|
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)
|
fd, err := formatMessage(attrs.MustString("fields", ptrStringEmpty), m, r, eventData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Wrap(err, "executing fields template")
|
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) IsAsync() bool { return false }
|
||||||
func (actor) Name() string { return actorName }
|
func (actor) Name() string { return actorName }
|
||||||
|
|
||||||
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
func (actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
if v, err := attrs.String("fields"); err != nil || v == "" {
|
if err = attrs.ValidateSchema(
|
||||||
return errors.New("fields is expected to be non-empty string")
|
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"),
|
||||||
for _, field := range []string{"fields", "schedule_in"} {
|
); err != nil {
|
||||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
return fmt.Errorf("validating attributes: %w", err)
|
||||||
return errors.Wrapf(err, "validating %s template", field)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gorm.io/gorm"
|
"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/database"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
@ -130,14 +131,14 @@ func handleCreateEvent(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(http.StatusNoContent)
|
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)
|
payload := make(map[string]any)
|
||||||
|
|
||||||
if err := json.NewDecoder(fieldData).Decode(&payload); err != nil {
|
if err := json.NewDecoder(fieldData).Decode(&payload); err != nil {
|
||||||
return nil, errors.Wrap(err, "parsing event payload")
|
return nil, errors.Wrap(err, "parsing event payload")
|
||||||
}
|
}
|
||||||
|
|
||||||
fields := plugins.FieldCollectionFromData(payload)
|
fields := fieldcollection.FieldCollectionFromData(payload)
|
||||||
fields.Set("channel", "#"+strings.TrimLeft(channel, "#"))
|
fields.Set("channel", "#"+strings.TrimLeft(channel, "#"))
|
||||||
|
|
||||||
return fields, nil
|
return fields, nil
|
||||||
|
|
|
@ -9,9 +9,9 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||||
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const cleanupTimeout = 15 * time.Minute
|
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)
|
fieldBuf := new(bytes.Buffer)
|
||||||
if err := json.NewEncoder(fieldBuf).Encode(fields); err != nil {
|
if err := json.NewEncoder(fieldBuf).Encode(fields); err != nil {
|
||||||
return errors.Wrap(err, "marshalling fields")
|
return errors.Wrap(err, "marshalling fields")
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
@ -87,7 +88,7 @@ func handleKoFiPost(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fields := plugins.NewFieldCollection()
|
fields := fieldcollection.NewFieldCollection()
|
||||||
fields.Set("channel", "#"+strings.TrimLeft(channel, "#"))
|
fields.Set("channel", "#"+strings.TrimLeft(channel, "#"))
|
||||||
|
|
||||||
switch payload.Type {
|
switch payload.Type {
|
||||||
|
|
|
@ -10,9 +10,9 @@ import (
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"github.com/Luzifer/go_helpers/v2/backoff"
|
"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/internal/helpers"
|
||||||
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -86,7 +86,7 @@ func getEventByID(db database.Connector, eventID uint64) (socketMessage, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o overlaysEvent) ToSocketMessage() (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 {
|
if err := json.NewDecoder(strings.NewReader(o.Fields)).Decode(fields); err != nil {
|
||||||
return socketMessage{}, errors.Wrap(err, "decoding fields")
|
return socketMessage{}, errors.Wrap(err, "decoding fields")
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"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/pkg/database"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEventDatabaseRoundtrip(t *testing.T) {
|
func TestEventDatabaseRoundtrip(t *testing.T) {
|
||||||
|
@ -30,7 +30,7 @@ func TestEventDatabaseRoundtrip(t *testing.T) {
|
||||||
IsLive: true,
|
IsLive: true,
|
||||||
Time: tEvent2,
|
Time: tEvent2,
|
||||||
Type: "event 2",
|
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.Equal(t, uint64(1), evtID)
|
||||||
assert.NoError(t, err, "adding second event")
|
assert.NoError(t, err, "adding second event")
|
||||||
|
@ -39,7 +39,7 @@ func TestEventDatabaseRoundtrip(t *testing.T) {
|
||||||
IsLive: true,
|
IsLive: true,
|
||||||
Time: tEvent1,
|
Time: tEvent1,
|
||||||
Type: "event 1",
|
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.Equal(t, uint64(2), evtID)
|
||||||
assert.NoError(t, err, "adding first event")
|
assert.NoError(t, err, "adding first event")
|
||||||
|
@ -48,7 +48,7 @@ func TestEventDatabaseRoundtrip(t *testing.T) {
|
||||||
IsLive: true,
|
IsLive: true,
|
||||||
Time: tEvent1,
|
Time: tEvent1,
|
||||||
Type: "event",
|
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.Equal(t, uint64(3), evtID)
|
||||||
assert.NoError(t, err, "adding other channel event")
|
assert.NoError(t, err, "adding other channel event")
|
||||||
|
@ -66,6 +66,6 @@ func TestEventDatabaseRoundtrip(t *testing.T) {
|
||||||
IsLive: false,
|
IsLive: false,
|
||||||
Time: tEvent1,
|
Time: tEvent1,
|
||||||
Type: "event 1",
|
Type: "event 1",
|
||||||
Fields: plugins.FieldCollectionFromData(map[string]any{"foo": "bar"}),
|
Fields: fieldcollection.FieldCollectionFromData(map[string]any{"foo": "bar"}),
|
||||||
}, evt)
|
}, evt)
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||||
"github.com/Luzifer/go_helpers/v2/str"
|
"github.com/Luzifer/go_helpers/v2/str"
|
||||||
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
|
@ -46,7 +47,7 @@ type (
|
||||||
Reason sendReason `json:"reason"`
|
Reason sendReason `json:"reason"`
|
||||||
Time time.Time `json:"time"`
|
Time time.Time `json:"time"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Fields *plugins.FieldCollection `json:"fields"`
|
Fields *fieldcollection.FieldCollection `json:"fields"`
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -180,7 +181,7 @@ func Register(args plugins.RegistrationArguments) (err error) {
|
||||||
return fmt.Errorf("registering API route: %w", err)
|
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()
|
subscribersLock.RLock()
|
||||||
defer subscribersLock.RUnlock()
|
defer subscribersLock.RUnlock()
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
package raffle
|
package raffle
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
@ -17,7 +19,7 @@ var ptrStrEmpty = ptrStr("")
|
||||||
|
|
||||||
func ptrStr(v string) *string { return &v }
|
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) == "" {
|
if m != nil || evtData.MustString("reward_id", ptrStrEmpty) == "" {
|
||||||
return false, errors.New("enter-raffle actor is only supposed to act on channelpoint redeems")
|
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(),
|
EnteredAt: time.Now().UTC(),
|
||||||
}
|
}
|
||||||
|
|
||||||
raffleEventFields := plugins.FieldCollectionFromData(map[string]any{
|
raffleEventFields := fieldcollection.FieldCollectionFromData(map[string]any{
|
||||||
"user_id": re.UserID,
|
"user_id": re.UserID,
|
||||||
"user": re.UserLogin,
|
"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) IsAsync() bool { return false }
|
||||||
func (enterRaffleActor) Name() string { return "enter-raffle" }
|
func (enterRaffleActor) Name() string { return "enter-raffle" }
|
||||||
|
|
||||||
func (enterRaffleActor) Validate(_ plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
func (enterRaffleActor) Validate(_ plugins.TemplateValidatorFunc, attrs *fieldcollection.FieldCollection) (err error) {
|
||||||
keyword, err := attrs.String("keyword")
|
if err = attrs.ValidateSchema(
|
||||||
if err != nil || keyword == "" {
|
fieldcollection.MustHaveField(fieldcollection.SchemaField{Name: "keyword", NonEmpty: true, Type: fieldcollection.SchemaFieldTypeString}),
|
||||||
return errors.New("keyword must be non-empty string")
|
); err != nil {
|
||||||
|
return fmt.Errorf("validating attributes: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -9,9 +9,9 @@ import (
|
||||||
"gopkg.in/irc.v4"
|
"gopkg.in/irc.v4"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||||
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
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.speakUp[strings.Join([]string{r.Channel, winner.UserLogin}, ":")] = &speakUpWait{RaffleEntryID: winner.ID, Until: speakUpUntil}
|
||||||
d.lock.Unlock()
|
d.lock.Unlock()
|
||||||
|
|
||||||
fields := plugins.FieldCollectionFromData(map[string]any{
|
fields := fieldcollection.FieldCollectionFromData(map[string]any{
|
||||||
"user_id": winner.UserID,
|
"user_id": winner.UserID,
|
||||||
"user": winner.UserLogin,
|
"user": winner.UserLogin,
|
||||||
"winner": winner,
|
"winner": winner,
|
||||||
|
@ -636,9 +636,9 @@ func (d *dbClient) Update(r raffle) error {
|
||||||
|
|
||||||
// SendEvent processes the text template and sends the message if
|
// SendEvent processes the text template and sends the message if
|
||||||
// enabled given through the event
|
// 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 {
|
if fields == nil {
|
||||||
fields = plugins.NewFieldCollection()
|
fields = fieldcollection.NewFieldCollection()
|
||||||
}
|
}
|
||||||
|
|
||||||
fields.Set("raffle", r) // Make raffle available to templating
|
fields.Set("raffle", r) // Make raffle available to templating
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"gopkg.in/irc.v4"
|
"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/pkg/twitch"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
@ -95,7 +96,7 @@ func handleRaffleEntry(m *irc.Message, channel, user string) error {
|
||||||
re.UserDisplayName = re.UserLogin
|
re.UserDisplayName = re.UserLogin
|
||||||
}
|
}
|
||||||
|
|
||||||
raffleEventFields := plugins.FieldCollectionFromData(map[string]any{
|
raffleEventFields := fieldcollection.FieldCollectionFromData(map[string]any{
|
||||||
"user_id": m.Tags["user-id"],
|
"user_id": m.Tags["user-id"],
|
||||||
"user": user,
|
"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
|
package userstate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"gopkg.in/irc.v4"
|
||||||
|
@ -16,7 +17,7 @@ func Register(args plugins.RegistrationArguments) error {
|
||||||
return errors.Wrap(err, "registering raw message handler")
|
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 {
|
return func(badge string) bool {
|
||||||
state := userState.Get(plugins.DeriveChannel(m, fields))
|
state := userState.Get(plugins.DeriveChannel(m, fields))
|
||||||
if state == nil {
|
if state == nil {
|
||||||
|
|
15
irc.go
15
irc.go
|
@ -13,6 +13,7 @@ import (
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"gopkg.in/irc.v4"
|
"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/pkg/twitch"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
@ -226,7 +227,7 @@ func (i ircHandler) handleClearChat(m *irc.Message) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
evt *string
|
evt *string
|
||||||
fields = plugins.NewFieldCollection()
|
fields = fieldcollection.NewFieldCollection()
|
||||||
)
|
)
|
||||||
|
|
||||||
fields.Set(eventFieldChannel, i.getChannel(m)) // Compatibility to plugins.DeriveChannel
|
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) {
|
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
|
eventFieldChannel: i.getChannel(m), // Compatibility to plugins.DeriveChannel
|
||||||
"message_id": m.Tags["target-msg-id"],
|
"message_id": m.Tags["target-msg-id"],
|
||||||
"target_name": m.Tags["login"],
|
"target_name": m.Tags["login"],
|
||||||
|
@ -270,7 +271,7 @@ func (i ircHandler) handleClearMessage(m *irc.Message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i ircHandler) handleJoin(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
|
eventFieldChannel: i.getChannel(m), // Compatibility to plugins.DeriveChannel
|
||||||
eventFieldUserName: m.User, // Compatibility to plugins.DeriveUser
|
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) {
|
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
|
eventFieldChannel: i.getChannel(m), // Compatibility to plugins.DeriveChannel
|
||||||
eventFieldUserName: m.User, // Compatibility to plugins.DeriveUser
|
eventFieldUserName: m.User, // Compatibility to plugins.DeriveUser
|
||||||
})
|
})
|
||||||
|
@ -299,7 +300,7 @@ func (i ircHandler) handlePermit(m *irc.Message) {
|
||||||
|
|
||||||
username := msgParts[1]
|
username := msgParts[1]
|
||||||
|
|
||||||
fields := plugins.FieldCollectionFromData(map[string]interface{}{
|
fields := fieldcollection.FieldCollectionFromData(map[string]interface{}{
|
||||||
eventFieldChannel: i.getChannel(m), // Compatibility to plugins.DeriveChannel
|
eventFieldChannel: i.getChannel(m), // Compatibility to plugins.DeriveChannel
|
||||||
eventFieldUserName: m.User, // Compatibility to plugins.DeriveUser
|
eventFieldUserName: m.User, // Compatibility to plugins.DeriveUser
|
||||||
eventFieldUserID: m.Tags["user-id"],
|
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 {
|
if bits := i.tagToNumeric(m, "bits", 0); bits > 0 {
|
||||||
fields := plugins.FieldCollectionFromData(map[string]interface{}{
|
fields := fieldcollection.FieldCollectionFromData(map[string]interface{}{
|
||||||
"bits": bits,
|
"bits": bits,
|
||||||
eventFieldChannel: i.getChannel(m), // Compatibility to plugins.DeriveChannel
|
eventFieldChannel: i.getChannel(m), // Compatibility to plugins.DeriveChannel
|
||||||
"message": m.Trailing(),
|
"message": m.Trailing(),
|
||||||
|
@ -380,7 +381,7 @@ func (i ircHandler) handleTwitchUsernotice(m *irc.Message) {
|
||||||
"trailing": m.Trailing(),
|
"trailing": m.Trailing(),
|
||||||
}).Trace("IRC USERNOTICE event")
|
}).Trace("IRC USERNOTICE event")
|
||||||
|
|
||||||
evtData := plugins.FieldCollectionFromData(map[string]any{
|
evtData := fieldcollection.FieldCollectionFromData(map[string]any{
|
||||||
eventFieldChannel: i.getChannel(m), // Compatibility to plugins.DeriveChannel
|
eventFieldChannel: i.getChannel(m), // Compatibility to plugins.DeriveChannel
|
||||||
eventFieldUserName: m.Tags["login"], // Compatibility to plugins.DeriveUser
|
eventFieldUserName: m.Tags["login"], // Compatibility to plugins.DeriveUser
|
||||||
eventFieldUserID: m.Tags["user-id"],
|
eventFieldUserID: m.Tags["user-id"],
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/irc.v4"
|
"gopkg.in/irc.v4"
|
||||||
|
|
||||||
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -19,7 +20,7 @@ var (
|
||||||
|
|
||||||
stripNewline = regexp.MustCompile(`(?m)\s*\n\s*`)
|
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,
|
formatMessageFieldChannel,
|
||||||
formatMessageFieldMessage,
|
formatMessageFieldMessage,
|
||||||
formatMessageFieldUserID,
|
formatMessageFieldUserID,
|
||||||
|
@ -27,8 +28,8 @@ var (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func formatMessage(tplString string, m *irc.Message, r *plugins.Rule, fields *plugins.FieldCollection) (string, error) {
|
func formatMessage(tplString string, m *irc.Message, r *plugins.Rule, fields *fieldcollection.FieldCollection) (string, error) {
|
||||||
compiledFields := plugins.NewFieldCollection()
|
compiledFields := fieldcollection.NewFieldCollection()
|
||||||
|
|
||||||
if config != nil {
|
if config != nil {
|
||||||
configLock.RLock()
|
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")
|
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))
|
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 {
|
if m == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -73,7 +74,7 @@ func formatMessageFieldMessage(compiledFields *plugins.FieldCollection, m *irc.M
|
||||||
compiledFields.Set("msg", 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 {
|
if m == nil {
|
||||||
return
|
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))
|
compiledFields.Set("username", plugins.DeriveUser(m, fields))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +94,7 @@ func validateTemplate(tplString string) error {
|
||||||
|
|
||||||
_, err := template.
|
_, err := template.
|
||||||
New(tplString).
|
New(tplString).
|
||||||
Funcs(tplFuncs.GetFuncMap(nil, nil, plugins.NewFieldCollection())).
|
Funcs(tplFuncs.GetFuncMap(nil, nil, fieldcollection.NewFieldCollection())).
|
||||||
Parse(tplString)
|
Parse(tplString)
|
||||||
return errors.Wrap(err, "parsing template")
|
return errors.Wrap(err, "parsing template")
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package plugins
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,9 +17,9 @@ type (
|
||||||
// (not returning ErrValueNotSet) and does not contain zero value
|
// (not returning ErrValueNotSet) and does not contain zero value
|
||||||
// recognized by reflect (to just check whether the field is set
|
// recognized by reflect (to just check whether the field is set
|
||||||
// but allow zero values use HasAll on the FieldCollection)
|
// 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 {
|
for _, field := range fields {
|
||||||
v, err := attrs.Any(field)
|
v, err := attrs.Get(field)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "getting field %s", field)
|
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
|
// ValidateRequireValidTemplate checks whether fields are gettable
|
||||||
// as strings and do have a template which validates (this does not
|
// as strings and do have a template which validates (this does not
|
||||||
// check for empty strings as an empty template is indeed valid)
|
// 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 {
|
for _, field := range fields {
|
||||||
v, err := attrs.String(field)
|
v, err := attrs.String(field)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -52,11 +53,11 @@ func (ActorKit) ValidateRequireValidTemplate(tplValidator TemplateValidatorFunc,
|
||||||
// ValidateRequireValidTemplateIfSet checks whether the field is
|
// ValidateRequireValidTemplateIfSet checks whether the field is
|
||||||
// either not set or a valid template (this does not
|
// either not set or a valid template (this does not
|
||||||
// check for empty strings as an empty template is indeed valid)
|
// 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 {
|
for _, field := range fields {
|
||||||
v, err := attrs.String(field)
|
v, err := attrs.String(field)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, ErrValueNotSet) {
|
if errors.Is(err, fieldcollection.ErrValueNotSet) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return errors.Wrapf(err, "getting string field %s", field)
|
return errors.Wrapf(err, "getting string field %s", field)
|
||||||
|
|
|
@ -4,11 +4,12 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestValidateRequireNonEmpty(t *testing.T) {
|
func TestValidateRequireNonEmpty(t *testing.T) {
|
||||||
attrs := FieldCollectionFromData(map[string]any{
|
attrs := fieldcollection.FieldCollectionFromData(map[string]any{
|
||||||
"str": "",
|
"str": "",
|
||||||
"str_v": "valid",
|
"str_v": "valid",
|
||||||
"int": 0,
|
"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"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||||
"gopkg.in/irc.v4"
|
"gopkg.in/irc.v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DeriveChannel takes an irc.Message and a FieldCollection and tries
|
// DeriveChannel takes an irc.Message and a FieldCollection and tries
|
||||||
// to extract from them the channel the event / message has taken place
|
// 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], "#") {
|
if m != nil && len(m.Params) > 0 && strings.HasPrefix(m.Params[0], "#") {
|
||||||
return 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
|
// DeriveUser takes an irc.Message and a FieldCollection and tries
|
||||||
// to extract from them the user causing the event / message
|
// 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 != "" {
|
if m != nil && m.User != "" {
|
||||||
return m.User
|
return m.User
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"gopkg.in/irc.v4"
|
"gopkg.in/irc.v4"
|
||||||
"gorm.io/gorm"
|
"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/database"
|
||||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
"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 defines an interface to implement in the plugin for actors
|
||||||
Actor interface {
|
Actor interface {
|
||||||
// Execute will be called after the config was read into the Actor
|
// 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
|
// 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
|
// in a Go routine as of long runtime. Normally it should return false
|
||||||
// except in very specific cases
|
// except in very specific cases
|
||||||
|
@ -26,7 +27,7 @@ type (
|
||||||
// Validate will be called to validate the loaded configuration. It should
|
// Validate will be called to validate the loaded configuration. It should
|
||||||
// return an error if required keys are missing from the AttributeStore
|
// return an error if required keys are missing from the AttributeStore
|
||||||
// or if keys contain broken configs
|
// 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
|
// 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
|
// EventHandlerFunc defines the type of function required to listen
|
||||||
// for events
|
// 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
|
// EventHandlerRegisterFunc is passed from the bot to the
|
||||||
// plugins RegisterFunc to register a new event handler function
|
// plugins RegisterFunc to register a new event handler function
|
||||||
// which is then fed with all events occurring in the bot
|
// which is then fed with all events occurring in the bot
|
||||||
|
@ -76,12 +77,12 @@ type (
|
||||||
// ModuleConfigGetterFunc is passed from the bot to the
|
// ModuleConfigGetterFunc is passed from the bot to the
|
||||||
// plugins RegisterFunc to fetch module generic or channel specific
|
// plugins RegisterFunc to fetch module generic or channel specific
|
||||||
// configuration from the module configuration
|
// 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
|
// MsgFormatter is passed from the bot to the
|
||||||
// plugins RegisterFunc to format messages using all registered and
|
// plugins RegisterFunc to format messages using all registered and
|
||||||
// available template functions
|
// 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
|
// MsgModificationFunc can be used to modify messages between the
|
||||||
// plugins generating them and the bot sending them to the Twitch
|
// 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
|
// TemplateFuncGetter is the type of function to implement in the
|
||||||
// plugin to create a new template function on request of the bot
|
// 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
|
// TemplateFuncRegister is passed from the bot to the
|
||||||
// plugins RegisterFunc to register a new TemplateFuncGetter
|
// plugins RegisterFunc to register a new TemplateFuncGetter
|
||||||
TemplateFuncRegister func(name string, fg TemplateFuncGetter, doc ...TemplateFuncDocumentation)
|
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
|
// requiring access to the irc.Message, Rule or FieldCollection to
|
||||||
// satisfy the TemplateFuncGetter interface
|
// satisfy the TemplateFuncGetter interface
|
||||||
func GenericTemplateFunctionGetter(f any) TemplateFuncGetter {
|
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
|
package plugins
|
||||||
|
|
||||||
import "strings"
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||||
|
)
|
||||||
|
|
||||||
// DefaultConfigName is the name the default configuration must have
|
// DefaultConfigName is the name the default configuration must have
|
||||||
// when defined
|
// when defined
|
||||||
|
@ -9,16 +13,16 @@ const DefaultConfigName = "default"
|
||||||
type (
|
type (
|
||||||
// ModuleConfig represents a mapping of configurations per channel
|
// ModuleConfig represents a mapping of configurations per channel
|
||||||
// and module
|
// and module
|
||||||
ModuleConfig map[string]map[string]*FieldCollection
|
ModuleConfig map[string]map[string]*fieldcollection.FieldCollection
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetChannelConfig reads the channel specific configuration for the
|
// GetChannelConfig reads the channel specific configuration for the
|
||||||
// given module. This is created by taking an empty FieldCollection,
|
// given module. This is created by taking an empty FieldCollection,
|
||||||
// merging in the default configuration and finally overwriting all
|
// merging in the default configuration and finally overwriting all
|
||||||
// existing channel configurations.
|
// existing channel configurations.
|
||||||
func (m ModuleConfig) GetChannelConfig(module, channel string) *FieldCollection {
|
func (m ModuleConfig) GetChannelConfig(module, channel string) *fieldcollection.FieldCollection {
|
||||||
channel = strings.TrimLeft(channel, "#@")
|
channel = strings.TrimLeft(channel, "#@")
|
||||||
composed := NewFieldCollection()
|
composed := fieldcollection.NewFieldCollection()
|
||||||
|
|
||||||
for _, i := range []string{DefaultConfigName, channel} {
|
for _, i := range []string{DefaultConfigName, channel} {
|
||||||
f := m[module][i]
|
f := m[module][i]
|
||||||
|
|
|
@ -3,6 +3,7 @@ package plugins
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
@ -10,12 +11,12 @@ import (
|
||||||
func TestModuleConfigGet(t *testing.T) {
|
func TestModuleConfigGet(t *testing.T) {
|
||||||
strPtrEmpty := func(v string) *string { return &v }("")
|
strPtrEmpty := func(v string) *string { return &v }("")
|
||||||
m := ModuleConfig{
|
m := ModuleConfig{
|
||||||
"test": map[string]*FieldCollection{
|
"test": map[string]*fieldcollection.FieldCollection{
|
||||||
DefaultConfigName: FieldCollectionFromData(map[string]any{
|
DefaultConfigName: fieldcollection.FieldCollectionFromData(map[string]any{
|
||||||
"setindefault": DefaultConfigName,
|
"setindefault": DefaultConfigName,
|
||||||
"setinboth": DefaultConfigName,
|
"setinboth": DefaultConfigName,
|
||||||
}),
|
}),
|
||||||
"test": FieldCollectionFromData(map[string]any{
|
"test": fieldcollection.FieldCollectionFromData(map[string]any{
|
||||||
"setinchannel": "channel",
|
"setinchannel": "channel",
|
||||||
"setinboth": "channel",
|
"setinboth": "channel",
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"gopkg.in/irc.v4"
|
"gopkg.in/irc.v4"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||||
"github.com/Luzifer/go_helpers/v2/str"
|
"github.com/Luzifer/go_helpers/v2/str"
|
||||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||||
)
|
)
|
||||||
|
@ -74,7 +75,7 @@ type (
|
||||||
// RuleAction represents an action to be executed when running a Rule
|
// RuleAction represents an action to be executed when running a Rule
|
||||||
RuleAction struct {
|
RuleAction struct {
|
||||||
Type string `json:"type" yaml:"type,omitempty"`
|
Type string `json:"type" yaml:"type,omitempty"`
|
||||||
Attributes *FieldCollection `json:"attributes" yaml:"attributes,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
|
// 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.msgFormatter = msgFormatter
|
||||||
r.timerStore = timerStore
|
r.timerStore = timerStore
|
||||||
r.twitchClient = twitchClient
|
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.allowExecuteDisable,
|
||||||
r.allowExecuteChannelWhitelist,
|
r.allowExecuteChannelWhitelist,
|
||||||
r.allowExecuteUserWhitelist,
|
r.allowExecuteUserWhitelist,
|
||||||
|
@ -144,7 +145,7 @@ func (r *Rule) GetMatchMessage() *regexp.Regexp {
|
||||||
|
|
||||||
// SetCooldown uses the given TimerStore to set the cooldowns for the
|
// SetCooldown uses the given TimerStore to set the cooldowns for the
|
||||||
// Rule after execution
|
// 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
|
var err error
|
||||||
|
|
||||||
if r.Cooldown != nil {
|
if r.Cooldown != nil {
|
||||||
|
@ -250,7 +251,7 @@ func (r Rule) Validate(tplValidate TemplateValidatorFunc) error {
|
||||||
return nil
|
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 {
|
for _, b := range r.DisableOn {
|
||||||
if badges.Has(b) {
|
if badges.Has(b) {
|
||||||
logger.Tracef("Non-Match: Disable-Badge %s", b)
|
logger.Tracef("Non-Match: Disable-Badge %s", b)
|
||||||
|
@ -261,7 +262,7 @@ func (r *Rule) allowExecuteBadgeBlacklist(logger *logrus.Entry, _ *irc.Message,
|
||||||
return true
|
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 {
|
if len(r.EnableOn) == 0 {
|
||||||
// No match criteria set, does not speak against matching
|
// No match criteria set, does not speak against matching
|
||||||
return true
|
return true
|
||||||
|
@ -276,7 +277,7 @@ func (r *Rule) allowExecuteBadgeWhitelist(_ *logrus.Entry, _ *irc.Message, _ *st
|
||||||
return false
|
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) == "" {
|
if r.ChannelCooldown == nil || DeriveChannel(m, evtData) == "" {
|
||||||
// No match criteria set, does not speak against matching
|
// No match criteria set, does not speak against matching
|
||||||
return true
|
return true
|
||||||
|
@ -301,7 +302,7 @@ func (r *Rule) allowExecuteChannelCooldown(logger *logrus.Entry, m *irc.Message,
|
||||||
return false
|
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 {
|
if len(r.MatchChannels) == 0 {
|
||||||
// No match criteria set, does not speak against matching
|
// No match criteria set, does not speak against matching
|
||||||
return true
|
return true
|
||||||
|
@ -315,7 +316,7 @@ func (r *Rule) allowExecuteChannelWhitelist(logger *logrus.Entry, m *irc.Message
|
||||||
return true
|
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 {
|
if r.Disable == nil {
|
||||||
// No match criteria set, does not speak against matching
|
// No match criteria set, does not speak against matching
|
||||||
return true
|
return true
|
||||||
|
@ -329,7 +330,7 @@ func (r *Rule) allowExecuteDisable(logger *logrus.Entry, _ *irc.Message, _ *stri
|
||||||
return true
|
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) == "" {
|
if r.DisableOnOffline == nil || !*r.DisableOnOffline || DeriveChannel(m, evtData) == "" {
|
||||||
// No match criteria set, does not speak against matching
|
// No match criteria set, does not speak against matching
|
||||||
return true
|
return true
|
||||||
|
@ -348,7 +349,7 @@ func (r *Rule) allowExecuteDisableOnOffline(logger *logrus.Entry, m *irc.Message
|
||||||
return true
|
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))
|
hasPermit, err := r.timerStore.HasPermit(DeriveChannel(m, evtData), DeriveUser(m, evtData))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Error("checking permit")
|
logger.WithError(err).Error("checking permit")
|
||||||
|
@ -363,7 +364,7 @@ func (r *Rule) allowExecuteDisableOnPermit(logger *logrus.Entry, m *irc.Message,
|
||||||
return true
|
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 == "" {
|
if r.DisableOnTemplate == nil || *r.DisableOnTemplate == "" {
|
||||||
// No match criteria set, does not speak against matching
|
// No match criteria set, does not speak against matching
|
||||||
return true
|
return true
|
||||||
|
@ -384,7 +385,7 @@ func (r *Rule) allowExecuteDisableOnTemplate(logger *logrus.Entry, m *irc.Messag
|
||||||
return true
|
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
|
// 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
|
// event to match. We now need to ensure this match is valid for
|
||||||
// the current execution:
|
// the current execution:
|
||||||
|
@ -430,7 +431,7 @@ func (r *Rule) allowExecuteEventMatch(logger *logrus.Entry, _ *irc.Message, even
|
||||||
return false
|
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 {
|
if len(r.DisableOnMatchMessages) == 0 {
|
||||||
// No match criteria set, does not speak against matching
|
// No match criteria set, does not speak against matching
|
||||||
return true
|
return true
|
||||||
|
@ -459,7 +460,7 @@ func (r *Rule) allowExecuteMessageMatcherBlacklist(logger *logrus.Entry, m *irc.
|
||||||
return true
|
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 {
|
if r.MatchMessage == nil {
|
||||||
// No match criteria set, does not speak against matching
|
// No match criteria set, does not speak against matching
|
||||||
return true
|
return true
|
||||||
|
@ -484,7 +485,7 @@ func (r *Rule) allowExecuteMessageMatcherWhitelist(logger *logrus.Entry, m *irc.
|
||||||
return true
|
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 {
|
if r.Cooldown == nil {
|
||||||
// No match criteria set, does not speak against matching
|
// No match criteria set, does not speak against matching
|
||||||
return true
|
return true
|
||||||
|
@ -509,7 +510,7 @@ func (r *Rule) allowExecuteRuleCooldown(logger *logrus.Entry, _ *irc.Message, _
|
||||||
return false
|
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 {
|
if r.UserCooldown == nil {
|
||||||
// No match criteria set, does not speak against matching
|
// No match criteria set, does not speak against matching
|
||||||
return true
|
return true
|
||||||
|
@ -534,7 +535,7 @@ func (r *Rule) allowExecuteUserCooldown(logger *logrus.Entry, m *irc.Message, _
|
||||||
return false
|
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 {
|
if len(r.MatchUsers) == 0 {
|
||||||
// No match criteria set, does not speak against matching
|
// No match criteria set, does not speak against matching
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"gopkg.in/irc.v4"
|
"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/pkg/twitch"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -141,7 +142,7 @@ func TestAllowExecuteDisableOnTemplate(t *testing.T) {
|
||||||
} {
|
} {
|
||||||
// We don't test the message formatter here but only the disable functionality
|
// We don't test the message formatter here but only the disable functionality
|
||||||
// so we fake the result of the evaluation
|
// 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
|
return msg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"gopkg.in/irc.v4"
|
"gopkg.in/irc.v4"
|
||||||
|
|
||||||
"github.com/Luzifer/go_helpers/v2/backoff"
|
"github.com/Luzifer/go_helpers/v2/backoff"
|
||||||
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||||
"github.com/Luzifer/go_helpers/v2/str"
|
"github.com/Luzifer/go_helpers/v2/str"
|
||||||
"github.com/Luzifer/twitch-bot/v3/internal/actors/announce"
|
"github.com/Luzifer/twitch-bot/v3/internal/actors/announce"
|
||||||
"github.com/Luzifer/twitch-bot/v3/internal/actors/ban"
|
"github.com/Luzifer/twitch-bot/v3/internal/actors/ban"
|
||||||
|
@ -181,12 +182,12 @@ func getRegistrationArguments() plugins.RegistrationArguments {
|
||||||
SendMessage: sendMessage,
|
SendMessage: sendMessage,
|
||||||
ValidateToken: authService.ValidateTokenFor,
|
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)
|
handleMessage(ircHdl.Client(), nil, &evt, eventData)
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
|
||||||
GetModuleConfigForChannel: func(module, channel string) *plugins.FieldCollection {
|
GetModuleConfigForChannel: func(module, channel string) *fieldcollection.FieldCollection {
|
||||||
return config.ModuleConfig.GetChannelConfig(module, channel)
|
return config.ModuleConfig.GetChannelConfig(module, channel)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"gopkg.in/irc.v4"
|
"gopkg.in/irc.v4"
|
||||||
|
|
||||||
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -88,7 +89,7 @@ func generateTplDocsRender(e *plugins.TemplateFuncDocumentationExample) (string,
|
||||||
rule.MatchMessage = &e.MatchMessage
|
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,
|
"testDuration": 5*time.Hour + 33*time.Minute + 12*time.Second,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,10 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
log "github.com/sirupsen/logrus"
|
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/helpers"
|
||||||
"github.com/Luzifer/twitch-bot/v3/internal/service/access"
|
"github.com/Luzifer/twitch-bot/v3/internal/service/access"
|
||||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -241,7 +241,7 @@ func (*twitchWatcher) handleEventSubChannelAdBreakBegin(m json.RawMessage) error
|
||||||
return errors.Wrap(err, "unmarshalling event")
|
return errors.Wrap(err, "unmarshalling event")
|
||||||
}
|
}
|
||||||
|
|
||||||
fields := plugins.FieldCollectionFromData(map[string]any{
|
fields := fieldcollection.FieldCollectionFromData(map[string]any{
|
||||||
"channel": "#" + payload.BroadcasterUserLogin,
|
"channel": "#" + payload.BroadcasterUserLogin,
|
||||||
"duration": payload.Duration,
|
"duration": payload.Duration,
|
||||||
"is_automatic": payload.IsAutomatic,
|
"is_automatic": payload.IsAutomatic,
|
||||||
|
@ -260,7 +260,7 @@ func (*twitchWatcher) handleEventSubChannelFollow(m json.RawMessage) error {
|
||||||
return errors.Wrap(err, "unmarshalling event")
|
return errors.Wrap(err, "unmarshalling event")
|
||||||
}
|
}
|
||||||
|
|
||||||
fields := plugins.FieldCollectionFromData(map[string]interface{}{
|
fields := fieldcollection.FieldCollectionFromData(map[string]interface{}{
|
||||||
"channel": "#" + payload.BroadcasterUserLogin,
|
"channel": "#" + payload.BroadcasterUserLogin,
|
||||||
"followed_at": payload.FollowedAt,
|
"followed_at": payload.FollowedAt,
|
||||||
"user_id": payload.UserID,
|
"user_id": payload.UserID,
|
||||||
|
@ -279,7 +279,7 @@ func (*twitchWatcher) handleEventSubChannelPointCustomRewardRedemptionAdd(m json
|
||||||
return errors.Wrap(err, "unmarshalling event")
|
return errors.Wrap(err, "unmarshalling event")
|
||||||
}
|
}
|
||||||
|
|
||||||
fields := plugins.FieldCollectionFromData(map[string]interface{}{
|
fields := fieldcollection.FieldCollectionFromData(map[string]interface{}{
|
||||||
"channel": "#" + payload.BroadcasterUserLogin,
|
"channel": "#" + payload.BroadcasterUserLogin,
|
||||||
"reward_cost": payload.Reward.Cost,
|
"reward_cost": payload.Reward.Cost,
|
||||||
"reward_id": payload.Reward.ID,
|
"reward_id": payload.Reward.ID,
|
||||||
|
@ -302,7 +302,7 @@ func (*twitchWatcher) handleEventSubChannelOutboundRaid(m json.RawMessage) error
|
||||||
return errors.Wrap(err, "unmarshalling event")
|
return errors.Wrap(err, "unmarshalling event")
|
||||||
}
|
}
|
||||||
|
|
||||||
fields := plugins.FieldCollectionFromData(map[string]interface{}{
|
fields := fieldcollection.FieldCollectionFromData(map[string]interface{}{
|
||||||
"channel": "#" + payload.FromBroadcasterUserLogin,
|
"channel": "#" + payload.FromBroadcasterUserLogin,
|
||||||
"to_id": payload.ToBroadcasterUserID,
|
"to_id": payload.ToBroadcasterUserID,
|
||||||
"to": payload.ToBroadcasterUserLogin,
|
"to": payload.ToBroadcasterUserLogin,
|
||||||
|
@ -333,7 +333,7 @@ func (*twitchWatcher) handleEventSubChannelPollChange(event *string) func(json.R
|
||||||
return errors.Wrap(err, "unmarshalling event")
|
return errors.Wrap(err, "unmarshalling event")
|
||||||
}
|
}
|
||||||
|
|
||||||
fields := plugins.FieldCollectionFromData(map[string]any{
|
fields := fieldcollection.FieldCollectionFromData(map[string]any{
|
||||||
"channel": "#" + payload.BroadcasterUserLogin,
|
"channel": "#" + payload.BroadcasterUserLogin,
|
||||||
"hasChannelPointVoting": payload.ChannelPointsVoting.IsEnabled,
|
"hasChannelPointVoting": payload.ChannelPointsVoting.IsEnabled,
|
||||||
"title": payload.Title,
|
"title": payload.Title,
|
||||||
|
@ -370,7 +370,7 @@ func (*twitchWatcher) handleEventSubHypetrainEvent(eventType *string) func(json.
|
||||||
return errors.Wrap(err, "unmarshalling event")
|
return errors.Wrap(err, "unmarshalling event")
|
||||||
}
|
}
|
||||||
|
|
||||||
fields := plugins.FieldCollectionFromData(map[string]any{
|
fields := fieldcollection.FieldCollectionFromData(map[string]any{
|
||||||
"channel": "#" + payload.BroadcasterUserLogin,
|
"channel": "#" + payload.BroadcasterUserLogin,
|
||||||
"level": payload.Level,
|
"level": payload.Level,
|
||||||
})
|
})
|
||||||
|
@ -394,7 +394,7 @@ func (*twitchWatcher) handleEventSubShoutoutCreated(m json.RawMessage) error {
|
||||||
return errors.Wrap(err, "unmarshalling event")
|
return errors.Wrap(err, "unmarshalling event")
|
||||||
}
|
}
|
||||||
|
|
||||||
fields := plugins.FieldCollectionFromData(map[string]any{
|
fields := fieldcollection.FieldCollectionFromData(map[string]any{
|
||||||
"channel": "#" + payload.BroadcasterUserLogin,
|
"channel": "#" + payload.BroadcasterUserLogin,
|
||||||
"to_id": payload.ToBroadcasterUserID,
|
"to_id": payload.ToBroadcasterUserID,
|
||||||
"to": payload.ToBroadcasterUserLogin,
|
"to": payload.ToBroadcasterUserLogin,
|
||||||
|
@ -413,7 +413,7 @@ func (*twitchWatcher) handleEventSubShoutoutReceived(m json.RawMessage) error {
|
||||||
return errors.Wrap(err, "unmarshalling event")
|
return errors.Wrap(err, "unmarshalling event")
|
||||||
}
|
}
|
||||||
|
|
||||||
fields := plugins.FieldCollectionFromData(map[string]any{
|
fields := fieldcollection.FieldCollectionFromData(map[string]any{
|
||||||
"channel": "#" + payload.BroadcasterUserLogin,
|
"channel": "#" + payload.BroadcasterUserLogin,
|
||||||
"from_id": payload.FromBroadcasterUserID,
|
"from_id": payload.FromBroadcasterUserID,
|
||||||
"from": payload.FromBroadcasterUserLogin,
|
"from": payload.FromBroadcasterUserLogin,
|
||||||
|
@ -570,7 +570,7 @@ func (t *twitchWatcher) triggerUpdate(channel string, title, category *string, o
|
||||||
"channel": channel,
|
"channel": channel,
|
||||||
"category": *category,
|
"category": *category,
|
||||||
}).Info("Category updated")
|
}).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,
|
"channel": "#" + channel,
|
||||||
"category": *category,
|
"category": *category,
|
||||||
}))
|
}))
|
||||||
|
@ -582,7 +582,7 @@ func (t *twitchWatcher) triggerUpdate(channel string, title, category *string, o
|
||||||
"channel": channel,
|
"channel": channel,
|
||||||
"title": *title,
|
"title": *title,
|
||||||
}).Info("Title updated")
|
}).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,
|
"channel": "#" + channel,
|
||||||
"title": *title,
|
"title": *title,
|
||||||
}))
|
}))
|
||||||
|
@ -600,7 +600,7 @@ func (t *twitchWatcher) triggerUpdate(channel string, title, category *string, o
|
||||||
evt = eventTypeTwitchStreamOffline
|
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,
|
"channel": "#" + channel,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue