diff --git a/bot/bot.go b/bot/bot.go index 2507586..eac6f28 100644 --- a/bot/bot.go +++ b/bot/bot.go @@ -110,10 +110,6 @@ func (b *bot) DB() *sqlx.DB { return b.db } -func (b *bot) Conn() Connector { - return b.conn -} - // Create any tables if necessary based on version of DB // Plugins should create their own tables, these are only for official bot stuff // Note: This does not return an error. Database issues are all fatal at this stage. diff --git a/bot/handlers.go b/bot/handlers.go index 9df5896..bb4c340 100644 --- a/bot/handlers.go +++ b/bot/handlers.go @@ -55,20 +55,20 @@ func (b *bot) EventReceived(msg msg.Message) { } } -func (b *bot) SendMessage(channel, message string) { - b.conn.SendMessage(channel, message) +func (b *bot) SendMessage(channel, message string) string { + return b.conn.SendMessage(channel, message) } -func (b *bot) SendAction(channel, message string) { - b.conn.SendAction(channel, message) +func (b *bot) SendAction(channel, message string) string { + return b.conn.SendAction(channel, message) } -func (b *bot) React(channel, reaction string, message msg.Message) { - b.conn.React(channel, reaction, message) +func (b *bot) React(channel, reaction string, message msg.Message) bool { + return b.conn.React(channel, reaction, message) } -func (b *bot) Edit(channel, newMessage, identifier string) { - b.conn.Edit(channel, newMessage, identifier) +func (b *bot) Edit(channel, newMessage, identifier string) bool { + return b.conn.Edit(channel, newMessage, identifier) } func (b *bot) GetEmojiList() map[string]string { diff --git a/bot/interfaces.go b/bot/interfaces.go index d476642..2fc783d 100644 --- a/bot/interfaces.go +++ b/bot/interfaces.go @@ -13,13 +13,12 @@ type Bot interface { Config() *config.Config DBVersion() int64 DB() *sqlx.DB - Conn() Connector Who(string) []user.User AddHandler(string, Handler) - SendMessage(string, string) - SendAction(string, string) - React(string, string, msg.Message) - Edit(string, string, string) + SendMessage(string, string) string + SendAction(string, string) string + React(string, string, msg.Message) bool + Edit(string, string, string) bool MsgReceived(msg.Message) EventReceived(msg.Message) Filter(msg.Message, string) string @@ -33,10 +32,10 @@ type Connector interface { RegisterEventReceived(func(message msg.Message)) RegisterMessageReceived(func(message msg.Message)) - SendMessage(channel, message string) - SendAction(channel, message string) - React(string, string, msg.Message) - Edit(string, string, string) + SendMessage(channel, message string) string + SendAction(channel, message string) string + React(string, string, msg.Message) bool + Edit(string, string, string) bool GetEmojiList() map[string]string Serve() error diff --git a/bot/mock.go b/bot/mock.go index 997fe5f..1e51bb9 100644 --- a/bot/mock.go +++ b/bot/mock.go @@ -3,7 +3,10 @@ package bot import ( + "fmt" "log" + "strconv" + "strings" "github.com/jmoiron/sqlx" "github.com/stretchr/testify/mock" @@ -25,14 +28,16 @@ type MockBot struct { func (mb *MockBot) Config() *config.Config { return &mb.Cfg } func (mb *MockBot) DBVersion() int64 { return 1 } func (mb *MockBot) DB() *sqlx.DB { return mb.db } -func (mb *MockBot) Conn() Connector { return nil } +func (mb *MockBot) Conn() Connector { return nil } func (mb *MockBot) Who(string) []user.User { return []user.User{} } func (mb *MockBot) AddHandler(name string, f Handler) {} -func (mb *MockBot) SendMessage(ch string, msg string) { +func (mb *MockBot) SendMessage(ch string, msg string) string { mb.Messages = append(mb.Messages, msg) + return fmt.Sprintf("m-%d", len(mb.Actions)-1) } -func (mb *MockBot) SendAction(ch string, msg string) { +func (mb *MockBot) SendAction(ch string, msg string) string { mb.Actions = append(mb.Actions, msg) + return fmt.Sprintf("a-%d", len(mb.Actions)-1) } func (mb *MockBot) MsgReceived(msg msg.Message) {} func (mb *MockBot) EventReceived(msg msg.Message) {} @@ -40,10 +45,38 @@ func (mb *MockBot) Filter(msg msg.Message, s string) string { return "" } 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) {} -func (mb *MockBot) Edit(channel, newMessage, identifier string) {} -func (mb *MockBot) GetEmojiList() map[string]string { return make(map[string]string) } -func (mb *MockBot) RegisterFilter(s string, f func(string) string) {} +func (mb *MockBot) React(channel, reaction string, message msg.Message) bool { return false } + +func (mb *MockBot) Edit(channel, newMessage, identifier string) bool { + isMessage := identifier[0] == 'm' + if !isMessage && identifier[0] != 'a' { + log.Printf("failed to parse identifier: %s", identifier) + return false + } + + index, err := strconv.Atoi(strings.Split(identifier, "-")[1]) + if err != nil { + log.Printf("failed to parse identifier: %s", identifier) + return false + } + + if isMessage { + if index < len(mb.Messages) { + mb.Messages[index] = newMessage + } else { + return false + } + } else { + if index < len(mb.Actions) { + mb.Actions[index] = newMessage + } else { + return false + } + } + return true +} +func (mb *MockBot) GetEmojiList() map[string]string { return make(map[string]string) } +func (mb *MockBot) RegisterFilter(s string, f func(string) string) {} func NewMockBot() *MockBot { db, err := sqlx.Open("sqlite3_custom", ":memory:") diff --git a/irc/irc.go b/irc/irc.go index da2a806..65de1a7 100644 --- a/irc/irc.go +++ b/irc/irc.go @@ -66,7 +66,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) { +func (i *Irc) SendMessage(channel, message string) string { for len(message) > 0 { m := irc.Msg{ Cmd: "PRIVMSG", @@ -90,21 +90,25 @@ func (i *Irc) SendMessage(channel, message string) { i.Client.Out <- m } + return "NO_IRC_IDENTIFIERS" } // Sends action to channel -func (i *Irc) SendAction(channel, message string) { +func (i *Irc) SendAction(channel, message string) string { message = actionPrefix + " " + message + "\x01" i.SendMessage(channel, message) + return "NO_IRC_IDENTIFIERS" } -func (i *Irc) React(channel, reaction string, message msg.Message) { +func (i *Irc) React(channel, reaction string, message msg.Message) bool { //we're not goign to do anything because it's IRC + return false } -func (i *Irc) Edit(channel, newMessage, identifier string) { +func (i *Irc) Edit(channel, newMessage, identifier string) bool { //we're not goign to do anything because it's IRC + return false } func (i *Irc) GetEmojiList() map[string]string { diff --git a/plugins/rpgORdie/rpgORdie.go b/plugins/rpgORdie/rpgORdie.go index 7201c1b..17418c8 100644 --- a/plugins/rpgORdie/rpgORdie.go +++ b/plugins/rpgORdie/rpgORdie.go @@ -7,25 +7,21 @@ import ( "github.com/velour/catbase/bot" "github.com/velour/catbase/bot/msg" - "github.com/velour/catbase/slack" ) type RPGPlugin struct { - Bot bot.Bot - Slack *slack.Slack //nasty + Bot bot.Bot } func New(b bot.Bot) *RPGPlugin { return &RPGPlugin{ - Bot: b, - Slack: b.Conn().(*slack.Slack), //oh boy, this is just filthy + Bot: b, } } func (p *RPGPlugin) Message(message msg.Message) bool { if strings.ToLower(message.Body) == "start rpg" { - p.Bot.SendMessage(message.Channel, "I'll edit this.") - ts := p.Slack.GetLastMessageId() + ts := p.Bot.SendMessage(message.Channel, "I'll edit this.") time.Sleep(2 * time.Second) diff --git a/plugins/rpgORdie/rpgORdie_test.go b/plugins/rpgORdie/rpgORdie_test.go index 42db0f4..ddcd924 100644 --- a/plugins/rpgORdie/rpgORdie_test.go +++ b/plugins/rpgORdie/rpgORdie_test.go @@ -1,4 +1,3 @@ package rpgORdie -import ( -) +import () diff --git a/slack/slack.go b/slack/slack.go index 22c5c3a..3e7e2ed 100644 --- a/slack/slack.go +++ b/slack/slack.go @@ -38,8 +38,6 @@ type Slack struct { emoji map[string]string - lastMessageId string - eventReceived func(msg.Message) messageReceived func(msg.Message) } @@ -162,10 +160,30 @@ func New(c *config.Config) *Slack { lastRecieved: time.Now(), users: make(map[string]string), emoji: make(map[string]string), - lastMessageId: "", } } +func checkReturnStatus(response *http.Response) bool { + type Response struct { + OK bool `json:"ok"` + } + + body, err := ioutil.ReadAll(response.Body) + response.Body.Close() + if err != nil { + log.Printf("Error reading Slack API body: %s", err) + return false + } + + var resp Response + err = json.Unmarshal(body, &resp) + if err != nil { + log.Printf("Error parsing message response: %s", err) + return false + } + return resp.OK +} + func (s *Slack) RegisterEventReceived(f func(msg.Message)) { s.eventReceived = f } @@ -174,11 +192,11 @@ func (s *Slack) RegisterMessageReceived(f func(msg.Message)) { s.messageReceived = f } -func (s *Slack) SendMessageType(channel, messageType, subType, message string) error { +func (s *Slack) SendMessageType(channel, messageType, subType, message string) (string, error) { resp, err := http.PostForm("https://slack.com/api/chat.postMessage", url.Values{"token": {s.config.Slack.Token}, - "channel": {channel}, - "text": {message}, + "channel": {channel}, + "text": {message}, }) if err != nil { @@ -194,9 +212,9 @@ func (s *Slack) SendMessageType(channel, messageType, subType, message string) e log.Println(string(body)) type MessageResponse struct { - OK bool `json:ok` - Channel string `json:channel` - Timestamp string `json:ts` + OK bool `json:"ok"` + Channel string `json:"channel"` + Timestamp string `json:"ts"` } var mr MessageResponse @@ -212,24 +230,22 @@ func (s *Slack) SendMessageType(channel, messageType, subType, message string) e mr.Timestamp = strings.Split(strings.Split(bodyAsString, "\"ts\":\"")[1], "\"")[0] } - s.lastMessageId = mr.Timestamp - - log.Println(mr) - - return err + return mr.Timestamp, err } -func (s *Slack) SendMessage(channel, message string) { +func (s *Slack) SendMessage(channel, message string) string { log.Printf("Sending message to %s: %s", channel, message) - s.SendMessageType(channel, "message", "", message) + identifier, _ := s.SendMessageType(channel, "message", "", message) + return identifier } -func (s *Slack) SendAction(channel, message string) { +func (s *Slack) SendAction(channel, message string) string { log.Printf("Sending action to %s: %s", channel, message) - s.SendMessageType(channel, "message", "me_message", "_"+message+"_") + identifier, _ := s.SendMessageType(channel, "message", "me_message", "_"+message+"_") + return identifier } -func (s *Slack) React(channel, reaction string, message msg.Message) { +func (s *Slack) React(channel, reaction string, message msg.Message) bool { log.Printf("Reacting in %s: %s", channel, reaction) resp, err := http.PostForm("https://slack.com/api/reactions.add", url.Values{"token": {s.config.Slack.Token}, @@ -237,49 +253,24 @@ func (s *Slack) React(channel, reaction string, message msg.Message) { "channel": {channel}, "timestamp": {message.AdditionalData["RAW_SLACK_TIMESTAMP"]}}) if err != nil { - log.Printf("Error sending Slack reaction: %s", err) + log.Println("reaction failed: %s", err) + return false } - log.Print(resp) + return checkReturnStatus(resp) } -func (s* Slack) GetLastMessageId() string { - return s.lastMessageId -} - -func (s* Slack) PrintHistory(channel string, howMany int) { - resp, err := http.PostForm("https://slack.com/api/channels.history", - url.Values{"token": {s.config.Slack.Token}, - "channel": {channel}, - "count": {fmt.Sprintf("%d", howMany)}}) - if err != nil { - log.Printf("Error getting slack history: %s", err) - } - body, err := ioutil.ReadAll(resp.Body) - resp.Body.Close() - if err != nil { - log.Fatalf("Error reading Slack API body: %s", err) - } - - log.Println(string(body)) -} - -func (s *Slack) Edit(channel, newMessage, identifier string) { +func (s *Slack) Edit(channel, newMessage, identifier string) bool { log.Printf("Editing in (%s) %s: %s", identifier, channel, newMessage) resp, err := http.PostForm("https://slack.com/api/chat.update", url.Values{"token": {s.config.Slack.Token}, - "channel": {channel}, - "text": {newMessage}, - "ts": {identifier}}) + "channel": {channel}, + "text": {newMessage}, + "ts": {identifier}}) if err != nil { - log.Printf("Error sending Slack reaction: %s", err) + log.Println("edit failed: %s", err) + return false } - body, err := ioutil.ReadAll(resp.Body) - resp.Body.Close() - if err != nil { - log.Fatalf("Error reading Slack API body: %s", err) - } - - log.Println(string(body)) + return checkReturnStatus(resp) } func (s *Slack) GetEmojiList() map[string]string {