GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( 7cd718...7f686a )
by Git
01:59
created

moderation.Moderation.warn()   C

Complexity

Conditions 8

Size

Total Lines 68
Code Lines 47

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 47
nop 5
dl 0
loc 68
rs 6.8678
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
import discord
2
import asyncio
3
from typing import Union
4
from discord.ext import commands
5
import variables as var
6
import database as db
7
from functions import get_prefix
8
from ext.permissions import has_command_permission
9
10
11
class Moderation(commands.Cog):
12
    def __init__(self, bot):
13
        self.bot = bot
14
15 View Code Duplication
    async def cog_check(self, ctx):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
16
        """Simple check to see if this cog (plugin) is enabled."""
17
        guild_doc = await db.PLUGINS.find_one({"_id": ctx.guild.id})
18
19
        if guild_doc.get("Moderation"):
20
            return True
21
22
        else:
23
            await ctx.send(
24
                embed=discord.Embed(
25
                    description=(
26
                        f"{var.E_DISABLE} The Moderation plugin "
27
                        "is disabled in this server"
28
                    ),
29
                    color=var.C_ORANGE
30
                )
31
            )
32
33
    @commands.command()
34
    @commands.has_permissions(ban_members=True)
35
    @has_command_permission()
36
    async def ban(
37
            self, ctx, user: discord.User = None, *, reason="No reason given"
38
    ):
39
        if user is not None and user != ctx.author:
40
41
            await ctx.guild.ban(user, reason=reason)
42
            await ctx.send(f"Applied ban to `{user}` :ok_hand:")
43
44
            try:
45
                await user.send(
46
                    embed=discord.Embed(
47
                        title=f"You have been banned from {ctx.guild.name}",
48
                        description=(
49
                            "Sorry I'm just a bot and I follow orders :("
50
                        ),
51
                        color=var.C_RED
52
                    ).add_field(
53
                        name="Reason",
54
                        value=reason
55
                    ).add_field(
56
                        name="Banned by", value=ctx.author
57
                    )
58
                )
59
60
            except discord.Forbidden:
61
                pass
62
63
            guild_log_doc = await db.LOGGING.find_one(
64
                            {"_id": ctx.guild.id}
65
            )
66
            if guild_log_doc is not None and guild_log_doc["modlog"]:
67
                channel = self.bot.get_channel(guild_log_doc["channel_id"])
68
                
69
                await channel.send(embed=discord.Embed(
70
                    title="🔨 Ban",
71
                    description=f"{user.mention} has been banned by {ctx.author.mention}",
72
                    color=var.C_GREEN
73
                ).add_field(
74
                    name="Reason",
75
                    value=reason
76
                )
77
                )
78
79
80
81
        elif user == ctx.author:
82
            await ctx.send("You can't ban yourself :eyes:")
83
84
        else:
85
            await ctx.send(
86
                embed=discord.Embed(
87
                    description=(
88
                        "🚫 You need to define the user to ban them,"
89
                        " reason is optional"
90
                    ),
91
                    color=var.C_RED
92
                ).add_field(
93
                    name="Format",
94
                    value=f"`{await get_prefix(ctx)}ban <user> <reason>`"
95
                ).set_footer(
96
                    text="For user either User mention or User ID can be used")
97
                )
98
99
    @ban.error
100
    async def ban_error(self, ctx, error):
101
        if isinstance(error, commands.CommandInvokeError):
102
            await ctx.send(
103
                embed=discord.Embed(
104
                    title="Permission error",
105
                    description=(
106
                        "🚫 I don't have permissions to ban the user, "
107
                        "make sure that my I have ban members permission"
108
                        " and role is placed above the highest role which"
109
                        " the user has"
110
                    ),
111
                    color=var.C_RED
112
                )
113
            )
114
115
    @commands.command()
116
    @commands.has_permissions(ban_members=True)
117
    @has_command_permission()
118
    async def unban(self, ctx, user: discord.User = None):
119
        if user is not None:
120
            bans = await ctx.guild.bans()
121
            banned_users = [ban.user for ban in bans]
122
123
            if user in banned_users:
124
                await ctx.guild.unban(user)
125
                await ctx.send(f'Successfully unbanned `{user}` :ok_hand:')
126
127
                try:
128
                    await user.send(
129
                        embed=discord.Embed(
130
                            title=(
131
                                f"You have been unbanned from {ctx.guild.name}!"
132
                            ),
133
                            description="Yay I would be happy to see you back!",
134
                            color=var.C_GREEN
135
                        ).add_field(
136
                            name="Unbanned by", value=ctx.author)
137
                        )
138
139
                except discord.Forbidden:
140
                    pass
141
                
