lunarflu HF Staff commited on
Commit
e440628
Β·
verified Β·
1 Parent(s): aa39bb3

test autoban (mods not exempt)

Browse files
Files changed (1) hide show
  1. app.py +85 -19
app.py CHANGED
@@ -35,6 +35,14 @@ logging.basicConfig(level=logging.DEBUG)
35
  #rate_limiter = RateLimiter(max_calls=10, period=60) # needs testing
36
  message_cache = {}
37
 
 
 
 
 
 
 
 
 
38
  # stats stuff ---------------------------------------------------------------------------------------------------------------------------------------------------------
39
  number_of_messages = 0
40
  user_cooldowns = {}
@@ -98,8 +106,8 @@ async def on_message(message):
98
  """
99
 
100
  # cooldown_duration = 3; false_positive_threshld = 3; -> 99% spam at spam_count of 10+ (could still be wrong, so we timeout)
101
- cooldown_duration = 5 # messages per n seconds, was 1, now 3, could try 5
102
- false_positive_threshold = 5 # big = alert less (catch less spam), small = alert more (catch more spam)
103
  timeout_threshold = 10 # number of messages before issuing a timeout (similar function to ban, easier to reverse)
104
  timeout_duration = 168 # timeout duration in hours (1 week)
105
 
@@ -119,7 +127,7 @@ async def on_message(message):
119
 
120
  # tldr; if we post 2 messages with less than [cooldown_duration]seconds between them
121
  if spam_count >= false_positive_threshold: # n in a row, helps avoid false positives for posting in threads
122
- # warning for 5+
123
  channel = message.channel
124
  if spam_count == false_positive_threshold:
125
  if channel.id != 996580741121065091: # admin channel excluded due to how automod messages are categorized by the discord bot
@@ -149,27 +157,85 @@ async def on_message(message):
149
  f"Message content: {message.content}\n"
150
  f"[Jump to message!](https://discord.com/channels/{message.guild.id}/{message.channel.id}/{message.id})\n"
151
  )
152
- # auto-ban
153
- """
154
- if spam_count >= timeout_threshold:
155
- try:
156
- member = message.author
157
- await member.send(
158
- "You have been auto-banned for spamming. \n If this was an error, message <@811235357663297546> ."
159
- )
160
- await member.ban()
161
- except Exception as e:
162
- print(f"Error: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
 
164
- """
165
-
166
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  user_cooldowns[message.author.id]['timestamp'] = message.created_at
168
 
169
  await bot.process_commands(message)
170
 
171
- except Exception as e:
172
- print(f"on_message Error: {e}")
173
 
174
  # moderation stuff-----------------------------------------------------------------------------------------------------------------------------------------------------
175
 
 
35
  #rate_limiter = RateLimiter(max_calls=10, period=60) # needs testing
36
  message_cache = {}
37
 
38
+ AUTO_BAN_ALERT_THRESHOLD = 5
39
+ AUTO_BAN_EXEMPT_ROLE_IDS = {897381378172264449, 897376942817419265}
40
+ # moderator = 1078351789843292311
41
+
42
+ def is_exempt(member: discord.Member) -> bool:
43
+ return any(getattr(r, "id", None) in AUTO_BAN_EXEMPT_ROLE_IDS for r in getattr(member, "roles", []))
44
+
45
+
46
  # stats stuff ---------------------------------------------------------------------------------------------------------------------------------------------------------
47
  number_of_messages = 0
48
  user_cooldowns = {}
 
106
  """
107
 
108
  # cooldown_duration = 3; false_positive_threshld = 3; -> 99% spam at spam_count of 10+ (could still be wrong, so we timeout)
109
+ cooldown_duration = 7 # messages per n seconds, was 1, now 3, could try 5 (adjusted 5->7)
110
+ false_positive_threshold = 4 # big = alert less (catch less spam), small = alert more (catch more spam)
111
  timeout_threshold = 10 # number of messages before issuing a timeout (similar function to ban, easier to reverse)
112
  timeout_duration = 168 # timeout duration in hours (1 week)
113
 
 
127
 
128
  # tldr; if we post 2 messages with less than [cooldown_duration]seconds between them
129
  if spam_count >= false_positive_threshold: # n in a row, helps avoid false positives for posting in threads
130
+ # warning for 4+
131
  channel = message.channel
132
  if spam_count == false_positive_threshold:
133
  if channel.id != 996580741121065091: # admin channel excluded due to how automod messages are categorized by the discord bot
 
157
  f"Message content: {message.content}\n"
158
  f"[Jump to message!](https://discord.com/channels/{message.guild.id}/{message.channel.id}/{message.id})\n"
159
  )
