1414logger = logging .getLogger (__name__ )
1515
1616TITLE = "Spam Detector"
17- REPEATED = 5
18- DURATION = 10
17+ TRIGGER_COUNT_DURATIONS = [(5 , 10 ), (3 , 2 )]
1918DD = collections .defaultdict
2019
2120
@@ -77,12 +76,22 @@ async def send_alert(self, message: discord.Message) -> None:
7776 if not isinstance (message .channel , discord .TextChannel ):
7877 return
7978 msg = f"<@&{ self .mod_role_id } > Banning { message .author .name } for spam "
80- msg += f"in { message .channel .name } . Same message { REPEATED } times.\n "
79+ msg += f"in { message .channel .name } . Same message multiple times in short period .\n "
8180 assert isinstance (self .mod_channel , discord .TextChannel )
8281 post = await self .mod_channel .send (msg )
8382 thread = await post .create_thread (name = "Banned post" , auto_archive_duration = 1440 )
8483 await thread .send (content = message .content )
8584
85+ def count_matching_messages (self , message : discord .Message , since : int ) -> int :
86+ """Return how many prior messages match since N timestamp."""
87+ return sum (
88+ 1
89+ for ts , messages in self .messages .items ()
90+ if ts >= since
91+ for prior in messages [message .author .id ]
92+ if self .message_match (message , prior )
93+ )
94+
8695 @commands .Cog .listener ()
8796 async def on_message (self , message : discord .Message ) -> None :
8897 """Detect repeated messages."""
@@ -99,24 +108,20 @@ async def on_message(self, message: discord.Message) -> None:
99108
100109 # Drop old messages
101110 now = int (time .time ())
102- cutoff = now - DURATION
111+ max_duration = max (duration for _ , duration in TRIGGER_COUNT_DURATIONS )
112+ cutoff = now - max_duration
103113 drop = [i for i in self .messages if i < cutoff ]
104114 for ts in drop :
105115 del self .messages [ts ]
106116
107117 # Add the new message
108118 self .messages [now ][message .author .id ].append (message )
109119
110- # Count occurances.
111- matching = sum (
112- 1
113- for messages in self .messages .values ()
114- for prior in messages [message .author .id ]
115- if self .message_match (message , prior )
116- )
117-
118- # Alert on spam.
119- if matching >= REPEATED :
120+ # Check if the message triggers the filter.
121+ if any (
122+ self .count_matching_messages (message , now - duration ) > count
123+ for count , duration in TRIGGER_COUNT_DURATIONS
124+ ):
120125 self .prom_counter .inc ()
121126 logging .info (
122127 "Spam detected. %s %s %s" ,
0 commit comments