142
            guild_log_doc = await db.LOGGING.find_one(
143
                            {"_id": ctx.guild.id}
144
            )
145
            if guild_log_doc is not None and guild_log_doc["modlog"]:
146
                channel = self.bot.get_channel(guild_log_doc["channel_id"])
147
                
148
                await channel.send(embed=discord.Embed(
149
                    title="🔨 Unban",
150
                    description=f"{user.mention} has been unbanned by {ctx.author.mention}",
151
                    color=var.C_BLUE
152
                )
153
                )
154
155
            else:
156
                await ctx.send(
157
                    embed=discord.Embed(
158
                        description=(
159
                            f"The user `{user}` is not banned, "
160
                            "therefore cannot unban them."
161
                        ),
162
                        color=var.C_ORANGE
163
                    )
164
                )
165
166
        else:
167
            await ctx.send(
168
                embed=discord.Embed(
169
                    description="🚫 You need to define the user to unban them",
170
                    color=var.C_RED
171
                ).add_field(
172
                    name="Format",
173
                    value=f"`{await get_prefix(ctx)}unban <user>`"
174
                ).set_footer(
175
                    text="For user either User mention or User ID can be used")
176
                )
177
178
    async def unban_error(self, ctx, error):
179
        if isinstance(error, commands.CommandInvokeError):
180
            await ctx.send(
181
                embed=discord.Embed(
182
                    title="Permission error",
183
                    description=(
184
                        "🚫 I don't have permissions to unban the user, make "
185
                        "sure that I have ban members permission and my role "
186
                        "is placed above the highest role which the user has"
187
                    ),
188
                    color=var.C_RED
189
                )
190
            )
191
192
    @commands.command()
193
    @commands.has_permissions(manage_roles=True)
194
    @has_command_permission()
195
    async def mute(self, ctx, member: discord.Member = None):
196
        if member is not None:
197
            if not discord.utils.get(ctx.guild.roles, name='Muted'):
198
                muted_role = await ctx.guild.create_role(
199
                    name="Muted", colour=discord.Colour(0xa8a8a8)
200
                )
201
202
                for i in ctx.guild.text_channels:
203
                    await i.set_permissions(muted_role, send_messages=False)
204
205
            else:
206
                muted_role = discord.utils.get(ctx.guild.roles, name="Muted")
207
208
            await member.add_roles(muted_role)
209
            await ctx.send(f"Applied chat mute to `{member}` :mute:")
210
211
            guild_log_doc = await db.LOGGING.find_one(
212
                            {"_id": ctx.guild.id}
213
            )
214
            if guild_log_doc is not None and guild_log_doc["modlog"]:
215
                channel = self.bot.get_channel(guild_log_doc["channel_id"])
216
                
217
                await channel.send(embed=discord.Embed(
218
                    title="🔈 Mute",
219
                    description=f"{member.mention} has been muted by {ctx.author.mention}",
220
                    color=var.C_GREEN
221
                )
222
                )
223
        else:
224
            await ctx.send(
225
                embed=discord.Embed(
226
                    description=(
227
                        "🚫 You need to define member in order to mute them"
228
                    ),
229
                    color=var.C_RED
230
                ).add_field(
231
                    name="Format",
232
                    value=f"`{await get_prefix(ctx)}mute <member>`"
233
                ).set_footer(
234
                    text=(
235
                        "For user either Member mention "
236
                        "or Member ID can be used"
237
                    )
238
                )
239
            )
240
241
    @mute.error
242
    async def mute_error(self, ctx, error):
243
        if isinstance(error, discord.Forbidden):
244
            await ctx.send(
245
                embed=discord.Embed(
246
                    title="Permission error",
247
                    description=(
248
                        "🚫 I don't have permissions to mute the member, make"
249
                        " sure that I have manage roles permission and my role"
250
                        " is placed above the highest role which the member has"
251
                    ),
252
                    color=var.C_RED
253
                )
254
            )
255
256
    @commands.command()
257
    @commands.has_permissions(manage_roles=True)
258
    @has_command_permission()
259
    async def unmute(self, ctx, member: discord.Member = None):
260
        if member is None:
261
            await ctx.send(
262
                embed=discord.Embed(
263
                    description=(
264
                        "🚫 You need to define the member to unmute them"
265
                    ),
266
                    color=var.C_RED
267
                ).add_field(
268
                    name="Format",
269
                    value=f"`{await get_prefix(ctx)}unmute <member>`"
270
                ).set_footer(
271
                    text=(
272
                        "For user either Member mention "
273
                        "or Member ID can be used"
274
                    )
275
                )
276
            )
277
        elif not discord.utils.get(ctx.guild.roles, name='Muted'):
