mirror of https://github.com/velour/catbase.git
fact: refactor
This commit is contained in:
parent
55a206760f
commit
8cb6b485cb
12
bot/bot.go
12
bot/bot.go
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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")
|
||||
}
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue