Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 91 additions & 5 deletions am_bot/cogs/quarantine.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,17 @@
from difflib import SequenceMatcher

import discord
from discord import app_commands
from discord.ext import commands

from am_bot.constants import (
QUARANTINE_HONEYPOT_CHANNEL_ID,
QUARANTINE_ROLE_ID,
STAFF_ROLE_ID,
)

logger = logging.getLogger(__name__)

QUARANTINE_HONEYPOT_CHANNEL_ID = int(
os.getenv("QUARANTINE_HONEYPOT_CHANNEL_ID", 0)
)
QUARANTINE_ROLE_ID = int(os.getenv("QUARANTINE_ROLE_ID", 0))
logger = logging.getLogger(__name__)

# Spam detection configuration
# Minimum similarity ratio (0.0 to 1.0) to consider messages as duplicates
Expand Down Expand Up @@ -307,3 +309,87 @@ async def on_message(self, message: discord.Message):

# Record the message for future spam detection
self._record_message(message)

def _is_staff(self, member: discord.Member) -> bool:
"""Check if a member has the staff role."""
if STAFF_ROLE_ID == 0:
return False
return any(role.id == STAFF_ROLE_ID for role in member.roles)

@app_commands.command(
name="quarantine",
description="Quarantine a user and purge their recent messages",
)
@app_commands.describe(
member="The member to quarantine", reason="Reason for the quarantine"
)
@app_commands.default_permissions(manage_roles=True)
async def quarantine_command(
self,
interaction: discord.Interaction,
member: discord.Member,
reason: str | None = None,
) -> None:
"""Slash command for staff to manually quarantine a user."""
# Check if user has staff role
if not self._is_staff(interaction.user):
await interaction.response.send_message(
"You must be staff to use this command.", ephemeral=True
)
return

reason = reason or "Manual quarantine by staff"
full_reason = f"{reason} (by {interaction.user})"

# Don't allow quarantining bots
if member.bot:
await interaction.response.send_message(
"Cannot quarantine bots.", ephemeral=True
)
return

# Don't allow self-quarantine
if member.id == interaction.user.id:
await interaction.response.send_message(
"You cannot quarantine yourself.", ephemeral=True
)
return

# Defer the response since purging may take time
await interaction.response.defer(ephemeral=True)

logger.info(
f"Manual quarantine initiated for {member} ({member.id}) "
f"by {interaction.user} ({interaction.user.id}): {reason}"
)

success = await self._assign_quarantine_role(
member, interaction.guild, full_reason
)

if not success:
await interaction.followup.send(
"Failed to assign quarantine role. Check bot permissions.",
ephemeral=True,
)
return

deleted_count = await self._purge_member_messages(
member, interaction.guild
)

# Clear their message history from memory
if member.id in self.message_history:
del self.message_history[member.id]

logger.info(
f"Manual quarantine complete for {member} ({member.id}). "
f"Deleted {deleted_count} messages from the last hour."
)

await interaction.followup.send(
f"✅ Quarantined {member.mention}.\n"
f"Deleted {deleted_count} messages from the last hour.\n"
f"Reason: {reason}",
ephemeral=True,
)
3 changes: 3 additions & 0 deletions am_bot/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
MODDER_ROLE_ID = 190385081523765248
MAPPER_ROLE_ID = 190385107297632257
WORKSHOP_ROLE_ID = 770207045357797378
STAFF_ROLE_ID = 322496447687819264
QUARANTINE_ROLE_ID = 886883973463166996

# Channel IDs
MODDER_STATS_CHANNEL_ID = 877564476315029525
Expand All @@ -14,3 +16,4 @@
WORKSHOP_TEXT_CHANNEL_ID = 770198077943971880
STARBOARD_TEXT_CHANNEL_ID = 863887933089906718
INVITE_HELP_TEXT_CHANNEL_ID = 372253844953890817
QUARANTINE_HONEYPOT_CHANNEL_ID = 1453143051332616223
9 changes: 0 additions & 9 deletions helm/am-bot/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,6 @@ spec:
name: {{ include "am-bot.awsSecretName" . }}
key: AWS_DEFAULT_REGION
{{- end }}
{{- /* Quarantine honeypot configuration */}}
{{- if .Values.quarantine.honeypotChannelId }}
- name: QUARANTINE_HONEYPOT_CHANNEL_ID
value: {{ .Values.quarantine.honeypotChannelId | quote }}
{{- end }}
{{- if .Values.quarantine.roleId }}
- name: QUARANTINE_ROLE_ID
value: {{ .Values.quarantine.roleId | quote }}
{{- end }}
{{- /* Spam detection configuration */}}
{{- if .Values.spamDetection.similarityThreshold }}
- name: SPAM_SIMILARITY_THRESHOLD
Expand Down
8 changes: 0 additions & 8 deletions helm/am-bot/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,6 @@ aws:
# AWS_SECRET_ACCESS_KEY: ""
# AWS_DEFAULT_REGION: ""

# Quarantine honeypot configuration
# Set these to enable the quarantine feature
quarantine:
# Channel ID that acts as the honeypot trap
honeypotChannelId: ""
# Role ID to assign to users who trigger the honeypot
roleId: ""

# Spam detection configuration
spamDetection:
# Similarity threshold (0.0-1.0) for detecting duplicate messages
Expand Down
Loading