This repository has been archived by the owner on Jan 3, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
270 lines (260 loc) · 8.65 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
package main
import (
"fmt"
"math/rand"
"os"
"os/signal"
"strings"
"syscall"
"github.com/bwmarrin/discordgo"
"github.com/dustin/go-humanize"
"github.com/joho/godotenv"
)
var (
botID string
adminIDs []string
topgg string
// CacheTime stores cache timer value
CacheTime int64
//BlacklistTime stores the blacklist time for all of the channels
BlacklistTime int64
// ServerMap this is all of the servers an the servers this gets wiped from memory as soon as the Bot gets killed
ServerMap map[string]string
// NSFWMap stores all nsfw values for each channel
NSFWMap map[string]bool
//PostCache stores all posts
PostCache map[string][]QuickPost
//Blacklist list of all of the post that are blacklisted from the specified channel
Blacklist map[string][]QuickPost // will be wiped every two to three hours
//LastPost gets the last post from the specified channel string
LastPost map[string]QuickPost
//SubMap contains all of the data for the subs
SubMap map[string][]string
//CachePopulating if true, do not run the populate cache until finished
CachePopulating bool
//ErrorMsg Main error message that gets send when something goes seriously wrong
ErrorMsg string
//JSONError JSON error message
JSONError string
// RequestCount counts how many requests a channel makes
// If over 10 in a minute then halt all posting
RequestCount map[string]uint8
// RequestTimer stores channel timers
// Resets every minute
RequestTimer map[string]int64
// RunMode the mode that the bot is running in
RunMode string
// QueueState checks if queue is running for specific channel
QueueState map[string]bool
)
// main loop
func main() {
godotenv.Load()
var err error
var key string
var adminRawIDs []string
ServerMap = make(map[string]string)
NSFWMap = make(map[string]bool)
PostCache = make(map[string][]QuickPost)
Blacklist = make(map[string][]QuickPost)
LastPost = make(map[string]QuickPost)
SubMap = make(map[string][]string)
RequestCount = make(map[string]uint8)
RequestTimer = make(map[string]int64)
QueueState = make(map[string]bool)
ErrorMsg = "There was an error processing your request. If this persists, please submit a report here: https://github.com/chand1012/Discord-Quick-Meme/issues"
JSONError = "Error reading JSON file"
key, topgg, RunMode, adminRawIDs = getDataEnv()
if err != nil {
panic(err) // can't run without a login
}
discord, err := discordgo.New("Bot " + key)
if err != nil {
fmt.Println("Error creating Discord bot!")
panic(err) // if it errors out at all in this init phase, its not gonna work anyway.
}
user, err := discord.User("@me")
if err != nil {
panic(err)
}
for _, admin := range adminRawIDs {
a, err := discord.User(admin)
if err != nil {
fmt.Println("WARNING: No admin IDs set, debug will not work!")
break
}
adminIDs = append(adminIDs, a.ID)
}
botID = user.ID
discord.AddHandler(commandHandler)
discord.AddHandler(readyHandler)
err = discord.Open()
if err != nil {
fmt.Println("Error opening Discord connection!")
panic(err)
}
defer discord.Close()
fmt.Println("Discord-Quick-Meme is starting up.")
sc := make(chan os.Signal, 1)
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt)
<-sc
// Clean up
fmt.Println("Cleaning up ..")
if lockFileExists() {
err = os.Remove("./thread.lock")
if err != nil {
fmt.Println(err)
}
}
fmt.Println("Cleanly shutdown.")
}
// handles bot initialization
func readyHandler(discord *discordgo.Session, ready *discordgo.Ready) {
servers := discord.State.Guilds
CachePopulating = true
PopulateCache()
ResetBlacklist()
serverCount := int64(len(servers))
fmt.Println("Discord-Quick-Meme has started on " + humanize.Comma(serverCount) + " servers.")
if RunMode == "prod" { // only run if production
go updateServerCount(serverCount, topgg)
}
go updateStatus(discord)
go queueThread(discord)
go GetAllChannelNames()
}
// handes incoming commands
func commandHandler(discord *discordgo.Session, message *discordgo.MessageCreate) {
var subs []string
var channelName string
go updateStatus(discord)
go UpdateBlacklistTime()
channel := message.ChannelID
commands := []string{"!meme", "!joke", "!hentai", "!news", "!fiftyfifty", "!5050", "!all", "!quickmeme", "!text", "!link", "!source", "!buzzword", "!revsearch"}
user := message.Author
content := message.Content
commandContent := strings.Split(content, " ")
command := commandContent[0]
guildID := message.GuildID
if user.ID == botID || user.Bot || !stringInSlice(commandContent[0], commands) {
return
}
canUserPost := updateChannelTimer(channel)
if !canUserPost {
if RequestCount[channel] == 6 {
fmt.Println("Channel " + channel + "is sending a lot of requests, limiting their input for 60 seconds.")
}
if RequestCount[channel] > 10 {
discord.ChannelMessageSend(channel, "You're sending a lot of requests, how about you slow it down a bit? All requests from this channel will be ignored for 60 seconds.")
}
return
}
channelName, nsfw := GetChannelData(discord, channel, guildID)
fmt.Println("Command '" + content + "' from " + user.Username + " on " + channelName + " (" + channel + ")")
switch {
case command == "!meme" && len(commandContent) == 1:
subs = SubMap["memes"]
getMediaPost(discord, channel, nsfw, subs, "hot")
case command == "!meme" && len(commandContent) >= 2:
subs = textFilterSlice(commandContent[1:])
if subs == nil {
discord.ChannelMessageSend(channel, ErrorMsg)
return
}
getMediaPost(discord, channel, nsfw, subs, "hot")
case (command == "!joke" || command == "!text") && len(commandContent) == 1:
subs = SubMap["text"]
getTextPost(discord, channel, nsfw, subs, "hot")
case (command == "!joke" || command == "!text") && len(commandContent) >= 2:
subs = textFilterSlice(commandContent[1:])
if subs == nil {
discord.ChannelMessageSend(channel, ErrorMsg)
return
}
getTextPost(discord, channel, nsfw, subs, "hot")
case (command == "!news" || command == "!link") && len(commandContent) == 1:
subs = SubMap["news"]
getLinkPost(discord, channel, nsfw, subs, "hot")
case (command == "!news" || command == "!link") && len(commandContent) >= 2:
subs = textFilterSlice(commandContent[1:])
if subs == nil {
discord.ChannelMessageSend(channel, ErrorMsg)
return
}
getLinkPost(discord, channel, nsfw, subs, "hot")
case command == "!fiftyfifty" || command == "!5050":
subs = []string{"fiftyfifty"}
getLinkPost(discord, channel, nsfw, subs, "hot")
case commandContent[0] == "!buzzword":
getBuzzWord(discord, channel)
case commandContent[0] == "!hentai":
// This is still only here because a friend of mine
// suggested this and I am a nice person
subs = SubMap["hentai"]
getMediaPost(discord, channel, nsfw, subs, "hot")
case command == "!all":
randchoice := rand.Intn(4) // skipcq
switch randchoice {
case 0:
getLinkPost(discord, channel, nsfw, []string{"all"}, "")
case 1:
getTextPost(discord, channel, nsfw, []string{"all"}, "")
default:
getMediaPost(discord, channel, nsfw, []string{"all"}, "")
}
case command == "!source":
err := getSource(discord, channel)
if err != nil {
fmt.Println("Error getting source of meme:", err)
discord.ChannelMessageSend(channel, "Error getting source of meme: "+err.Error())
return
}
case command == "!quickmeme":
var subcommand string
if len(commandContent) > 1 {
subcommand = commandContent[1]
} else {
subcommand = ""
}
subcommand = textFilter(subcommand)
if !stringInSlice(user.ID, adminIDs) && !isUserMemeBotAdmin(discord, guildID, user) {
fmt.Println("Intruder tried to execute admin only command:")
fmt.Println(user.Username)
} else if stringInSlice(user.ID, adminIDs) {
switch subcommand {
case "ban":
banSubRoutine(discord, channel, commandContent, guildID, user)
case "unban":
unbanSubRoutine(discord, channel, commandContent, guildID, user)
case "getbanned":
getbannedSubRoutine(discord, channel, commandContent, guildID, user)
case "subscribe":
setQueueRoutine(discord, channel, commandContent, nsfw)
case "unsubscribe":
delQueueRoutine(discord, channel)
case "help":
helpRoutine(discord, channel)
default:
quickMemeDefault(discord, channel)
}
} else {
switch subcommand {
case "ban":
banSubRoutine(discord, channel, commandContent, guildID, user)
case "unban":
unbanSubRoutine(discord, channel, commandContent, guildID, user)
case "getbanned":
getbannedSubRoutine(discord, channel, commandContent, guildID, user)
case "subscribe":
setQueueRoutine(discord, channel, commandContent, nsfw)
case "unsubscribe":
delQueueRoutine(discord, channel)
case "help":
helpRoutine(discord, channel)
default:
quickMemeDefault(discord, channel)
}
}
}
fmt.Println("Posted.")
}