* Fix issue with parsing AOC leaderboard JSON * Add aoc-util for different things * go mod * Makefilemaster
parent
24c7c80fbb
commit
14e2827377
@ -0,0 +1,15 @@ |
||||
|
||||
helperbot: |
||||
go build -o build/helperbot cmd/helperbot/*.go
|
||||
|
||||
plugins: |
||||
./buildplugins.sh
|
||||
|
||||
package: |
||||
go build -o build/helperbot cmd/helperbot/*.go
|
||||
./buildplugins.sh
|
||||
cp cmd/helperbot/helperbot.service build/
|
||||
cd build && tar -zcvf helperbot.tgz *
|
||||
|
||||
aoc-util: |
||||
go build -o build/aoc-util cmd/aoc-util/*.go
|
@ -1,11 +1,12 @@ |
||||
#!/bin/bash |
||||
|
||||
mkdir -p build/plugins |
||||
cd plugins_src |
||||
for i in `ls`; do |
||||
echo "Building plugin: $i" |
||||
go build -buildmode=plugin $i |
||||
if [ $? -eq 0 ]; then |
||||
mv *.so ../cmd/plugins |
||||
mv *.so ../build/plugins |
||||
fi |
||||
done |
||||
cd .. |
||||
|
@ -0,0 +1,211 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"fmt" |
||||
"os" |
||||
"sort" |
||||
"strconv" |
||||
"time" |
||||
|
||||
"git.bullercodeworks.com/brian/boltease" |
||||
) |
||||
|
||||
var db *boltease.DB |
||||
|
||||
func main() { |
||||
_, err := os.Stat("helperbot.db") |
||||
if err != nil { |
||||
fmt.Println("Couldn't find helperbot.db (is it in the CWD?)") |
||||
os.Exit(1) |
||||
} |
||||
if len(os.Args) == 1 { |
||||
printUsage([]string{}) |
||||
os.Exit(1) |
||||
} |
||||
run(os.Args[1:]) |
||||
} |
||||
|
||||
func run(args []string) int { |
||||
var cmd string |
||||
if len(args) == 0 { |
||||
printUsage(args) |
||||
return 1 |
||||
} |
||||
var err error |
||||
db, err = boltease.Create("helperbot.db", 0600, nil) |
||||
if err != nil { |
||||
fmt.Println("Error opening database") |
||||
return 1 |
||||
} |
||||
err = db.OpenDB() |
||||
if err != nil { |
||||
fmt.Println("Error opening database") |
||||
return 1 |
||||
} |
||||
defer db.CloseDB() |
||||
|
||||
cmd, args = args[0], args[1:] |
||||
switch cmd { |
||||
case "clear-stars": |
||||
return clearYearStars(args) |
||||
case "print-member-list": |
||||
return printMemberList(args) |
||||
case "view-member": |
||||
return viewMember(args) |
||||
} |
||||
return 0 |
||||
} |
||||
|
||||
func clearYearStars(args []string) int { |
||||
if len(args) < 1 { |
||||
printUsage([]string{"clear-stars"}) |
||||
return 1 |
||||
} |
||||
yr := args[0] |
||||
if !isValidYear(yr) { |
||||
fmt.Println("Invalid year provided") |
||||
return 1 |
||||
} |
||||
var err error |
||||
var members []string |
||||
membersPath := []string{"aoc", "leaderboards", yr, "members"} |
||||
members, err = db.GetBucketList(membersPath) |
||||
if err != nil { |
||||
fmt.Println("Error getting member list for year", yr) |
||||
return 1 |
||||
} |
||||
for _, v := range members { |
||||
memberPath := append(membersPath, v) |
||||
err = db.SetInt(memberPath, "stars", 0) |
||||
if err != nil { |
||||
fmt.Printf("Error resetting stars for [%s].\n", v) |
||||
fmt.Println(err) |
||||
fmt.Println("") |
||||
} |
||||
} |
||||
|
||||
return 0 |
||||
} |
||||
|
||||
func printMemberList(args []string) int { |
||||
memberMap := make(map[string]string) |
||||
memberIdMap := make(map[string]string) |
||||
var memberIds []string |
||||
var memberNames []string |
||||
years := getYearsInDB() |
||||
for _, v := range years { |
||||
var err error |
||||
var members []string |
||||
yearMembersPath := []string{"aoc", "leaderboards", v, "members"} |
||||
members, err = db.GetBucketList(yearMembersPath) |
||||
if err != nil { |
||||
fmt.Println("Error getting member list for year:", v) |
||||
continue |
||||
} |
||||
for _, mid := range members { |
||||
memberPath := append(yearMembersPath, mid) |
||||
_, ok := memberIdMap[mid] |
||||
if !ok { |
||||
memberIds = append(memberIds, mid) |
||||
name, err := db.GetValue(memberPath, "name") |
||||
if err != nil { |
||||
continue |
||||
} |
||||
memberNames = append(memberNames, name) |
||||
memberMap[name] = mid |
||||
memberIdMap[mid] = name |
||||
} |
||||
} |
||||
} |
||||
|
||||
sort.Strings(memberNames) |
||||
for _, v := range memberNames { |
||||
fmt.Printf("%s %s\n", v, memberMap[v]) |
||||
} |
||||
return 0 |
||||
} |
||||
|
||||
func viewMember(args []string) int { |
||||
if len(args) == 0 { |
||||
printUsage([]string{"view-member"}) |
||||
return 1 |
||||
} |
||||
years := getYearsInDB() |
||||
mId := args[0] |
||||
pInfo := false |
||||
for _, v := range years { |
||||
memberPath := []string{"aoc", "leaderboards", v, "members", mId} |
||||
if !pInfo { |
||||
name, err := db.GetValue(memberPath, "name") |
||||
if err != nil { |
||||
continue |
||||
} |
||||
fmt.Println(name, mId) |
||||
pInfo = true |
||||
} |
||||
stars, err := db.GetValue(memberPath, "stars") |
||||
if err != nil { |
||||
continue |
||||
} |
||||
fmt.Println(v, "stars:", stars) |
||||
} |
||||
|
||||
return 0 |
||||
} |
||||
|
||||
func printUsage(args []string) { |
||||
if len(args) == 0 { |
||||
fmt.Println("Usage: aoc-util [command]") |
||||
fmt.Println("Commands:") |
||||
fmt.Println(" clear-stars [year] Reset all member's star count for the given year") |
||||
return |
||||
} |
||||
switch args[0] { |
||||
case "clear-stars": |
||||
fmt.Println("Usage: aoc-util clear-stars [year]") |
||||
case "print-member-list": |
||||
fmt.Println("Usage: aoc-util print-member-list") |
||||
case "print-member": |
||||
fmt.Println("Usage: aoc-util view-member [id]") |
||||
} |
||||
} |
||||
|
||||
func getLatestYear() int { |
||||
latestYear := time.Now().Year() |
||||
if time.Now().Month() < 12 { |
||||
latestYear-- |
||||
} |
||||
return latestYear |
||||
} |
||||
|
||||
func getListOfAoCYears() []int { |
||||
var ret []int |
||||
for k := getLatestYear(); k > 2014; k-- { |
||||
ret = append(ret, k) |
||||
} |
||||
return ret |
||||
} |
||||
|
||||
func getYearsInDB() []string { |
||||
leaderboardsPath := []string{"aoc", "leaderboards"} |
||||
years, err := db.GetBucketList(leaderboardsPath) |
||||
if err != nil { |
||||
fmt.Println("Error getting year list") |
||||
return []string{} |
||||
} |
||||
return years |
||||
} |
||||
|
||||
func isValidYear(yr string) bool { |
||||
i, err := strconv.Atoi(yr) |
||||
if err != nil { |
||||
return false |
||||
} |
||||
yrs := getListOfAoCYears() |
||||
for k := range yrs { |
||||
if yrs[k] == i { |
||||
return true |
||||
} |
||||
} |
||||
return false |
||||
} |
@ -1,105 +0,0 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"bufio" |
||||
"fmt" |
||||
"os" |
||||
"strings" |
||||
|
||||
"github.com/nlopes/slack" |
||||
) |
||||
|
||||
type App struct { |
||||
DebugMode bool |
||||
running bool |
||||
|
||||
m *BotModel |
||||
|
||||
plugins []HelperPlugin |
||||
} |
||||
|
||||
func NewApp() (*App, error) { |
||||
a := new(App) |
||||
if DebugMode { |
||||
fmt.Println("Running in Debug Mode. All messages will be sent to Admin DM") |
||||
} |
||||
a.DebugMode = DebugMode |
||||
|
||||
err := a.initialize() |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
a.running = true |
||||
|
||||
go a.MonitorSlackMessages() |
||||
return a, nil |
||||
} |
||||
|
||||
func (a *App) initialize() error { |
||||
var err 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
|
||||
pluginDir := strings.TrimSpace(a.m.getPluginDir()) |
||||
a.LoadPluginsFromDirectory(pluginDir) |
||||
if err != nil { |
||||
fmt.Println("Error loading plugins") |
||||
fmt.Println(err.Error()) |
||||
os.Exit(1) |
||||
} |
||||
|
||||
// Now initialize the Slack stuff
|
||||
var slackToken string |
||||
// var slackDmid string
|
||||
slackToken, err = a.m.getSlackToken() |
||||
if err != nil || slackToken == "" { |
||||
fmt.Print("Slack API Token: ") |
||||
slackToken, _ = reader.ReadString('\n') |
||||
a.m.setSlackToken(strings.TrimSpace(slackToken)) |
||||
} |
||||
|
||||
go a.watchMessageChannel() |
||||
go a.watchRTMEventChannel() |
||||
return nil |
||||
} |
||||
|
||||
func (a *App) MonitorSlackMessages() { |
||||
for msg := range a.m.IncomingSlackMessages { |
||||
a.m.SendMessage("slack", "main", slack.Message(*msg)) |
||||
} |
||||
} |
||||
|
||||
func (a *App) watchMessageChannel() { |
||||
for a.running { |
||||
msg := <-a.m.messages |
||||
slackMsg := msg.GetMessage() |
||||
if slackMsg.Type == "control" && slackMsg.Text == "quit" { |
||||
a.running = false |
||||
break |
||||
} else if msg.GetDestination() == "error" { |
||||
fmt.Printf("ERROR: %s: %s\n", msg.GetSource(), msg.GetMessage().Text) |
||||
} else if msg.GetDestination() == "slack" { |
||||
a.m.SendSlackChannelMessage(&slackMsg) |
||||
} |
||||
|
||||
for _, v := range a.plugins { |
||||
v.State.ProcessMessage(msg) |
||||
} |
||||
} |
||||
} |
||||
|
||||
func (a *App) watchRTMEventChannel() { |
||||
for a.running { |
||||
msg := <-a.m.OtherRTMEvents |
||||
for _, v := range a.plugins { |
||||
v.State.ProcessRTMEvent(*msg) |
||||
} |
||||
} |
||||
} |
@ -1,64 +0,0 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"fmt" |
||||
"io/ioutil" |
||||
"os" |
||||
"plugin" |
||||
"strings" |
||||
|
||||
"git.bullercodeworks.com/brian/helperbot" |
||||
) |
||||
|
||||
type HelperPlugin struct { |
||||
p *plugin.Plugin |
||||
|
||||
State helperbot.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.(helperbot.PluginState) |
||||
return h, nil |
||||
} |
@ -1,16 +0,0 @@ |
||||
[Unit] |
||||
Description= |
||||
After=syslog.target |
||||
After=network.target |
||||
|
||||
[Service] |
||||
Type=simple |
||||
User=brbuller |
||||
Group=brbuller |
||||
WorkingDirectory=/home/brbuller/helperbot/ |
||||
ExecStart=/home/brbuller/helperbot/helperbot |
||||
Restart=always |
||||
Environment="HOME=/home/brbuller/helperbot","USER=brbuller" |
||||
|
||||
[Install] |
||||
WantedBy=multi-user.target |
@ -1,14 +0,0 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"encoding/json" |
||||
|
||||
"github.com/nlopes/slack" |
||||
) |
||||
|
||||
func GetMessageJson(msg *slack.Message) string { |
||||
if mb, me := json.Marshal(msg); me == nil { |
||||
return string(mb) |
||||
} |
||||
return "" |
||||
} |
@ -1,47 +0,0 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"fmt" |
||||
"os" |
||||
"os/signal" |
||||
"syscall" |
||||
"time" |
||||
|
||||
"github.com/nlopes/slack" |
||||
) |
||||
|
||||
var DebugMode = false |
||||
|
||||
var a *App |
||||
|
||||
func main() { |
||||
if len(os.Args) > 1 { |
||||
if os.Args[1] == "-debug" || os.Args[1] == "--debug" { |
||||
DebugMode = true |
||||
} |
||||
} |
||||
a, err := NewApp() |
||||
if err != nil { |
||||
fmt.Println(err) |
||||
os.Exit(1) |
||||
} |
||||
|
||||
// Set up a channel to intercept Ctrl+C for graceful shutdowns
|
||||
c := make(chan os.Signal, 1) |
||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM) |
||||
go func() { |
||||
<-c |
||||
// Save the changes when the app quits
|
||||
fmt.Println("\nFinishing up...") |
||||
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) |
||||
} |
@ -1,21 +0,0 @@ |
||||
package main |
||||
|
||||
import "github.com/nlopes/slack" |
||||
|
||||
// This message type is for communications over the messages channel
|
||||
type BotMessage struct { |
||||
source string |
||||
dest string |
||||
message slack.Message |
||||
} |
||||
|
||||
func NewBotMessage(src, dst string, msg slack.Message) BotMessage { |
||||
return BotMessage{ |
||||
source: src, |
||||
dest: dst, |
||||
message: msg, |
||||
} |
||||
} |
||||
func (m BotMessage) GetSource() string { return m.source } |
||||
func (m BotMessage) GetDestination() string { return m.dest } |
||||
func (m BotMessage) GetMessage() slack.Message { return m.message } |
@ -1,111 +0,0 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"errors" |
||||
"fmt" |
||||
"os" |
||||
"strings" |
||||
"time" |
||||
|
||||
"git.bullercodeworks.com/brian/helperbot" |
||||
"github.com/br0xen/boltease" |
||||
"github.com/nlopes/slack" |
||||
) |
||||
|
||||
type BotModel struct { |
||||
db *boltease.DB |
||||
|
||||
messages chan helperbot.Message |
||||
|
||||
slackApiToken string |
||||
slackApi *slack.Client |
||||
slackRTM *slack.RTM |
||||
slackRTMLatency time.Duration |
||||
slackIdToFriendly map[string]string |
||||
IncomingSlackMessages chan *slack.MessageEvent |
||||
OtherRTMEvents chan *slack.RTMEvent |
||||
|
||||
dataCache map[string][]byte |
||||
} |
||||
|
||||
func NewBotModel() (*BotModel, error) { |
||||
var err error |
||||
m := new(BotModel) |
||||
m.dataCache = make(map[string][]byte) |
||||
m.messages = make(chan helperbot.Message, 100) |
||||
m.db, err = boltease.Create("helperbot.db", 0600, nil) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
if err = m.NewSlack(); err != nil { |
||||
return nil, err |
||||
} |
||||
return m, nil |
||||
} |
||||
|
||||
func (m *BotModel) SendMessage(src, dst string, msg slack.Message) { |
||||
m.messages <- NewBotMessage(src, dst, msg) |
||||
} |
||||
|
||||
func (m *BotModel) getPluginDir() string { |
||||
ret, err := m.GetString([]string{"config", "plugin_dir"}) |
||||
if err != nil || strings.TrimSpace(ret) == "" { |
||||
ret = "./plugins/" |
||||
if err = m.SetString([]string{"config", "plugin_dir"}, ret); err != nil { |
||||
fmt.Println("Error setting plugin directory") |
||||
fmt.Println(err.Error()) |
||||
os.Exit(1) |
||||
} |
||||
} |
||||
fmt.Println("Plugin Dir: ", ret) |
||||
return ret |
||||
} |
||||
|
||||
func (m *BotModel) GetBytes(path []string) ([]byte, error) { |
||||
var err error |
||||
var v []byte |
||||
var ok bool |
||||
joinedPath := strings.Join(path, "/") |
||||
if v, ok = m.dataCache[joinedPath]; !ok { |
||||
// Value is not cached, try to pull it from the DB
|
||||
if len(path) > 2 { |
||||
path, key := path[:len(path)-1], path[len(path)-1] |
||||
v, err = m.db.GetBytes(path, key) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
m.dataCache[joinedPath] = v |
||||
} |
||||
} |
||||
return v, nil |
||||
} |
||||
|
||||
func (m *BotModel) SetBytes(path []string, val []byte) error { |
||||
if len(path) > 1 { |
||||
joinedPath := strings.Join(path, "/") |
||||
path, key := path[:len(path)-1], path[len(path)-1] |
||||
err := m.db.SetBytes(path, key, val) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
// Update the cache
|
||||
m.dataCache[joinedPath] = val |
||||
return nil |
||||
} |
||||
return errors.New("Invalid path") |
||||
} |
||||
|
||||
func (m *BotModel) GetString(path []string) (string, error) { |
||||
bts, err := m.GetBytes(path) |
||||
if err != nil { |
||||
return "", err |
||||
} |
||||
if len(bts) == 0 { |
||||
return "", nil |
||||
} |
||||
return string(bts), nil |
||||
} |
||||
|
||||
func (m *BotModel) SetString(path []string, val string) error { |
||||
return m.SetBytes(path, []byte(val)) |
||||
} |
@ -1,228 +0,0 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"bufio" |
||||
"errors" |
||||
"fmt" |
||||
"os" |
||||
"strings" |
||||
"time" |
||||
|
||||
"github.com/nlopes/slack" |
||||
) |
||||
|
||||
/* DB Functions */ |
||||
func (m *BotModel) setSlackToken(token string) error { |
||||
return m.SetBytes([]string{"slack", "config", "token"}, []byte(token)) |
||||
} |
||||
|
||||
func (m *BotModel) getSlackToken() (string, error) { |
||||
return m.GetString([]string{"slack", "config", "token"}) |
||||
} |
||||
|
||||
func (m *BotModel) setSlackAdminDMId(adminId string) error { |
||||
return m.SetString([]string{"slack", "config", "admin_dm_id"}, adminId) |
||||
} |
||||
|
||||
func (m *BotModel) GetSlackAdminDMId() (string, error) { |
||||
return m.GetString([]string{"slack", "config", "admin_dm_id"}) |
||||
} |
||||
|
||||
/* End DB Functions */ |
||||
|
||||
func (m *BotModel) NewSlack() error { |
||||
var err error |
||||
m.slackApiToken, err = m.getSlackToken() |
||||
if err != nil { |
||||
if strings.HasPrefix(err.Error(), "Couldn't find") { |
||||
m.RequestSlackToken() |
||||
} else { |
||||
return err |
||||
} |
||||
} |
||||
var slackDMid string |
||||
slackDMid, err = m.GetSlackAdminDMId() |
||||
if err != nil || slackDMid == "" { |
||||
m.RequestAdminDMId() |
||||
} |
||||
m.IncomingSlackMessages = make(chan *slack.MessageEvent, 50) |
||||
m.OtherRTMEvents = make(chan *slack.RTMEvent, 50) |
||||
m.slackApi = slack.New(m.slackApiToken) |
||||
m.slackIdToFriendly = make(map[string]string) |
||||
m.slackRTM = m.slackApi.NewRTM() |
||||
m.slackRTMLatency = time.Duration(0) |
||||
go m.slackRTM.ManageConnection() |
||||
go m.HandleRTMEvents() |
||||
return nil |
||||
} |
||||
|
||||
func (m *BotModel) RequestAdminDMId() { |
||||
reader := bufio.NewReader(os.Stdin) |
||||
fmt.Print("Slack Admin DM ID: ") |
||||
dmId, _ := reader.ReadString('\n') |
||||
m.setSlackAdminDMId(strings.TrimSpace(dmId)) |
||||
} |
||||
|
||||
func (m *BotModel) RequestSlackToken() { |
||||
reader := bufio.NewReader(os.Stdin) |
||||
fmt.Print("Slack Token: ") |
||||
token, _ := reader.ReadString('\n') |
||||
m.slackApiToken = strings.TrimSpace(token) |
||||
m.setSlackToken(m.slackApiToken) |
||||
} |
||||
|
||||
func (m *BotModel) HandleRTMEvents() { |
||||
for msg := range m.slackRTM.IncomingEvents { |
||||
switch ev := msg.Data.(type) { |
||||
case *slack.MessageEvent: |
||||
m.processMessageEvent(ev) |
||||
|
||||
case *slack.LatencyReport: |
||||
m.OtherRTMEvents <- &msg |
||||
|
||||
case *slack.RTMError: |
||||
fmt.Printf("RTM ERROR: (%d) %s", ev.Code, ev.Msg) |
||||
m.OtherRTMEvents <- &msg |
||||
|
||||
default: // Ignore other events
|
||||
} |
||||
} |
||||
} |
||||
|
||||
func (m *BotModel) SendSlackChannelMessage(msg *slack.Message) error { |
||||
if DebugMode { |
||||
return m.SendSlackAdminMessage(msg) |
||||
} |
||||
// Send message to slack channel
|
||||
m.PostSlackMessage(msg) |
||||
return nil |
||||
} |
||||
|
||||
func (m *BotModel) SendSlackAdminMessage(msg *slack.Message) error { |
||||
// Send message to slack admin
|
||||
var err error |
||||
msg.Channel, err = m.GetSlackAdminDMId() |
||||
if err != nil { |
||||
return err |
||||
} |
||||
m.PostSlackMessage(msg) |
||||
return nil |
||||
} |
||||
|
||||
func (m *BotModel) LoadDirectMessages() { |
||||
cs, err := m.slackApi.GetIMChannels() |
||||
if err != nil { |
||||
return |
||||
} |
||||
for _, v := range cs { |
||||
uname, err := m.GetSlackUserName(v.User) |
||||
if err != nil { |
||||
uname = v.User |
||||
} |
||||
m.slackIdToFriendly[v.ID] = uname |
||||
} |
||||
} |
||||
|
||||
func (m *BotModel) processMessageEvent(ev *slack.MessageEvent) { |
||||
m.GetSlackUserName(ev.User) |
||||
m.GetSlackIdName(ev.Channel) |
||||
m.IncomingSlackMessages <- ev |
||||
} |
||||
|
||||
func (m *BotModel) GetSlackIdName(id string) (string, error) { |
||||
switch id[0] { |
||||
case 'U': |
||||
return m.GetSlackUserName(id) |
||||
case 'G': |
||||
return m.GetSlackGroupName(id) |
||||
case 'C': |
||||
return m.GetSlackChannelName(id) |
||||
case 'D': |
||||
return m.GetSlackIMName(id) |
||||
} |
||||
return "", errors.New("Unknown ID Type") |
||||
} |
||||
|
||||
func (m *BotModel) GetSlackUserName(id string) (string, error) { |
||||
if v, ok := m.slackIdToFriendly[id]; ok { |
||||
return v, nil |
||||
} |
||||
user, err := m.slackApi.GetUserInfo(id) |
||||
if err != nil { |
||||
return "", err |
||||
} |
||||
m.slackIdToFriendly[id] = user.Profile.DisplayName |
||||
return user.Profile.DisplayName, nil |
||||
} |
||||
|
||||
func (m *BotModel) GetSlackIMName(id string) (string, error) { |
||||
if v, ok := m.slackIdToFriendly[id]; ok { |
||||
return v, nil |
||||
} |
||||
c, err := m.slackApi.GetChannelInfo(id) |
||||
if err != nil { |
||||
return "", err |
||||
} |
||||
m.slackIdToFriendly[id] = c.Name |
||||
return c.Name, nil |
||||
} |
||||
|
||||
func (m *BotModel) GetSlackChannelName(id string) (string, error) { |
||||
if v, ok := m.slackIdToFriendly[id]; ok { |
||||
return v, nil |
||||
} |
||||
c, err := m.slackApi.GetChannelInfo(id) |
||||
if err != nil { |
||||
return "", err |
||||
} |
||||
m.slackIdToFriendly[id] = c.Name |
||||
return c.Name, nil |
||||
} |
||||
|
||||
func (m *BotModel) GetSlackUserIM(id string) (string, error) { |
||||
for k, v := range m.slackIdToFriendly { |
||||
if v == id { |
||||
return k, nil |
||||
} |
||||
} |
||||
_, _, newId, err := m.slackApi.OpenIMChannel(id) |
||||
if err != nil { |
||||
return "", err |
||||
} |
||||
m.slackIdToFriendly[id] = newId |
||||
return newId, nil |
||||
} |
||||
|
||||
func (m *BotModel) GetSlackGroupName(id string) (string, error) { |
||||
if v, ok := m.slackIdToFriendly[id]; ok { |
||||
return v, nil |
||||
} |
||||
g, err := m.slackApi.GetGroupInfo(id) |
||||
if err != nil { |
||||
return "", err |
||||
} |
||||
m.slackIdToFriendly[id] = g.Name |
||||
return g.Name, nil |
||||
} |
||||
|
||||
func (m *BotModel) PostSlackMessage(msg *slack.Message) { |
||||
m.slackRTM.SendMessage(m.slackRTM.NewOutgoingMessage(msg.Text, msg.Channel)) |
||||
} |
||||
|
||||
func (m *BotModel) SendMessageToUser(msg *slack.Message, uid string) error { |
||||
dmId, err := m.GetSlackUserIM(uid) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
msg.Channel = dmId |
||||
m.PostSlackMessage(msg) |
||||
return nil |
||||
} |
||||
|
||||
func (m *BotModel) GetSlackUserInfo(uid string) (*slack.User, error) { |
||||
return m.slackApi.GetUserInfo(uid) |
||||
} |
||||
|
||||
func (m *BotModel) GetSlackLatency() time.Duration { |
||||
return m.slackRTMLatency |
||||
} |
@ -0,0 +1,18 @@ |
||||
module git.bullercodeworks.com/brian/helperbot |
||||
|
||||
go 1.17 |
||||
|
||||
replace git.bullercodeworks.com/brian/go-adventofcode => /home/brbuller/Development/go/src/git.bullercodeworks.com/brian/go-adventofcode |
||||
|
||||
require ( |
||||
git.bullercodeworks.com/brian/boltease v1.0.0 |
||||
git.bullercodeworks.com/brian/go-adventofcode v1.0.0 |
||||
github.com/nlopes/slack v0.6.0 |
||||
) |
||||
|
||||
require ( |
||||
github.com/boltdb/bolt v1.3.1 // indirect |
||||
github.com/gorilla/websocket v1.2.0 // indirect |
||||
github.com/pkg/errors v0.8.0 // indirect |
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf // indirect |
||||
) |
@ -0,0 +1,20 @@ |
||||
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/go-adventofcode v1.0.0 h1:y5FH3gPLaaBtJeJxkDNOfDQSA9i4+BChYf+UNd8pCsA= |
||||
git.bullercodeworks.com/brian/go-adventofcode v1.0.0/go.mod h1:h/W8Nm8zsrVSjnoA6BRlf38LbaXHR/m6dIq804LOO3w= |
||||
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= |
||||
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= |
||||
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/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ= |
||||
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= |
||||
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/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= |
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= |
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf h1:2ucpDCmfkl8Bd/FsLtiD653Wf96cW37s+iGx93zsu4k= |
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
Loading…
Reference in new issue