I believe it's all working

This commit is contained in:
Brian Buller 2023-12-01 09:26:25 -06:00
parent de126011c4
commit ff58d1ddf4
18 changed files with 137 additions and 306 deletions

View File

@ -2,9 +2,9 @@ package app
import ( import (
"fmt" "fmt"
"os"
"git.bullercodeworks.com/brian/helperbot/models" "git.bullercodeworks.com/brian/helperbot/models"
"git.bullercodeworks.com/brian/helperbot/plugins"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
@ -14,7 +14,7 @@ type App struct {
m *models.BotModel m *models.BotModel
plugins []HelperPlugin plugins []models.PluginState
} }
func NewApp(debugMode bool) (*App, error) { func NewApp(debugMode bool) (*App, error) {
@ -29,6 +29,7 @@ func NewApp(debugMode bool) (*App, error) {
return nil, err return nil, err
} }
a.Running = true a.Running = true
go a.watchMessageChannel()
return a, err return a, err
} }
@ -55,14 +56,14 @@ func (a *App) initialize() error {
} }
// Load up the plugins // Load up the plugins
pluginDir := a.m.GetPluginDir() a.plugins = append(a.plugins, &plugins.StatsState{}, &plugins.AoCState{})
a.loadPluginsFromDirectory(pluginDir) for _, p := range a.plugins {
if err != nil { p.Initialize(a.m)
fmt.Println("Error loading plugins")
fmt.Println(err.Error())
os.Exit(1)
} }
a.setupMessageWatchers() a.setupMessageWatchers()
for _, p := range a.plugins {
p.Run()
}
a.m.SendSlackAdminMessage(":robot_face: Helperbot Initialized :robot_face:") a.m.SendSlackAdminMessage(":robot_face: Helperbot Initialized :robot_face:")
return err return err
@ -71,9 +72,10 @@ func (a *App) initialize() error {
func (a *App) SendQuitMessage() { a.m.SendMessage(models.QuitMessage) } func (a *App) SendQuitMessage() { a.m.SendMessage(models.QuitMessage) }
func (a *App) setupMessageWatchers() { func (a *App) setupMessageWatchers() {
a.m.AddMessageWatcher(func(msg models.BotMessage) bool { a.m.AddMessageWatcher("main", func(msg models.BotMessage) bool {
if msg.Is(models.QuitMessage) { if msg.Is(models.QuitMessage) {
// App is shutting down // App is shutting down
fmt.Println("Received QuitMessage")
a.Running = false a.Running = false
} else if msg.IsError() { } else if msg.IsError() {
// Received an Error Message // Received an Error Message
@ -87,8 +89,9 @@ func (a *App) setupMessageWatchers() {
}) })
for _, v := range a.plugins { for _, v := range a.plugins {
a.m.AddMessageWatcher(v.State.ProcessMessage) fmt.Println("Setting up watchers for", v.Name())
a.m.AddRTMWatcher(v.State.ProcessRTMEvent) a.m.AddMessageWatcher(fmt.Sprintf("plugin-%s", v.Name()), v.ProcessMessage)
a.m.AddRTMWatcher(fmt.Sprintf("plugin-%s", v.Name()), v.ProcessRTMEvent)
} }
} }

View File

@ -1,61 +0,0 @@
package app
import (
"fmt"
"io/ioutil"
"os"
"plugin"
"strings"
"git.bullercodeworks.com/brian/helperbot/models"
)
type HelperPlugin struct {
p *plugin.Plugin
State models.PluginState
}
func (a *App) loadPluginsFromDirectory(dir string) error {
fmt.Println("Loading Plugins (", dir, ")")
files, err := ioutil.ReadDir(dir)
if err != nil {
fmt.Println("Error loading plugins")
fmt.Println(err.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.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.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)
}
return nil
}
func NewHelperPlugin(p *plugin.Plugin) (*HelperPlugin, error) {
h := &HelperPlugin{p: p}
// Parse the plugin's state
pluginStateSymbol, err := p.Lookup("State")
if err != nil {
return nil, err
}
h.State = pluginStateSymbol.(models.PluginState)
return h, nil
}

View File

@ -1,6 +1,5 @@
/* /*
Copyright © 2023 Brian Buller <brian@bullercodeworks.com> Copyright © 2023 Brian Buller <brian@bullercodeworks.com>
*/ */
package cmd package cmd
@ -13,7 +12,6 @@ import (
"git.bullercodeworks.com/brian/helperbot/app" "git.bullercodeworks.com/brian/helperbot/app"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
var debug = false var debug = false
@ -38,6 +36,7 @@ var rootCmd = &cobra.Command{
// Save the changes when the app quits // Save the changes when the app quits
fmt.Println("\nFinishing up...") fmt.Println("\nFinishing up...")
a.SendQuitMessage() a.SendQuitMessage()
a.Running = false
}() }()
for a.Running { for a.Running {
time.Sleep(time.Second * 1) time.Sleep(time.Second * 1)
@ -58,5 +57,4 @@ func Execute() {
func init() { func init() {
rootCmd.Flags().BoolVarP(&debug, "debug", "d", false, "Debug mode") rootCmd.Flags().BoolVarP(&debug, "debug", "d", false, "Debug mode")
viper.SetDefault("plugin_dir", "plugins")
} }

3
go.mod
View File

@ -2,6 +2,8 @@ module git.bullercodeworks.com/brian/helperbot
go 1.20 go 1.20
replace git.bullercodeworks.com/brian/boltease => ../boltease
require ( require (
git.bullercodeworks.com/brian/boltease v1.0.0 git.bullercodeworks.com/brian/boltease v1.0.0
github.com/slack-go/slack v0.12.3 github.com/slack-go/slack v0.12.3
@ -10,6 +12,7 @@ require (
) )
require ( require (
git.bullercodeworks.com/brian/go-adventofcode v1.1.1 // indirect
github.com/boltdb/bolt v1.3.1 // indirect github.com/boltdb/bolt v1.3.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gorilla/websocket v1.4.2 // indirect github.com/gorilla/websocket v1.4.2 // indirect

2
go.sum
View File

@ -38,6 +38,8 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
git.bullercodeworks.com/brian/boltease v1.0.0 h1:kSCdJi+qfnPwdCP2oNUfQ6P4JKWaSWoh10Mx51uuD+Y= git.bullercodeworks.com/brian/boltease v1.0.0 h1:kSCdJi+qfnPwdCP2oNUfQ6P4JKWaSWoh10Mx51uuD+Y=
git.bullercodeworks.com/brian/boltease v1.0.0/go.mod h1:3EuVzLDHy1zrjBEYc7RsaBohUzYrH1bx2aKM2Fk6t98= git.bullercodeworks.com/brian/boltease v1.0.0/go.mod h1:3EuVzLDHy1zrjBEYc7RsaBohUzYrH1bx2aKM2Fk6t98=
git.bullercodeworks.com/brian/go-adventofcode v1.1.1 h1:5pp9bPVpTKdErkEcIAqoyuMsvmpQkO8upJ+NUQ+MUv0=
git.bullercodeworks.com/brian/go-adventofcode v1.1.1/go.mod h1:h/W8Nm8zsrVSjnoA6BRlf38LbaXHR/m6dIq804LOO3w=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=

View File

@ -1,37 +0,0 @@
package helperbot
import (
"time"
"git.bullercodeworks.com/brian/helperbot/models"
"github.com/slack-go/slack"
)
type Model interface {
SendMessage(msg models.BotMessage)
GetSlackAdminDMId() string
GetSlackLatency() time.Duration
GetBytes(path []string) ([]byte, error)
SetBytes(path []string, val []byte) error
GetString(path []string) (string, error)
SetString(path []string, val string) error
GetInt(path []string) (int, error)
SetInt(path []string, val int) error
}
type Message interface {
GetSource() string
GetDestination() string
GetType() string
GetTarget() string
GetText() string
}
type PluginState interface {
Name() string
Initialize(Model) error
ProcessMessage(models.BotMessage) bool
ProcessRTMEvent(*slack.RTMEvent) bool
Run()
Exit()
}

View File

@ -1,36 +0,0 @@
package models
import (
"time"
"github.com/slack-go/slack"
)
type Model interface {
SendMessage(msg BotMessage)
GetSlackAdminDMId() string
GetSlackLatency() time.Duration
GetBytes(path []string) ([]byte, error)
SetBytes(path []string, val []byte) error
GetString(path []string) (string, error)
SetString(path []string, val string) error
GetInt(path []string) (int, error)
SetInt(path []string, val int) error
}
type Message interface {
GetSource() string
GetDestination() string
GetType() string
GetTarget() string
GetText() string
}
type PluginState interface {
Name() string
Initialize(Model) error
ProcessMessage(BotMessage) bool
ProcessRTMEvent(*slack.RTMEvent) bool
Run()
Exit()
}

View File

@ -9,6 +9,7 @@ import (
const ( const (
MsgSrcApp = "app" MsgSrcApp = "app"
MsgSrcSlack = "slack" MsgSrcSlack = "slack"
MsgTpStatus = "status"
MsgTpControl = "control" MsgTpControl = "control"
MsgTpError = "error" MsgTpError = "error"
MsgTpMessage = "message" MsgTpMessage = "message"

View File

@ -22,8 +22,8 @@ type BotModel struct {
incomingSlackMessages chan *slack.MessageEvent incomingSlackMessages chan *slack.MessageEvent
otherRTMEvents chan *slack.RTMEvent otherRTMEvents chan *slack.RTMEvent
messageWatchers []func(msg BotMessage) bool messageWatchers map[string]func(msg BotMessage) bool
rtmWatchers []func(event *slack.RTMEvent) bool rtmWatchers map[string]func(event *slack.RTMEvent) bool
} }
func NewBotModel(debug bool) (*BotModel, error) { func NewBotModel(debug bool) (*BotModel, error) {
@ -31,9 +31,10 @@ func NewBotModel(debug bool) (*BotModel, error) {
m := new(BotModel) m := new(BotModel)
m.debug = debug m.debug = debug
m.messages = make(chan BotMessage, 100) m.messages = make(chan BotMessage, 100)
m.messageWatchers = make([]func(msg BotMessage) bool, 1) m.messageWatchers = make(map[string]func(msg BotMessage) bool)
m.AddMessageWatcher(m.DebugMessageWatcher) m.rtmWatchers = make(map[string]func(even *slack.RTMEvent) bool)
m.AddRTMWatcher(m.DebugRTMWatcher) m.AddMessageWatcher("debug", m.DebugMessageWatcher)
m.AddRTMWatcher("debug", m.DebugRTMWatcher)
m.db, err = boltease.Create("helperbot.db", 0600, nil) m.db, err = boltease.Create("helperbot.db", 0600, nil)
if err != nil { if err != nil {
return nil, err return nil, err
@ -63,26 +64,32 @@ func (m *BotModel) SendMessage(msg BotMessage) {
m.messages <- msg m.messages <- msg
} }
func (m *BotModel) AddMessageWatcher(watcher func(msg BotMessage) bool) { func (m *BotModel) AddMessageWatcher(name string, watcher func(msg BotMessage) bool) {
m.messageWatchers = append(m.messageWatchers, watcher) m.messageWatchers[name] = watcher
} }
func (m *BotModel) AddRTMWatcher(watcher func(event *slack.RTMEvent) bool) { func (m *BotModel) AddRTMWatcher(name string, watcher func(event *slack.RTMEvent) bool) {
m.rtmWatchers = append(m.rtmWatchers, watcher) m.rtmWatchers[name] = watcher
} }
func (m *BotModel) ProcessMessageChannel() { func (m *BotModel) ProcessMessageChannel() {
fmt.Println(">> ProcessMessageChannel")
msg := <-m.messages msg := <-m.messages
for _, v := range m.messageWatchers { fmt.Println(">>>> Received Message", msg)
for k, v := range m.messageWatchers {
fmt.Printf(">>>> Message Watcher [%s]\n", k)
// Pass the message to the watcher // Pass the message to the watcher
if v(msg) { if v != nil && v(msg) {
// if a watcher returns true, the message was consumed // if a watcher returns true, the message was consumed
break break
} }
} }
} }
func (m *BotModel) ProcessRTMChannel() { func (m *BotModel) ProcessRTMChannel() {
fmt.Println(">> ProcessRTMChannel")
msg := <-m.otherRTMEvents msg := <-m.otherRTMEvents
for _, v := range m.rtmWatchers { fmt.Println(">>>> Received Message", msg)
for k, v := range m.rtmWatchers {
fmt.Printf(">>>> RTM Watcher [%s]\n", k)
// Pass the event to the watcher // Pass the event to the watcher
if v(msg) { if v(msg) {
// if a watcher returns true, the message was consumed // if a watcher returns true, the message was consumed

View File

@ -12,13 +12,10 @@ import (
) )
const ( const (
keyPluginDir = "plugin_dir"
keySlackToken = "slack.token" keySlackToken = "slack.token"
keySlackAdminDmId = "slack.admin_dm_id" keySlackAdminDmId = "slack.admin_dm_id"
) )
func (m *BotModel) GetPluginDir() string { return viper.GetString(keyPluginDir) }
/* Slack Config Functions */ /* Slack Config Functions */
func (m *BotModel) getSlackToken() string { return viper.GetString(keySlackToken) } func (m *BotModel) getSlackToken() string { return viper.GetString(keySlackToken) }
func (m *BotModel) setSlackToken(token string) error { func (m *BotModel) setSlackToken(token string) error {

14
models/plugin_model.go Normal file
View File

@ -0,0 +1,14 @@
package models
import (
"github.com/slack-go/slack"
)
type PluginState interface {
Name() string
Initialize(*BotModel) error
ProcessMessage(BotMessage) bool
ProcessRTMEvent(*slack.RTMEvent) bool
Run()
Exit()
}

View File

@ -1,8 +1,5 @@
package main package plugins
import (
"C"
)
import ( import (
"bufio" "bufio"
"errors" "errors"
@ -14,13 +11,13 @@ import (
"time" "time"
aoc "git.bullercodeworks.com/brian/go-adventofcode" aoc "git.bullercodeworks.com/brian/go-adventofcode"
"git.bullercodeworks.com/brian/helperbot" "git.bullercodeworks.com/brian/helperbot/models"
"github.com/slack-go/slack" "github.com/slack-go/slack"
) )
/* Plugin State */ /* Plugin State */
type AoCState struct { type AoCState struct {
model helperbot.Model model *models.BotModel
boardId string boardId string
sessionCookie string sessionCookie string
sessionNeedsUpdate bool sessionNeedsUpdate bool
@ -29,11 +26,9 @@ type AoCState struct {
lastYear int lastYear int
} }
var State AoCState
/* Plugin Interface Functions */ /* Plugin Interface Functions */
func (s *AoCState) Name() string { return "advent-of-code" } func (s *AoCState) Name() string { return "advent-of-code" }
func (s *AoCState) Initialize(m helperbot.Model) error { func (s *AoCState) Initialize(m *models.BotModel) error {
// Initialize AoC stuff // Initialize AoC stuff
var err error var err error
var boardId, aocSession, aocChannelId string var boardId, aocSession, aocChannelId string
@ -65,31 +60,29 @@ func (s *AoCState) Initialize(m helperbot.Model) error {
return nil return nil
} }
func (s *AoCState) ProcessMessage(m helperbot.Message) { func (s *AoCState) ProcessMessage(m models.BotMessage) bool {
if m.GetSource() == "slack" { if m.Source == models.MsgSrcSlack {
slackMsg := m.GetMessage() if len(m.Target) == 0 {
if len(slackMsg.Channel) == 0 { return false
return
} }
switch slackMsg.Channel[0] { switch m.Target[0] {
case 'C', 'G': case 'C', 'G':
s.ProcessChannelMessage(slackMsg) return s.ProcessChannelMessage(m)
case 'D': case 'D':
admin, err := s.model.GetSlackAdminDMId() admin := s.model.GetSlackAdminDMId()
if err != nil { if m.Target == admin {
s.SendAdminIdError() return s.ProcessAdminDirectMessage(m)
return
}
if slackMsg.Channel == admin {
s.ProcessAdminDirectMessage(slackMsg)
} else { } else {
s.ProcessDirectMessage(slackMsg) return s.ProcessDirectMessage(m)
} }
} }
} }
return false
} }
func (s *AoCState) ProcessRTMEvent(msg slack.RTMEvent) {} func (s *AoCState) ProcessRTMEvent(msg *slack.RTMEvent) bool {
return false
}
func (s *AoCState) Run() { func (s *AoCState) Run() {
go s.runLoop() go s.runLoop()
@ -140,8 +133,8 @@ func (s *AoCState) runLoop() {
if s.GetLatestYear() != s.lastYear { if s.GetLatestYear() != s.lastYear {
// Latest year changed. Grab that board first. // Latest year changed. Grab that board first.
s.lastYear = s.GetLatestYear() s.lastYear = s.GetLatestYear()
admin, adminErr := s.model.GetSlackAdminDMId() admin := s.model.GetSlackAdminDMId()
if adminErr != nil { if admin == "" {
s.SendAdminIdError() s.SendAdminIdError()
return return
} }
@ -156,78 +149,88 @@ func (s *AoCState) runLoop() {
time.Sleep(time.Minute) time.Sleep(time.Minute)
} }
s.model.SendMessage(s.Name(), "main", s.BuildMessage("status", "done", "")) s.model.SendMessage(models.NewBotMessage(s.Name(), models.MsgSrcApp, "status", "done", ""))
} }
func (s *AoCState) ProcessDirectMessage(slackMsg slack.Message) { func (s *AoCState) ProcessDirectMessage(m models.BotMessage) bool {
msgPts := strings.Fields(slackMsg.Text) msgPts := strings.Fields(m.Text)
if len(msgPts) < 2 || msgPts[0] != "!aoc" { if len(msgPts) < 2 || msgPts[0] != "!aoc" {
return return false
} }
switch msgPts[1] { switch msgPts[1] {
case "help": case "help":
s.DoHelpCmd(slackMsg) return s.DoHelpCmd(m)
case "ping": case "ping":
s.DoPingCmd(slackMsg) return s.DoPingCmd(m)
case "top": case "top":
s.DoTopCmd(slackMsg) return s.DoTopCmd(m)
} }
return false
} }
func (s *AoCState) ProcessAdminDirectMessage(slackMsg slack.Message) { func (s *AoCState) ProcessAdminDirectMessage(m models.BotMessage) bool {
msgPts := strings.Fields(slackMsg.Text) msgPts := strings.Fields(m.Text)
if len(msgPts) < 2 || msgPts[0] != "!aoc" { if len(msgPts) < 2 || msgPts[0] != "!aoc" {
return return false
} }
switch msgPts[1] { switch msgPts[1] {
case "help": case "help":
s.DoHelpAdminCmd(slackMsg) s.DoHelpAdminCmd(m)
return true
case "ping": case "ping":
s.DoPingCmd(slackMsg) s.DoPingCmd(m)
return true
case "top": case "top":
s.DoTopCmd(slackMsg) s.DoTopCmd(m)
return true
case "session": case "session":
s.DoSessionCmd(slackMsg) s.DoSessionCmd(m)
return true
} }
return false
} }
func (s *AoCState) ProcessChannelMessage(slackMsg slack.Message) { func (s *AoCState) ProcessChannelMessage(m models.BotMessage) bool {
msgPts := strings.Fields(slackMsg.Text) msgPts := strings.Fields(m.Text)
if len(msgPts) < 2 || msgPts[0] != "!aoc" { if len(msgPts) < 2 || msgPts[0] != "!aoc" {
return return false
} }
switch msgPts[1] { switch msgPts[1] {
case "top": case "top":
s.DoTopCmd(slackMsg) return s.DoTopCmd(m)
} }
return false
} }
func (s *AoCState) DoHelpCmd(slackMsg slack.Message) { func (s *AoCState) DoHelpCmd(m models.BotMessage) bool {
txt := fmt.Sprint(":christmas_tree: AoC Help :christmas_tree:\n", txt := fmt.Sprint(":christmas_tree: AoC Help :christmas_tree:\n",
"-- WiP --", "-- WiP --",
) )
s.SendSlackMessage(txt, slackMsg.Channel) s.SendSlackMessage(txt, m.Target)
return true
} }
func (s *AoCState) DoHelpAdminCmd(slackMsg slack.Message) { func (s *AoCState) DoHelpAdminCmd(m models.BotMessage) bool {
txt := fmt.Sprint(":christmas_tree: AoC Help :christmas_tree:\n", txt := fmt.Sprint(":christmas_tree: AoC Help :christmas_tree:\n",
"-- WiP --", "-- WiP --",
) )
s.SendSlackMessage(txt, slackMsg.Channel) s.SendSlackMessage(txt, m.Target)
return true
} }
func (s *AoCState) DoPingCmd(slackMsg slack.Message) { func (s *AoCState) DoPingCmd(m models.BotMessage) bool {
s.SendSlackMessage(":christmas_tree: PONG :christmas_tree:", slackMsg.Channel) s.SendSlackMessage(":christmas_tree: PONG :christmas_tree:", m.Target)
return true
} }
func (s *AoCState) DoSessionCmd(slackMsg slack.Message) { func (s *AoCState) DoSessionCmd(m models.BotMessage) bool {
msgPts := strings.Fields(slackMsg.Text) msgPts := strings.Fields(m.Text)
if len(msgPts) == 3 && msgPts[1] == "session" { if len(msgPts) == 3 && msgPts[1] == "session" {
// Set the session cookie // Set the session cookie
admin, err := s.model.GetSlackAdminDMId() admin := s.model.GetSlackAdminDMId()
if err != nil { if admin == "" {
s.SendAdminIdError() s.SendAdminIdError()
return return true
} }
aocSession := msgPts[2] aocSession := msgPts[2]
s.setAoCSessionCookie(strings.TrimSpace(aocSession)) s.setAoCSessionCookie(strings.TrimSpace(aocSession))
@ -236,18 +239,19 @@ func (s *AoCState) DoSessionCmd(slackMsg slack.Message) {
s.SendSlackMessage(":christmas_tree: New Session: "+s.sessionCookie, admin) s.SendSlackMessage(":christmas_tree: New Session: "+s.sessionCookie, admin)
} else if len(msgPts) == 2 && msgPts[1] == "session" { } else if len(msgPts) == 2 && msgPts[1] == "session" {
// Print the session cookie // Print the session cookie
admin, err := s.model.GetSlackAdminDMId() admin := s.model.GetSlackAdminDMId()
if err != nil { if admin == "" {
s.SendAdminIdError() s.SendAdminIdError()
return return true
} }
// We only send the session cookie to the admin // We only send the session cookie to the admin
s.SendSlackMessage(":christmas_tree: session: "+s.sessionCookie, admin) s.SendSlackMessage(":christmas_tree: session: "+s.sessionCookie, admin)
} }
return true
} }
func (s *AoCState) DoTopCmd(slackMsg slack.Message) { func (s *AoCState) DoTopCmd(m models.BotMessage) bool {
msgPts := strings.Fields(slackMsg.Text) msgPts := strings.Fields(m.Text)
var err error var err error
var yr int var yr int
if len(msgPts) > 2 { if len(msgPts) > 2 {
@ -270,7 +274,8 @@ func (s *AoCState) DoTopCmd(slackMsg slack.Message) {
} else { } else {
txt = s.DoTopForYear(yr) txt = s.DoTopForYear(yr)
} }
s.SendSlackMessage(txt, slackMsg.Channel) s.SendSlackMessage(txt, m.Target)
return true
} }
func (s *AoCState) DoTopForAll() (string, error) { func (s *AoCState) DoTopForAll() (string, error) {
@ -367,8 +372,8 @@ func (s *AoCState) AoCSilentBoardCheckAndUpdate(yr int) {
if s.AoCBoardNeedsUpdate(yr) { if s.AoCBoardNeedsUpdate(yr) {
l, err := s.aoc.GetLeaderboard(yr) l, err := s.aoc.GetLeaderboard(yr)
if err != nil { if err != nil {
admin, adminErr := s.model.GetSlackAdminDMId() admin := s.model.GetSlackAdminDMId()
if adminErr != nil { if admin == "" {
s.SendAdminIdError() s.SendAdminIdError()
return return
} }
@ -379,8 +384,7 @@ func (s *AoCState) AoCSilentBoardCheckAndUpdate(yr int) {
return return
} }
s.model.SendMessage(s.Name(), "main", s.model.SendMessage(models.NewBotMessage(s.Name(), models.MsgSrcApp, models.MsgTpStatus, "", fmt.Sprintf("Received leaderboard (%d)", yr)))
s.BuildMessage("success", fmt.Sprintf("Received leaderboard (%d)", yr), ""))
// Save the leaderboard to the db // Save the leaderboard to the db
s.saveLeaderboard(l) s.saveLeaderboard(l)
} }
@ -392,8 +396,8 @@ func (s *AoCState) AoCBoardCheckAndUpdate(yr int) {
if s.AoCBoardNeedsUpdate(yr) { if s.AoCBoardNeedsUpdate(yr) {
l, err := s.aoc.GetLeaderboard(yr) l, err := s.aoc.GetLeaderboard(yr)
if err != nil { if err != nil {
admin, adminErr := s.model.GetSlackAdminDMId() admin := s.model.GetSlackAdminDMId()
if adminErr != nil { if admin == "" {
s.SendAdminIdError() s.SendAdminIdError()
return return
} }
@ -404,8 +408,7 @@ func (s *AoCState) AoCBoardCheckAndUpdate(yr int) {
return return
} }
s.model.SendMessage(s.Name(), "main", s.model.SendMessage(models.NewBotMessage(s.Name(), models.MsgSrcApp, models.MsgTpStatus, "", fmt.Sprintf("Received leaderboard (%d)", yr)))
s.BuildMessage("success", fmt.Sprintf("Received leaderboard (%d)", yr), ""))
// Compare the new leaderboard to the saved one // Compare the new leaderboard to the saved one
for _, v := range l.Members { for _, v := range l.Members {
mbr, err := s.getMember(l.Event, v.ID) mbr, err := s.getMember(l.Event, v.ID)
@ -538,7 +541,7 @@ func (s *AoCState) saveLeaderboard(l *aoc.Leaderboard) error {
} }
for _, v := range l.Members { for _, v := range l.Members {
if err = s.saveMember(l.Event, &v); err != nil { if err = s.saveMember(l.Event, &v); err != nil {
s.model.SendMessage(s.Name(), "error", s.BuildMessage("error", fmt.Sprintf("Error Saving Member (%s)", v.Name), "")) s.model.SendMessage(models.NewErrorBotMessage(s.Name(), models.MsgSrcApp, fmt.Sprintf("Error Saving Member (%s)", v.Name)))
} }
} }
return nil return nil
@ -629,17 +632,9 @@ func (s *AoCState) getMember(event string, memberId int) (*aoc.Member, error) {
} }
func (s *AoCState) SendAdminIdError() { func (s *AoCState) SendAdminIdError() {
s.model.SendMessage(s.Name(), "error", s.BuildMessage("error", "Error getting Admin DM Id", "")) s.model.SendMessage(models.NewBotMessage(s.Name(), models.MsgSrcApp, models.MsgTpError, models.MsgSrcApp, "No Admin ID Found"))
} }
func (s *AoCState) SendSlackMessage(text, dest string) { func (s *AoCState) SendSlackMessage(text, dest string) {
s.model.SendMessage(s.Name(), "slack", s.BuildMessage("message", text, dest)) s.model.SendMessage(models.NewBotMessage(s.Name(), models.MsgSrcSlack, models.MsgTpMessage, dest, text))
}
func (s *AoCState) BuildMessage(tp, text, ch string) slack.Message {
ret := slack.Message{}
ret.Type = tp
ret.Text = text
ret.Channel = ch
return ret
} }

View File

@ -1,27 +1,20 @@
package main package plugins
import (
"C"
)
import ( import (
"fmt" "fmt"
"strings" "strings"
"time"
"git.bullercodeworks.com/brian/helperbot/models" "git.bullercodeworks.com/brian/helperbot/models"
"github.com/slack-go/slack" "github.com/slack-go/slack"
) )
type StatsState struct { type StatsState struct {
model models.Model model *models.BotModel
lag time.Duration
} }
var State StatsState
/* Plugin Interface Functions */ /* Plugin Interface Functions */
func (s *StatsState) Name() string { return "slack-stats" } func (s *StatsState) Name() string { return "slack-stats" }
func (s *StatsState) Initialize(m models.Model) error { func (s *StatsState) Initialize(m *models.BotModel) error {
s.model = m s.model = m
return nil return nil
} }
@ -37,11 +30,7 @@ func (s *StatsState) ProcessMessage(m models.BotMessage) bool {
return false return false
} }
func (s *StatsState) ProcessRTMEvent(msg slack.RTMEvent) bool { func (s *StatsState) ProcessRTMEvent(msg *slack.RTMEvent) bool {
switch ev := msg.Data.(type) {
case *slack.LatencyReport:
s.lag = ev.Value
}
return false return false
} }
@ -63,11 +52,11 @@ func (s *StatsState) ProcessAdminDirectMessage(m models.BotMessage) bool {
} }
func (s *StatsState) DoLatencyCommand() { func (s *StatsState) DoLatencyCommand() {
if s.lag == 0 { if s.model.GetSlackLatency() == 0 {
s.SendSlackMessage("Unknown") s.SendSlackMessage("Latency is Unknown")
return return
} }
s.SendSlackMessage(s.lag.String()) s.SendSlackMessage(s.model.GetSlackLatency().String())
} }
func (s *StatsState) SendSlackMessage(text string) { func (s *StatsState) SendSlackMessage(text string) {

View File

@ -1,15 +0,0 @@
module git.bullercodeworks.com/brian/helperbot/plugins_src/plugin_aoc
go 1.20
require (
git.bullercodeworks.com/brian/go-adventofcode v1.1.1
git.bullercodeworks.com/brian/helperbot v0.0.0-20221201132802-09a662a8cd4b
github.com/slack-go/slack v0.12.3
)
require (
github.com/gorilla/websocket v1.4.2 // indirect
github.com/nlopes/slack v0.6.0 // indirect
github.com/pkg/errors v0.8.0 // indirect
)

View File

@ -1,24 +0,0 @@
git.bullercodeworks.com/brian/go-adventofcode v1.1.1 h1:5pp9bPVpTKdErkEcIAqoyuMsvmpQkO8upJ+NUQ+MUv0=
git.bullercodeworks.com/brian/go-adventofcode v1.1.1/go.mod h1:h/W8Nm8zsrVSjnoA6BRlf38LbaXHR/m6dIq804LOO3w=
git.bullercodeworks.com/brian/helperbot v0.0.0-20221201132802-09a662a8cd4b h1:2BCAIENJo1r+h/+qHBJ3eCQTsa1kdsxwYFGTrPdZX3o=
git.bullercodeworks.com/brian/helperbot v0.0.0-20221201132802-09a662a8cd4b/go.mod h1:mjMh+IvDRLyD1WscFcZ1OC78C3CgVUi9zIz5trnFK0Y=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho=
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/nlopes/slack v0.6.0 h1:jt0jxVQGhssx1Ib7naAOZEZcGdtIhTzkP0nopK0AsRA=
github.com/nlopes/slack v0.6.0/go.mod h1:JzQ9m3PMAqcpeCam7UaHSuBuupz7CmpjehYMayT6YOk=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/slack-go/slack v0.12.3 h1:92/dfFU8Q5XP6Wp5rr5/T5JHLM5c5Smtn53fhToAP88=
github.com/slack-go/slack v0.12.3/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -1 +0,0 @@
go 1.20

View File

@ -1,3 +0,0 @@
module git.bullercodeworks.com/brian/helperbot/plugins_src/plugin_stats
go 1.20

View File

@ -1 +0,0 @@
go 1.20