Files
2026-03-03 23:19:23 +00:00

77 lines
1.7 KiB
Go

package decision
import (
"strings"
)
// Rule maps a condition to a set of actions.
type Rule struct {
Name string
Match MatchFunc
Actions []Action
}
// MatchFunc is a pure predicate over a MessageContext.
type MatchFunc func(ctx MessageContext) bool
// Evaluate runs all rules against the context and returns the matching actions. Pure.
func Evaluate(ctx MessageContext, rules []Rule) []Action {
var actions []Action
for _, rule := range rules {
if rule.Match(ctx) {
actions = append(actions, rule.Actions...)
}
}
return actions
}
// MatchCommand returns a MatchFunc that matches when the command equals cmd.
func MatchCommand(cmd string) MatchFunc {
return func(ctx MessageContext) bool {
return strings.EqualFold(ctx.Command, cmd)
}
}
// MatchPrefix returns a MatchFunc that matches when content starts with prefix.
func MatchPrefix(prefix string) MatchFunc {
return func(ctx MessageContext) bool {
return strings.HasPrefix(ctx.Content, prefix)
}
}
// MatchAny returns a MatchFunc that matches any message.
func MatchAny() MatchFunc {
return func(_ MessageContext) bool { return true }
}
// MatchMinPowerLevel returns a MatchFunc that requires a minimum Matrix power level.
func MatchMinPowerLevel(level int) MatchFunc {
return func(ctx MessageContext) bool {
return ctx.PowerLevel >= level
}
}
// And composes multiple MatchFuncs with logical AND.
func And(fns ...MatchFunc) MatchFunc {
return func(ctx MessageContext) bool {
for _, fn := range fns {
if !fn(ctx) {
return false
}
}
return true
}
}
// Or composes multiple MatchFuncs with logical OR.
func Or(fns ...MatchFunc) MatchFunc {
return func(ctx MessageContext) bool {
for _, fn := range fns {
if fn(ctx) {
return true
}
}
return false
}
}