Skip to content

Commit 3ba7337

Browse files
committed
Add spam-bait module.
1 parent 0a87c5d commit 3ba7337

File tree

4 files changed

+123
-4
lines changed

4 files changed

+123
-4
lines changed

nameless/command/honeypot.py

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import contextlib
2+
import logging
3+
4+
import discord
5+
import discord.ui
6+
from discord.ext import commands
7+
from prisma.models import Guild
8+
9+
from nameless import Nameless
10+
from nameless.custom.cache import nameless_cache
11+
from nameless.custom.prisma import NamelessPrisma
12+
from nameless.utils import create_cache_key
13+
14+
__all__ = ["HoneypotCommand"]
15+
16+
17+
class HoneypotCommand(commands.Cog):
18+
def __init__(self, bot: Nameless):
19+
self.bot: Nameless = bot
20+
21+
def _create_honeypot_cache_key(self, this_guild: discord.Guild) -> str:
22+
"""Create honeypot cache key."""
23+
return create_cache_key("honeypot", str(this_guild.id))
24+
25+
@commands.Cog.listener()
26+
async def on_message(self, message: discord.Message):
27+
assert message.author is not None
28+
assert message.guild is not None
29+
assert message.channel is not None
30+
assert self.bot.user is not None
31+
32+
if not nameless_cache.get_key(self._create_honeypot_cache_key(message.guild)):
33+
return
34+
35+
# don't ban self, let admin do it.
36+
if message.author.id == self.bot.user.id:
37+
return
38+
39+
assert isinstance(message.author, discord.Member)
40+
41+
db_guild = await Guild.prisma().find_unique_or_raise(
42+
where={"Id": message.guild.id}
43+
)
44+
45+
if message.channel.id == db_guild.HoneypotChannelId:
46+
with contextlib.suppress(discord.errors.Forbidden):
47+
await message.author.ban(
48+
delete_message_days=0,
49+
reason="Chat in spam bait channel.",
50+
)
51+
52+
@commands.hybrid_group(fallback="activate")
53+
@commands.guild_only()
54+
@commands.has_guild_permissions(manage_guild=True)
55+
@commands.bot_has_guild_permissions(manage_channels=True)
56+
async def honeypot(self, ctx: commands.Context[Nameless]):
57+
"""Create a spam-bait channel."""
58+
await ctx.defer()
59+
60+
assert ctx.guild is not None
61+
62+
await NamelessPrisma.get_guild_entry(ctx.guild)
63+
64+
if nameless_cache.get_key(self._create_honeypot_cache_key(ctx.guild)):
65+
await ctx.send("You already activated the honeypot.")
66+
return
67+
68+
created_channel = await ctx.guild.create_text_channel(
69+
"spam-goes-here", reason="Spam-bait activation."
70+
)
71+
72+
await created_channel.send("# DO NOT TEXT IN HERE, YOU WILL BE BANNED.")
73+
74+
await Guild.prisma().update_many(
75+
data={"HoneypotChannelId": created_channel.id}, where={"Id": ctx.guild.id}
76+
)
77+
78+
nameless_cache.set_key(self._create_honeypot_cache_key(ctx.guild))
79+
80+
await ctx.send(
81+
f"Created spam-bait channel {created_channel.mention}. "
82+
+ "Make sure everyone does not *accidentally* chat in it. "
83+
)
84+
85+
@honeypot.command()
86+
@commands.guild_only()
87+
@commands.has_guild_permissions(manage_guild=True)
88+
async def deactivate(self, ctx: commands.Context[Nameless]):
89+
"""Deactivate spam-bait."""
90+
await ctx.defer()
91+
92+
assert ctx.guild is not None
93+
94+
if not nameless_cache.get_key(self._create_honeypot_cache_key(ctx.guild)):
95+
await ctx.send("You don't have spam-bait activated.")
96+
return
97+
98+
await NamelessPrisma.get_guild_entry(ctx.guild)
99+
db_guild = await Guild.prisma().find_unique_or_raise(where={"Id": ctx.guild.id})
100+
101+
created_channel = await ctx.guild.fetch_channel(db_guild.HoneypotChannelId)
102+
103+
nameless_cache.invalidate_key(self._create_honeypot_cache_key(ctx.guild))
104+
await created_channel.delete()
105+
106+
await ctx.send(f"Deleted spam-bait channel `#{created_channel.name}`.")
107+
108+
109+
async def setup(bot: Nameless):
110+
await bot.add_cog(HoneypotCommand(bot))
111+
logging.info("%s added!", __name__)
112+
113+
114+
async def teardown(bot: Nameless):
115+
await bot.remove_cog(HoneypotCommand.__cog_name__)
116+
logging.warning("%s removed!", __name__)

nameless/custom/prisma.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ async def dispose():
2828
async def get_guild_entry(guild: discord.Guild) -> models.Guild:
2929
"""Create a Prisma Guild entry if not exist."""
3030
return await _raw_db.guild.upsert(
31-
where={"Id": guild.id}, data={"create": {"Id": guild.id}, "update": {}}
31+
where={"Id": guild.id},
32+
data={"create": {"Id": guild.id, "HoneypotChannelId": 0}, "update": {}},
3233
)
3334

3435
@staticmethod

nameless/nameless.py

+1
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ def get_needed_permissions() -> Permissions:
9999
perms.connect = True
100100
perms.speak = True
101101
perms.use_voice_activation = True
102+
perms.manage_channels = True
102103

103104
return perms
104105

prisma/schema.prisma

+4-3
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ model User {
1414
}
1515

1616
model Guild {
17-
Id BigInt @id
18-
HostedChats CrossChatRoom[]
19-
ConnectedChats CrossChatConnection[]
17+
Id BigInt @id
18+
HoneypotChannelId BigInt
19+
HostedChats CrossChatRoom[]
20+
ConnectedChats CrossChatConnection[]
2021
}
2122

2223
model CrossChatRoom {

0 commit comments

Comments
 (0)