diff --git a/go.mod b/go.mod index db19b76..c1e5076 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/velour/catbase go 1.13 require ( + code.chrissexton.org/cws/getaoc v0.0.0-20191201043947-d5417d4b618d github.com/AlekSi/pointer v1.1.0 // indirect github.com/ChimeraCoder/anaconda v2.0.0+incompatible github.com/ChimeraCoder/tokenbucket v0.0.0-20131201223612-c5a927568de7 // indirect diff --git a/go.sum b/go.sum index 460a027..64d1b90 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,7 @@ +code.chrissexton.org/cws/getaoc v0.0.0-20191201041923-dc696067b57c h1:X5c+asGWxR/Whkgl/YYXDanC4n2RHYeFcC7mT37+uZ4= +code.chrissexton.org/cws/getaoc v0.0.0-20191201041923-dc696067b57c/go.mod h1:rEpfJR9MplF2TUj2Oy+u4XAaLve2kwB8I2zlzeIQxl8= +code.chrissexton.org/cws/getaoc v0.0.0-20191201043947-d5417d4b618d h1:XS13tP+cMAvXYHQiYqcst64wQ854pueMRZSU4+6puU4= +code.chrissexton.org/cws/getaoc v0.0.0-20191201043947-d5417d4b618d/go.mod h1:rEpfJR9MplF2TUj2Oy+u4XAaLve2kwB8I2zlzeIQxl8= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AlekSi/pointer v1.0.0 h1:KWCWzsvFxNLcmM5XmiqHsGTTsuwZMsLFwWF9Y+//bNE= github.com/AlekSi/pointer v1.0.0/go.mod h1:1kjywbfcPFCmncIxtk6fIEub6LKrfMz3gc5QKVOSOA8= @@ -29,8 +33,6 @@ github.com/azr/backoff v0.0.0-20160115115103-53511d3c7330 h1:ekDALXAVvY/Ub1UtNta github.com/azr/backoff v0.0.0-20160115115103-53511d3c7330/go.mod h1:nH+k0SvAt3HeiYyOlJpLLv1HG1p7KWP7qU9QPp2/pCo= github.com/cdipaolo/goml v0.0.0-20190412180403-e1f51f713598 h1:j2XRGH5Y5uWtBYXGwmrjKeM/kfu/jh7ZcnrGvyN5Ttk= github.com/cdipaolo/goml v0.0.0-20190412180403-e1f51f713598/go.mod h1:sduMkaHcXDIWurl/Bd/z0rNEUHw5tr6LUA9IO8E9o0o= -github.com/chrissexton/gofuck v0.0.0-20191020114617-e7a1e23dde7e h1:JXogTwz6EUZbanZNfUsKcomEkFOTo0tSIVlbd2o8u9c= -github.com/chrissexton/gofuck v0.0.0-20191020114617-e7a1e23dde7e/go.mod h1:voOFh7xp5oNB4N516blAUT0Vh2JQq/cFX9autdChv9o= github.com/chrissexton/gofuck v1.0.0 h1:vxg/tIfI2HunJOErSotmMqMRNfLRVO+BTjSKpFoAizA= github.com/chrissexton/gofuck v1.0.0/go.mod h1:voOFh7xp5oNB4N516blAUT0Vh2JQq/cFX9autdChv9o= github.com/chrissexton/leftpad v0.0.0-20181207133115-1e93189d2fff h1:+TEqaP0eO1unI7XHHFeMDhsxhLDIb0x8KYuZbqbAmxA= @@ -156,9 +158,11 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.6.0 h1:DJy6UzXbahnGUf1ujUNkh/NEtK14qMo2nvlBPs4U5yw= gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPjXu+YNeGvK9VTSHY6+Qihc= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/go-playground/webhooks.v5 v5.13.0 h1:e9vtkQZK464+UdL3YjRox2yR8JSmh2094PUBMvdriFs= gopkg.in/go-playground/webhooks.v5 v5.13.0/go.mod h1:LZbya/qLVdbqDR1aKrGuWV6qbia2zCYSR5dpom2SInQ= diff --git a/main.go b/main.go index 80eafe3..a82c944 100644 --- a/main.go +++ b/main.go @@ -9,6 +9,7 @@ import ( "os" "time" + "github.com/velour/catbase/plugins/aoc" "github.com/velour/catbase/plugins/twitter" "github.com/rs/zerolog" @@ -134,6 +135,7 @@ func main() { b.AddPlugin(twitter.New(b)) b.AddPlugin(git.New(b)) b.AddPlugin(cli.New(b)) + b.AddPlugin(aoc.New(b)) // catches anything left, will always return true b.AddPlugin(fact.New(b)) diff --git a/plugins/aoc/aoc.go b/plugins/aoc/aoc.go new file mode 100644 index 0000000..8dfac77 --- /dev/null +++ b/plugins/aoc/aoc.go @@ -0,0 +1,110 @@ +package aoc + +import ( + "fmt" + "sort" + "strconv" + "strings" + "time" + + "code.chrissexton.org/cws/getaoc" + + "github.com/velour/catbase/bot" + "github.com/velour/catbase/bot/msg" + "github.com/velour/catbase/config" +) + +type AOC struct { + b bot.Bot + c *config.Config +} + +func New(b bot.Bot) *AOC { + aoc := &AOC{ + b: b, + c: b.Config(), + } + b.Register(aoc, bot.Message, aoc.message) + return aoc +} + +func (p *AOC) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool { + if !message.Command { + return false + } + cleaned := strings.TrimSpace(strings.ToLower(message.Body)) + fields := strings.Split(cleaned, " ") + if strings.HasPrefix(cleaned, "aoc") { + year := time.Now().Year() + if len(fields) > 1 { + year, _ = strconv.Atoi(fields[1]) + } + boardId := p.c.GetInt("aoc.board", 0) + var err error + if len(fields) > 2 { + boardId, err = strconv.Atoi(fields[2]) + if err != nil { + p.b.Send(c, bot.Message, message.Channel, fmt.Sprintf("Error getting leaderboard: %s", err)) + return true + } + } + session := p.c.Get("aoc.session", "") + if session == "" { + p.b.Send(c, bot.Message, message.Channel, "Error getting leaderboard: must have a session ID.") + return true + } + if boardId == 0 { + p.b.Send(c, bot.Message, message.Channel, "Error getting leaderboard: must have a board ID.") + return true + } + board, err := getaoc.GetLeaderboard(session, year, boardId) + if err != nil { + p.b.Send(c, bot.Message, message.Channel, fmt.Sprintf("Error getting leaderboard: %s", err)) + return true + } + + members := []getaoc.Member{} + for _, m := range board.Members { + members = append(members, m) + } + sort.Slice(members, func(i, j int) bool { + return members[i].LocalScore > members[j].LocalScore + }) + + gold, silver, bronze := -1, -1, -1 + goldID, silverID, bronzeID := "", "", "" + for _, m := range members { + if m.LocalScore > gold { + gold = m.LocalScore + goldID = m.ID + } + if m.LocalScore < gold && m.LocalScore > silver { + silver = m.LocalScore + silverID = m.ID + } + if m.LocalScore < silver && m.LocalScore > bronze { + bronze = m.LocalScore + bronzeID = m.ID + } + } + + msg := "AoC Leaderboard:\n" + for _, m := range members { + trophy := "" + switch m.ID { + case goldID: + trophy = ":gold-trophy:" + case silverID: + trophy = ":silver-trophy:" + case bronzeID: + trophy = ":bronze-trophy:" + } + msg += fmt.Sprintf("%s has %d :star: for a score of %d%s\n", m.Name, m.Stars, m.LocalScore, trophy) + } + msg = strings.TrimSpace(msg) + + p.b.Send(c, bot.Message, message.Channel, msg) + return true + } + return false +}