mirror of
https://github.com/Luzifer/twitch-bot.git
synced 2024-12-20 11:51:17 +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
|
@ -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"))+
|
return errors.New("no conditions are provided")
|
||||||
len(attrs.MustStringSlice("disallowed_links"))+
|
}
|
||||||
len(attrs.MustStringSlice("allowed_clip_channels"))+
|
return nil
|
||||||
len(attrs.MustStringSlice("disallowed_clip_channels")) == 0 {
|
},
|
||||||
return errors.New("no conditions are provided")
|
); 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"
|
||||||
|
@ -25,11 +28,9 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
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"
|
||||||
|
@ -41,12 +42,12 @@ type (
|
||||||
|
|
||||||
// socketMessage represents the message overlay sockets will receive
|
// socketMessage represents the message overlay sockets will receive
|
||||||
socketMessage struct {
|
socketMessage struct {
|
||||||
EventID uint64 `json:"event_id"`
|
EventID uint64 `json:"event_id"`
|
||||||
IsLive bool `json:"is_live"`
|
IsLive bool `json:"is_live"`
|
||||||
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"
|
||||||
)
|
)
|
||||||
|
@ -73,8 +74,8 @@ 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