|
|
@@ -78,6 +78,31 @@ def saveGuildContext(gc):
|
|
78
|
78
|
|
|
79
|
79
|
# -- Classes ----------------------------------------------------------------
|
|
80
|
80
|
|
|
|
81
|
+class JoinRaid:
|
|
|
82
|
+ def __init__(self, joins):
|
|
|
83
|
+ self.joins = joins[:]
|
|
|
84
|
+
|
|
|
85
|
+ async def addJoin(self, member):
|
|
|
86
|
+ for join in self.joins:
|
|
|
87
|
+ if join.member.id == member.id:
|
|
|
88
|
+ # TODO: Move to front of list
|
|
|
89
|
+ return # Already added
|
|
|
90
|
+ self.joins.append(JoinRecord(member))
|
|
|
91
|
+
|
|
|
92
|
+ async def kickAll(self):
|
|
|
93
|
+ for join in self.joins:
|
|
|
94
|
+ if join.isKicked or join.isBanned:
|
|
|
95
|
+ continue
|
|
|
96
|
+ await join.member.kick()
|
|
|
97
|
+ join.isKicked = True
|
|
|
98
|
+
|
|
|
99
|
+ async def banAll(self):
|
|
|
100
|
+ for join in self.joins:
|
|
|
101
|
+ if join.isBanned:
|
|
|
102
|
+ continue
|
|
|
103
|
+ await join.member.ban()
|
|
|
104
|
+ join.isBanned = True
|
|
|
105
|
+
|
|
81
|
106
|
class JoinRecord:
|
|
82
|
107
|
def __init__(self, member):
|
|
83
|
108
|
self.member = member
|
|
|
@@ -108,6 +133,34 @@ class GuildContext:
|
|
108
|
133
|
self.joins.append(JoinRecord(member))
|
|
109
|
134
|
await self.__checkJoins()
|
|
110
|
135
|
|
|
|
136
|
+ async def handleReactionAdd(self, message, member, emoji):
|
|
|
137
|
+ global config
|
|
|
138
|
+ if member.bot:
|
|
|
139
|
+ return
|
|
|
140
|
+ print('User {0} added emoji {1}'.format(member, emoji))
|
|
|
141
|
+ if not member.permissions_in(message.channel).ban_members:
|
|
|
142
|
+ print('Reactor does not have ban permissions')
|
|
|
143
|
+ return
|
|
|
144
|
+ if self.lastWarningMessage == None or message.id != self.lastWarningMessage.id:
|
|
|
145
|
+ print('Reacted to a non-warning message')
|
|
|
146
|
+ return
|
|
|
147
|
+ if emoji.name == config['kickEmoji']:
|
|
|
148
|
+ print('Kicking these users:')
|
|
|
149
|
+ for join in self.joins:
|
|
|
150
|
+ await join.member.kick(reason='Kicked by rocketbot for join raiding')
|
|
|
151
|
+ join.isKicked = True
|
|
|
152
|
+ print(' ' + join.member.name)
|
|
|
153
|
+ elif emoji.name == config['banEmoji']:
|
|
|
154
|
+ print('Banning these users:')
|
|
|
155
|
+ for join in self.joins:
|
|
|
156
|
+ await join.member.ban(reason='Banned by rocketbot for join raiding', delete_message_days=0)
|
|
|
157
|
+ join.isBanned = True
|
|
|
158
|
+ print(' ' + join.member.name)
|
|
|
159
|
+ else:
|
|
|
160
|
+ print('Unhandled emoji. Doing nothing.')
|
|
|
161
|
+ return
|
|
|
162
|
+ await self.__updateLastJoinRaidMessage()
|
|
|
163
|
+
|
|
111
|
164
|
async def handleSetWarningChannel(self, context):
|
|
112
|
165
|
print('{0.guild.name}: Warning channel set to {0.channel.name}'.format(context))
|
|
113
|
166
|
self.warningChannel = context.channel
|
|
|
@@ -162,25 +215,52 @@ class GuildContext:
|
|
162
|
215
|
else:
|
|
163
|
216
|
i += 1
|
|
164
|
217
|
|
|
|
218
|
+ def __joinRaidMessage(self):
|
|
|
219
|
+ global config
|
|
|
220
|
+ # TODO: Mention mod role
|
|
|
221
|
+ message = 'A join raid has been detected! It includes these users:'
|
|
|
222
|
+ canKick = False
|
|
|
223
|
+ canBan = False
|
|
|
224
|
+ for join in self.joins:
|
|
|
225
|
+ message += '\n• '
|
|
|
226
|
+ if join.isBanned:
|
|
|
227
|
+ message += '~~' + join.member.mention + '~~ - banned'
|
|
|
228
|
+ elif join.isKicked:
|
|
|
229
|
+ message += '~~' + join.member.mention + '~~ - kicked'
|
|
|
230
|
+ canBan = True
|
|
|
231
|
+ else:
|
|
|
232
|
+ message += join.member.mention
|
|
|
233
|
+ canKick = True
|
|
|
234
|
+ canBan = True
|
|
|
235
|
+ if canKick:
|
|
|
236
|
+ message += '\nTo kick all these users, react with :' + config['kickEmojiName'] + ':'
|
|
|
237
|
+ if canBan:
|
|
|
238
|
+ message += '\nTo ban all these users, react with :' + config['banEmojiName'] + ':'
|
|
|
239
|
+ return (message, canKick, canBan)
|
|
|
240
|
+
|
|
|
241
|
+ async def __updateLastJoinRaidMessage(self):
|
|
|
242
|
+ if self.lastWarningMessage == None:
|
|
|
243
|
+ print('No previous warning message to update')
|
|
|
244
|
+ return
|
|
|
245
|
+ (message, canKick, canBan) = self.__joinRaidMessage()
|
|
|
246
|
+ await self.lastWarningMessage.edit(content=message)
|
|
|
247
|
+
|
|
165
|
248
|
async def __onJoinRaidBegin(self):
|
|
|
249
|
+ global config
|
|
166
|
250
|
print('A join raid has begun!')
|
|
167
|
251
|
if self.warningChannel == None:
|
|
168
|
252
|
print('No warning channel set')
|
|
169
|
253
|
return
|
|
170
|
|
- # TODO: Mention mod role
|
|
171
|
|
- message = 'A join raid has been detected! It includes these users:'
|
|
172
|
|
- for join in self.joins:
|
|
173
|
|
- message += '\n• ' + join.member.mention
|
|
|
254
|
+ (message, canKick, canBan) = self.__joinRaidMessage()
|
|
174
|
255
|
self.lastWarningMessage = await self.warningChannel.send(message)
|
|
|
256
|
+ if canKick:
|
|
|
257
|
+ await self.lastWarningMessage.add_reaction(config['kickEmoji'])
|
|
|
258
|
+ if canBan:
|
|
|
259
|
+ await self.lastWarningMessage.add_reaction(config['banEmoji'])
|
|
175
|
260
|
|
|
176
|
261
|
async def __onJoinRaidUpdated(self):
|
|
177
|
262
|
print('Join raid still occurring')
|
|
178
|
|
- if self.lastWarningMessage == None:
|
|
179
|
|
- return
|
|
180
|
|
- message = 'A join raid has been detected! It includes these users:'
|
|
181
|
|
- for join in self.joins:
|
|
182
|
|
- message += '\n• ' + join.member.mention
|
|
183
|
|
- await self.lastWarningMessage.edit(content=message)
|
|
|
263
|
+ await self.__updateLastJoinRaidMessage()
|
|
184
|
264
|
|
|
185
|
265
|
async def __onJoinRaidEnd(self):
|
|
186
|
266
|
print('Join raid has ended')
|
|
|
@@ -190,6 +270,7 @@ guildIdToGuildContext = {}
|
|
190
|
270
|
|
|
191
|
271
|
def getOrCreateGuildContext(obj, save=True):
|
|
192
|
272
|
gid = None
|
|
|
273
|
+ guild = None
|
|
193
|
274
|
if obj == None:
|
|
194
|
275
|
return None
|
|
195
|
276
|
if isinstance(obj, int):
|
|
|
@@ -198,8 +279,10 @@ def getOrCreateGuildContext(obj, save=True):
|
|
198
|
279
|
return obj
|
|
199
|
280
|
elif isinstance(obj, discord.Guild):
|
|
200
|
281
|
gid = obj.id
|
|
|
282
|
+ guild = obj
|
|
201
|
283
|
elif isinstance(obj, (discord.Message, discord.Member, discord.TextChannel, discord.ext.commands.context.Context)):
|
|
202
|
284
|
gid = obj.guild.id
|
|
|
285
|
+ guild = obj.guild
|
|
203
|
286
|
if gid == None:
|
|
204
|
287
|
print('Unhandled datatype', type(obj))
|
|
205
|
288
|
return None
|
|
|
@@ -207,6 +290,7 @@ def getOrCreateGuildContext(obj, save=True):
|
|
207
|
290
|
if lookedUp != None:
|
|
208
|
291
|
return lookedUp
|
|
209
|
292
|
g = GuildContext(gid)
|
|
|
293
|
+ g.guild = guild or g.guild
|
|
210
|
294
|
guildIdToGuildContext[gid] = g
|
|
211
|
295
|
if save:
|
|
212
|
296
|
saveGuildContext(g)
|
|
|
@@ -224,7 +308,7 @@ bot = commands.Bot(command_prefix='$', intents=intents)
|
|
224
|
308
|
async def hello(ctx):
|
|
225
|
309
|
message = ctx.message
|
|
226
|
310
|
print('Got message from {0.author.name} in {0.channel.id}'.format(message))
|
|
227
|
|
- await message.channel.send('Hello, {0.author.mention}!'.format(message))
|
|
|
311
|
+ m = await message.channel.send('Hello, {0.author.mention}!'.format(message))
|
|
228
|
312
|
print('Replied "Hello!"')
|
|
229
|
313
|
bot.add_command(hello)
|
|
230
|
314
|
|
|
|
@@ -248,7 +332,7 @@ bot.add_command(setwarningchannel)
|
|
248
|
332
|
|
|
249
|
333
|
@commands.command()
|
|
250
|
334
|
@commands.has_permissions(manage_messages=True)
|
|
251
|
|
-async def setwarningrole(ctx):
|
|
|
335
|
+async def setwarningrole(ctx, role: str):
|
|
252
|
336
|
g = getOrCreateGuildContext(ctx)
|
|
253
|
337
|
if g == None:
|
|
254
|
338
|
return
|
|
|
@@ -291,6 +375,24 @@ async def on_member_join(member):
|
|
291
|
375
|
async def on_member_remove(member):
|
|
292
|
376
|
print('User {0.name} left'.format(member))
|
|
293
|
377
|
|
|
|
378
|
+@bot.listen()
|
|
|
379
|
+async def on_raw_reaction_add(payload: discord.RawReactionActionEvent):
|
|
|
380
|
+ # payload.message_id: int
|
|
|
381
|
+ # payload.user_id: int
|
|
|
382
|
+ # payload.channel_id: int
|
|
|
383
|
+ # payload.guild_id: int
|
|
|
384
|
+ # payload.emoji: PartialEmoji
|
|
|
385
|
+ # payload.member: Member
|
|
|
386
|
+ # payload.event_type: str
|
|
|
387
|
+ global bot
|
|
|
388
|
+ guild = bot.get_guild(payload.guild_id)
|
|
|
389
|
+ channel = guild.get_channel(payload.channel_id)
|
|
|
390
|
+ message = await channel.fetch_message(payload.message_id)
|
|
|
391
|
+ member = payload.member
|
|
|
392
|
+ emoji = payload.emoji
|
|
|
393
|
+ gc = getOrCreateGuildContext(guild)
|
|
|
394
|
+ await gc.handleReactionAdd(message, member, emoji)
|
|
|
395
|
+
|
|
294
|
396
|
print('Starting bot')
|
|
295
|
397
|
bot.run(config['clientToken'])
|
|
296
|
398
|
print('Bot done')
|