278
            await ctx.send(
279
                "There is no muted role yet hence I cannot unmute, "
280
                "Muting someone automatically makes one."
281
            )
282
283
        else:
284
            muted_role = discord.utils.get(ctx.guild.roles, name='Muted')
285
286
            await member.remove_roles(muted_role)
287
            await ctx.send(f"Unmuted `{member}` :sound:")
288
289
            guild_log_doc = await db.LOGGING.find_one(
290
                            {"_id": ctx.guild.id}
291
            )
292
            if guild_log_doc is not None and guild_log_doc["modlog"]:
293
                channel = self.bot.get_channel(guild_log_doc["channel_id"])
294
                
295
                await channel.send(embed=discord.Embed(
296
                    title="🔈 Unmute",
297
                    description=f"{member.mention} has been unmuted by {ctx.author.mention}",
298
                    color=var.C_BLUE
299
                )
300
                )
301
302
    @unmute.error
303
    async def unmute_error(self, ctx, error):
304
        if isinstance(error, commands.CommandInvokeError):
305
            await ctx.send(
306
                embed=discord.Embed(
307
                    title="Permission error",
308
                    description=(
309
                        "🚫 I don't have permissions to unmute the user, "
310
                        "make sure that I have manage roles permission and "
311
                        "my role is placed above the highest role which the "
312
                        "user has"
313
                    ),
314
                    color=var.C_RED
315
                )
316
            )
317
318
    @commands.command()
319
    @commands.has_permissions(kick_members=True)
320
    @has_command_permission()
321
    async def kick(
322
        self, ctx, member: discord.Member = None, *, reason="No reason provided"
323
    ):
324
        if member is not None and member != ctx.author:
325
            await member.kick(reason=reason)
326
            await ctx.send(f"`{member}` have been kicked from the server")
327
328
            try:
329
                await member.send(
330
                    embed=discord.Embed(
331
                        title=f"You have been kicked from {ctx.guild.name}",
332
                        color=var.C_RED
333
                    ).add_field(
334
                        name="Reason", value=reason
335
                    ).add_field(
336
                        name="Kicked by", value=ctx.author
337
                    )
338
                )
339
340
            except discord.Forbidden:
341
                pass
342
343
            guild_log_doc = await db.LOGGING.find_one(
344
                            {"_id": ctx.guild.id}
345
            )
346
            if guild_log_doc is not None and guild_log_doc["modlog"]:
347
                channel = self.bot.get_channel(guild_log_doc["channel_id"])
348
                
349
                await channel.send(embed=discord.Embed(
350
                    title="🧹 Kick",
351
                    description=f"{member.mention} has been kicked by {ctx.author.mention}",
352
                    color=var.C_GREEN
353
                )
354
                )
355
        elif member == ctx.author:
356
            await ctx.send("You can't kick yourself :eyes:")
357
358
        else:
359
            await ctx.send(embed=discord.Embed(
360
                description="🚫 You need to define the member to kick them",
361
                color=var.C_RED
362
            ).add_field(
363
                name="Format",
364
                value=f"`{await get_prefix(ctx)}kick <member>`"
365
            ).set_footer(
366
                text="For user either Member mention or Member ID can be used")
367
            )
368
369
    @kick.error
370
    async def kick_error(self, ctx, error):
371
        if isinstance(error, commands.CommandInvokeError):
372
            await ctx.send(
373
                embed=discord.Embed(
374
                    title="Permission error",
375
                    description=(
376
                        "🚫 I don't have permissions to kick the member,"
377
                        " make sure that I have kick members permission"
378
                        " and my role is placed above the highest role "
379
                        "which the member has"
380
                    ),
381
                    color=var.C_RED
382
                )
383
            )
384
385
    @commands.command(aliases=["nickname", "changenick"])
386
    @commands.has_permissions(change_nickname=True)
387
    @has_command_permission()
388
    async def nick(self, ctx, member: discord.Member = None, *, nick=None):
389
        if member and nick is not None:
390
            previous_nick = member.nick
391
            await member.edit(nick=nick)
392
            await ctx.send(
393
                embed=discord.Embed(
394
                    description=(
395
                        f"{var.E_ACCEPT} Nickname changed "
396
                        f"for `{member}` to {nick}"
397
                    ),
398
                    color=var.C_GREEN
399
                )
400
            )
401
            guild_log_doc = await db.LOGGING.find_one(
402
                            {"_id": ctx.guild.id}
403
            )
404
            if guild_log_doc is not None and guild_log_doc["modlog"]:
405
                channel = self.bot.get_channel(guild_log_doc["channel_id"])
406
                
