mirror of https://github.com/velour/catbase.git
bot: hook connectors up to events
This includes a full test of `admin`
This commit is contained in:
parent
d85c855d47
commit
82dcf410f2
14
bot/bot.go
14
bot/bot.go
|
@ -83,9 +83,7 @@ func New(config *config.Config, connector Connector) Bot {
|
|||
addr := config.Get("HttpAddr", "127.0.0.1:1337")
|
||||
go http.ListenAndServe(addr, nil)
|
||||
|
||||
connector.RegisterMessageReceived(bot.MsgReceived)
|
||||
connector.RegisterEventReceived(bot.EventReceived)
|
||||
connector.RegisterReplyMessageReceived(bot.ReplyMsgReceived)
|
||||
connector.RegisterEvent(bot.Receive)
|
||||
|
||||
return bot
|
||||
}
|
||||
|
@ -249,10 +247,14 @@ func (b *bot) RegisterFilter(name string, f func(string) string) {
|
|||
b.filters[name] = f
|
||||
}
|
||||
|
||||
// Send a message to the connection
|
||||
func (b *bot) Send(kind Kind, args ...interface{}) (error, string) { return nil, "" }
|
||||
|
||||
// Register a callback
|
||||
func (b *bot) Register(name string, kind Kind, cb Callback) {
|
||||
name = strings.ToLower(name)
|
||||
if _, ok := b.callbacks[name]; !ok {
|
||||
b.callbacks[name] = make(map[Kind][]Callback)
|
||||
}
|
||||
if _, ok := b.callbacks[name][kind]; !ok {
|
||||
b.callbacks[name][kind] = []Callback{}
|
||||
}
|
||||
b.callbacks[name][kind] = append(b.callbacks[name][kind], cb)
|
||||
}
|
||||
|
|
|
@ -17,23 +17,18 @@ import (
|
|||
)
|
||||
|
||||
func (b *bot) Receive(kind Kind, msg msg.Message, args ...interface{}) {
|
||||
panic("I don't know what to do here yet")
|
||||
}
|
||||
|
||||
// Handles incomming PRIVMSG requests
|
||||
func (b *bot) MsgReceived(msg msg.Message) {
|
||||
log.Println("Received message: ", msg)
|
||||
log.Println("Received event: ", msg)
|
||||
|
||||
// msg := b.buildMessage(client, inMsg)
|
||||
// do need to look up user and fix it
|
||||
if strings.HasPrefix(msg.Body, "help ") && msg.Command {
|
||||
if kind == Message && strings.HasPrefix(msg.Body, "help ") && msg.Command {
|
||||
parts := strings.Fields(strings.ToLower(msg.Body))
|
||||
b.checkHelp(msg.Channel, parts)
|
||||
goto RET
|
||||
}
|
||||
|
||||
for _, name := range b.pluginOrdering {
|
||||
if b.runCallback(name, Message, msg) {
|
||||
if b.runCallback(name, kind, msg, args) {
|
||||
goto RET
|
||||
}
|
||||
}
|
||||
|
@ -43,59 +38,18 @@ RET:
|
|||
return
|
||||
}
|
||||
|
||||
// Handle incoming events
|
||||
func (b *bot) EventReceived(msg msg.Message) {
|
||||
log.Println("Received event: ", msg)
|
||||
//msg := b.buildMessage(conn, inMsg)
|
||||
for _, name := range b.pluginOrdering {
|
||||
if b.runCallback(name, Event, msg) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *bot) runCallback(plugin string, evt Kind, message msg.Message, args ...interface{}) bool {
|
||||
for _, cb := range b.callbacks[plugin][evt] {
|
||||
if cb(evt, message) {
|
||||
if cb(evt, message, args) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Handle incoming replys
|
||||
func (b *bot) ReplyMsgReceived(msg msg.Message, identifier string) {
|
||||
log.Println("Received message: ", msg)
|
||||
|
||||
for _, name := range b.pluginOrdering {
|
||||
if b.runCallback(name, Reply, msg, identifier) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *bot) SendMessage(channel, message string) (error, string) {
|
||||
return b.conn.Send(Message, channel, message)
|
||||
}
|
||||
|
||||
func (b *bot) SendAction(channel, message string) (error, string) {
|
||||
return b.conn.Send(Action, channel, message)
|
||||
}
|
||||
|
||||
func (b *bot) ReplyToMessageIdentifier(channel, message, identifier string) (error, string) {
|
||||
return b.conn.Send(Reply, channel, message, identifier)
|
||||
}
|
||||
|
||||
func (b *bot) ReplyToMessage(channel, message string, replyTo msg.Message) (error, string) {
|
||||
return b.conn.Send(Reply, channel, message, replyTo)
|
||||
}
|
||||
|
||||
func (b *bot) React(channel, reaction string, message msg.Message) (error, string) {
|
||||
return b.conn.Send(Reaction, channel, reaction, message)
|
||||
}
|
||||
|
||||
func (b *bot) Edit(channel, newMessage, identifier string) (error, string) {
|
||||
return b.conn.Send(Edit, channel, newMessage, identifier)
|
||||
// Send a message to the connection
|
||||
func (b *bot) Send(kind Kind, args ...interface{}) (string, error) {
|
||||
return b.conn.Send(kind, args...)
|
||||
}
|
||||
|
||||
func (b *bot) GetEmojiList() map[string]string {
|
||||
|
@ -110,7 +64,7 @@ func (b *bot) checkHelp(channel string, parts []string) {
|
|||
for name, _ := range b.plugins {
|
||||
topics = fmt.Sprintf("%s, %s", topics, name)
|
||||
}
|
||||
b.SendMessage(channel, topics)
|
||||
b.Send(Message, channel, topics)
|
||||
} else {
|
||||
// trigger the proper plugin's help response
|
||||
if parts[1] == "about" {
|
||||
|
@ -127,7 +81,7 @@ func (b *bot) checkHelp(channel string, parts []string) {
|
|||
b.runCallback(parts[1], Help, msg.Message{Channel: channel}, channel, parts)
|
||||
} else {
|
||||
msg := fmt.Sprintf("I'm sorry, I don't know what %s is!", parts[1])
|
||||
b.SendMessage(channel, msg)
|
||||
b.Send(Message, channel, msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -223,14 +177,14 @@ func (b *bot) listVars(channel string, parts []string) {
|
|||
if len(variables) > 0 {
|
||||
msg += ", " + strings.Join(variables, ", ")
|
||||
}
|
||||
b.SendMessage(channel, msg)
|
||||
b.Send(Message, channel, msg)
|
||||
}
|
||||
|
||||
func (b *bot) Help(channel string, parts []string) {
|
||||
msg := fmt.Sprintf("Hi, I'm based on godeepintir version %s. I'm written in Go, and you "+
|
||||
"can find my source code on the internet here: "+
|
||||
"http://github.com/velour/catbase", b.version)
|
||||
b.SendMessage(channel, msg)
|
||||
b.Send(Message, channel, msg)
|
||||
}
|
||||
|
||||
// Send our own musings to the plugins
|
||||
|
|
|
@ -45,7 +45,7 @@ type Bot interface {
|
|||
// AddPlugin registers a new plugin handler
|
||||
AddPlugin(string, Plugin)
|
||||
// First arg should be one of bot.Message/Reply/Action/etc
|
||||
Send(Kind, ...interface{}) (error, string)
|
||||
Send(Kind, ...interface{}) (string, error)
|
||||
// First arg should be one of bot.Message/Reply/Action/etc
|
||||
Receive(Kind, msg.Message, ...interface{})
|
||||
// Register a callback
|
||||
|
@ -61,11 +61,9 @@ type Bot interface {
|
|||
|
||||
// Connector represents a server connection to a chat service
|
||||
type Connector interface {
|
||||
RegisterEventReceived(func(message msg.Message))
|
||||
RegisterMessageReceived(func(message msg.Message))
|
||||
RegisterReplyMessageReceived(func(msg.Message, string))
|
||||
RegisterEvent(func(Kind, msg.Message, ...interface{}))
|
||||
|
||||
Send(Kind, ...interface{}) (error, string)
|
||||
Send(Kind, ...interface{}) (string, error)
|
||||
|
||||
GetEmojiList() map[string]string
|
||||
Serve() error
|
||||
|
|
24
bot/mock.go
24
bot/mock.go
|
@ -29,14 +29,14 @@ type MockBot struct {
|
|||
func (mb *MockBot) Config() *config.Config { return mb.Cfg }
|
||||
func (mb *MockBot) DB() *sqlx.DB { return mb.Cfg.DB }
|
||||
func (mb *MockBot) Who(string) []user.User { return []user.User{} }
|
||||
func (mb *MockBot) Send(kind Kind, args ...interface{}) (error, string) {
|
||||
func (mb *MockBot) Send(kind Kind, args ...interface{}) (string, error) {
|
||||
switch kind {
|
||||
case Message:
|
||||
mb.Messages = append(mb.Messages, args[1].(string))
|
||||
return nil, fmt.Sprintf("m-%d", len(mb.Actions)-1)
|
||||
return fmt.Sprintf("m-%d", len(mb.Actions)-1), nil
|
||||
case Action:
|
||||
mb.Actions = append(mb.Actions, args[1].(string))
|
||||
return nil, fmt.Sprintf("a-%d", len(mb.Actions)-1)
|
||||
return fmt.Sprintf("a-%d", len(mb.Actions)-1), nil
|
||||
case Edit:
|
||||
ch, m, id := args[0].(string), args[1].(string), args[2].(string)
|
||||
return mb.edit(ch, m, id)
|
||||
|
@ -44,7 +44,7 @@ func (mb *MockBot) Send(kind Kind, args ...interface{}) (error, string) {
|
|||
ch, re, msg := args[0].(string), args[1].(string), args[2].(msg.Message)
|
||||
return mb.react(ch, re, msg)
|
||||
}
|
||||
return fmt.Errorf("Mesasge type unhandled"), "ERROR"
|
||||
return "ERR", fmt.Errorf("Mesasge type unhandled")
|
||||
}
|
||||
func (mb *MockBot) AddPlugin(name string, f Plugin) {}
|
||||
func (mb *MockBot) Register(name string, kind Kind, cb Callback) {}
|
||||
|
@ -53,40 +53,40 @@ func (mb *MockBot) Filter(msg msg.Message, s string) string { re
|
|||
func (mb *MockBot) LastMessage(ch string) (msg.Message, error) { return msg.Message{}, nil }
|
||||
func (mb *MockBot) CheckAdmin(nick string) bool { return false }
|
||||
|
||||
func (mb *MockBot) react(channel, reaction string, message msg.Message) (error, string) {
|
||||
func (mb *MockBot) react(channel, reaction string, message msg.Message) (string, error) {
|
||||
mb.Reactions = append(mb.Reactions, reaction)
|
||||
return nil, ""
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (mb *MockBot) edit(channel, newMessage, identifier string) (error, string) {
|
||||
func (mb *MockBot) edit(channel, newMessage, identifier string) (string, error) {
|
||||
isMessage := identifier[0] == 'm'
|
||||
if !isMessage && identifier[0] != 'a' {
|
||||
err := fmt.Errorf("failed to parse identifier: %s", identifier)
|
||||
log.Println(err)
|
||||
return err, ""
|
||||
return "", err
|
||||
}
|
||||
|
||||
index, err := strconv.Atoi(strings.Split(identifier, "-")[1])
|
||||
if err != nil {
|
||||
err := fmt.Errorf("failed to parse identifier: %s", identifier)
|
||||
log.Println(err)
|
||||
return err, ""
|
||||
return "", err
|
||||
}
|
||||
|
||||
if isMessage {
|
||||
if index < len(mb.Messages) {
|
||||
mb.Messages[index] = newMessage
|
||||
} else {
|
||||
return fmt.Errorf("No message"), ""
|
||||
return "", fmt.Errorf("No message")
|
||||
}
|
||||
} else {
|
||||
if index < len(mb.Actions) {
|
||||
mb.Actions[index] = newMessage
|
||||
} else {
|
||||
return fmt.Errorf("No action"), ""
|
||||
return "", fmt.Errorf("No action")
|
||||
}
|
||||
}
|
||||
return nil, ""
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (mb *MockBot) GetEmojiList() map[string]string { return make(map[string]string) }
|
||||
|
|
78
irc/irc.go
78
irc/irc.go
|
@ -42,9 +42,7 @@ type Irc struct {
|
|||
config *config.Config
|
||||
quit chan bool
|
||||
|
||||
eventReceived func(msg.Message)
|
||||
messageReceived func(msg.Message)
|
||||
replyMessageReceived func(msg.Message, string)
|
||||
event func(bot.Kind, msg.Message, ...interface{})
|
||||
}
|
||||
|
||||
func New(c *config.Config) *Irc {
|
||||
|
@ -54,19 +52,11 @@ func New(c *config.Config) *Irc {
|
|||
return &i
|
||||
}
|
||||
|
||||
func (i *Irc) RegisterEventReceived(f func(msg.Message)) {
|
||||
i.eventReceived = f
|
||||
func (i *Irc) RegisterEvent(f func(bot.Kind, msg.Message, ...interface{})) {
|
||||
i.event = f
|
||||
}
|
||||
|
||||
func (i *Irc) RegisterMessageReceived(f func(msg.Message)) {
|
||||
i.messageReceived = f
|
||||
}
|
||||
|
||||
func (i *Irc) RegisterReplyMessageReceived(f func(msg.Message, string)) {
|
||||
i.replyMessageReceived = f
|
||||
}
|
||||
|
||||
func (i *Irc) Send(kind bot.Kind, args ...interface{}) (error, string) {
|
||||
func (i *Irc) Send(kind bot.Kind, args ...interface{}) (string, error) {
|
||||
switch kind {
|
||||
case bot.Reply:
|
||||
case bot.Message:
|
||||
|
@ -75,7 +65,7 @@ func (i *Irc) Send(kind bot.Kind, args ...interface{}) (error, string) {
|
|||
return i.sendAction(args[0].(string), args[1].(string))
|
||||
default:
|
||||
}
|
||||
return nil, ""
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (i *Irc) JoinChannel(channel string) {
|
||||
|
@ -83,7 +73,7 @@ func (i *Irc) JoinChannel(channel string) {
|
|||
i.Client.Out <- irc.Msg{Cmd: irc.JOIN, Args: []string{channel}}
|
||||
}
|
||||
|
||||
func (i *Irc) sendMessage(channel, message string) (error, string) {
|
||||
func (i *Irc) sendMessage(channel, message string) (string, error) {
|
||||
for len(message) > 0 {
|
||||
m := irc.Msg{
|
||||
Cmd: "PRIVMSG",
|
||||
|
@ -107,11 +97,11 @@ func (i *Irc) sendMessage(channel, message string) (error, string) {
|
|||
|
||||
i.Client.Out <- m
|
||||
}
|
||||
return nil, "NO_IRC_IDENTIFIERS"
|
||||
return "NO_IRC_IDENTIFIERS", nil
|
||||
}
|
||||
|
||||
// Sends action to channel
|
||||
func (i *Irc) sendAction(channel, message string) (error, string) {
|
||||
func (i *Irc) sendAction(channel, message string) (string, error) {
|
||||
message = actionPrefix + " " + message + "\x01"
|
||||
|
||||
return i.sendMessage(channel, message)
|
||||
|
@ -123,7 +113,7 @@ func (i *Irc) GetEmojiList() map[string]string {
|
|||
}
|
||||
|
||||
func (i *Irc) Serve() error {
|
||||
if i.eventReceived == nil || i.messageReceived == nil {
|
||||
if i.event == nil {
|
||||
return fmt.Errorf("Missing an event handler")
|
||||
}
|
||||
|
||||
|
@ -202,53 +192,53 @@ func (i *Irc) handleMsg(msg irc.Msg) {
|
|||
// OK, ignore
|
||||
|
||||
case irc.ERR_NOSUCHNICK:
|
||||
i.eventReceived(botMsg)
|
||||
fallthrough
|
||||
|
||||
case irc.ERR_NOSUCHCHANNEL:
|
||||
i.eventReceived(botMsg)
|
||||
fallthrough
|
||||
|
||||
case irc.RPL_MOTD:
|
||||
i.eventReceived(botMsg)
|
||||
fallthrough
|
||||
|
||||
case irc.RPL_NAMREPLY:
|
||||
i.eventReceived(botMsg)
|
||||
fallthrough
|
||||
|
||||
case irc.RPL_TOPIC:
|
||||
i.eventReceived(botMsg)
|
||||
fallthrough
|
||||
|
||||
case irc.KICK:
|
||||
i.eventReceived(botMsg)
|
||||
fallthrough
|
||||
|
||||
case irc.TOPIC:
|
||||
i.eventReceived(botMsg)
|
||||
fallthrough
|
||||
|
||||
case irc.MODE:
|
||||
i.eventReceived(botMsg)
|
||||
fallthrough
|
||||
|
||||
case irc.JOIN:
|
||||
i.eventReceived(botMsg)
|
||||
fallthrough
|
||||
|
||||
case irc.PART:
|
||||
i.eventReceived(botMsg)
|
||||
fallthrough
|
||||
|
||||
case irc.NOTICE:
|
||||
fallthrough
|
||||
|
||||
case irc.NICK:
|
||||
fallthrough
|
||||
|
||||
case irc.RPL_WHOREPLY:
|
||||
fallthrough
|
||||
|
||||
case irc.RPL_ENDOFWHO:
|
||||
i.event(bot.Event, botMsg)
|
||||
|
||||
case irc.PRIVMSG:
|
||||
i.event(bot.Message, botMsg)
|
||||
|
||||
case irc.QUIT:
|
||||
os.Exit(1)
|
||||
|
||||
case irc.NOTICE:
|
||||
i.eventReceived(botMsg)
|
||||
|
||||
case irc.PRIVMSG:
|
||||
i.messageReceived(botMsg)
|
||||
|
||||
case irc.NICK:
|
||||
i.eventReceived(botMsg)
|
||||
|
||||
case irc.RPL_WHOREPLY:
|
||||
i.eventReceived(botMsg)
|
||||
|
||||
case irc.RPL_ENDOFWHO:
|
||||
i.eventReceived(botMsg)
|
||||
|
||||
default:
|
||||
cmd := irc.CmdNames[msg.Cmd]
|
||||
log.Println("(" + cmd + ") " + msg.Raw)
|
||||
|
|
3
main.go
3
main.go
|
@ -35,6 +35,7 @@ import (
|
|||
"github.com/velour/catbase/plugins/twitch"
|
||||
"github.com/velour/catbase/plugins/your"
|
||||
"github.com/velour/catbase/plugins/zork"
|
||||
"github.com/velour/catbase/slack"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -70,7 +71,7 @@ func main() {
|
|||
case "irc":
|
||||
client = irc.New(c)
|
||||
case "slack":
|
||||
//client = slack.New(c)
|
||||
client = slack.New(c)
|
||||
default:
|
||||
log.Fatalf("Unknown connection type: %s", c.Get("type", "UNSET"))
|
||||
}
|
||||
|
|
|
@ -25,12 +25,14 @@ type AdminPlugin struct {
|
|||
}
|
||||
|
||||
// NewAdminPlugin creates a new AdminPlugin with the Plugin interface
|
||||
func New(bot bot.Bot) *AdminPlugin {
|
||||
func New(b bot.Bot) *AdminPlugin {
|
||||
p := &AdminPlugin{
|
||||
Bot: bot,
|
||||
db: bot.DB(),
|
||||
cfg: bot.Config(),
|
||||
Bot: b,
|
||||
db: b.DB(),
|
||||
cfg: b.Config(),
|
||||
}
|
||||
b.Register("admin", bot.Message, p.message)
|
||||
b.Register("admin", bot.Help, p.help)
|
||||
return p
|
||||
}
|
||||
|
||||
|
@ -44,7 +46,7 @@ var forbiddenKeys = map[string]bool{
|
|||
// 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 *AdminPlugin) Message(message msg.Message) bool {
|
||||
func (p *AdminPlugin) message(k bot.Kind, message msg.Message, args ...interface{}) bool {
|
||||
body := message.Body
|
||||
|
||||
if p.quiet {
|
||||
|
@ -143,23 +145,12 @@ func (p *AdminPlugin) handleVariables(message msg.Message) bool {
|
|||
}
|
||||
|
||||
// Help responds to help requests. Every plugin must implement a help function.
|
||||
func (p *AdminPlugin) Help(channel string, parts []string) {
|
||||
p.Bot.Send(bot.Message, channel, "This does super secret things that you're not allowed to know about.")
|
||||
}
|
||||
|
||||
// Empty event handler because this plugin does not do anything on event recv
|
||||
func (p *AdminPlugin) Event(kind string, message msg.Message) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Handler for bot's own messages
|
||||
func (p *AdminPlugin) BotMessage(message msg.Message) bool {
|
||||
return false
|
||||
func (p *AdminPlugin) help(kind bot.Kind, m msg.Message, args ...interface{}) bool {
|
||||
p.Bot.Send(bot.Message, m.Channel, "This does super secret things that you're not allowed to know about.")
|
||||
return true
|
||||
}
|
||||
|
||||
// Register any web URLs desired
|
||||
func (p *AdminPlugin) RegisterWeb() *string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *AdminPlugin) ReplyMessage(message msg.Message, identifier string) bool { return false }
|
||||
|
|
|
@ -22,12 +22,12 @@ func setup(t *testing.T) (*AdminPlugin, *bot.MockBot) {
|
|||
return a, mb
|
||||
}
|
||||
|
||||
func makeMessage(payload string) msg.Message {
|
||||
func makeMessage(payload string) (bot.Kind, msg.Message) {
|
||||
isCmd := strings.HasPrefix(payload, "!")
|
||||
if isCmd {
|
||||
payload = payload[1:]
|
||||
}
|
||||
return msg.Message{
|
||||
return bot.Message, msg.Message{
|
||||
User: &user.User{Name: "tester"},
|
||||
Channel: "test",
|
||||
Body: payload,
|
||||
|
@ -38,7 +38,7 @@ func makeMessage(payload string) msg.Message {
|
|||
func TestSet(t *testing.T) {
|
||||
a, mb := setup(t)
|
||||
expected := "test value"
|
||||
a.Message(makeMessage("!set test.key " + expected))
|
||||
a.message(makeMessage("!set test.key " + expected))
|
||||
actual := mb.Config().Get("test.key", "ERR")
|
||||
assert.Equal(t, expected, actual)
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ func TestGetValue(t *testing.T) {
|
|||
a, mb := setup(t)
|
||||
expected := "value"
|
||||
mb.Config().Set("test.key", "value")
|
||||
a.Message(makeMessage("!get test.key"))
|
||||
a.message(makeMessage("!get test.key"))
|
||||
assert.Len(t, mb.Messages, 1)
|
||||
assert.Contains(t, mb.Messages[0], expected)
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ func TestGetValue(t *testing.T) {
|
|||
func TestGetEmpty(t *testing.T) {
|
||||
a, mb := setup(t)
|
||||
expected := "test.key: <unknown>"
|
||||
a.Message(makeMessage("!get test.key"))
|
||||
a.message(makeMessage("!get test.key"))
|
||||
assert.Len(t, mb.Messages, 1)
|
||||
assert.Equal(t, expected, mb.Messages[0])
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ func TestGetEmpty(t *testing.T) {
|
|||
func TestGetForbidden(t *testing.T) {
|
||||
a, mb := setup(t)
|
||||
expected := "cannot access"
|
||||
a.Message(makeMessage("!get slack.token"))
|
||||
a.message(makeMessage("!get slack.token"))
|
||||
assert.Len(t, mb.Messages, 1)
|
||||
assert.Contains(t, mb.Messages[0], expected)
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ func New(b bot.Bot) *RPGPlugin {
|
|||
func (p *RPGPlugin) Message(message msg.Message) bool {
|
||||
if strings.ToLower(message.Body) == "start rpg" {
|
||||
b := NewRandomBoard()
|
||||
_, ts := p.Bot.Send(bot.Message, message.Channel, b.toMessageString())
|
||||
ts, _ := p.Bot.Send(bot.Message, message.Channel, b.toMessageString())
|
||||
p.listenFor[ts] = b
|
||||
p.Bot.Send(bot.Reply, message.Channel, "Over here.", ts)
|
||||
return true
|
||||
|
|
|
@ -47,7 +47,7 @@ func NewRandomGame(b bot.Bot, channel, who string) *game {
|
|||
size: size,
|
||||
current: size / 2,
|
||||
}
|
||||
_, g.id = b.Send(bot.Message, channel, g.toMessageString())
|
||||
g.id, _ = b.Send(bot.Message, channel, g.toMessageString())
|
||||
|
||||
g.schedulePush()
|
||||
g.scheduleDecrement()
|
||||
|
|
108
slack/slack.go
108
slack/slack.go
|
@ -44,9 +44,7 @@ type Slack struct {
|
|||
|
||||
emoji map[string]string
|
||||
|
||||
eventReceived func(msg.Message)
|
||||
messageReceived func(msg.Message)
|
||||
replyMessageReceived func(msg.Message, string)
|
||||
event func(bot.Kind, msg.Message, ...interface{})
|
||||
}
|
||||
|
||||
var idCounter uint64
|
||||
|
@ -177,7 +175,31 @@ func New(c *config.Config) *Slack {
|
|||
}
|
||||
}
|
||||
|
||||
func checkReturnStatus(response *http.Response) bool {
|
||||
func (s *Slack) Send(kind bot.Kind, args ...interface{}) (string, error) {
|
||||
switch kind {
|
||||
case bot.Message:
|
||||
return s.sendMessage(args[0].(string), args[1].(string))
|
||||
case bot.Action:
|
||||
return s.sendAction(args[0].(string), args[1].(string))
|
||||
case bot.Edit:
|
||||
return s.edit(args[0].(string), args[1].(string), args[2].(string))
|
||||
case bot.Reply:
|
||||
switch args[2].(type) {
|
||||
case msg.Message:
|
||||
return s.replyToMessage(args[0].(string), args[1].(string), args[2].(msg.Message))
|
||||
case string:
|
||||
return s.replyToMessageIdentifier(args[0].(string), args[1].(string), args[2].(string))
|
||||
default:
|
||||
return "", fmt.Errorf("Invalid types given to Reply")
|
||||
}
|
||||
case bot.Reaction:
|
||||
return s.react(args[0].(string), args[1].(string), args[2].(msg.Message))
|
||||
default:
|
||||
}
|
||||
return "", fmt.Errorf("No handler for message type %d", kind)
|
||||
}
|
||||
|
||||
func checkReturnStatus(response *http.Response) error {
|
||||
type Response struct {
|
||||
OK bool `json:"ok"`
|
||||
}
|
||||
|
@ -185,32 +207,24 @@ func checkReturnStatus(response *http.Response) bool {
|
|||
body, err := ioutil.ReadAll(response.Body)
|
||||
response.Body.Close()
|
||||
if err != nil {
|
||||
log.Printf("Error reading Slack API body: %s", err)
|
||||
return false
|
||||
err := fmt.Errorf("Error reading Slack API body: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
var resp Response
|
||||
err = json.Unmarshal(body, &resp)
|
||||
if err != nil {
|
||||
log.Printf("Error parsing message response: %s", err)
|
||||
return false
|
||||
err := fmt.Errorf("Error parsing message response: %s", err)
|
||||
return err
|
||||
}
|
||||
return resp.OK
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Slack) RegisterEventReceived(f func(msg.Message)) {
|
||||
s.eventReceived = f
|
||||
func (s *Slack) RegisterEvent(f func(bot.Kind, msg.Message, ...interface{})) {
|
||||
s.event = f
|
||||
}
|
||||
|
||||
func (s *Slack) RegisterMessageReceived(f func(msg.Message)) {
|
||||
s.messageReceived = f
|
||||
}
|
||||
|
||||
func (s *Slack) RegisterReplyMessageReceived(f func(msg.Message, string)) {
|
||||
s.replyMessageReceived = f
|
||||
}
|
||||
|
||||
func (s *Slack) SendMessageType(channel, message string, meMessage bool) (string, error) {
|
||||
func (s *Slack) sendMessageType(channel, message string, meMessage bool) (string, error) {
|
||||
postUrl := "https://slack.com/api/chat.postMessage"
|
||||
if meMessage {
|
||||
postUrl = "https://slack.com/api/chat.meMessage"
|
||||
|
@ -262,19 +276,19 @@ func (s *Slack) SendMessageType(channel, message string, meMessage bool) (string
|
|||
return mr.Timestamp, err
|
||||
}
|
||||
|
||||
func (s *Slack) SendMessage(channel, message string) string {
|
||||
func (s *Slack) sendMessage(channel, message string) (string, error) {
|
||||
log.Printf("Sending message to %s: %s", channel, message)
|
||||
identifier, _ := s.SendMessageType(channel, message, false)
|
||||
return identifier
|
||||
identifier, err := s.sendMessageType(channel, message, false)
|
||||
return identifier, err
|
||||
}
|
||||
|
||||
func (s *Slack) SendAction(channel, message string) string {
|
||||
func (s *Slack) sendAction(channel, message string) (string, error) {
|
||||
log.Printf("Sending action to %s: %s", channel, message)
|
||||
identifier, _ := s.SendMessageType(channel, "_"+message+"_", true)
|
||||
return identifier
|
||||
identifier, err := s.sendMessageType(channel, "_"+message+"_", true)
|
||||
return identifier, err
|
||||
}
|
||||
|
||||
func (s *Slack) ReplyToMessageIdentifier(channel, message, identifier string) (string, bool) {
|
||||
func (s *Slack) replyToMessageIdentifier(channel, message, identifier string) (string, error) {
|
||||
nick := s.config.Get("Nick", "bot")
|
||||
icon := s.config.Get("IconURL", "https://placekitten.com/128/128")
|
||||
|
||||
|
@ -288,15 +302,15 @@ func (s *Slack) ReplyToMessageIdentifier(channel, message, identifier string) (s
|
|||
})
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Error sending Slack reply: %s", err)
|
||||
return "", false
|
||||
err := fmt.Errorf("Error sending Slack reply: %s", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
resp.Body.Close()
|
||||
if err != nil {
|
||||
log.Printf("Error reading Slack API body: %s", err)
|
||||
return "", false
|
||||
err := fmt.Errorf("Error reading Slack API body: %s", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
log.Println(string(body))
|
||||
|
@ -309,22 +323,22 @@ func (s *Slack) ReplyToMessageIdentifier(channel, message, identifier string) (s
|
|||
var mr MessageResponse
|
||||
err = json.Unmarshal(body, &mr)
|
||||
if err != nil {
|
||||
log.Printf("Error parsing message response: %s", err)
|
||||
return "", false
|
||||
err := fmt.Errorf("Error parsing message response: %s", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
if !mr.OK {
|
||||
return "", false
|
||||
return "", fmt.Errorf("Got !OK from slack message response")
|
||||
}
|
||||
|
||||
return mr.Timestamp, err == nil
|
||||
return mr.Timestamp, err
|
||||
}
|
||||
|
||||
func (s *Slack) ReplyToMessage(channel, message string, replyTo msg.Message) (string, bool) {
|
||||
return s.ReplyToMessageIdentifier(channel, message, replyTo.AdditionalData["RAW_SLACK_TIMESTAMP"])
|
||||
func (s *Slack) replyToMessage(channel, message string, replyTo msg.Message) (string, error) {
|
||||
return s.replyToMessageIdentifier(channel, message, replyTo.AdditionalData["RAW_SLACK_TIMESTAMP"])
|
||||
}
|
||||
|
||||
func (s *Slack) React(channel, reaction string, message msg.Message) bool {
|
||||
func (s *Slack) react(channel, reaction string, message msg.Message) (string, error) {
|
||||
log.Printf("Reacting in %s: %s", channel, reaction)
|
||||
resp, err := http.PostForm("https://slack.com/api/reactions.add",
|
||||
url.Values{"token": {s.token},
|
||||
|
@ -332,13 +346,13 @@ func (s *Slack) React(channel, reaction string, message msg.Message) bool {
|
|||
"channel": {channel},
|
||||
"timestamp": {message.AdditionalData["RAW_SLACK_TIMESTAMP"]}})
|
||||
if err != nil {
|
||||
log.Printf("reaction failed: %s", err)
|
||||
return false
|
||||
err := fmt.Errorf("reaction failed: %s", err)
|
||||
return "", err
|
||||
}
|
||||
return checkReturnStatus(resp)
|
||||
return "", checkReturnStatus(resp)
|
||||
}
|
||||
|
||||
func (s *Slack) Edit(channel, newMessage, identifier string) bool {
|
||||
func (s *Slack) edit(channel, newMessage, identifier string) (string, error) {
|
||||
log.Printf("Editing in (%s) %s: %s", identifier, channel, newMessage)
|
||||
resp, err := http.PostForm("https://slack.com/api/chat.update",
|
||||
url.Values{"token": {s.token},
|
||||
|
@ -346,10 +360,10 @@ func (s *Slack) Edit(channel, newMessage, identifier string) bool {
|
|||
"text": {newMessage},
|
||||
"ts": {identifier}})
|
||||
if err != nil {
|
||||
log.Printf("edit failed: %s", err)
|
||||
return false
|
||||
err := fmt.Errorf("edit failed: %s", err)
|
||||
return "", err
|
||||
}
|
||||
return checkReturnStatus(resp)
|
||||
return "", checkReturnStatus(resp)
|
||||
}
|
||||
|
||||
func (s *Slack) GetEmojiList() map[string]string {
|
||||
|
@ -441,11 +455,11 @@ func (s *Slack) Serve() error {
|
|||
log.Printf("Ignoring message: %+v\nlastRecieved: %v msg: %v", msg.ID, s.lastRecieved, m.Time)
|
||||
} else {
|
||||
s.lastRecieved = m.Time
|
||||
s.messageReceived(m)
|
||||
s.event(bot.Message, m)
|
||||
}
|
||||
} else if msg.ThreadTs != "" {
|
||||
//we're throwing away some information here by not parsing the correct reply object type, but that's okay
|
||||
s.replyMessageReceived(s.buildLightReplyMessage(msg), msg.ThreadTs)
|
||||
s.event(bot.Reply, s.buildLightReplyMessage(msg), msg.ThreadTs)
|
||||
} else {
|
||||
log.Printf("THAT MESSAGE WAS HIDDEN: %+v", msg.ID)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue