diff --git a/actions.go b/actions.go index cad6342..befa353 100644 --- a/actions.go +++ b/actions.go @@ -72,11 +72,18 @@ func handleMessage(c *irc.Client, m *irc.Message, event *string, eventData *plug } for _, r := range config.GetMatchingRules(m, event, eventData) { - var preventCooldown bool + var ( + ruleEventData = plugins.NewFieldCollection() + preventCooldown bool + ) + + if eventData != nil { + ruleEventData.SetFromData(eventData.Data()) + } ActionsLoop: for _, a := range r.Actions { - apc, err := triggerAction(c, m, r, a, eventData) + apc, err := triggerAction(c, m, r, a, ruleEventData) switch { case err == nil: // Rule execution did not cause an error, we store the diff --git a/internal/actors/eventmod/actor.go b/internal/actors/eventmod/actor.go new file mode 100644 index 0000000..174d0f7 --- /dev/null +++ b/internal/actors/eventmod/actor.go @@ -0,0 +1,80 @@ +package eventmod + +import ( + "encoding/json" + + "github.com/go-irc/irc" + "github.com/pkg/errors" + + "github.com/Luzifer/twitch-bot/v3/plugins" +) + +const actorName = "eventmod" + +var formatMessage plugins.MsgFormatter + +func Register(args plugins.RegistrationArguments) error { + formatMessage = args.FormatMessage + + args.RegisterActor(actorName, func() plugins.Actor { return &actor{} }) + + args.RegisterActorDocumentation(plugins.ActionDocumentation{ + Description: "Add custom fields to the event to be used as template variables later on", + Name: "Add Fields to Event", + Type: actorName, + + Fields: []plugins.ActionDocumentationField{ + { + Default: "", + Description: "Fields to set in the event (must produce valid JSON: `map[string]any`)", + Key: "fields", + Name: "Fields", + Optional: false, + SupportTemplate: true, + Type: plugins.ActionDocumentationFieldTypeString, + }, + }, + }) + + return nil +} + +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") + } + + if fd == "" { + return false, errors.New("fields template evaluated to empty string") + } + + fields := map[string]any{} + if err = json.Unmarshal([]byte(fd), &fields); err != nil { + return false, errors.Wrap(err, "parsing fields") + } + + eventData.SetFromData(fields) + + return false, nil +} + +func (a actor) IsAsync() bool { return false } +func (a actor) Name() string { return actorName } + +func (a actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) { + fieldsTemplate, err := attrs.String("fields") + if err != nil || fieldsTemplate == "" { + return errors.New("fields must be non-empty string") + } + + if err = tplValidator(fieldsTemplate); err != nil { + return errors.Wrap(err, "validating fields template") + } + + return nil +} diff --git a/plugins_core.go b/plugins_core.go index 6268f10..a5416f1 100644 --- a/plugins_core.go +++ b/plugins_core.go @@ -15,6 +15,7 @@ import ( "github.com/Luzifer/twitch-bot/v3/internal/actors/counter" "github.com/Luzifer/twitch-bot/v3/internal/actors/delay" deleteactor "github.com/Luzifer/twitch-bot/v3/internal/actors/delete" + "github.com/Luzifer/twitch-bot/v3/internal/actors/eventmod" "github.com/Luzifer/twitch-bot/v3/internal/actors/filesay" logActor "github.com/Luzifer/twitch-bot/v3/internal/actors/log" "github.com/Luzifer/twitch-bot/v3/internal/actors/modchannel" @@ -53,6 +54,7 @@ var ( counter.Register, delay.Register, deleteactor.Register, + eventmod.Register, filesay.Register, logActor.Register, modchannel.Register, diff --git a/wiki/Actors.md b/wiki/Actors.md index 1b0862b..7ef296d 100644 --- a/wiki/Actors.md +++ b/wiki/Actors.md @@ -1,6 +1,19 @@ # Available Actions +## Add Fields to Event + +Add custom fields to the event to be used as template variables later on + +```yaml +- type: eventmod + attributes: + # Fields to set in the event (must produce valid JSON: `map[string]any`) + # Optional: false + # Type: string (Supports Templating) + fields: "" +``` + ## Add VIP Add VIP for the given channel