407
                await channel.send(embed=discord.Embed(
408
                    title="🧹 Nickname change",
409
                    description=f"{member.mention}'s nickname has been changed by {ctx.author.mention} to {nick}",
410
                    color=var.C_GREEN
411
                ).add_field(
412
                    name="Previous nick",
413
                    value=previous_nick
414
                )
415
                )
416
        else:
417
            await ctx.send(
418
                embed=discord.Embed(
419
                    description=(
420
                        "🚫 You need to define both the member"
421
                        " and their new nick"
422
                    ),
423
                    color=var.C_RED
424
                ).add_field(
425
                    name="Format",
426
                    value=f"`{await get_prefix(ctx)}nick <member> <new nick>`"
427
                ).set_footer(
428
                    text="For Member either mention or Member ID can be used"
429
                )
430
            )
431
432
    @nick.error
433
    async def nick_error(self, ctx, error):
434
        if isinstance(error, commands.CommandInvokeError):
435
            await ctx.send(
436
                embed=discord.Embed(
437
                    title="Permission error",
438
                    description=(
439
                        "🚫 I don't have permissions to change the nickname "
440
                        "of the member, make sure that I have change nickname "
441
                        "permission and my role is placed above the highest "
442
                        "role which the member has"
443
                    ),
444
                    color=var.C_RED
445
                )
446
            )
447
448
    @commands.command(aliases=["clean", "clear"])
449
    @commands.has_permissions(manage_messages=True)
450
    @has_command_permission()
451
    async def purge(self, ctx, limit: int = None):
452
        if limit is not None:
453
            await ctx.channel.purge(limit=limit + 1)
454
455
            info = await ctx.send(embed=discord.Embed(
456
                description=f"Deleted {limit} messages",
457
                color=var.C_ORANGE)
458
            )
459
            await asyncio.sleep(1)
460
            await info.delete()
461
462
            guild_log_doc = await db.LOGGING.find_one(
463
                            {"_id": ctx.guild.id}
464
            )
465
            if guild_log_doc is not None and guild_log_doc["modlog"]:
466
                channel = self.bot.get_channel(guild_log_doc["channel_id"])
467
                
468
                await channel.send(embed=discord.Embed(
469
                    title="🧹 Purge",
470
                    description=f"{ctx.author.mention} has deleted {limit} messages from {ctx.channel.mention}",
471
                    color=var.C_GREEN
472
                )
473
                )
474
        else:
475
            await ctx.send(
476
                embed=discord.Embed(
477
                    description=(
478
                        "🚫 You need to define the amount"
479
                        " to delete messages too! Make sure the amount is numerical."
480
                    ),
481
                    color=var.C_RED
482
                ).add_field(
483
                    name="Format",
484
                    value=f"`{await get_prefix(ctx)}purge <amount>`"
485
                )
486
            )
487
488
    @purge.error
489
    async def purge_error(self, ctx, error):
490
        if isinstance(error, commands.CommandInvokeError):
491
            await ctx.send(
492
                embed=discord.Embed(
493
                    title="Permission error",
494
                    description="🚫 I don't have permissions to delete messages",
495
                    color=var.C_RED
496
                )
497
            )
498
499 View Code Duplication
    @commands.command(aliases=["giverole"])
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
500
    @has_command_permission()
501
    async def addrole(
502
        self, ctx, member: discord.Member = None, role: discord.Role = None
503
    ):
504
        if member and role is not None:
505
            try:
506
                await member.add_roles(role)
507
                await ctx.send(
508
                    embed=discord.Embed(
509
                        description=(
510
                            f"Successfully updated {member.mention} "
511
                            f"with {role.mention} role"
512
                        ),
513
                        color=var.C_GREEN
514
                    )
515
                )
516
517
            except discord.Forbidden:
518
                await ctx.send(
519
                    embed=discord.Embed(
520
                        title="Missing permissions",
521
                        description=(
522
                            f"I don't have permissions to update the roles"
523
                            f" of {member.mention}, either I don't have the"
524
                            f" permission or the member is above me"
525
                        ),
526
                        color=var.C_RED
527
                    )
528
                )
529
        else:
530
            await ctx.send(
531
                embed=discord.Embed(
532
                    title=f"🚫 Missing arguments",
533
                    description="You need to define both member and role",
534
                    color=var.C_RED
535
                ).add_field(
536
                    name="Format",
537
                    value=f"```{await get_prefix(ctx)}addrole <member> <role>```"
538
                ).set_footer(
539
                    text=(
540
                        "For both member and role, "
541
                        "either ping or ID can be used"
542
                    )
543
                )
544
            )
545
546 View Code Duplication
    @commands.command(name="removerole")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
547
    @has_command_permission()
548
    async def remove_role(
549
        self, ctx, member: discord.Member = None, role: discord.Role = None
550
    ):