160
+ # AUTO BAN ======================================================================================================
161
+ # Only in guild text contexts
162
+ if not message.guild:
163
+ # DMs or weird contexts β€” never autoban
164
+ pass
165
+ else:
166
+ # Resolve a proper Member object
167
+ member = message.author if isinstance(message.author, discord.Member) else message.guild.get_member(message.author.id)
168
+
169
+ if member is None:
170
+ print("Autoban: could not resolve Member, skipping.")
171
+ else:
172
+ # Prepare alert ping safely
173
+ test_server = os.environ.get('TEST_SERVER')
174
+ if test_server == 'True':
175
+ alert = "<@&1106995261487710411>" # test alerts
176
+ elif test_server == 'False':
177
+ alert = "<@&1108342563628404747>" # prod alerts
178
+ else:
179
+ alert = "" # no ping fallback
180
+
181
+ # Skip bots and exempt roles
182
+ if member.bot or is_exempt(member):
183
+ pass
184
+ elif spam_count >= AUTO_BAN_ALERT_THRESHOLD:
185
+ me: discord.Member = message.guild.me
186
+ can_ban = (
187
+ isinstance(me, discord.Member)
188
+ and me.guild_permissions.ban_members
189
+ and (member.top_role < me.top_role) # role hierarchy check
190
+ )
191
 
192
+ if not can_ban:
193
+ try:
194
+ await bot.log_channel.send(
195
+ f"❌ Auto-ban skipped for {member.mention} β€” missing `Ban Members` or role hierarchy issue."
196
+ )
197
+ except Exception as e:
198
+ print(f"Autoban permission log error: {e}")
199
+ else:
200
+ try:
201
+ # Try to DM; ignore failures
202
+ try:
203
+ await member.send(
204
+ f"You have been automatically banned from **{message.guild.name}** for repeated spam. "
205
+ f"If this was an error, please contact @lunarflu."
206
+ )
207
+ except Exception as dm_err:
208
+ print(f"Could not DM user before ban: {dm_err}")
209
+
210
+ await member.ban(
211
+ reason=f"Auto-ban: reached {spam_count} spam alerts within ~{cooldown_duration}s inter-arrival window"
212
+ )
213
+
214
+ try:
215
+ await bot.log_channel.send(
216
+ f"🚨 **AUTO-BANNED** {member.mention} ({member.id}) for repeated spam "
217
+ f"({spam_count}/{AUTO_BAN_ALERT_THRESHOLD} within ~{cooldown_duration}s). {alert}"
218
+ )
219
+ except Exception as log_err:
220
+ print(f"Autoban log error: {log_err}")
221
+
222
+ except discord.Forbidden:
223
+ await bot.log_channel.send(
224
+ f"❌ Forbidden when auto-banning {member.mention} β€” check role order / perms."
225
+ )
226
+ except discord.HTTPException as e:
227
+ await bot.log_channel.send(f"❌ HTTPException during auto-ban for {member.mention}: `{e}`")
228
+ except Exception as e:
229
+ await bot.log_channel.send(f"❌ Unexpected error during auto-ban for {member.mention}: `{e}`")
230
+
231
+ # Reset their burst window so we don't double-trigger
232
+ user_cooldowns.pop(member.id, None)
233
+ # ================= END AUTO BAN (hardened) =================
234
+
235
  user_cooldowns[message.author.id]['timestamp'] = message.created_at
236
 
237
  await bot.process_commands(message)
238
 
 
 
239
 
240
  # moderation stuff-----------------------------------------------------------------------------------------------------------------------------------------------------
241