11"Admin cog with commands for moderation"
2+
23import asyncio
34from datetime import timedelta
45
6+ import discord
57from discord .ext import tasks
68from discord import Interaction , Member , Message , TextChannel
79from discord .app_commands import command , describe , checks , errors
10+ import typing
811
912from .basecog import BaseCog , Bot
1013
1114
1215class SpamMessage :
1316 "A message representation"
14- __slots__ = ('i' ,)
17+
18+ __slots__ = ("i" ,)
19+
1520 def __init__ (self , i : int ):
1621 self .i = i
1722
@@ -21,7 +26,9 @@ def __repr__(self):
2126
2227class SpamChannel :
2328 "A channel representation that holds messages"
24- __slots__ = ('i' , 'messages' )
29+
30+ __slots__ = ("i" , "messages" )
31+
2532 def __init__ (self , i : int , messages : list [SpamMessage ]):
2633 self .i = i
2734 self .messages = messages
@@ -37,7 +44,9 @@ def get_message(self, i: int) -> SpamMessage | None:
3744
3845class SpamUser :
3946 "A user representation that holds channels"
40- __slots__ = ('i' , 'channels' )
47+
48+ __slots__ = ("i" , "channels" )
49+
4150 def __init__ (self , i : int , channels : list [SpamChannel ]):
4251 self .i = i
4352 self .channels = channels
@@ -53,11 +62,12 @@ def get_channel(self, i: int) -> SpamChannel | None:
5362
5463class Admin (BaseCog ):
5564 "Admin cog with commands for moderation"
65+
5666 def __init__ (self , bot : Bot ):
57- super ().__init__ (bot )
58- self .spammers = []
59- self .clear_spammers .start () # pylint: disable=E1101
67+ self .spammers : typing .List [SpamUser ] = []
68+ self .clear_spammers .start () # pylint: disable=E1101
6069 self .description = "This is the moderation cog"
70+ super ().__init__ (bot )
6171
6272 @command (name = "clean" , description = "Clean messages from channel" )
6373 @describe (count = "Amount of messages to delete" )
@@ -66,10 +76,12 @@ def __init__(self, bot: Bot):
6676 async def clean (self , inter : Interaction , count : int , member : Member | None = None ):
6777 "Cleans `count` messages from optional `member` in the channel it's used"
6878 if not isinstance (inter .channel , TextChannel ):
69- return await inter .response .send_message ("Not a text channel, doing nothing." , ephemeral = True )
79+ return await inter .response .send_message (
80+ "Not a text channel, doing nothing." , ephemeral = True
81+ )
7082 await inter .response .defer (ephemeral = True )
7183 if member :
72- del_messages = []
84+ del_messages : typing . List [ Message ] = []
7385 async for message in inter .channel .history (limit = 200 ):
7486 if len (del_messages ) >= count :
7587 break
@@ -78,59 +90,81 @@ async def clean(self, inter: Interaction, count: int, member: Member | None = No
7890 await inter .channel .delete_messages (del_messages )
7991 else :
8092 del_messages = await inter .channel .purge (limit = count )
81- await inter .followup .send (f"Attempted to delete { count } messages,"
82- f"actually deleted { len (del_messages )} !" , ephemeral = True )
93+ await inter .followup .send (
94+ f"Attempted to delete { count } messages,"
95+ f"actually deleted { len (del_messages )} !" ,
96+ ephemeral = True ,
97+ )
8398
8499 @clean .error
85100 async def app_command_error (self , inter : Interaction , err : errors .AppCommandError ):
86101 "Handle app command errors"
87102 if isinstance (err , errors .MissingPermissions ):
88- return await inter .response .send_message ("You do not have permission to run this command." ,
89- ephemeral = True )
103+ return await inter .response .send_message (
104+ "You do not have permission to run this command." , ephemeral = True
105+ )
90106 return await inter .response .send_message (f"{ err } " , ephemeral = True )
91107
92108 @tasks .loop (minutes = 30 )
93109 async def clear_spammers (self ):
94110 "Clears the current 'spammer' list"
95- print (self .spammers )
111+ self . logger . debug (self .spammers )
96112 self .spammers = []
97- print ("Cleared spammers" )
113+ self . logger . debug ("Cleared spammers" )
98114
99115 @BaseCog .listener ()
100116 async def on_message (self , message : Message ):
101117 "Handle messages to detect for spam"
102- if self .bot .user is None or message .guild is None or message .author .id == self .bot .user .id :
118+ if (
119+ self .bot .user is None
120+ or message .guild is None
121+ or message .author .id == self .bot .user .id
122+ ):
103123 return
104124 if message .author .id not in [su .i for su in self .spammers ]:
105- self .spammers .append (SpamUser (message .author .id ,
106- [SpamChannel (message .channel .id , [SpamMessage (message .id )])]))
125+ self .spammers .append (
126+ SpamUser (
127+ message .author .id ,
128+ [SpamChannel (message .channel .id , [SpamMessage (message .id )])],
129+ )
130+ )
107131 return
108132 cur = [su for su in self .spammers if su .i == message .author .id ][0 ]
109133 curch = cur .get_channel (message .channel .id )
110134 if curch :
111135 curch .messages .append (SpamMessage (message .id ))
112136 else :
113- cur .channels .append (SpamChannel (message .channel .id , [SpamMessage (message .id )]))
137+ cur .channels .append (
138+ SpamChannel (message .channel .id , [SpamMessage (message .id )])
139+ )
114140
115141 if len (cur .channels ) >= 4 :
116- print (f"Spammer alert! { message .author .name } has sent "
117- f"messages to { len (cur .channels )} different channels recently!" )
118- await message .author .timeout (timedelta (seconds = 30 ),
119- reason = f"For spamming { len (cur .channels )} channels" )
142+ self .logger .info (
143+ f"Spammer alert! { message .author .name } has sent "
144+ f"messages to { len (cur .channels )} different channels recently!"
145+ )
146+ if not isinstance (message .author , discord .User ):
147+ await message .author .timeout (
148+ timedelta (seconds = 30 ),
149+ reason = f"For spamming { len (cur .channels )} channels" ,
150+ )
120151 del_chans = []
121152 for channel in cur .channels :
122153 chan = self .bot .get_channel (channel .i )
123154 if isinstance (chan , TextChannel ):
124155 del_chans .append (
125156 chan .delete_messages (
126- [chan .get_partial_message (msg .i ) for msg in channel .messages ]
157+ [
158+ chan .get_partial_message (msg .i )
159+ for msg in channel .messages
160+ ]
127161 )
128162 )
129163 await asyncio .gather (* del_chans )
130- #await message.channel.send(f"Spammer alert! {message.author.name}
131- #has sent messages to {len(cur)} different channels recently!", delete_after=5)
164+ # await message.channel.send(f"Spammer alert! {message.author.name}
165+ # has sent messages to {len(cur)} different channels recently!", delete_after=5)
132166 self .spammers .pop (self .spammers .index (cur ))
133- print (self .spammers )
167+ self . logger . debug (self .spammers )
134168
135169
136170setup = Admin .setup
0 commit comments