551
        if member and role is not None:
552
            try:
553
                await member.remove_roles(role)
554
                await ctx.send(
555
                    embed=discord.Embed(
556
                        description=(
557
                            f"Successfully updated {member.mention} "
558
                            f"by removing {role.mention} role"
559
                        ),
560
                        color=var.C_GREEN
561
                    )
562
                )
563
564
            except discord.Forbidden:
565
                await ctx.send(
566
                    embed=discord.Embed(
567
                        title="Missing permissions",
568
                        description=(
569
                            f"I don't have permissions to update the roles of"
570
                            f" {member.mention}, either I don't have the"
571
                            f" permission or the member is above me"
572
                        ),
573
                        color=var.C_RED
574
                    )
575
                )
576
        else:
577
            await ctx.send(
578
                embed=discord.Embed(
579
                    title=f"🚫 Missing arguments",
580
                    description="You need to define both member and role",
581
                    color=var.C_RED
582
                ).add_field(
583
                    name="Format",
584
                    value=(
585
                        f"```{await get_prefix(ctx)}removerole"
586
                        f" <member> <role>```"
587
                    )
588
                ).set_footer(
589
                    text=(
590
                        "For both member and role,"
591
                        " either ping or ID can be used"
592
                    )
593
                )
594
            )
595
596 View Code Duplication
    @commands.command(name="massrole")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
597
    @has_command_permission()
598
    async def mass_role(
599
        self, ctx, role: discord.Role = None, role2: discord.Role = None
600
    ):
601
        if role is not None and role2 is not None:
602
            bot_msg = await ctx.send(
603
                embed=discord.Embed(
604
                    title="Confirmation",
605
                    description=(
606
                        f"Are you sure you want to update all members"
607
                        f" with the role {role.mention} with {role2.mention}?"
608
                    ),
609
                    color=var.C_BLUE
610
                ).add_field(
611
                    name=(
612
                        "Note that this action is irreversible "
613
                        "and cannot be stopped once started"
614
                    ),
615
                    value=(
616
                        f"{var.E_ACCEPT} to accept\n"
617
                        f"{var.E_ENABLE} to accept with live stats\n"
618
                        f"{var.E_DECLINE} to decline"
619
                    )
620
                )
621
            )
622
623
            await bot_msg.add_reaction(var.E_ACCEPT)
624
            await bot_msg.add_reaction(var.E_ENABLE)
625
            await bot_msg.add_reaction(var.E_DECLINE)
626
627
            def reaction_check(r, u):
628
                return u == ctx.author and r.message == bot_msg
0 ignored issues
show
introduced by
The variable bot_msg does not seem to be defined for all execution paths.
Loading history...
629
630
            reaction, _ = await self.bot.wait_for(
631
                "reaction_add", check=reaction_check
632
            )
633
634
            updates = False
635
636
            try:
637
                await bot_msg.clear_reactions()
638
            except Exception:
639
                pass
640
641
            if str(reaction.emoji) == var.E_DECLINE:
642
                return await ctx.send("Cancelled mass role update")
643
644
            if str(reaction.emoji) == var.E_ENABLE:
645
                updates = True
646
647
            if (
648
                str(reaction.emoji) == var.E_ENABLE
649
                or str(reaction.emoji) == var.E_ACCEPT
650
            ):
651
652
                count = 0
653
654
                for member in [
655
                    member
656
                    for member in ctx.guild.members
657
                    if role in member.roles
658
                ]:
659
                    try:
660
                        await member.add_roles(role2)
661
                        count += 1
662
663
                        if updates:
664
                            await ctx.send(f"{member} updated")
665
666
                    except discord.Forbidden:
667
                        await ctx.send(
668
                            embed=discord.Embed(
669
                                description=(
670
                                    f"Error giving role to {member.mention}"
671
                                ),
672
                                color=var.C_ORANGE
673
                            )
674
                        )
675
676
                    await asyncio.sleep(1)
677
678
                await ctx.send(
679
                    f"Done, updated **{count}** members "
680
                    f"with the {role2.name} role"
681
                )
682
683
        else:
684
            await ctx.send(
685
                embed=discord.Embed(
686
                    title=f"🚫 Missing arguments",
687
                    description=(
688
                        "You need to define both Role 1 and Role 2\n`role1` "
689
                        "are the members having that role and `role2` is the"
690
                        " one to be given to them"
691
                    ),
692
                    color=var.C_RED
693
                ).add_field(
694
                    name="Format",
695
                    value=f"```{await get_prefix(ctx)}massrole <role1> <role2>```"
696
                ).set_footer(
697
                    text="For role, either ping or ID can be used"
698
                )
699
            )
