fact: refactor

This commit is contained in:
Chris Sexton 2021-02-01 21:25:19 -05:00 committed by Chris Sexton
parent 55a206760f
commit 8cb6b485cb
6 changed files with 80 additions and 132 deletions

View File

@ -245,15 +245,17 @@ func (b *bot) RegisterTable(p Plugin, handlers HandlerTable) {
func (b *bot) RegisterRegex(p Plugin, kind Kind, r *regexp.Regexp, resp ResponseHandler) {
t := reflect.TypeOf(p).String()
if _, ok := b.callbacks[t]; !ok {
b.callbacks[t] = make(map[Kind]map[*regexp.Regexp][]ResponseHandler)
b.callbacks[t] = make(map[Kind][]HandlerSpec)
}
if _, ok := b.callbacks[t][kind]; !ok {
b.callbacks[t][kind] = map[*regexp.Regexp][]ResponseHandler{}
b.callbacks[t][kind] = []HandlerSpec{}
}
if _, ok := b.callbacks[t][kind][r]; !ok {
b.callbacks[t][kind][r] = []ResponseHandler{}
spec := HandlerSpec{
Kind: kind,
Regex: r,
Handler: resp,
}
b.callbacks[t][kind][r] = append(b.callbacks[t][kind][r], resp)
b.callbacks[t][kind] = append(b.callbacks[t][kind], spec)
}
// RegisterRegexCmd is a shortcut to filter non-command messages from a registration

View File

@ -55,19 +55,17 @@ func ParseValues(r *regexp.Regexp, body string) RegexValues {
func (b *bot) runCallback(conn Connector, plugin Plugin, evt Kind, message msg.Message, args ...interface{}) bool {
t := reflect.TypeOf(plugin).String()
for r, cbs := range b.callbacks[t][evt] {
if r.MatchString(message.Body) {
for _, spec := range b.callbacks[t][evt] {
if spec.Regex.MatchString(message.Body) {
req := Request{
Conn: conn,
Kind: evt,
Msg: message,
Values: ParseValues(r, message.Body),
Values: ParseValues(spec.Regex, message.Body),
Args: args,
}
for _, cb := range cbs {
if cb(req) {
return true
}
if spec.Handler(req) {
return true
}
}
}

View File

@ -59,7 +59,7 @@ type Request struct {
type Kind int
type Callback func(Connector, Kind, msg.Message, ...interface{}) bool
type ResponseHandler func(Request) bool
type CallbackMap map[string]map[Kind]map[*regexp.Regexp][]ResponseHandler
type CallbackMap map[string]map[Kind][]HandlerSpec
type HandlerSpec struct {
Kind Kind

View File

@ -7,12 +7,12 @@ import (
"io/ioutil"
"math/rand"
"net/http"
"regexp"
"strings"
"github.com/rs/zerolog/log"
"github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
)
type EmojifyMePlugin struct {
@ -54,11 +54,13 @@ func New(b bot.Bot) *EmojifyMePlugin {
GotBotEmoji: false,
Emoji: emojiMap,
}
b.Register(ep, bot.Message, ep.message)
b.RegisterRegex(ep, bot.Message, regexp.MustCompile(`.*`), ep.message)
return ep
}
func (p *EmojifyMePlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *EmojifyMePlugin) message(r bot.Request) bool {
c := r.Conn
message := r.Msg
if !p.GotBotEmoji {
p.GotBotEmoji = true
emojiMap := p.Bot.GetEmojiList()

View File

@ -1,60 +0,0 @@
package fact
import (
"github.com/velour/catbase/plugins/cli"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
"github.com/velour/catbase/bot/user"
)
var c = &cli.CliPlugin{}
func makeMessage(nick, payload string) msg.Message {
isCmd := strings.HasPrefix(payload, "!")
if isCmd {
payload = payload[1:]
}
return msg.Message{
User: &user.User{Name: nick},
Channel: "test",
Body: payload,
Command: isCmd,
}
}
func makePlugin(t *testing.T) (*FactoidPlugin, *bot.MockBot) {
mb := bot.NewMockBot()
f := New(mb) // for DB table
return f, mb
}
func TestReact(t *testing.T) {
msgs := []msg.Message{
makeMessage("user1", "!testing123 <react> jesus"),
makeMessage("user2", "testing123"),
}
p, mb := makePlugin(t)
for _, m := range msgs {
p.message(c, bot.Message, m)
}
assert.Len(t, mb.Reactions, 1)
assert.Contains(t, mb.Reactions[0], "jesus")
}
func TestReactCantLearnSpaces(t *testing.T) {
msgs := []msg.Message{
makeMessage("user1", "!test <react> jesus christ"),
}
p, mb := makePlugin(t)
for _, m := range msgs {
p.message(c, bot.Message, m)
}
assert.Len(t, mb.Messages, 1)
assert.Contains(t, mb.Messages[0], "not a valid")
}

View File

@ -263,6 +263,7 @@ type FactoidPlugin struct {
NotFound []string
LastFact *Factoid
db *sqlx.DB
handlers bot.HandlerTable
}
// NewFactoid creates a new Factoid with the Plugin interface
@ -320,7 +321,7 @@ func New(botInst bot.Bot) *FactoidPlugin {
}(channel)
}
botInst.Register(p, bot.Message, p.message)
p.register()
botInst.Register(p, bot.Help, p.help)
p.registerWeb()
@ -664,68 +665,73 @@ func (p *FactoidPlugin) changeFact(c bot.Connector, message msg.Message) bool {
return true
}
// Message responds to the bot hook on recieving messages.
// This function returns true if the plugin responds in a meaningful way to the users message.
// Otherwise, the function returns false and the bot continues execution of other plugins.
func (p *FactoidPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
if strings.ToLower(message.Body) == "what was that?" {
return p.tellThemWhatThatWas(c, message)
}
func (p *FactoidPlugin) register() {
p.handlers = bot.HandlerTable{
bot.HandlerSpec{Kind: bot.Message, IsCmd: true,
Regex: regexp.MustCompile(`(?i)^what was that\??$`),
Handler: func(r bot.Request) bool {
return p.tellThemWhatThatWas(r.Conn, r.Msg)
}},
bot.HandlerSpec{Kind: bot.Message, IsCmd: true,
Regex: regexp.MustCompile(`(?i)^alias (?P<from>\S+) to (?P<to>\S+)$`),
Handler: func(r bot.Request) bool {
from := r.Values["from"]
to := r.Values["to"]
log.Debug().Msgf("alias: %+v", r)
a := aliasFromStrings(from, to)
if err := a.save(p.db); err != nil {
p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, err.Error())
} else {
p.Bot.Send(r.Conn, bot.Action, r.Msg.Channel, "learns a new synonym")
}
return true
}},
bot.HandlerSpec{Kind: bot.Message, IsCmd: true,
Regex: regexp.MustCompile(`(?i)^factoid$`),
Handler: func(r bot.Request) bool {
fact := p.randomFact()
p.sayFact(r.Conn, r.Msg, *fact)
return true
}},
bot.HandlerSpec{Kind: bot.Message, IsCmd: true,
Regex: regexp.MustCompile(`(?i)^forget that$`),
Handler: func(r bot.Request) bool {
return p.forgetLastFact(r.Conn, r.Msg)
}},
bot.HandlerSpec{Kind: bot.Message, IsCmd: false,
Regex: regexp.MustCompile(`.*`),
Handler: func(r bot.Request) bool {
message := r.Msg
c := r.Conn
// This plugin has no business with normal messages
if !message.Command {
// look for any triggers in the db matching this message
return p.trigger(c, message)
}
log.Debug().Msgf("Message: %+v", r)
if strings.HasPrefix(strings.ToLower(message.Body), "alias") {
log.Debug().
Str("alias", message.Body).
Msg("Trying to learn an alias")
m := strings.TrimPrefix(message.Body, "alias ")
parts := strings.SplitN(m, "->", 2)
if len(parts) != 2 {
p.Bot.Send(c, bot.Message, message.Channel, "If you want to alias something, use: `alias this -> that`")
return true
}
a := aliasFromStrings(strings.TrimSpace(parts[1]), strings.TrimSpace(parts[0]))
if err := a.save(p.db); err != nil {
p.Bot.Send(c, bot.Message, message.Channel, err.Error())
} else {
p.Bot.Send(c, bot.Action, message.Channel, "learns a new synonym")
}
return true
}
// This plugin has no business with normal messages
if !message.Command {
// look for any triggers in the db matching this message
return p.trigger(c, message)
}
if strings.ToLower(message.Body) == "factoid" {
if fact := p.randomFact(); fact != nil {
p.sayFact(c, message, *fact)
return true
}
log.Debug().Msg("Got a nil fact.")
}
if changeOperator(message.Body) != "" {
return p.changeFact(c, message)
}
if strings.ToLower(message.Body) == "forget that" {
return p.forgetLastFact(c, message)
}
action := findAction(message.Body)
if action != "" {
return p.learnAction(c, message, action)
}
if changeOperator(message.Body) != "" {
return p.changeFact(c, message)
}
// look for any triggers in the db matching this message
if p.trigger(c, message) {
return true
}
action := findAction(message.Body)
if action != "" {
return p.learnAction(c, message, action)
// We didn't find anything, panic!
p.Bot.Send(c, bot.Message, message.Channel, p.NotFound[rand.Intn(len(p.NotFound))])
return true
}},
}
// look for any triggers in the db matching this message
if p.trigger(c, message) {
return true
}
// We didn't find anything, panic!
p.Bot.Send(c, bot.Message, message.Channel, p.NotFound[rand.Intn(len(p.NotFound))])
return true
p.Bot.RegisterTable(p, p.handlers)
}
// Help responds to help requests. Every plugin must implement a help function.