diff --git a/cmd/app.go b/cmd/app.go index 5cfd92c..d68d98f 100644 --- a/cmd/app.go +++ b/cmd/app.go @@ -23,12 +23,11 @@ func NewApp() (*App, error) { } a.DebugMode = DebugMode - a.running = true err := a.initialize() if err != nil { - a.running = false return nil, err } + a.running = true go a.MonitorSlackMessages() return a, nil @@ -39,6 +38,10 @@ func (a *App) initialize() error { if a.m, err = NewBotModel(); err != nil { return err } + bt, bterr := a.m.GetString([]string{"config", "plugin_dir"}) + if bterr == nil { + fmt.Println(bt) + } reader := bufio.NewReader(os.Stdin) // Load up the plugins @@ -65,12 +68,10 @@ func (a *App) initialize() error { a.m.setSlackAdminDMId(strings.TrimSpace(slackDMid)) } - fmt.Println("Creating Slack Model") if err = a.m.NewSlack(); err != nil { return err } - fmt.Println("Starting gofunc watchMessageChannel") go a.watchMessageChannel() return nil } @@ -79,10 +80,7 @@ func (a *App) watchMessageChannel() { for a.running { msg := <-a.m.messages slackMsg := msg.GetMessage() - if slackMsg.Type != "user_typing" { - fmt.Println(slackMsg) - } - if slackMsg.Type == "control" && slackMsg.Name == "quit" { + if slackMsg.Type == "control" && slackMsg.Text == "quit" { a.running = false break } else if msg.GetDestination() == "error" { @@ -95,4 +93,5 @@ func (a *App) watchMessageChannel() { v.State.ProcessMessage(msg) } } + close(a.m.messages) } diff --git a/cmd/helper_plugin.go b/cmd/helper_plugin.go index 400a51c..8ccfa8d 100644 --- a/cmd/helper_plugin.go +++ b/cmd/helper_plugin.go @@ -5,6 +5,7 @@ import ( "io/ioutil" "os" "plugin" + "strings" "git.bullercodeworks.com/brian/helperbot" ) @@ -24,22 +25,26 @@ func (a *App) LoadPluginsFromDirectory(dir string) error { os.Exit(1) } for _, f := range files { + if !strings.HasSuffix(f.Name(), ".so") { + fmt.Printf("Skipping file (%s)\n", f.Name()) + continue + } p, err := plugin.Open(dir + f.Name()) if err != nil { - fmt.Printf("Error loading plugin (%s)\n", f.Name()) + fmt.Println(fmt.Sprintf("Error loading plugin (%s)\n", f.Name())) fmt.Println(err.Error()) os.Exit(1) } hp, err := NewHelperPlugin(p) if err != nil { - fmt.Printf("Error loading plugin (%s)\n", f.Name()) + fmt.Println(fmt.Sprintf("Error loading plugin (%s)\n", f.Name())) fmt.Println(err.Error()) os.Exit(1) } hp.State.Initialize(a.m) hp.State.Run() + fmt.Printf("Plugin Loaded (%s)\n", f.Name()) a.plugins = append(a.plugins, *hp) - fmt.Printf("Plugin loaded: %s\n", f.Name()) } return nil } diff --git a/cmd/helpers.go b/cmd/helpers.go index 73b09e7..8584f3c 100644 --- a/cmd/helpers.go +++ b/cmd/helpers.go @@ -3,7 +3,7 @@ package main import ( "encoding/json" - slack "git.bullercodeworks.com/brian/go-slack" + "github.com/nlopes/slack" ) func GetMessageJson(msg *slack.Message) string { diff --git a/cmd/main.go b/cmd/main.go index 60cd2c2..480efad 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -7,7 +7,7 @@ import ( "syscall" "time" - slack "git.bullercodeworks.com/brian/go-slack" + "github.com/nlopes/slack" ) var DebugMode = false @@ -26,6 +26,11 @@ func main() { os.Exit(1) } + // Monitor the Advent of Code Boards + //go m.MonitorAoCBoards() + // Monitor incoming Slack messages + //go m.MonitorSlackMessages() + // Set up a channel to intercept Ctrl+C for graceful shutdowns c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt, syscall.SIGTERM) @@ -33,11 +38,15 @@ func main() { <-c // Save the changes when the app quits fmt.Println("\nFinishing up...") - a.m.messages <- NewBotMessage("main", "main", slack.Message{Type: "control", Name: "quit"}) + msg := slack.Message{} + msg.Type = "control" + msg.Text = "quit" + a.m.messages <- NewBotMessage("main", "main", msg) }() for a.running { time.Sleep(time.Second * 2) } + fmt.Println("Model has stopped running") fmt.Println("Done") os.Exit(0) } diff --git a/cmd/message.go b/cmd/message.go index 59ad448..761b166 100644 --- a/cmd/message.go +++ b/cmd/message.go @@ -1,6 +1,6 @@ package main -import slack "git.bullercodeworks.com/brian/go-slack" +import "github.com/nlopes/slack" // This message type is for communications over the messages channel type BotMessage struct { diff --git a/cmd/model.go b/cmd/model.go index 745e888..22dce55 100644 --- a/cmd/model.go +++ b/cmd/model.go @@ -6,9 +6,10 @@ import ( "os" "strings" - slack "git.bullercodeworks.com/brian/go-slack" + goslack "git.bullercodeworks.com/brian/go-slack" "git.bullercodeworks.com/brian/helperbot" "github.com/br0xen/boltease" + "github.com/nlopes/slack" ) type BotModel struct { @@ -16,7 +17,7 @@ type BotModel struct { messages chan helperbot.Message - slack *slack.Slack + slack *goslack.Slack cache map[string][]byte } @@ -30,8 +31,6 @@ func NewBotModel() (*BotModel, error) { if err != nil { return nil, err } - m.db.MkBucketPath([]string{"slack", "users"}) - m.db.MkBucketPath([]string{"slack", "channels"}) return m, nil } @@ -93,6 +92,9 @@ func (m *BotModel) GetString(path []string) (string, error) { if err != nil { return "", err } + if len(bts) == 0 { + return "", nil + } return string(bts), nil } diff --git a/cmd/model_slack.go b/cmd/model_slack.go index 87ebcc5..030b8b5 100644 --- a/cmd/model_slack.go +++ b/cmd/model_slack.go @@ -1,11 +1,10 @@ package main import ( - slack "git.bullercodeworks.com/brian/go-slack" + goslack "git.bullercodeworks.com/brian/go-slack" + "github.com/nlopes/slack" ) -// TODO: Look into switching to: https://github.com/nlopes/slack - /* DB Functions */ func (m *BotModel) setSlackToken(token string) error { return m.SetBytes([]string{"slack", "config", "token"}, []byte(token)) @@ -30,18 +29,16 @@ func (m *BotModel) NewSlack() error { if err != nil { return err } - if m.slack, err = slack.CreateSlack(token); err != nil { + if m.slack, err = goslack.CreateSlack(token); err != nil { return err } + m.slack.StartRTM() return nil } func (a *App) MonitorSlackMessages() { - for a.running { - msg, err := a.m.slack.GetMessage() - if err == nil { - a.m.SendMessage("slack", "main", msg) - } + for msg := range a.m.slack.IncomingMessages { + a.m.SendMessage("slack", "main", slack.Message(*msg)) } } @@ -50,10 +47,7 @@ func (m *BotModel) SendSlackChannelMessage(msg *slack.Message) error { return m.SendSlackAdminMessage(msg) } // Send message to slack channel - var err error - if err = m.slack.PostMessage(*msg); err != nil { - return err - } + m.slack.PostMessage(msg) return nil } @@ -64,8 +58,6 @@ func (m *BotModel) SendSlackAdminMessage(msg *slack.Message) error { if err != nil { return err } - if err = m.slack.PostMessage(*msg); err != nil { - return err - } + m.slack.PostMessage(msg) return nil } diff --git a/interfaces.go b/interfaces.go index a9dfac2..651bf16 100644 --- a/interfaces.go +++ b/interfaces.go @@ -1,6 +1,6 @@ package helperbot -import slack "git.bullercodeworks.com/brian/go-slack" +import "github.com/nlopes/slack" type Model interface { SendMessage(src, dest string, message slack.Message) diff --git a/plugins_src/plugin_aoc.go b/plugins_src/plugin_aoc.go index 68fb074..b7efa6a 100644 --- a/plugins_src/plugin_aoc.go +++ b/plugins_src/plugin_aoc.go @@ -14,8 +14,8 @@ import ( "time" aoc "git.bullercodeworks.com/brian/go-adventofcode" - slack "git.bullercodeworks.com/brian/go-slack" "git.bullercodeworks.com/brian/helperbot" + "github.com/nlopes/slack" ) /* Plugin State */ @@ -76,11 +76,7 @@ func (s *AoCState) ProcessMessage(m helperbot.Message) { case 'D': admin, err := s.model.GetSlackAdminDMId() if err != nil { - s.model.SendMessage(s.Name(), "error", slack.Message{ - Type: "error", - Text: "Error getting Admin DM Id", - Time: time.Now(), - }) + s.SendAdminIdError() return } if slackMsg.Channel == admin { @@ -129,11 +125,8 @@ func (s *AoCState) runLoop() { } time.Sleep(time.Minute) } - s.model.SendMessage(s.Name(), "main", slack.Message{ - Type: "status", - Text: "done", - Time: time.Now(), - }) + + s.model.SendMessage(s.Name(), "main", s.BuildMessage("status", "done", "")) } func (s *AoCState) ProcessDirectMessage(slackMsg slack.Message) { @@ -183,30 +176,18 @@ func (s *AoCState) DoHelpCmd(slackMsg slack.Message) { txt := fmt.Sprint(":christmas_tree: AoC Help :christmas_tree:\n", "-- WiP --", ) - s.model.SendMessage(s.Name(), "slack", slack.Message{ - Type: "message", - Channel: slackMsg.Channel, - Text: txt, - }) + s.SendSlackMessage(txt, slackMsg.Channel) } func (s *AoCState) DoHelpAdminCmd(slackMsg slack.Message) { txt := fmt.Sprint(":christmas_tree: AoC Help :christmas_tree:\n", "-- WiP --", ) - s.model.SendMessage(s.Name(), "slack", slack.Message{ - Type: "message", - Channel: slackMsg.Channel, - Text: txt, - }) + s.SendSlackMessage(txt, slackMsg.Channel) } func (s *AoCState) DoPingCmd(slackMsg slack.Message) { - s.model.SendMessage(s.Name(), "slack", slack.Message{ - Type: "message", - Channel: slackMsg.Channel, - Text: ":christmas_tree: PONG :christmas_tree:", - }) + s.SendSlackMessage(":christmas_tree: PONG :christmas_tree:", slackMsg.Channel) } func (s *AoCState) DoSessionCmd(slackMsg slack.Message) { @@ -215,39 +196,23 @@ func (s *AoCState) DoSessionCmd(slackMsg slack.Message) { // Set the session cookie admin, err := s.model.GetSlackAdminDMId() if err != nil { - s.model.SendMessage(s.Name(), "error", slack.Message{ - Type: "error", - Text: "Error getting Admin DM Id", - Time: time.Now(), - }) + s.SendAdminIdError() return } aocSession := msgPts[2] s.setAoCSessionCookie(strings.TrimSpace(aocSession)) s.sessionCookie = aocSession s.sessionNeedsUpdate = false - s.model.SendMessage(s.Name(), "slack", slack.Message{ - Type: "message", - Channel: admin, - Text: ":christmas_tree: New Session: " + s.sessionCookie, - }) + s.SendSlackMessage(":christmas_tree: New Session: "+s.sessionCookie, admin) } else if len(msgPts) == 2 && msgPts[1] == "session" { // Print the session cookie admin, err := s.model.GetSlackAdminDMId() if err != nil { - s.model.SendMessage(s.Name(), "error", slack.Message{ - Type: "error", - Text: "Error getting Admin DM Id", - Time: time.Now(), - }) + s.SendAdminIdError() return } // We only send the session cookie to the admin - s.model.SendMessage(s.Name(), "slack", slack.Message{ - Type: "message", - Channel: admin, - Text: ":christmas_tree: session: " + s.sessionCookie, - }) + s.SendSlackMessage(":christmas_tree: session: "+s.sessionCookie, admin) } } @@ -275,11 +240,7 @@ func (s *AoCState) DoTopCmd(slackMsg slack.Message) { } else { txt = s.DoTopForYear(yr) } - s.model.SendMessage(s.Name(), "slack", slack.Message{ - Type: "message", - Channel: slackMsg.Channel, - Text: txt, - }) + s.SendSlackMessage(txt, slackMsg.Channel) } func (s *AoCState) DoTopForAll() (string, error) { @@ -379,30 +340,18 @@ func (s *AoCState) AoCBoardCheckAndUpdate(yr int) { if err != nil { admin, adminErr := s.model.GetSlackAdminDMId() if adminErr != nil { - s.model.SendMessage(s.Name(), "error", slack.Message{ - Type: "error", - Text: "Error getting Admin DM Id", - Time: time.Now(), - }) + s.SendAdminIdError() return } if err.Error() == "Invalid Session Cookie" { s.sessionNeedsUpdate = true } - s.model.SendMessage(s.Name(), "slack", slack.Message{ - Type: "message", - Channel: admin, - Text: fmt.Sprintf(":warning: AoC Error processing leaderboard (%d) - %s", yr, err.Error()), - }) + s.SendSlackMessage(fmt.Sprintf(":warning: AoC Error processing leaderboard (%d) - %s", yr, err.Error()), admin) return } - msg := slack.Message{ - Type: "success", - Text: fmt.Sprintf("Received leaderboard (%d)", yr), - Time: time.Now(), - } - s.model.SendMessage(s.Name(), "main", msg) + s.model.SendMessage(s.Name(), "main", + s.BuildMessage("success", fmt.Sprintf("Received leaderboard (%d)", yr), "")) // Compare the new leaderboard to the saved one for _, v := range l.Members { mbr, err := s.getMember(l.Event, v.ID) @@ -410,11 +359,7 @@ func (s *AoCState) AoCBoardCheckAndUpdate(yr int) { continue } if mbr.Stars != v.Stars { - s.model.SendMessage(s.Name(), "slack", slack.Message{ - Type: "message", - Channel: channelId, - Text: ":christmas_tree: " + v.Name + " now has " + strconv.Itoa(v.Stars) + " stars! :christmas_tree:", - }) + s.SendSlackMessage(":christmas_tree: "+v.Name+" now has "+strconv.Itoa(v.Stars)+" stars! :christmas_tree:", channelId) } } // Save the leaderboard to the db @@ -499,11 +444,7 @@ func (s *AoCState) saveLeaderboard(l *aoc.Leaderboard) error { } for _, v := range l.Members { if err = s.saveMember(l.Event, &v); err != nil { - s.model.SendMessage(s.Name(), "error", slack.Message{ - Type: "error", - Text: fmt.Sprintf("Error Saving Member (%s)", v.Name), - Time: time.Now(), - }) + s.model.SendMessage(s.Name(), "error", s.BuildMessage("error", fmt.Sprintf("Error Saving Member (%s)", v.Name), "")) } } return nil @@ -579,3 +520,19 @@ func (s *AoCState) getMember(event string, memberId string) (*aoc.Member, error) mbr.GlobalScore, err = strconv.Atoi(wrk) return mbr, nil } + +func (s *AoCState) SendAdminIdError() { + s.model.SendMessage(s.Name(), "error", s.BuildMessage("error", "Error getting Admin DM Id", "")) +} + +func (s *AoCState) SendSlackMessage(text, dest string) { + s.model.SendMessage(s.Name(), "slack", s.BuildMessage("message", text, dest)) +} + +func (s *AoCState) BuildMessage(tp, text, ch string) slack.Message { + ret := slack.Message{} + ret.Type = tp + ret.Text = text + ret.Channel = ch + return ret +}