Files
Syntrel/cogs/events/baitbot.py

366 lines
14 KiB
Python
Raw Permalink Normal View History

2025-11-02 18:57:40 -05:00
import discord
from discord.ext import commands
from discord.ext.commands import Context
import asyncio
# Make a pr to add your own server config here, you shouldn't need to touch the rest of the file, please fill in all the values for your own server
BAIT_CONFIGS = {
"SideStore": {
"guild_id": 949183273383395328,
"channel_ids": [
1432134748062482586,
1432204211009097819,
],
"protected_role_id": 959598279685963776,
"log_channel_id": 1433532504647667823,
},
"neotest": {
"guild_id": 1069946178659160076,
"channel_ids": [
1432175690270118012,
1433987189670281278,
1433988339031080991,
],
"protected_role_id": 1432165329483857940,
"log_channel_id": 1433987853184139365,
},
"idevice": {
"guild_id": 1329314147434758175,
"channel_ids": [
1434317669695492177,
],
"protected_role_id": 1333666918548111373,
"log_channel_id": 1333673259446571022,
},
"melonx": {
"guild_id": 1300369899704680479,
"channel_ids": [
1434327970679492830,
],
"protected_role_id": 1300372178138697758,
"log_channel_id": 1300374786471366696,
},
}
2025-11-02 23:32:52 -05:00
BAN_REASON = "Detected bot/scammer in bait channel"
2025-11-02 18:57:40 -05:00
def has_protected_role():
async def predicate(context: Context):
if not context.guild:
2025-11-02 23:32:52 -05:00
context.bot.logger.warning(
f"[BAITBOT] Unauthorized baitbot command attempt by {context.author} ({context.author.id}) in DMs"
)
2025-11-02 18:57:40 -05:00
embed = discord.Embed(
title="Permission Denied",
description="You don't have permission to use this command.",
2025-11-02 23:32:52 -05:00
color=0xE02B2B,
)
embed.set_author(
name="Events", icon_url="https://yes.nighty.works/raw/C8Hh6o.png"
2025-11-02 18:57:40 -05:00
)
await context.send(embed=embed, ephemeral=True)
return False
2025-11-02 23:32:52 -05:00
if not hasattr(context.author, "roles"):
context.bot.logger.warning(
f"[BAITBOT] Unauthorized baitbot command attempt by {context.author} ({context.author.id}) in {context.guild.name} - no roles"
)
2025-11-02 18:57:40 -05:00
embed = discord.Embed(
title="Permission Denied",
description="You don't have permission to use this command.",
2025-11-02 23:32:52 -05:00
color=0xE02B2B,
)
embed.set_author(
name="Events", icon_url="https://yes.nighty.works/raw/C8Hh6o.png"
2025-11-02 18:57:40 -05:00
)
await context.send(embed=embed, ephemeral=True)
return False
2025-11-02 23:32:52 -05:00
2025-11-02 18:57:40 -05:00
for config in BAIT_CONFIGS.values():
protected_role_id = config.get("protected_role_id")
if protected_role_id:
protected_role = context.guild.get_role(protected_role_id)
if protected_role:
for role in context.author.roles:
2025-11-02 23:32:52 -05:00
if (
role.position >= protected_role.position
and role.id != context.guild.default_role.id
):
2025-11-02 18:57:40 -05:00
return True
2025-11-02 23:32:52 -05:00
context.bot.logger.warning(
f"[BAITBOT] Unauthorized baitbot command attempt by {context.author} ({context.author.id}) in {context.guild.name} - insufficient role permissions"
)
2025-11-02 18:57:40 -05:00
embed = discord.Embed(
title="Permission Denied",
description="You don't have permission to use this command.",
2025-11-02 23:32:52 -05:00
color=0xE02B2B,
)
embed.set_author(
name="Events", icon_url="https://yes.nighty.works/raw/C8Hh6o.png"
2025-11-02 18:57:40 -05:00
)
await context.send(embed=embed, ephemeral=True)
return False
2025-11-02 23:32:52 -05:00
2025-11-02 18:57:40 -05:00
return commands.check(predicate)
2025-11-02 23:32:52 -05:00
2025-11-02 18:57:40 -05:00
def baitbot_command():
async def wrapper(self, context: Context):
embed = discord.Embed(
title="Bait Bot",
description="Bans people who post in a specific channel.",
2025-11-02 23:32:52 -05:00
color=0x7289DA,
)
embed.set_author(
name="Events", icon_url="https://yes.nighty.works/raw/C8Hh6o.png"
2025-11-02 18:57:40 -05:00
)
found_config = False
if BAIT_CONFIGS:
for name, config in BAIT_CONFIGS.items():
guild_id = config.get("guild_id")
if context.guild and guild_id == context.guild.id:
channel_ids = config.get("channel_ids", [])
if not channel_ids:
channel_id = config.get("channel_id")
if channel_id:
channel_ids = [channel_id]
role_id = config.get("protected_role_id", "Not set")
channel_displays = []
for channel_id in channel_ids:
channel = context.guild.get_channel(channel_id)
2025-11-02 23:32:52 -05:00
channel_display = (
f"<#{channel_id}> (`{channel_id}`)"
if channel
else f"`{channel_id}`"
)
2025-11-02 18:57:40 -05:00
channel_displays.append(channel_display)
2025-11-02 23:32:52 -05:00
channels_text = (
"\n".join(channel_displays) if channel_displays else "Not set"
)
2025-11-02 18:57:40 -05:00
role = context.guild.get_role(role_id)
2025-11-02 23:32:52 -05:00
role_display = (
f"<@&{role_id}> (`{role_id}`)" if role else f"`{role_id}`"
)
2025-11-02 18:57:40 -05:00
log_channel_id = config.get("log_channel_id")
log_channel = None
if log_channel_id:
log_channel = context.guild.get_channel(log_channel_id)
2025-11-02 23:32:52 -05:00
log_display = (
f"<#{log_channel_id}> (`{log_channel_id}`)"
if log_channel
else (f"`{log_channel_id}`" if log_channel_id else "Not set")
)
2025-11-02 18:57:40 -05:00
embed.add_field(
name="\u200b",
value=f"Channels:\n{channels_text}\n\nProtected Role:\n{role_display}\n\nLog Channel:\n{log_display}",
2025-11-02 23:32:52 -05:00
inline=False,
2025-11-02 18:57:40 -05:00
)
found_config = True
if not found_config:
embed.add_field(
name="No Configurations",
value="No bait channels configured for this server",
2025-11-02 23:32:52 -05:00
inline=False,
2025-11-02 18:57:40 -05:00
)
if context.guild and context.guild.icon:
embed.set_thumbnail(url=context.guild.icon.url)
await context.send(embed=embed)
2025-11-02 23:32:52 -05:00
2025-11-02 18:57:40 -05:00
return wrapper
2025-11-02 23:32:52 -05:00
2025-11-02 18:57:40 -05:00
class BaitBotListener(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.Cog.listener()
async def on_message(self, message: discord.Message):
if message.guild is None:
return
2025-11-02 23:32:52 -05:00
2025-11-02 18:57:40 -05:00
if message.author.bot:
return
2025-11-02 23:32:52 -05:00
2025-11-02 18:57:40 -05:00
bait_config = None
config_name = None
for name, config in BAIT_CONFIGS.items():
if message.guild.id != config.get("guild_id"):
continue
2025-11-02 23:32:52 -05:00
2025-11-02 18:57:40 -05:00
channel_ids = config.get("channel_ids", [])
if not channel_ids:
channel_id = config.get("channel_id")
if channel_id:
channel_ids = [channel_id]
2025-11-02 23:32:52 -05:00
2025-11-02 18:57:40 -05:00
if message.channel.id in channel_ids:
bait_config = config
config_name = name
break
2025-11-02 23:32:52 -05:00
2025-11-02 18:57:40 -05:00
if not bait_config:
return
2025-11-02 23:32:52 -05:00
2025-11-02 18:57:40 -05:00
protected_role_id = bait_config.get("protected_role_id")
is_protected = False
2025-11-02 23:32:52 -05:00
if protected_role_id and hasattr(message.author, "roles"):
2025-11-02 18:57:40 -05:00
protected_role = message.guild.get_role(protected_role_id)
if protected_role:
for role in message.author.roles:
2025-11-02 23:32:52 -05:00
if (
role.position >= protected_role.position
and role.id != message.guild.default_role.id
):
self.bot.logger.info(
f"[BAITBOT] Skipped banning {message.author} ({message.author.id}) in #{message.channel.name}: protected role ({role.name})"
)
2025-11-02 18:57:40 -05:00
is_protected = True
break
2025-11-02 23:32:52 -05:00
2025-11-02 18:57:40 -05:00
message_content = message.content if message.content else "*No text content*"
message_attachments = message.attachments
2025-11-02 23:32:52 -05:00
2025-11-02 18:57:40 -05:00
try:
await message.delete()
2025-11-02 23:32:52 -05:00
self.bot.logger.info(
f"[BAITBOT] Deleted message from {message.author} in #{message.channel.name}"
)
2025-11-02 18:57:40 -05:00
except Exception as e:
2025-11-02 23:32:52 -05:00
self.bot.logger.warning(
f"[BAITBOT] Could not delete message from {message.author}: {e}"
)
2025-11-02 18:57:40 -05:00
banned = False
if not is_protected:
try:
2025-11-02 23:32:52 -05:00
self.bot.logger.warning(
f"[BAITBOT] Detected user in bait channel [{config_name}]: {message.author.name} ({message.author.id}) in #{message.channel.name}"
)
2025-11-02 18:57:40 -05:00
if not message.guild.me.guild_permissions.ban_members:
2025-11-02 23:32:52 -05:00
self.bot.logger.error(
f"[BAITBOT] No permission to ban members in {message.guild.name}"
)
2025-11-02 18:57:40 -05:00
else:
try:
2025-11-02 23:32:52 -05:00
await message.author.ban(
reason=BAN_REASON, delete_message_days=7
)
self.bot.logger.info(
f"[BAITBOT] Banned {message.author.name} - deleted messages from last 7 days"
)
2025-11-02 18:57:40 -05:00
banned = True
except discord.Forbidden:
2025-11-02 23:32:52 -05:00
self.bot.logger.error(
f"[BAITBOT] Could not ban {message.author.name}: missing permissions"
)
2025-11-02 18:57:40 -05:00
except Exception as e:
2025-11-02 23:32:52 -05:00
self.bot.logger.error(
f"[BAITBOT] Error banning {message.author.name}: {e}"
)
2025-11-02 18:57:40 -05:00
if banned:
await asyncio.sleep(2)
try:
2025-11-02 23:32:52 -05:00
await message.guild.unban(
message.author, reason="Auto-unban after cleanup"
)
self.bot.logger.info(
f"[BAITBOT] Unbanned {message.author.name} - cleanup complete"
)
2025-11-02 18:57:40 -05:00
except Exception as e:
2025-11-02 23:32:52 -05:00
self.bot.logger.error(
f"[BAITBOT] Error unbanning {message.author.name}: {e}"
)
2025-11-02 18:57:40 -05:00
except Exception as e:
2025-11-02 23:32:52 -05:00
self.bot.logger.error(f"[BAITBOT] Error handling bait message: {e}")
2025-11-02 18:57:40 -05:00
log_channel_id = bait_config.get("log_channel_id")
if log_channel_id:
try:
log_channel = self.bot.get_channel(log_channel_id)
if log_channel:
2025-11-02 23:32:52 -05:00
action_text = (
"Message deleted (user banned and unbanned)"
if banned
else "Message deleted (protected user)"
if is_protected
else "Message deleted"
)
2025-11-02 18:57:40 -05:00
log_embed = discord.Embed(
title="Bait Bot",
description=action_text,
color=0xE02B2B,
2025-11-02 23:32:52 -05:00
timestamp=message.created_at,
)
log_embed.set_author(
name=str(message.author),
icon_url=message.author.display_avatar.url,
)
log_embed.add_field(
name="User", value=message.author.mention, inline=True
2025-11-02 18:57:40 -05:00
)
2025-11-02 23:32:52 -05:00
log_embed.add_field(
name="Channel", value=message.channel.mention, inline=True
)
2025-11-02 18:57:40 -05:00
combined_content = []
if message_content and message_content != "*No text content*":
combined_content.append(message_content)
2025-11-02 23:32:52 -05:00
2025-11-02 18:57:40 -05:00
image_url = None
if message_attachments:
for attachment in message_attachments:
2025-11-02 23:32:52 -05:00
if (
attachment.content_type
and attachment.content_type.startswith("image/")
):
2025-11-02 18:57:40 -05:00
if not image_url:
image_url = attachment.url
combined_content.append(attachment.filename)
2025-11-02 23:32:52 -05:00
content_text = (
"\n".join(combined_content)
if combined_content
else "*No content*"
)
2025-11-02 18:57:40 -05:00
if len(content_text) > 1000:
content_text = content_text[:997] + "..."
2025-11-02 23:32:52 -05:00
log_embed.add_field(
name="Content", value=f"```\n{content_text}\n```", inline=False
)
2025-11-02 18:57:40 -05:00
if image_url:
log_embed.set_image(url=image_url)
2025-11-02 23:32:52 -05:00
2025-11-02 18:57:40 -05:00
log_embed.set_footer(text=f"Message ID: {message.id}")
2025-11-02 23:32:52 -05:00
2025-11-02 18:57:40 -05:00
try:
await log_channel.send(embed=log_embed)
2025-11-02 23:32:52 -05:00
self.bot.logger.info(
f"[BAITBOT] Sent log to #{log_channel.name}"
)
2025-11-02 18:57:40 -05:00
except discord.Forbidden:
2025-11-02 23:32:52 -05:00
self.bot.logger.error(
f"[BAITBOT] No permission to send log to #{log_channel.name}"
)
2025-11-02 18:57:40 -05:00
except Exception as e:
2025-11-02 23:32:52 -05:00
self.bot.logger.error(f"[BAITBOT] Error sending log: {e}")
2025-11-02 18:57:40 -05:00
else:
2025-11-02 23:32:52 -05:00
self.bot.logger.warning(
f"[BAITBOT] Log channel {log_channel_id} not found"
)
2025-11-02 18:57:40 -05:00
except Exception as e:
2025-11-02 23:32:52 -05:00
self.bot.logger.error(f"[BAITBOT] Error handling log channel: {e}")