From 82dcf410f2145715ddc83a15d8e3728820e47ab0 Mon Sep 17 00:00:00 2001 From: Chris Sexton Date: Tue, 5 Feb 2019 13:33:18 -0500 Subject: [PATCH] bot: hook connectors up to events This includes a full test of `admin` --- bot/bot.go | 14 +++-- bot/handlers.go | 68 ++++------------------ bot/interfaces.go | 8 +-- bot/mock.go | 24 ++++---- irc/irc.go | 78 +++++++++++-------------- main.go | 3 +- plugins/admin/admin.go | 29 ++++------ plugins/admin/admin_test.go | 12 ++-- plugins/rpgORdie/rpgORdie.go | 2 +- plugins/sisyphus/sisyphus.go | 2 +- slack/slack.go | 108 ++++++++++++++++++++--------------- 11 files changed, 149 insertions(+), 199 deletions(-) diff --git a/bot/bot.go b/bot/bot.go index f0a1dac..9d8c55f 100644 --- a/bot/bot.go +++ b/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) } diff --git a/bot/handlers.go b/bot/handlers.go index 06814c7..70f0754 100644 --- a/bot/handlers.go +++ b/bot/handlers.go @@ -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 diff --git a/bot/interfaces.go b/bot/interfaces.go index 950a8b2..b3dc6d7 100644 --- a/bot/interfaces.go +++ b/bot/interfaces.go @@ -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 diff --git a/bot/mock.go b/bot/mock.go index 3e300af..65409fc 100644 --- a/bot/mock.go +++ b/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) } diff --git a/irc/irc.go b/irc/irc.go index de6c992..58e1359 100644 --- a/irc/irc.go +++ b/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) diff --git a/main.go b/main.go index 95527c8..18ff59f 100644 --- a/main.go +++ b/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")) } diff --git a/plugins/admin/admin.go b/plugins/admin/admin.go index 628125e..cb2eba2 100644 --- a/plugins/admin/admin.go +++ b/plugins/admin/admin.go @@ -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 } diff --git a/plugins/admin/admin_test.go b/plugins/admin/admin_test.go index f4ce489..069b21d 100644 --- a/plugins/admin/admin_test.go +++ b/plugins/admin/admin_test.go @@ -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: " - 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) } diff --git a/plugins/rpgORdie/rpgORdie.go b/plugins/rpgORdie/rpgORdie.go index 8c69174..1763e73 100644 --- a/plugins/rpgORdie/rpgORdie.go +++ b/plugins/rpgORdie/rpgORdie.go @@ -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 diff --git a/plugins/sisyphus/sisyphus.go b/plugins/sisyphus/sisyphus.go index a96ce74..0eac02d 100644 --- a/plugins/sisyphus/sisyphus.go +++ b/plugins/sisyphus/sisyphus.go @@ -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() diff --git a/slack/slack.go b/slack/slack.go index 3c1049b..dcf616b 100644 --- a/slack/slack.go +++ b/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) }