[stopexec] Add stopexec actor

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2023-02-05 16:08:22 +01:00
parent 5aa8d521fe
commit 7b20e4d3fe
Signed by: luzifer
GPG key ID: D91C3E91E4CAD6F5
5 changed files with 110 additions and 3 deletions

View file

@ -74,13 +74,29 @@ func handleMessage(c *irc.Client, m *irc.Message, event *string, eventData *plug
for _, r := range config.GetMatchingRules(m, event, eventData) { for _, r := range config.GetMatchingRules(m, event, eventData) {
var preventCooldown bool var preventCooldown bool
ActionsLoop:
for _, a := range r.Actions { for _, a := range r.Actions {
apc, err := triggerAction(c, m, r, a, eventData) apc, err := triggerAction(c, m, r, a, eventData)
if err != nil { switch {
case err == nil:
// Rule execution did not cause an error, we store the
// cooldown modifier and continue
preventCooldown = preventCooldown || apc
continue ActionsLoop
case errors.Is(err, plugins.ErrStopRuleExecution):
// Action has asked to stop executing this rule so we store
// the cooldown modifier and stop executing the actions stack
preventCooldown = preventCooldown || apc
break ActionsLoop
default:
// Action experienced an error: We don't store the cooldown
// state of this action and stop executing the actions stack
// for this rule
log.WithError(err).Error("Unable to trigger action") log.WithError(err).Error("Unable to trigger action")
break // Break execution when one action fails break ActionsLoop // Break execution for this rule when one action fails
} }
preventCooldown = preventCooldown || apc
} }
// Lock command // Lock command

View file

@ -0,0 +1,71 @@
package stopexec
import (
"github.com/go-irc/irc"
"github.com/pkg/errors"
"github.com/Luzifer/twitch-bot/v3/plugins"
)
const actorName = "stopexec"
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: "Stop Rule Execution on Condition",
Name: "Stop Execution",
Type: actorName,
Fields: []plugins.ActionDocumentationField{
{
Default: "",
Description: "Condition when to stop execution (must evaluate to \"true\" to stop execution)",
Key: "when",
Name: "When",
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 }("")
when, err := formatMessage(attrs.MustString("when", ptrStringEmpty), m, r, eventData)
if err != nil {
return false, errors.Wrap(err, "executing when template")
}
if when == "true" {
return false, plugins.ErrStopRuleExecution
}
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) {
whenTemplate, err := attrs.String("when")
if err != nil || whenTemplate == "" {
return errors.New("when must be non-empty string")
}
if err = tplValidator(whenTemplate); err != nil {
return errors.Wrap(err, "validating when template")
}
return nil
}

View file

@ -28,6 +28,11 @@ const (
remoteRuleFetchTimeout = 5 * time.Second remoteRuleFetchTimeout = 5 * time.Second
) )
// ErrStopRuleExecution is a way for actions to terminate execution
// of the current rule gracefully. No actions after this has been
// returned will be executed and no error state will be set
var ErrStopRuleExecution = errors.New("stop rule execution now")
type ( type (
Rule struct { Rule struct {
UUID string `hash:"-" json:"uuid,omitempty" yaml:"uuid,omitempty"` UUID string `hash:"-" json:"uuid,omitempty" yaml:"uuid,omitempty"`

View file

@ -25,6 +25,7 @@ import (
"github.com/Luzifer/twitch-bot/v3/internal/actors/respond" "github.com/Luzifer/twitch-bot/v3/internal/actors/respond"
"github.com/Luzifer/twitch-bot/v3/internal/actors/shield" "github.com/Luzifer/twitch-bot/v3/internal/actors/shield"
"github.com/Luzifer/twitch-bot/v3/internal/actors/shoutout" "github.com/Luzifer/twitch-bot/v3/internal/actors/shoutout"
"github.com/Luzifer/twitch-bot/v3/internal/actors/stopexec"
"github.com/Luzifer/twitch-bot/v3/internal/actors/timeout" "github.com/Luzifer/twitch-bot/v3/internal/actors/timeout"
"github.com/Luzifer/twitch-bot/v3/internal/actors/variables" "github.com/Luzifer/twitch-bot/v3/internal/actors/variables"
"github.com/Luzifer/twitch-bot/v3/internal/actors/vip" "github.com/Luzifer/twitch-bot/v3/internal/actors/vip"
@ -62,6 +63,7 @@ var (
respond.Register, respond.Register,
shield.Register, shield.Register,
shoutout.Register, shoutout.Register,
stopexec.Register,
timeout.Register, timeout.Register,
variables.Register, variables.Register,
vip.Register, vip.Register,

View file

@ -357,6 +357,19 @@ Perform a Twitch-native shoutout
user: "" user: ""
``` ```
## Stop Execution
Stop Rule Execution on Condition
```yaml
- type: stopexec
attributes:
# Condition when to stop execution (must evaluate to "true" to stop execution)
# Optional: false
# Type: string (Supports Templating)
when: ""
```
## Timeout User ## Timeout User
Timeout user from chat Timeout user from chat