mirror of
https://github.com/Luzifer/twitch-bot.git
synced 2024-12-20 11:51:17 +00:00
[core] Add config validation command
- Fix missing field validation for required fields - Add validation of template fields - Report all issues in configuration Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
ae7879447e
commit
2c71f57d02
23 changed files with 180 additions and 29 deletions
|
@ -37,6 +37,7 @@ Supported sub-commands are:
|
|||
actor-docs Generate markdown documentation for available actors
|
||||
api-token <name> <scope...> Generate an api-token to be entered into the config
|
||||
migrate-v2 <old file> Migrate old (*.json.gz) storage file into new database
|
||||
validate-config Try to load configuration file and report errors if any
|
||||
help Prints this help message
|
||||
```
|
||||
|
||||
|
|
|
@ -124,10 +124,17 @@ func (a ActorScript) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eve
|
|||
func (a ActorScript) IsAsync() bool { return false }
|
||||
func (a ActorScript) Name() string { return "script" }
|
||||
|
||||
func (a ActorScript) Validate(attrs *plugins.FieldCollection) (err error) {
|
||||
if cmd, err := attrs.StringSlice("command"); err != nil || len(cmd) == 0 {
|
||||
func (a ActorScript) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
cmd, err := attrs.StringSlice("command")
|
||||
if err != nil || len(cmd) == 0 {
|
||||
return errors.New("command must be slice of strings with length > 0")
|
||||
}
|
||||
|
||||
for i, el := range cmd {
|
||||
if err = tplValidator(el); err != nil {
|
||||
return errors.Wrapf(err, "validating cmd template (element %d)", i)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
19
config.go
19
config.go
|
@ -357,21 +357,34 @@ func (c *configFile) updateAutoMessagesFromConfig(old *configFile) {
|
|||
}
|
||||
|
||||
func (c configFile) validateRuleActions() error {
|
||||
var hasError bool
|
||||
|
||||
for _, r := range c.Rules {
|
||||
logger := log.WithField("rule", r.MatcherID())
|
||||
|
||||
if err := r.Validate(validateTemplate); err != nil {
|
||||
logger.WithError(err).Error("Rule reported invalid config")
|
||||
hasError = true
|
||||
}
|
||||
|
||||
for idx, a := range r.Actions {
|
||||
actor, err := getActorByName(a.Type)
|
||||
if err != nil {
|
||||
logger.WithField("index", idx).WithError(err).Error("Cannot get actor by type")
|
||||
return errors.Wrap(err, "getting actor by type")
|
||||
hasError = true
|
||||
continue
|
||||
}
|
||||
|
||||
if err = actor.Validate(a.Attributes); err != nil {
|
||||
if err = actor.Validate(validateTemplate, a.Attributes); err != nil {
|
||||
logger.WithField("index", idx).WithError(err).Error("Actor reported invalid config")
|
||||
return errors.Wrap(err, "validating action attributes")
|
||||
hasError = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if hasError {
|
||||
return errors.New("config validation reported errors, see log")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -103,7 +103,18 @@ func (a actor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData
|
|||
func (a actor) IsAsync() bool { return false }
|
||||
func (a actor) Name() string { return actorName }
|
||||
|
||||
func (a actor) Validate(attrs *plugins.FieldCollection) (err error) { return nil }
|
||||
func (a actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
reasonTemplate, err := attrs.String("reason")
|
||||
if err != nil || reasonTemplate == "" {
|
||||
return errors.New("reason must be non-empty string")
|
||||
}
|
||||
|
||||
if err = tplValidator(reasonTemplate); err != nil {
|
||||
return errors.Wrap(err, "validating reason template")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleAPIBan(w http.ResponseWriter, r *http.Request) {
|
||||
var (
|
||||
|
|
|
@ -187,11 +187,17 @@ func (a ActorCounter) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, ev
|
|||
func (a ActorCounter) IsAsync() bool { return false }
|
||||
func (a ActorCounter) Name() string { return "counter" }
|
||||
|
||||
func (a ActorCounter) Validate(attrs *plugins.FieldCollection) (err error) {
|
||||
func (a ActorCounter) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if cn, err := attrs.String("counter"); err != nil || cn == "" {
|
||||
return errors.New("counter name must be non-empty string")
|
||||
}
|
||||
|
||||
for _, field := range []string{"counter", "counter_step", "counter_set"} {
|
||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
||||
return errors.Wrapf(err, "validating %s template", field)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -69,4 +69,6 @@ func (a actor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData
|
|||
func (a actor) IsAsync() bool { return false }
|
||||
func (a actor) Name() string { return actorName }
|
||||
|
||||
func (a actor) Validate(attrs *plugins.FieldCollection) (err error) { return nil }
|
||||
func (a actor) Validate(plugins.TemplateValidatorFunc, *plugins.FieldCollection) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -46,4 +46,6 @@ func (a actor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData
|
|||
func (a actor) IsAsync() bool { return false }
|
||||
func (a actor) Name() string { return actorName }
|
||||
|
||||
func (a actor) Validate(attrs *plugins.FieldCollection) (err error) { return nil }
|
||||
func (a actor) Validate(plugins.TemplateValidatorFunc, *plugins.FieldCollection) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -106,10 +106,15 @@ func (a actor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData
|
|||
func (a actor) IsAsync() bool { return true }
|
||||
func (a actor) Name() string { return actorName }
|
||||
|
||||
func (a actor) Validate(attrs *plugins.FieldCollection) error {
|
||||
if v, err := attrs.String("source"); err != nil || v == "" {
|
||||
func (a actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) error {
|
||||
sourceTpl, err := attrs.String("source")
|
||||
if err != nil || sourceTpl == "" {
|
||||
return errors.New("source is expected to be non-empty string")
|
||||
}
|
||||
|
||||
if err = tplValidator(sourceTpl); err != nil {
|
||||
return errors.Wrap(err, "validating source template")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ const actorName = "modchannel"
|
|||
var (
|
||||
formatMessage plugins.MsgFormatter
|
||||
tcGetter func(string) (*twitch.Client, error)
|
||||
|
||||
ptrStringEmpty = func(s string) *string { return &s }("")
|
||||
)
|
||||
|
||||
func Register(args plugins.RegistrationArguments) error {
|
||||
|
@ -67,7 +69,6 @@ type actor struct{}
|
|||
|
||||
func (a actor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
var (
|
||||
ptrStringEmpty = func(v string) *string { return &v }("")
|
||||
game = attrs.MustString("game", ptrStringEmpty)
|
||||
title = attrs.MustString("title", ptrStringEmpty)
|
||||
)
|
||||
|
@ -115,10 +116,16 @@ func (a actor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData
|
|||
func (a actor) IsAsync() bool { return false }
|
||||
func (a actor) Name() string { return actorName }
|
||||
|
||||
func (a actor) Validate(attrs *plugins.FieldCollection) (err error) {
|
||||
func (a actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if v, err := attrs.String("channel"); err != nil || v == "" {
|
||||
return errors.New("channel must be non-empty string")
|
||||
}
|
||||
|
||||
for _, field := range []string{"channel", "game", "title"} {
|
||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
||||
return errors.Wrapf(err, "validating %s template", field)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ var (
|
|||
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")
|
||||
)
|
||||
|
||||
|
@ -230,10 +231,16 @@ func (a actor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData
|
|||
func (a actor) IsAsync() bool { return false }
|
||||
func (a actor) Name() string { return actorName }
|
||||
|
||||
func (a actor) Validate(attrs *plugins.FieldCollection) (err error) {
|
||||
func (a actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if v, err := attrs.String("match"); err != nil || v == "" {
|
||||
return errors.New("match must be non-empty string")
|
||||
}
|
||||
|
||||
for _, field := range []string{"scan", "action", "match"} {
|
||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
||||
return errors.Wrapf(err, "validating %s template", field)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -214,7 +214,7 @@ func (a actorPunish) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eve
|
|||
func (a actorPunish) IsAsync() bool { return false }
|
||||
func (a actorPunish) Name() string { return actorNamePunish }
|
||||
|
||||
func (a actorPunish) Validate(attrs *plugins.FieldCollection) (err error) {
|
||||
func (a actorPunish) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if v, err := attrs.String("user"); err != nil || v == "" {
|
||||
return errors.New("user must be non-empty string")
|
||||
}
|
||||
|
@ -223,6 +223,10 @@ func (a actorPunish) Validate(attrs *plugins.FieldCollection) (err error) {
|
|||
return errors.New("levels must be slice of strings with length > 0")
|
||||
}
|
||||
|
||||
if err = tplValidator(attrs.MustString("user", ptrStringEmpty)); err != nil {
|
||||
return errors.Wrap(err, "validating user template")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -247,10 +251,14 @@ func (a actorResetPunish) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule
|
|||
func (a actorResetPunish) IsAsync() bool { return false }
|
||||
func (a actorResetPunish) Name() string { return actorNameResetPunish }
|
||||
|
||||
func (a actorResetPunish) Validate(attrs *plugins.FieldCollection) (err error) {
|
||||
func (a actorResetPunish) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if v, err := attrs.String("user"); err != nil || v == "" {
|
||||
return errors.New("user must be non-empty string")
|
||||
}
|
||||
|
||||
if err = tplValidator(attrs.MustString("user", ptrStringEmpty)); err != nil {
|
||||
return errors.Wrap(err, "validating user template")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -173,7 +173,7 @@ func (a actor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData
|
|||
func (a actor) IsAsync() bool { return false }
|
||||
func (a actor) Name() string { return actorName }
|
||||
|
||||
func (a actor) Validate(attrs *plugins.FieldCollection) (err error) {
|
||||
func (a actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
action := attrs.MustString("action", ptrStringEmpty)
|
||||
|
||||
switch action {
|
||||
|
@ -194,5 +194,11 @@ func (a actor) Validate(attrs *plugins.FieldCollection) (err error) {
|
|||
return errors.New("action must be one of add, del or get")
|
||||
}
|
||||
|
||||
for _, field := range []string{"index", "quote", "format"} {
|
||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
||||
return errors.Wrapf(err, "validating %s template", field)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ const actorName = "raw"
|
|||
var (
|
||||
formatMessage plugins.MsgFormatter
|
||||
send plugins.SendMessageFunc
|
||||
|
||||
ptrStringEmpty = func(s string) *string { return &s }("")
|
||||
)
|
||||
|
||||
func Register(args plugins.RegistrationArguments) error {
|
||||
|
@ -63,10 +65,14 @@ func (a actor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData
|
|||
func (a actor) IsAsync() bool { return false }
|
||||
func (a actor) Name() string { return actorName }
|
||||
|
||||
func (a actor) Validate(attrs *plugins.FieldCollection) (err error) {
|
||||
func (a actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if v, err := attrs.String("message"); err != nil || v == "" {
|
||||
return errors.New("message must be non-empty string")
|
||||
}
|
||||
|
||||
if err = tplValidator(attrs.MustString("message", ptrStringEmpty)); err != nil {
|
||||
return errors.Wrap(err, "validating message template")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ var (
|
|||
send plugins.SendMessageFunc
|
||||
|
||||
ptrBoolFalse = func(v bool) *bool { return &v }(false)
|
||||
ptrStringEmpty = func(s string) *string { return &s }("")
|
||||
)
|
||||
|
||||
func Register(args plugins.RegistrationArguments) error {
|
||||
|
@ -121,10 +122,16 @@ func (a actor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData
|
|||
func (a actor) IsAsync() bool { return false }
|
||||
func (a actor) Name() string { return actorName }
|
||||
|
||||
func (a actor) Validate(attrs *plugins.FieldCollection) (err error) {
|
||||
func (a actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if v, err := attrs.String("message"); err != nil || v == "" {
|
||||
return errors.New("message must be non-empty string")
|
||||
}
|
||||
|
||||
for _, field := range []string{"message", "fallback"} {
|
||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
||||
return errors.Wrapf(err, "validating %s template", field)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -82,11 +82,19 @@ func (a actor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData
|
|||
func (a actor) IsAsync() bool { return false }
|
||||
func (a actor) Name() string { return actorName }
|
||||
|
||||
func (a actor) Validate(attrs *plugins.FieldCollection) (err error) {
|
||||
func (a actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if v, err := attrs.Duration("duration"); err != nil || v < time.Second {
|
||||
return errors.New("duration must be of type duration greater or equal one second")
|
||||
}
|
||||
|
||||
if v, err := attrs.String("reason"); err != nil || v == "" {
|
||||
return errors.New("reason must be non-empty string")
|
||||
}
|
||||
|
||||
if err = tplValidator(attrs.MustString("reason", ptrStringEmpty)); err != nil {
|
||||
return errors.Wrap(err, "validating reason template")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -150,11 +150,17 @@ func (a ActorSetVariable) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule
|
|||
func (a ActorSetVariable) IsAsync() bool { return false }
|
||||
func (a ActorSetVariable) Name() string { return "setvariable" }
|
||||
|
||||
func (a ActorSetVariable) Validate(attrs *plugins.FieldCollection) (err error) {
|
||||
func (a ActorSetVariable) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if v, err := attrs.String("variable"); err != nil || v == "" {
|
||||
return errors.New("variable name must be non-empty string")
|
||||
}
|
||||
|
||||
for _, field := range []string{"set", "variable"} {
|
||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
||||
return errors.Wrapf(err, "validating %s template", field)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ const actorName = "whisper"
|
|||
var (
|
||||
botTwitchClient *twitch.Client
|
||||
formatMessage plugins.MsgFormatter
|
||||
|
||||
ptrStringEmpty = func(s string) *string { return &s }("")
|
||||
)
|
||||
|
||||
func Register(args plugins.RegistrationArguments) error {
|
||||
|
@ -73,7 +75,7 @@ func (a actor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData
|
|||
func (a actor) IsAsync() bool { return false }
|
||||
func (a actor) Name() string { return actorName }
|
||||
|
||||
func (a actor) Validate(attrs *plugins.FieldCollection) (err error) {
|
||||
func (a actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if v, err := attrs.String("to"); err != nil || v == "" {
|
||||
return errors.New("to must be non-empty string")
|
||||
}
|
||||
|
@ -82,5 +84,11 @@ func (a actor) Validate(attrs *plugins.FieldCollection) (err error) {
|
|||
return errors.New("message must be non-empty string")
|
||||
}
|
||||
|
||||
for _, field := range []string{"message", "to"} {
|
||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
||||
return errors.Wrapf(err, "validating %s template", field)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -13,8 +13,6 @@ import (
|
|||
type actor struct{}
|
||||
|
||||
func (a actor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
ptrStringEmpty := func(v string) *string { return &v }("")
|
||||
|
||||
fd, err := formatMessage(attrs.MustString("fields", ptrStringEmpty), m, r, eventData)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "executing fields template")
|
||||
|
@ -51,10 +49,16 @@ func (a actor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData
|
|||
func (a actor) IsAsync() bool { return false }
|
||||
func (a actor) Name() string { return actorName }
|
||||
|
||||
func (a actor) Validate(attrs *plugins.FieldCollection) (err error) {
|
||||
func (a actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
if v, err := attrs.String("fields"); err != nil || v == "" {
|
||||
return errors.New("fields is expected to be non-empty string")
|
||||
}
|
||||
|
||||
for _, field := range []string{"fields", "schedule_in"} {
|
||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
||||
return errors.Wrapf(err, "validating %s template", field)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ var (
|
|||
eventCreatorFunc plugins.EventHandlerFunc
|
||||
formatMessage plugins.MsgFormatter
|
||||
mc *memoryCache
|
||||
|
||||
ptrStringEmpty = func(s string) *string { return &s }("")
|
||||
)
|
||||
|
||||
func Register(args plugins.RegistrationArguments) error {
|
||||
|
|
6
main.go
6
main.go
|
@ -179,6 +179,7 @@ func handleSubCommand(args []string) {
|
|||
fmt.Println(" actor-docs Generate markdown documentation for available actors")
|
||||
fmt.Println(" api-token <name> <scope...> Generate an api-token to be entered into the config")
|
||||
fmt.Println(" migrate-v2 <old file> Migrate old (*.json.gz) storage file into new database")
|
||||
fmt.Println(" validate-config Try to load configuration file and report errors if any")
|
||||
fmt.Println(" help Prints this help message")
|
||||
|
||||
case "migrate-v2":
|
||||
|
@ -197,6 +198,11 @@ func handleSubCommand(args []string) {
|
|||
|
||||
log.Info("v2 storage file was migrated")
|
||||
|
||||
case "validate-config":
|
||||
if err := loadConfig(cfg.Config); err != nil {
|
||||
log.WithError(err).Fatal("loading config")
|
||||
}
|
||||
|
||||
default:
|
||||
handleSubCommand([]string{"help"})
|
||||
log.Fatalf("Unknown sub-command %q", args[0])
|
||||
|
|
|
@ -86,3 +86,14 @@ func formatMessageFieldUserID(compiledFields *plugins.FieldCollection, m *irc.Me
|
|||
func formatMessageFieldUsername(compiledFields *plugins.FieldCollection, m *irc.Message, fields *plugins.FieldCollection) {
|
||||
compiledFields.Set("username", plugins.DeriveUser(m, fields))
|
||||
}
|
||||
|
||||
func validateTemplate(tplString string) error {
|
||||
// Template in frontend supports newlines, messages do not
|
||||
tplString = stripNewline.ReplaceAllString(tplString, " ")
|
||||
|
||||
_, err := template.
|
||||
New(tplString).
|
||||
Funcs(tplFuncs.GetFuncMap(nil, nil, plugins.NewFieldCollection())).
|
||||
Parse(tplString)
|
||||
return errors.Wrap(err, "parsing template")
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ type (
|
|||
// Validate will be called to validate the loaded configuration. It should
|
||||
// return an error if required keys are missing from the AttributeStore
|
||||
// or if keys contain broken configs
|
||||
Validate(*FieldCollection) error
|
||||
Validate(TemplateValidatorFunc, *FieldCollection) error
|
||||
}
|
||||
|
||||
ActorCreationFunc func() Actor
|
||||
|
@ -105,6 +105,8 @@ type (
|
|||
TemplateFuncGetter func(*irc.Message, *Rule, *FieldCollection) interface{}
|
||||
TemplateFuncRegister func(name string, fg TemplateFuncGetter)
|
||||
|
||||
TemplateValidatorFunc func(raw string) error
|
||||
|
||||
ValidateTokenFunc func(token string, modules ...string) error
|
||||
)
|
||||
|
||||
|
|
|
@ -193,6 +193,22 @@ func (r *Rule) UpdateFromSubscription() (bool, error) {
|
|||
return true, nil
|
||||
}
|
||||
|
||||
func (r Rule) Validate(tplValidate TemplateValidatorFunc) error {
|
||||
if r.MatchMessage != nil {
|
||||
if _, err := regexp.Compile(*r.MatchMessage); err != nil {
|
||||
return errors.Wrap(err, "compiling match_message field regex")
|
||||
}
|
||||
}
|
||||
|
||||
if r.DisableOnTemplate != nil {
|
||||
if err := tplValidate(*r.DisableOnTemplate); err != nil {
|
||||
return errors.Wrap(err, "parsing disable_on_template template")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Rule) allowExecuteBadgeBlacklist(logger *log.Entry, m *irc.Message, event *string, badges twitch.BadgeCollection, evtData *FieldCollection) bool {
|
||||
for _, b := range r.DisableOn {
|
||||
if badges.Has(b) {
|
||||
|
|
Loading…
Reference in a new issue