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) {
|
func (b *bot) RegisterRegex(p Plugin, kind Kind, r *regexp.Regexp, resp ResponseHandler) {
|
||||||
t := reflect.TypeOf(p).String()
|
t := reflect.TypeOf(p).String()
|
||||||
if _, ok := b.callbacks[t]; !ok {
|
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 {
|
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 {
|
spec := HandlerSpec{
|
||||||
b.callbacks[t][kind][r] = []ResponseHandler{}
|
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
|
// RegisterRegexCmd is a shortcut to filter non-command messages from a registration
|
||||||
|
|
|
@ -55,22 +55,20 @@ func ParseValues(r *regexp.Regexp, body string) RegexValues {
|
||||||
|
|
||||||
func (b *bot) runCallback(conn Connector, plugin Plugin, evt Kind, message msg.Message, args ...interface{}) bool {
|
func (b *bot) runCallback(conn Connector, plugin Plugin, evt Kind, message msg.Message, args ...interface{}) bool {
|
||||||
t := reflect.TypeOf(plugin).String()
|
t := reflect.TypeOf(plugin).String()
|
||||||
for r, cbs := range b.callbacks[t][evt] {
|
for _, spec := range b.callbacks[t][evt] {
|
||||||
if r.MatchString(message.Body) {
|
if spec.Regex.MatchString(message.Body) {
|
||||||
req := Request{
|
req := Request{
|
||||||
Conn: conn,
|
Conn: conn,
|
||||||
Kind: evt,
|
Kind: evt,
|
||||||
Msg: message,
|
Msg: message,
|
||||||
Values: ParseValues(r, message.Body),
|
Values: ParseValues(spec.Regex, message.Body),
|
||||||
Args: args,
|
Args: args,
|
||||||
}
|
}
|
||||||
for _, cb := range cbs {
|
if spec.Handler(req) {
|
||||||
if cb(req) {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ type Request struct {
|
||||||
type Kind int
|
type Kind int
|
||||||
type Callback func(Connector, Kind, msg.Message, ...interface{}) bool
|
type Callback func(Connector, Kind, msg.Message, ...interface{}) bool
|
||||||
type ResponseHandler func(Request) 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 {
|
type HandlerSpec struct {
|
||||||
Kind Kind
|
Kind Kind
|
||||||
|
|
|
@ -7,12 +7,12 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
"github.com/velour/catbase/bot"
|
"github.com/velour/catbase/bot"
|
||||||
"github.com/velour/catbase/bot/msg"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type EmojifyMePlugin struct {
|
type EmojifyMePlugin struct {
|
||||||
|
@ -54,11 +54,13 @@ func New(b bot.Bot) *EmojifyMePlugin {
|
||||||
GotBotEmoji: false,
|
GotBotEmoji: false,
|
||||||
Emoji: emojiMap,
|
Emoji: emojiMap,
|
||||||
}
|
}
|
||||||
b.Register(ep, bot.Message, ep.message)
|
b.RegisterRegex(ep, bot.Message, regexp.MustCompile(`.*`), ep.message)
|
||||||
return ep
|
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 {
|
if !p.GotBotEmoji {
|
||||||
p.GotBotEmoji = true
|
p.GotBotEmoji = true
|
||||||
emojiMap := p.Bot.GetEmojiList()
|
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
|
NotFound []string
|
||||||
LastFact *Factoid
|
LastFact *Factoid
|
||||||
db *sqlx.DB
|
db *sqlx.DB
|
||||||
|
handlers bot.HandlerTable
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFactoid creates a new Factoid with the Plugin interface
|
// NewFactoid creates a new Factoid with the Plugin interface
|
||||||
|
@ -320,7 +321,7 @@ func New(botInst bot.Bot) *FactoidPlugin {
|
||||||
}(channel)
|
}(channel)
|
||||||
}
|
}
|
||||||
|
|
||||||
botInst.Register(p, bot.Message, p.message)
|
p.register()
|
||||||
botInst.Register(p, bot.Help, p.help)
|
botInst.Register(p, bot.Help, p.help)
|
||||||
|
|
||||||
p.registerWeb()
|
p.registerWeb()
|
||||||
|
@ -664,13 +665,46 @@ func (p *FactoidPlugin) changeFact(c bot.Connector, message msg.Message) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Message responds to the bot hook on recieving messages.
|
func (p *FactoidPlugin) register() {
|
||||||
// This function returns true if the plugin responds in a meaningful way to the users message.
|
p.handlers = bot.HandlerTable{
|
||||||
// Otherwise, the function returns false and the bot continues execution of other plugins.
|
bot.HandlerSpec{Kind: bot.Message, IsCmd: true,
|
||||||
func (p *FactoidPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
|
Regex: regexp.MustCompile(`(?i)^what was that\??$`),
|
||||||
if strings.ToLower(message.Body) == "what was that?" {
|
Handler: func(r bot.Request) bool {
|
||||||
return p.tellThemWhatThatWas(c, message)
|
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
|
||||||
|
|
||||||
|
log.Debug().Msgf("Message: %+v", r)
|
||||||
|
|
||||||
// This plugin has no business with normal messages
|
// This plugin has no business with normal messages
|
||||||
if !message.Command {
|
if !message.Command {
|
||||||
|
@ -678,37 +712,6 @@ func (p *FactoidPlugin) message(c bot.Connector, kind bot.Kind, message msg.Mess
|
||||||
return p.trigger(c, message)
|
return p.trigger(c, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
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 strings.ToLower(message.Body) == "forget that" {
|
|
||||||
return p.forgetLastFact(c, message)
|
|
||||||
}
|
|
||||||
|
|
||||||
if changeOperator(message.Body) != "" {
|
if changeOperator(message.Body) != "" {
|
||||||
return p.changeFact(c, message)
|
return p.changeFact(c, message)
|
||||||
}
|
}
|
||||||
|
@ -726,6 +729,9 @@ func (p *FactoidPlugin) message(c bot.Connector, kind bot.Kind, message msg.Mess
|
||||||
// We didn't find anything, panic!
|
// We didn't find anything, panic!
|
||||||
p.Bot.Send(c, bot.Message, message.Channel, p.NotFound[rand.Intn(len(p.NotFound))])
|
p.Bot.Send(c, bot.Message, message.Channel, p.NotFound[rand.Intn(len(p.NotFound))])
|
||||||
return true
|
return true
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
p.Bot.RegisterTable(p, p.handlers)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help responds to help requests. Every plugin must implement a help function.
|
// Help responds to help requests. Every plugin must implement a help function.
|
||||||
|
|
Loading…
Reference in New Issue