700
701 View Code Duplication
    @commands.command(name="massroleremove")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
702
    @has_command_permission()
703
    async def mass_role_remove(
704
        self, ctx, role: discord.Role = None, role2: discord.Role = None
705
    ):
706
        if role is not None and role2 is not None:
707
            bot_msg = await ctx.send(
708
                embed=discord.Embed(
709
                    title="Confirmation",
710
                    description=(
711
                        f"Are you sure you want to update"
712
                        f" all members with the role {role.mention}"
713
                        f" by removing {role2.mention}?"
714
                    ),
715
                    color=var.C_BLUE
716
                ).add_field(
717
                    name=(
718
                        "Note that this action is irreversable"
719
                        " and cannot be stopped once started"
720
                    ),
721
                    value=(
722
                        f"{var.E_ACCEPT} to accept\n{var.E_ENABLE}"
723
                        f" to accept with live stats\n{var.E_DECLINE} to decline"
724
                    )
725
                )
726
            )
727
728
            await bot_msg.add_reaction(var.E_ACCEPT)
729
            await bot_msg.add_reaction(var.E_ENABLE)
730
            await bot_msg.add_reaction(var.E_DECLINE)
731
732
            def reaction_check(r, u):
733
                return u == ctx.author and r.message == bot_msg
0 ignored issues
show
introduced by
The variable bot_msg does not seem to be defined for all execution paths.
Loading history...
734
735
            reaction, _ = await self.bot.wait_for(
736
                "reaction_add", check=reaction_check
737
            )
738
739
            updates = False
740
741
            try:
742
                await bot_msg.clear_reactions()
743
744
            except Exception:
745
                pass
746
747
            if str(reaction.emoji) == var.E_DECLINE:
748
                return await ctx.send("Cancelled mass role update")
749
750
            if str(reaction.emoji) == var.E_ENABLE:
751
                updates = True
752
753
            if str(reaction.emoji) == var.E_ENABLE or str(
754
                    reaction.emoji) == var.E_ACCEPT:
755
                count = 0
756
                for member in [
757
                    member
758
                    for member in ctx.guild.members
759
                    if role in member.roles
760
                ]:
761
                    try:
762
                        await member.remove_roles(role2)
763
                        count += 1
764
                        if updates:
765
                            await ctx.send(f"{member} updated")
766
767
                    except discord.Forbidden:
768
                        await ctx.send(
769
                            embed=discord.Embed(
770
                                description=(
771
                                    f"Error giving role to {member.mention}"
772
                                ),
773
                                color=var.C_ORANGE
774
                            )
775
                        )
776
                    await asyncio.sleep(1)
777
778
                await ctx.send(
779
                    f"Done,"
780
                    f" updated **{count}** members with the {role2.name} role"
781
                )
782
        else:
783
784
            await ctx.send(
785
                embed=discord.Embed(
786
                    title=f"🚫 Missing arguments",
787
                    description=(
788
                        "You need to define both Role 1 and Role 2\n"
789
                        "`role1` are the members having that role"
790
                        " and `role2` is the one to be removed from them"
791
                    ),
792
                    color=var.C_RED
793
                ).add_field(
794
                    name="Format",
795
                    value=(
796
                        f"```{await get_prefix(ctx)}massroleremove"
797
                        f" <role1> <role2>```"
798
                    )
799
                ).set_footer(
800
                    text="For role, either ping or ID can be used"
801
                )
802
            )
803
804
    @commands.command()
805
    @has_command_permission()
806
    async def warn(self, ctx, member: discord.Member = None, *, reason=None):
807
        if member and reason is not None:
808
            guild_col = db.WARNINGS_DATABASE[str(ctx.guild.id)]
809
            user_warns = await guild_col.find_one({"_id": member.id})
810
811
            if user_warns is None:
812
                new_warns = [reason]
813
                await guild_col.insert_one(
814
                    {"_id": member.id, "warns": new_warns}
815
                )
816
817
            else:
818
                current_warns = user_warns["warns"]
819
                new_warns = current_warns.copy()
820
                new_warns.append(reason)
821
                new_data = {
822
                    "$set": {
823
                        "warns": new_warns
824
                    }
825
                }
826
827
                await guild_col.update_one(user_warns, new_data)
828
829
            await ctx.send(
830
                content=f"{member.mention} has been warned!",
831
                embed=discord.Embed(
832
                    description=(
833
                        f"Reason: **{reason}**\n"
834
                        f"Total warns: **{len(new_warns)}**"
835
                    ),
836
                    color=var.C_BLUE
837
                ).set_footer(
838
                    text=f"Moderator: {ctx.author}"
839
                )
840
            )
