2020-12-21 00:32:39 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"github.com/go-irc/irc"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
2021-06-11 11:52:42 +00:00
|
|
|
type (
|
|
|
|
Actor interface {
|
|
|
|
// Execute will be called after the config was read into the Actor
|
2021-08-11 22:12:10 +00:00
|
|
|
Execute(*irc.Client, *irc.Message, *Rule) (preventCooldown bool, err error)
|
2021-06-11 11:52:42 +00:00
|
|
|
// IsAsync may return true if the Execute function is to be executed
|
|
|
|
// in a Go routine as of long runtime. Normally it should return false
|
|
|
|
// except in very specific cases
|
|
|
|
IsAsync() bool
|
|
|
|
// Name must return an unique name for the actor in order to identify
|
|
|
|
// it in the logs for debugging purposes
|
|
|
|
Name() string
|
|
|
|
}
|
|
|
|
ActorCreationFunc func() Actor
|
|
|
|
)
|
|
|
|
|
2020-12-21 00:32:39 +00:00
|
|
|
var (
|
2021-06-11 11:52:42 +00:00
|
|
|
availableActions []ActorCreationFunc
|
2020-12-21 00:32:39 +00:00
|
|
|
availableActionsLock = new(sync.RWMutex)
|
|
|
|
)
|
|
|
|
|
2021-06-11 11:52:42 +00:00
|
|
|
func registerAction(af ActorCreationFunc) {
|
2020-12-21 00:32:39 +00:00
|
|
|
availableActionsLock.Lock()
|
|
|
|
defer availableActionsLock.Unlock()
|
|
|
|
|
|
|
|
availableActions = append(availableActions, af)
|
|
|
|
}
|
|
|
|
|
2021-08-11 22:12:10 +00:00
|
|
|
func triggerActions(c *irc.Client, m *irc.Message, rule *Rule, ra *RuleAction) (preventCooldown bool, err error) {
|
2020-12-21 00:32:39 +00:00
|
|
|
availableActionsLock.RLock()
|
|
|
|
defer availableActionsLock.RUnlock()
|
|
|
|
|
2021-06-11 11:52:42 +00:00
|
|
|
for _, acf := range availableActions {
|
|
|
|
var (
|
|
|
|
a = acf()
|
|
|
|
logger = log.WithField("actor", a.Name())
|
|
|
|
)
|
|
|
|
|
|
|
|
if err := ra.Unmarshal(a); err != nil {
|
|
|
|
logger.WithError(err).Trace("Unable to unmarshal config")
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if a.IsAsync() {
|
|
|
|
go func() {
|
2021-08-11 22:12:10 +00:00
|
|
|
if _, err := a.Execute(c, m, rule); err != nil {
|
2021-06-11 11:52:42 +00:00
|
|
|
logger.WithError(err).Error("Error in async actor")
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-08-11 22:12:10 +00:00
|
|
|
apc, err := a.Execute(c, m, rule)
|
|
|
|
if err != nil {
|
|
|
|
return preventCooldown, errors.Wrap(err, "execute action")
|
2020-12-21 00:32:39 +00:00
|
|
|
}
|
2021-08-11 22:12:10 +00:00
|
|
|
preventCooldown = preventCooldown || apc
|
2020-12-21 00:32:39 +00:00
|
|
|
}
|
|
|
|
|
2021-08-11 22:12:10 +00:00
|
|
|
return preventCooldown, nil
|
2020-12-21 00:32:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func handleMessage(c *irc.Client, m *irc.Message, event *string) {
|
|
|
|
for _, r := range config.GetMatchingRules(m, event) {
|
2021-08-11 22:12:10 +00:00
|
|
|
var preventCooldown bool
|
|
|
|
|
2020-12-21 00:32:39 +00:00
|
|
|
for _, a := range r.Actions {
|
2021-08-11 22:12:10 +00:00
|
|
|
apc, err := triggerActions(c, m, r, a)
|
|
|
|
if err != nil {
|
2020-12-21 00:32:39 +00:00
|
|
|
log.WithError(err).Error("Unable to trigger action")
|
|
|
|
}
|
2021-08-11 22:12:10 +00:00
|
|
|
preventCooldown = preventCooldown || apc
|
2020-12-21 00:32:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Lock command
|
2021-08-11 22:12:10 +00:00
|
|
|
if !preventCooldown {
|
|
|
|
r.setCooldown(m)
|
|
|
|
}
|
2020-12-21 00:32:39 +00:00
|
|
|
}
|
|
|
|
}
|