-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
320 lines (273 loc) · 9.16 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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
package main
import (
"fmt"
"math"
"sort"
"strings"
"time"
"github.com/slack-go/slack"
"golang.org/x/text/language"
"golang.org/x/text/message"
)
// START of things you should edit
// See config.go for more things to edit
const (
// Caching all emoji images can take a lot of time and storage, so you
// may want to leave it off. It takes 547MB for my company's Slack.
// The only use of cashing all images is to see what deleted emojis were.
// After all emojis have been downloaded the first time, this will only download new emojis.
// You can also download the image for a deleted emoji if it has not been deleted for very long.
cacheImages = false
// This controls if the JSON blob of all current emojis is cached. This is only used for detecting
// deleted emojis.
cacheEmojiDumps = true
// Top uploaders of all time is noisy.
// I only send at the end of the year, if someone has recently moved up a lot, etc.
sendTopUploadersAllTime = false
findLongestEmojisAllTime = false
skipTopEmojisByReactionVote = false
// If this is turned on, emojis in the format "emoji-name-123" will be skipped.
// This is the format used by Slack if another work space's emojis are merged in and there are duplicate names.
skipDuplicateBulkImportEmojis = false
// Do not include emojis if after removing - and _ they are a dupe of an existing emoji.
strictUniqueMode = false
// Skip emojis that begin with screen-shot-, the format that Mac uses by default.
skipScreenShots = true
// Disables the emojis to skip list.
literally1984Mode = true
// Replaces all emoijs sent with a single emoji, ideally an old school windows broken image emoji.
aprilFoolsMode = false
// Do not include the colons
aprilFoolsEmoji = "broken-img"
// Needs to be used after turning off April Fools mode
// to prevent the joke emoji from being detected as the last mew emoji.
// Can also be used when running the script for the first time.
// Can have colons or not, doesn't matter.
overRideLastNewEmoji = ""
// The channel to post these messages in when in FULL_SEND mode.
emojiChannel = "#emojis"
// This controls if things are printed, DMed or posted publicly.
// See values below.
runMode Mode = MODE__DM_FOR_REVIEW
// When doing Emojis Wrapped, fast mode is ignored
doEmojisWrapped = false
doHeBringsYouCounter = true
// FastMode will not fetch all emojis, just the ones since the last emoji post.
// Detecting deleted emojis is not possible in fast mode.
fastMode = true
)
// END of things you should edit
// See config.go for more things to edit
type Mode int
const (
MODE__PRINT_EVERYTHING Mode = iota
MODE__DM_FOR_REVIEW
MODE__DM_FOR_TESTING
MODE__FULL_SEND
)
func main() {
start := time.Now()
defer func() {
fmt.Printf("Time spent: %v\n", time.Since(start))
}()
slackApi = slack.New(botOauthToken)
// This will get the last new emoji.
err := dealWithLastWeekMessages()
if err != nil {
panic(err)
}
var allEmojis *SlackEmojiResponseMessage
if !fastMode || doEmojisWrapped {
allEmojis, err = getAllEmojis()
if err != nil {
panic(err)
}
} else {
allEmojis, err = getEmojisBackTo(previousLastNewEmoji)
if err != nil {
panic(err)
}
}
if !skipTopEmojisByReactionVote {
err = printTopEmojisByReactionVote(allEmojis, false, 10, reactionMessage)
if err != nil {
panic(err)
}
}
if doEmojisWrapped {
err = emojisWrapped(allEmojis)
if err != nil {
panic(err)
}
return
}
// cacheEmojiImages and detectDeletedEmojis should be called before removeSkippedEmojis
err = cacheEmojiImages(allEmojis)
if err != nil {
panic(err)
}
if !fastMode {
err = detectDeletedEmojis(allEmojis)
if err != nil {
panic(err)
}
}
removeSkippedEmojis(allEmojis)
// mostRecentEmojis, topUploaders, and longestEmojis should be called after removeSkippedEmojis
err = mostRecentEmojis(allEmojis)
if err != nil {
panic(err)
}
err = topAndNewUploaders(allEmojis)
if err != nil {
panic(err)
}
if doHeBringsYouCounter {
err = memeCounter(allEmojis)
if err != nil {
panic(err)
}
}
if findLongestEmojisAllTime {
err = longestEmojis(allEmojis)
if err != nil {
panic(err)
}
}
}
var (
slackApi *slack.Client
printer = message.NewPrinter(language.English)
lastNewEmoji, previousLastNewEmoji string
reactionMessage *slack.Message
)
const (
maxEmojisPerMessage = 22
maxPeopleForTopUploaders = 100
maxEmojisForLongestEmojis = 100
maxCharactersPerMessage = 10000
TopPeopleToPrint = 5
lastWeek = ":trophy: *Congratulations* to the top new emojis from last week (sorted by emoji reactions from %v voters):\n"
lastYear = ":trophy::trophy::trophy: *CONGRATULATIONS TO THE TOP EMOJIS OF %v!!!* (sorted by emoji reactions from %v voters):\n"
introMessage = ":new-shine: Here are all the new emojis! There are %v new emojis from %v people."
votePrompt = ":votesticker: *Vote for the best new emoji of the week by reacting here!*"
votePromptPrevious = "Vote for the best new emoji of the week by reacting here!"
topAllTimeMessage = ":tophat: Top Emoji Uploaders of All Time:"
topThisWeekMessage = ":rocket: Top Emoji Uploaders This Week:"
topSecondMessage = "More Top Emoji Uploaders:"
newUploadersMessage = ":welcome: *Welcome* to %d New Emoji Uploaders!"
newUploadersSecondMessage = "More New Emoji Uploaders:"
muteMessage = "If you do not want to be pinged by this bot, message @%s to request that you be added to the mute list so the script prints your name without the @ sign.\n"
skipMessage = "If you want to be excluded from the bot all together, you can ask @%s to add you to the skip list.\n"
)
func mostRecentEmojis(response *SlackEmojiResponseMessage) error {
var allNewEmojis []string
response.peopleThisWeek = map[string]*stringCount{}
var foundLastEmoji bool
lastNewEmojiSanitized := strings.ReplaceAll(lastNewEmoji, ":", "")
sort.Sort(EmojiUploadDateSort(response.Emoji))
for _, emoji := range response.Emoji {
if emoji.Name == lastNewEmojiSanitized {
foundLastEmoji = true
break
}
count, ok := response.peopleThisWeek[emoji.UserId]
if !ok {
response.peopleThisWeek[emoji.UserId] = &stringCount{
name: emoji.UserDisplayName,
id: emoji.UserId,
count: 1,
}
} else {
count.count++
}
allNewEmojis = append(allNewEmojis, emoji.Name)
}
if !foundLastEmoji {
fmt.Printf("Did not find the last emoji %v. This is probably a problem.\n", lastNewEmoji)
}
slackMessages := make([]string, 0, len(response.Emoji)/maxEmojisPerMessage+1)
i := 0
j := 0
auditMessage := []string{""}
for z := len(allNewEmojis) - 1; z >= 0; z-- {
emojiName := allNewEmojis[z]
if emojiName == lastNewEmojiSanitized {
foundLastEmoji = true
break
}
if aprilFoolsMode {
emojiName = aprilFoolsEmoji
}
newPart := ":" + emojiName + ": " + emojiName + "\n"
if len(newPart)+len(auditMessage[len(auditMessage)-1]) > maxCharactersPerMessage {
auditMessage = append(auditMessage, newPart)
} else {
auditMessage[len(auditMessage)-1] += newPart
}
if len(slackMessages) > i {
slackMessages[i] = slackMessages[i] + ":" + emojiName + ":"
} else {
slackMessages = append(slackMessages, ":"+emojiName+":")
}
if j == maxEmojisPerMessage {
i++
j = 0
} else {
j++
}
}
_, err := printMessage(MSG_TYPE__SEND_AND_REVIEW, printer.Sprintf(introMessage, len(allNewEmojis), len(response.peopleThisWeek)))
if err != nil {
return err
}
for _, msg := range slackMessages {
_, err := printMessage(MSG_TYPE__SEND_AND_REVIEW, msg)
if err != nil {
return err
}
}
var peopleNameArray []string
for _, person := range response.peopleThisWeek {
peopleNameArray = append(peopleNameArray, person.name)
}
threadId, err := printMessage(MSG_TYPE__SEND, votePrompt)
if err != nil {
return err
}
// Side by side message
for _, part := range auditMessage {
_, err := printMessageWithThreadId(MSG_TYPE__SEND, part, threadId)
if err != nil {
return err
}
}
// List everyone's names
_, err = printMessageWithThreadId(MSG_TYPE__SEND, createNameString(peopleNameArray), threadId)
if err != nil {
return err
}
return printTopPeople(topThisWeekMessage, topSecondMessage, response.peopleThisWeek, math.MaxInt64, false)
}
type EmojiUploadDateSort []*emoji
func (p EmojiUploadDateSort) Len() int { return len(p) }
func (p EmojiUploadDateSort) Less(i, j int) bool { return p[i].Created > p[j].Created }
func (p EmojiUploadDateSort) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
type EmojiUploadDateSortBackwards []*emoji
func (p EmojiUploadDateSortBackwards) Len() int { return len(p) }
func (p EmojiUploadDateSortBackwards) Less(i, j int) bool { return p[i].Created < p[j].Created }
func (p EmojiUploadDateSortBackwards) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
type ByCount []*stringCount
func (a ByCount) Len() int { return len(a) }
func (a ByCount) Less(i, j int) bool {
if a[i].count == a[j].count {
return a[i].name < a[j].name
}
return a[i].count > a[j].count
}
func (a ByCount) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
type stringCount struct {
count int
name string
id string
}