841
            guild_log_doc = await db.LOGGING.find_one(
842
                            {"_id": ctx.guild.id}
843
            )
844
            if guild_log_doc is not None and guild_log_doc["modlog"]:
845
                channel = self.bot.get_channel(guild_log_doc["channel_id"])
846
                
847
                await channel.send(embed=discord.Embed(
848
                    title="⚠️ Warn",
849
                    description=f"{member.mention} has been warned by {ctx.author.mention}",
850
                    color=var.C_GREEN
851
                ).add_field(
852
                    name="Total warns now",
853
                    value=len(new_warns)
854
                )
855
                )
856
857
        elif member is not None and reason is None:
858
            await ctx.send("Reason is required too!")
859
860
        else:
861
            await ctx.send(
862
                embed=discord.Embed(
863
                    title=f"🚫 Missing arguments",
864
                    description=(
865
                        "You need to define both the member"
866
                        " and reason to warn them!"
867
                    ),
868
                    color=var.C_RED
869
                ).add_field(
870
                    name="Format",
871
                    value=f"```{await get_prefix(ctx)}warn <member> <reason>```"
872
                )
873
            )
874
875
    @commands.command(name="removewarn", aliases=["remove-warn", "unwarn"])
876
    @has_command_permission()
877
    async def remove_warn(
878
        self, ctx, member: discord.Member = None, position=None
879
    ):
880
        if member and position is not None:
881
            try:
882
                position = int(position)
883
884
            except ValueError:
885
                await ctx.send(
886
                    embed=discord.Embed(
887
                        description=f"The position should be a number!",
888
                        color=var.C_RED)
889
                    )
890
                return
891
892
            guild_col = db.WARNINGS_DATABASE[str(ctx.guild.id)]
893
            user_doc = await guild_col.find_one({"_id": member.id})
894
895
            if user_doc is None:
896
                await ctx.send(
897
                    embed=discord.Embed(
898
                        description=f"{member.mention} does not have any warns",
899
                        color=var.C_RED
900
                    ).set_footer(
901
                        text=(
902
                            "Note that this warn's position has been taken by"
903
                            " the warn below it, therefore moving all warns "
904
                            "below this one position above"
905
                        )
906
                    )
907
                )
908
909
            else:
910
                warns = user_doc["warns"]
911
                if len(warns) - 1 >= position - 1:
912
                    reason = warns[position - 1]
913
                    new_warns = warns.copy()
914
                    removed_warn = new_warns.pop(position - 1)
915
                    new_data = {
916
                        "$set": {
917
                            "warns": new_warns
918
                        }
919
                    }
920
921
                    await guild_col.update_one(user_doc, new_data)
922
                    await ctx.send(
923
                        embed=discord.Embed(
924
                            description=(
925
                                f"{var.E_ACCEPT} Removed {position} warn with "
926
                                f"the reason **{reason}** from {member.mention}"
927
                            ),
928
                            color=var.C_GREEN
929
                        ).set_footer(
930
                            text=(
931
                                "Note that if there are any warns below this "
932
                                "one then they are moved one position up to "
933
                                "take the removed warn's place"
934
                            )
935
                        )
936
                    )
937
                    guild_log_doc = await db.LOGGING.find_one(
938
                                    {"_id": ctx.guild.id}
939
                    )
940
                    if guild_log_doc is not None and guild_log_doc["modlog"]:
941
                        channel = self.bot.get_channel(guild_log_doc["channel_id"])
942
                        
943
                        await channel.send(embed=discord.Embed(
944
                            title="⚠️ Remove warn",
945
                            description=f"{member.mention} has been unwarned by {ctx.author.mention}",
946
                            color=var.C_BLUE
947
                        ).add_field(
948
                            name="Removed warn",
949
                            value=removed_warn
950
                        )
951
                        )
952
                else:
953
                    await ctx.send(
954
                        embed=discord.Embed(
955
                            description=(
956
                                f"{member.mention} does not have"
957
                                f" {position} warn(s)"
958
                            ),
959
                            color=var.C_RED
960
                        )
961
                    )
962
963
        else:
964
            await ctx.send(
965
                embed=discord.Embed(
966
                    title=f"🚫 Missing arguments",
967
                    description=(
968
                        "You need to define both the member "
969
                        "and the warn position to remove the warn"
970
                    ),
971
                    color=var.C_RED
972
                ).add_field(
973
                    name="Format",
974
                    value=(
975
                        f"```{await get_prefix(ctx)}removewarn "
976
                        "<member> <position>```"
977
                    )
978
                ).set_footer(
979
                    text="Note that position here is just a number"
980
                )
981
            )
982
983
    @commands.command()
984
    @has_command_permission()
