117 lines
2.2 KiB
Go
117 lines
2.2 KiB
Go
package action
|
|
|
|
import (
|
|
"slices"
|
|
|
|
lib "git.sr.ht/~cco/go-scopes"
|
|
"git.sr.ht/~cco/go-scopes/core/message"
|
|
"git.sr.ht/~cco/go-scopes/logging"
|
|
)
|
|
|
|
type BaseSpec = baseSpec
|
|
|
|
type baseSpec struct {
|
|
handler lib.ActionHandler
|
|
receivers []lib.Addressable
|
|
}
|
|
|
|
func (spec *baseSpec) Handler() lib.ActionHandler {
|
|
return spec.handler
|
|
}
|
|
|
|
func (spec *baseSpec) Receivers() []lib.Addressable {
|
|
return spec.receivers
|
|
}
|
|
|
|
func (spec *baseSpec) AddReceiver(rcv lib.Addressable) lib.ActionSpec {
|
|
if slices.Index(spec.receivers, rcv) == -1 {
|
|
spec.receivers = append(spec.receivers, rcv)
|
|
}
|
|
return spec
|
|
}
|
|
|
|
func (spec *baseSpec) RemoveReceiver(rcv lib.Addressable) {
|
|
rcvs := spec.receivers
|
|
idx := slices.Index(rcvs, rcv)
|
|
if idx != -1 {
|
|
spec.receivers = slices.Delete(rcvs, idx, idx+1)
|
|
}
|
|
}
|
|
|
|
func Base(hdlr lib.ActionHandler, rcvs ...string) *baseSpec {
|
|
spec := baseSpec{handler: hdlr}
|
|
for _, rcv := range rcvs {
|
|
spec.receivers = append(spec.receivers, message.SimpleAddress(rcv))
|
|
}
|
|
return &spec
|
|
}
|
|
|
|
// action selection
|
|
|
|
func Select(ctx lib.Context, msg lib.Message) []lib.Action {
|
|
var acts []lib.Action
|
|
for _, ac := range ctx.Config().Actions() {
|
|
if match(ac, msg) {
|
|
for _, spec := range ac.Specs() {
|
|
act := action{ctx, spec, msg}
|
|
logging.DebugA(&act).
|
|
Str("pattern", ac.Pattern().String()).
|
|
Msg("action.Select")
|
|
acts = append(acts, &act)
|
|
}
|
|
}
|
|
}
|
|
if len(acts) == 0 {
|
|
logging.WarnM(ctx, msg).Msg("action.Select: no match")
|
|
}
|
|
return acts
|
|
}
|
|
|
|
func match(ac lib.ActionConfig, msg lib.Message) bool {
|
|
pat := ac.Pattern().Slice()
|
|
if len(pat) == 1 {
|
|
return pat[0] == msg.Action()
|
|
}
|
|
mh := msg.Slice()
|
|
for idx, p := range pat {
|
|
if p != "" && mh[idx] != p {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// action handling
|
|
|
|
type action struct {
|
|
ctx lib.Context
|
|
spec lib.ActionSpec
|
|
msg lib.Message
|
|
}
|
|
|
|
func (act *action) Context() lib.Context {
|
|
return act.ctx
|
|
}
|
|
|
|
func (act *action) Spec() lib.ActionSpec {
|
|
return act.spec
|
|
}
|
|
|
|
func (act *action) Message() lib.Message {
|
|
return act.msg
|
|
}
|
|
|
|
func (act *action) Handle() bool {
|
|
return act.spec.Handler()(act)
|
|
}
|
|
|
|
// predefined action handlers
|
|
|
|
func Forward(act lib.Action) bool {
|
|
ctx := act.Context()
|
|
msg := act.Message()
|
|
for _, rcv := range act.Spec().Receivers() {
|
|
message.Send(ctx, rcv, msg)
|
|
}
|
|
return true
|
|
}
|