-
Notifications
You must be signed in to change notification settings - Fork 21
/
replier.go
162 lines (139 loc) · 4 KB
/
replier.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
package main
import (
"log"
"strings"
"sync"
"time"
"github.com/bwmarrin/discordgo"
)
const replySenderTimeout = 30 * time.Second
// a map from ID of a message I sent, to the ID of who is allowed to delete it (aka who sent the message that I was responding to)
var messageSender = make(map[string]string)
var messageSenderLock sync.Mutex
func onMessageReactedTo(session *discordgo.Session, reaction *discordgo.MessageReactionAdd) {
messageSenderLock.Lock()
defer messageSenderLock.Unlock()
// If the reaction isn't trash we don't care
if reaction.Emoji.Name != trash {
return
}
// Get the reply we sent
reply, err := session.ChannelMessage(reaction.ChannelID, reaction.MessageID)
if err != nil {
return //wtf
}
// If we didn't send the reply or we added the reaction
if reply.Author.ID != myselfID || reaction.UserID == myselfID {
return
}
user, err := GetMember(reaction.UserID)
if err != nil {
return
}
// Filter approved users
if !isMessageSender(reaction.UserID, reaction.MessageID) && !IsUserStaff(user) {
return
}
// Delete the reply
// sometimes errors since it was already trashcanned, dont spam logs with this error its too common
go session.ChannelMessageDelete(reply.ChannelID, reply.ID)
}
func onMessageSent(session *discordgo.Session, m *discordgo.MessageCreate) {
msg := m.Message
if msg == nil || msg.Author == nil || (msg.Type != discordgo.MessageTypeDefault && msg.Type != discordgo.MessageTypeReply) {
return // wtf
}
// Don't talk to oneself
if msg.Author.ID == myselfID {
return
}
author, err := GetMember(msg.Author.ID)
if err != nil {
return
}
if m.GuildID == impactServer {
memberSanityCheck(author)
emojiMsg(msg)
}
// Unless we're being spoken to
if !triggeredManually(msg) {
// Don't talk where we're not welcome
whitelist := []string{general, help, bot, betterHelp, testing}
if !includes(whitelist, msg.ChannelID) {
return
}
// Ignore messages from ‘know-it-all’s
if IsUserStaff(author) || hasRole(author, Stupid) {
return
}
}
// Phew, actually start doing stuff
response := ""
replyLoop:
for _, reply := range replies {
if includes(reply.excludeChannels, msg.ChannelID) {
continue replyLoop
}
if hasRole(author, reply.excludeRoles...) {
continue replyLoop
}
if len(reply.onlyChannels) > 0 && !includes(reply.onlyChannels, msg.ChannelID) {
continue replyLoop
}
if len(reply.onlyRoles) > 0 {
if !hasRole(author, reply.onlyRoles...) {
continue replyLoop
}
}
lower := strings.ToLower(msg.Content)
if !reply.regex.MatchString(lower) {
continue replyLoop
}
if reply.notRegex != nil && reply.notRegex.MatchString(lower) {
continue replyLoop
}
// Not excluded, append to response
response += reply.message + "\n"
}
if response == "" {
return
}
response = strings.TrimSpace(response)
messageSenderLock.Lock()
defer messageSenderLock.Unlock()
embed := &discordgo.MessageEmbed{
Author: &discordgo.MessageEmbedAuthor{},
Color: prettyembedcolor,
Description: response,
}
reply, err := session.ChannelMessageSendEmbed(msg.ChannelID, embed)
if err != nil {
log.Println(err)
return // if this failed, msg will be nil, so we cannot continue!
}
// Add a trashcan icon if the message wasn't triggered manually
// Keep track of who is allowed to delete the message too
if !triggeredManually(msg) {
err = session.MessageReactionAdd(reply.ChannelID, reply.ID, trash)
if err != nil {
log.Println(err)
}
// Add the message to the sender map then delete it later
messageSender[reply.ID] = msg.Author.ID
go func() {
time.Sleep(replySenderTimeout)
messageSenderLock.Lock()
defer messageSenderLock.Unlock()
delete(messageSender, reply.ID)
}()
}
}
func triggeredManually(msg *discordgo.Message) bool {
// TODO other methods of manual triggering, e.g. i!commands
return mentionsMe(msg)
}
// Check the given user was the sender that triggered message
func isMessageSender(user, message string) bool {
author, ok := messageSender[message]
return ok && user == author
}