985
    async def warns(self, ctx, member: discord.Member = None):
986
        if member is not None:
987
            guild_col = db.WARNINGS_DATABASE[str(ctx.guild.id)]
988
            userdata = await guild_col.find_one({"_id": member.id})
989
990
            if userdata is None:
991
                await ctx.send(f"{member} does not have any warnings")
992
993
            else:
994
                warns = userdata["warns"]
995
                embed = discord.Embed(
996
                    title=f"{member} warns", color=var.C_MAIN
997
                )
998
                for i in warns:
999
                    embed.add_field(
1000
                        name=f"Warn {warns.index(i) + 1}", value=i,
1001
                        inline=False
1002
                    )
1003
                await ctx.send(embed=embed)
1004
                guild_doc = await db.LOGGING.find_one(
1005
                                    {"_id": ctx.guild.id}
1006
                                )
1007
                if guild_doc["modlog"]:
1008
                    channel = self.bot.get_channel(guild_doc["channel_id"])
1009
1010
                    await channel.send(embed=discord.Embed(
1011
                        title="New warn",
1012
                        description=f"{member.mention} has been warned by {ctx.author.mention}",
1013
                        color=var.C_GREEN
1014
                    ))
1015
1016
        else:
1017
            await ctx.send(
1018
                embed=discord.Embed(
1019
                    title=f"🚫 Missing arguments",
1020
                    description=(
1021
                        "You need to define the member to view their warns"
1022
                    ),
1023
                    color=var.C_RED
1024
                ).add_field(
1025
                    name="Format",
1026
                    value=f"```{await get_prefix(ctx)}warns <member>```"
1027
                )
1028
            )
1029
1030
    @commands.command()
1031
    async def modlog(self, ctx):
1032
        guild_doc = await db.LOGGING.find_one({
1033
                        "_id": ctx.guild.id
1034
                    })
1035
1036
        status = False if not guild_doc or not guild_doc["modlog"] else True
1037
1038
        def check(reaction, user):
1039
            return user == ctx.author and reaction.message == bot_msg
1040
1041
        def message_check(message):
1042
            return (
1043
                message.author == ctx.author
1044
                and message.channel.id == ctx.channel.id
1045
            )  
1046
1047
        embed = discord.Embed(title="Mod log")
1048
        if status:
1049
            embed.description = (
1050
                "Moderation log is currently enabled"
1051
                f"\nReact to the {var.E_DISABLE} emoji to disable it."
1052
            )
1053
            embed.color = var.C_GREEN
1054
1055
        else:
1056
            embed.description = (
1057
                "Moderation log is currently disabled"
1058
                f"\nReact to the {var.E_ENABLE} emoji to disable it."
1059
            )
1060
            embed.color = var.C_RED
1061
1062
        bot_msg = await ctx.send(embed=embed)
1063
        
1064
        await bot_msg.add_reaction(
1065
            var.E_DISABLE 
1066
            if status else 
1067
            var.E_ENABLE
1068
            )
1069
        reaction, _ = await self.bot.wait_for(
1070
                                        "reaction_add", 
1071
                                        check=check, 
1072
                                        timeout=60
1073
                                        )
1074
1075
        if str(reaction.emoji) == var.E_ENABLE:
1076
            if not guild_doc:
1077
                await ctx.send("Send the channel where you would like to log moderation events!")
1078
                while True:
1079
                    user_msg = await self.bot.wait_for("message", 
1080
                                                    check=message_check, 
1081
                                                    timeout=60
1082
                                                    )
1083
                    try:
1084
                        channel = self.bot.get_channel(
1085
                            int(user_msg.content.strip("<>#"))
1086
                            )
1087
                        break
1088
                    except Exception:
1089
                        await ctx.send("Invalid channel ID, try again.")
1090
1091
1092
                await db.LOGGING.insert_one(
1093
                    {
1094
                    "_id": ctx.guild.id,
1095
                    "channel_id": channel.id, 
1096
                    "modlog": True
1097
                    }
1098
                )
1099
            else:
1100
                await db.LOGGING.insert(
1101
                    guild_doc,
1102
                    {"set":{'modlog': True}}
1103
                )
1104
                
1105
        elif str(reaction.emoji) == var.E_DISABLE:
1106
            await db.LOGGING.update_db(
1107
                guild_doc,
1108
                {"set": {'modlog': True}}
1109
            )
1110
1111
        await ctx.send(embed=discord.Embed(
1112
            description=f"Successfully {'disabled' if status else 'enabled'} moderation logging.",
1113
            color=var.C_RED if status else var.C_GREEN
1114
        ))
1115
1116
def setup(bot):
1117
    bot.add_cog(Moderation(bot))
1118