/
main.go
138 lines (107 loc) · 2.86 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package main
import (
"context"
"fmt"
"os"
"strings"
"time"
"github.com/nlopes/slack"
"github.com/tylerchr/backtalk"
)
var SlackToken = os.Getenv("SLACK_TOKEN")
type (
Accomplishment struct {
User string
Timestamp time.Time
Text string
}
Storage interface {
Save(a Accomplishment) error
Range(user string, from, to time.Time, cb func(i int, a Accomplishment) bool) error
}
memoryStorage []Accomplishment
)
func (ms *memoryStorage) Save(a Accomplishment) error {
if a.Timestamp.IsZero() {
a.Timestamp = time.Now()
}
*ms = append(*ms, a)
return nil
}
func (ms memoryStorage) Range(u string, from, to time.Time, cb func(i int, a Accomplishment) bool) error {
var i int
RangeLoop:
for _, a := range ms {
switch {
case a.User != u:
// not the right user
continue
case !from.IsZero() && a.Timestamp.Before(from):
// happened too early
continue
case !to.IsZero() && a.Timestamp.After(to):
// happened too late
continue
default:
if stop := cb(i, a); stop {
break RangeLoop
}
i++
}
}
return nil
}
func main() {
var s Storage = &memoryStorage{}
api := slack.New(SlackToken)
// start the bot
ijust, _ := backtalk.New(api)
ijust.Start(context.TODO(), backtalk.ReplyFunc(func(rtm *slack.RTM, evt *slack.MessageEvent) error {
// look up the user
info := rtm.GetInfo()
user := info.GetUserByID(evt.User)
// fmt.Printf("From: %#v\n", user)
prefix := fmt.Sprintf("<@%s> ", info.User.ID)
text := strings.TrimSpace(strings.TrimPrefix(evt.Text, prefix))
switch {
// Special command: list accomplishments
case strings.HasPrefix(strings.ToLower(text), "what"):
fmt.Printf("Looking up accomplishments of %s\n", user.Name)
var all []Accomplishment
s.Range(user.Name, time.Now().Add(-24*time.Hour), time.Now(), func(i int, a Accomplishment) bool {
fmt.Printf("%d\t%s\t%s\t%s\n", i, a.User, a.Timestamp, a.Text)
all = append(all, a)
return false
})
if len(all) == 0 {
rtm.SendMessage(rtm.NewOutgoingMessage(
fmt.Sprintf("<@%s> Looks like you've gotten nothing done!", evt.User),
evt.Channel,
))
} else {
var list string
for _, c := range all {
list = fmt.Sprintf("%s\n- %s (%s ago)", list, c.Text, time.Now().Sub(c.Timestamp).Round(1*time.Second))
}
rtm.SendMessage(rtm.NewOutgoingMessage(
fmt.Sprintf("<@%s> Here's the rundown:\n%s", evt.User, strings.TrimSpace(list)),
evt.Channel,
))
}
// New accomplishment
default:
a := Accomplishment{
User: user.Name,
Timestamp: backtalk.ParseTime(evt.Timestamp),
Text: text,
}
fmt.Printf("New accomplishment from %s: %s\n", user.Name, a)
s.Save(a)
// add a reaction
if err := api.AddReaction("thumbsup", slack.NewRefToMessage(evt.Channel, evt.Timestamp)); err != nil {
fmt.Printf("error adding reaction: %s\n", err)
}
}
return nil
}))
}