From 91830e1f494d90394506d009c90f998bed19d3e0 Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 19 Nov 2024 23:16:15 +0200 Subject: [PATCH 1/8] added permafk command --- prisma/schema.prisma | 3 +- tux/cogs/utility/afk.py | 3 +- tux/cogs/utility/permafk.py | 55 ++++++++++++++++++++++++++++ tux/database/controllers/__init__.py | 1 + tux/database/controllers/afk.py | 18 ++++++++- 5 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 tux/cogs/utility/permafk.py diff --git a/prisma/schema.prisma b/prisma/schema.prisma index b94708ff..f9ae8a8c 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -125,6 +125,7 @@ model AFKModel { reason String since DateTime @default(now()) guild_id BigInt + perma_afk Boolean @default(false) guild Guild @relation(fields: [guild_id], references: [guild_id]) @@unique([member_id, guild_id]) @@ -187,4 +188,4 @@ enum CaseType { UNTEMPBAN POLLBAN POLLUNBAN -} +} \ No newline at end of file diff --git a/tux/cogs/utility/afk.py b/tux/cogs/utility/afk.py index 7306b258..aae4207e 100644 --- a/tux/cogs/utility/afk.py +++ b/tux/cogs/utility/afk.py @@ -90,7 +90,8 @@ async def remove_afk(self, message: discord.Message) -> None: if entry.since + timedelta(seconds=10) > datetime.now(ZoneInfo("UTC")): return - + if await self.db.is_perma_afk(message.author.id, guild_id=message.guild.id): + return assert isinstance(message.author, discord.Member) await self.db.remove_afk(message.author.id) diff --git a/tux/cogs/utility/permafk.py b/tux/cogs/utility/permafk.py new file mode 100644 index 00000000..c5941604 --- /dev/null +++ b/tux/cogs/utility/permafk.py @@ -0,0 +1,55 @@ +import contextlib +import textwrap + +import discord +from discord.ext import commands + +from tux.bot import Tux +from tux.database.controllers import AfkController +from tux.utils.constants import CONST +from tux.utils.flags import generate_usage + + +class PERMAFK(commands.Cog): + def __init__(self, bot: Tux) -> None: + self.bot = bot + self.db = AfkController() + self.permafk.usage = generate_usage(self.permafk) + + async def remove_afk(self, target: int) -> None: + await self.db.remove_afk(target) + + @commands.hybrid_command(name="permafk") + @commands.guild_only() + async def permafk(self, ctx: commands.Context[Tux], *, reason: str = "No reason.") -> discord.Message: + target = ctx.author + assert ctx.guild + assert isinstance(target, discord.Member) + if await self.db.is_afk(target.id, guild_id=ctx.guild.id): + await self.remove_afk(target.id) + return await ctx.send("Welcome back!") + + if len(target.display_name) >= CONST.NICKNAME_MAX_LENGTH - 6: + truncated_name = f"{target.display_name[: CONST.NICKNAME_MAX_LENGTH - 9]}..." + new_name = f"[AFK] {truncated_name}" + else: + new_name = f"[AFK] {target.display_name}" + + shortened_reason = textwrap.shorten(reason, width=100, placeholder="...") + await self.db.insert_afk(target.id, target.display_name, shortened_reason, ctx.guild.id, True) + + with contextlib.suppress(discord.Forbidden): + await target.edit(nick=new_name) + return await ctx.send( + content="\N{SLEEPING SYMBOL} || You are now permanently afk! To remove afk run this command again." + + f"Reason: `{shortened_reason}`", + allowed_mentions=discord.AllowedMentions( + users=False, + everyone=False, + roles=False, + ), + ) + + +async def setup(bot: Tux): + await bot.add_cog(PERMAFK(bot)) diff --git a/tux/database/controllers/__init__.py b/tux/database/controllers/__init__.py index b1c5b60a..3be2b854 100644 --- a/tux/database/controllers/__init__.py +++ b/tux/database/controllers/__init__.py @@ -17,5 +17,6 @@ def __init__(self): self.guild = GuildController() self.guild_config = GuildConfigController() self.afk = AfkController() + self.permafk = AfkController() self.starboard = StarboardController() self.starboard_message = StarboardMessageController() diff --git a/tux/database/controllers/afk.py b/tux/database/controllers/afk.py index 5e54c047..ad2b2807 100644 --- a/tux/database/controllers/afk.py +++ b/tux/database/controllers/afk.py @@ -22,7 +22,22 @@ async def is_afk(self, member_id: int, *, guild_id: int) -> bool: entry = await self.get_afk_member(member_id, guild_id=guild_id) return entry is not None - async def insert_afk(self, member_id: int, nickname: str, reason: str, guild_id: int) -> AFKModel: + async def is_perma_afk(self, member_id: int, *, guild_id: int) -> bool: + is_user_perma_afk = await self.table.find_first( + where={"member_id": member_id, "guild_id": guild_id, "perma_afk": True}, + ) + if is_user_perma_afk is None: + return is_user_perma_afk is not None + return True + + async def insert_afk( + self, + member_id: int, + nickname: str, + reason: str, + guild_id: int, + perma_afk: bool = False, + ) -> AFKModel: await self.ensure_guild_exists(guild_id) return await self.table.create( @@ -31,6 +46,7 @@ async def insert_afk(self, member_id: int, nickname: str, reason: str, guild_id: "nickname": nickname, "reason": reason, "guild_id": guild_id, + "perma_afk": perma_afk, }, ) From 689f0690bc8721b516783e9223e97969353a9dcc Mon Sep 17 00:00:00 2001 From: Luna Date: Wed, 20 Nov 2024 18:44:32 +0200 Subject: [PATCH 2/8] made code more readable and fixed some issues --- tux/database/controllers/__init__.py | 1 - tux/database/controllers/afk.py | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/tux/database/controllers/__init__.py b/tux/database/controllers/__init__.py index 3be2b854..b1c5b60a 100644 --- a/tux/database/controllers/__init__.py +++ b/tux/database/controllers/__init__.py @@ -17,6 +17,5 @@ def __init__(self): self.guild = GuildController() self.guild_config = GuildConfigController() self.afk = AfkController() - self.permafk = AfkController() self.starboard = StarboardController() self.starboard_message = StarboardMessageController() diff --git a/tux/database/controllers/afk.py b/tux/database/controllers/afk.py index ad2b2807..b0a5156d 100644 --- a/tux/database/controllers/afk.py +++ b/tux/database/controllers/afk.py @@ -26,9 +26,7 @@ async def is_perma_afk(self, member_id: int, *, guild_id: int) -> bool: is_user_perma_afk = await self.table.find_first( where={"member_id": member_id, "guild_id": guild_id, "perma_afk": True}, ) - if is_user_perma_afk is None: - return is_user_perma_afk is not None - return True + return is_user_perma_afk is not None async def insert_afk( self, From e31d59cef3f215711083e9ddf72194a9593708fe Mon Sep 17 00:00:00 2001 From: Luna Date: Wed, 20 Nov 2024 18:45:26 +0200 Subject: [PATCH 3/8] made code more readable and fixed some issue --- tux/cogs/utility/permafk.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tux/cogs/utility/permafk.py b/tux/cogs/utility/permafk.py index c5941604..cf35f072 100644 --- a/tux/cogs/utility/permafk.py +++ b/tux/cogs/utility/permafk.py @@ -22,6 +22,16 @@ async def remove_afk(self, target: int) -> None: @commands.hybrid_command(name="permafk") @commands.guild_only() async def permafk(self, ctx: commands.Context[Tux], *, reason: str = "No reason.") -> discord.Message: + """ + Set yourself permanently AFK so it doesnt remove your afk status if you send a message. + + Parameters + ---------- + ctx : commands.Context[Tux] + The context of the command. + reason : str, optional + The reason you are AFK. + """ target = ctx.author assert ctx.guild assert isinstance(target, discord.Member) From 3cab29a5e7bdc0503bdf862f2d32e52d4ca32d8b Mon Sep 17 00:00:00 2001 From: kzndotsh Date: Wed, 20 Nov 2024 14:58:36 -0500 Subject: [PATCH 4/8] style(afk.py): change class name from AFK to Afk to follow PEP 8 naming conventions --- tux/cogs/utility/afk.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tux/cogs/utility/afk.py b/tux/cogs/utility/afk.py index aae4207e..dc0857e8 100644 --- a/tux/cogs/utility/afk.py +++ b/tux/cogs/utility/afk.py @@ -14,7 +14,7 @@ from tux.utils.flags import generate_usage -class AFK(commands.Cog): +class Afk(commands.Cog): def __init__(self, bot: Tux) -> None: self.bot = bot self.db = AfkController() @@ -144,4 +144,4 @@ async def check_afk(self, message: discord.Message) -> None: async def setup(bot: Tux): - await bot.add_cog(AFK(bot)) + await bot.add_cog(Afk(bot)) From 52c89f577d23c884ff2741f54ef9c411d38be151 Mon Sep 17 00:00:00 2001 From: Luna Date: Wed, 20 Nov 2024 22:19:11 +0200 Subject: [PATCH 5/8] fixed naming issues --- prisma/schema.prisma | 2 +- tux/cogs/utility/afk.py | 2 +- tux/cogs/utility/permafk.py | 6 +++--- tux/database/controllers/afk.py | 10 +++++----- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index f9ae8a8c..8c9eb83a 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -125,7 +125,7 @@ model AFKModel { reason String since DateTime @default(now()) guild_id BigInt - perma_afk Boolean @default(false) + perm_afk Boolean @default(false) guild Guild @relation(fields: [guild_id], references: [guild_id]) @@unique([member_id, guild_id]) diff --git a/tux/cogs/utility/afk.py b/tux/cogs/utility/afk.py index dc0857e8..92fefac2 100644 --- a/tux/cogs/utility/afk.py +++ b/tux/cogs/utility/afk.py @@ -90,7 +90,7 @@ async def remove_afk(self, message: discord.Message) -> None: if entry.since + timedelta(seconds=10) > datetime.now(ZoneInfo("UTC")): return - if await self.db.is_perma_afk(message.author.id, guild_id=message.guild.id): + if await self.db.is_perm_afk(message.author.id, guild_id=message.guild.id): return assert isinstance(message.author, discord.Member) diff --git a/tux/cogs/utility/permafk.py b/tux/cogs/utility/permafk.py index cf35f072..8818ac05 100644 --- a/tux/cogs/utility/permafk.py +++ b/tux/cogs/utility/permafk.py @@ -10,7 +10,7 @@ from tux.utils.flags import generate_usage -class PERMAFK(commands.Cog): +class PermAfk(commands.Cog): def __init__(self, bot: Tux) -> None: self.bot = bot self.db = AfkController() @@ -51,7 +51,7 @@ async def permafk(self, ctx: commands.Context[Tux], *, reason: str = "No reason. with contextlib.suppress(discord.Forbidden): await target.edit(nick=new_name) return await ctx.send( - content="\N{SLEEPING SYMBOL} || You are now permanently afk! To remove afk run this command again." + content="\N{SLEEPING SYMBOL} || You are now permanently afk! To remove afk run this command again. " + f"Reason: `{shortened_reason}`", allowed_mentions=discord.AllowedMentions( users=False, @@ -62,4 +62,4 @@ async def permafk(self, ctx: commands.Context[Tux], *, reason: str = "No reason. async def setup(bot: Tux): - await bot.add_cog(PERMAFK(bot)) + await bot.add_cog(PermAfk(bot)) diff --git a/tux/database/controllers/afk.py b/tux/database/controllers/afk.py index b0a5156d..6577eabe 100644 --- a/tux/database/controllers/afk.py +++ b/tux/database/controllers/afk.py @@ -22,11 +22,11 @@ async def is_afk(self, member_id: int, *, guild_id: int) -> bool: entry = await self.get_afk_member(member_id, guild_id=guild_id) return entry is not None - async def is_perma_afk(self, member_id: int, *, guild_id: int) -> bool: - is_user_perma_afk = await self.table.find_first( + async def is_perm_afk(self, member_id: int, *, guild_id: int) -> bool: + is_user_perm_afk = await self.table.find_first( where={"member_id": member_id, "guild_id": guild_id, "perma_afk": True}, ) - return is_user_perma_afk is not None + return is_user_perm_afk is not None async def insert_afk( self, @@ -34,7 +34,7 @@ async def insert_afk( nickname: str, reason: str, guild_id: int, - perma_afk: bool = False, + perm_afk: bool = False, ) -> AFKModel: await self.ensure_guild_exists(guild_id) @@ -44,7 +44,7 @@ async def insert_afk( "nickname": nickname, "reason": reason, "guild_id": guild_id, - "perma_afk": perma_afk, + "perma_afk": perm_afk, }, ) From ab9033136b44ad2b61ede37519191bfdc38365af Mon Sep 17 00:00:00 2001 From: Luna Date: Wed, 20 Nov 2024 22:50:29 +0200 Subject: [PATCH 6/8] fixed naming issues --- tux/database/controllers/afk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tux/database/controllers/afk.py b/tux/database/controllers/afk.py index 6577eabe..5c6695cd 100644 --- a/tux/database/controllers/afk.py +++ b/tux/database/controllers/afk.py @@ -44,7 +44,7 @@ async def insert_afk( "nickname": nickname, "reason": reason, "guild_id": guild_id, - "perma_afk": perm_afk, + "perm_afk": perm_afk, }, ) From 7b382f5886bca8dc1be26a3e678478d5b202145b Mon Sep 17 00:00:00 2001 From: Luna Date: Wed, 20 Nov 2024 22:54:17 +0200 Subject: [PATCH 7/8] i am blind --- tux/database/controllers/afk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tux/database/controllers/afk.py b/tux/database/controllers/afk.py index 5c6695cd..c1867dbd 100644 --- a/tux/database/controllers/afk.py +++ b/tux/database/controllers/afk.py @@ -24,7 +24,7 @@ async def is_afk(self, member_id: int, *, guild_id: int) -> bool: async def is_perm_afk(self, member_id: int, *, guild_id: int) -> bool: is_user_perm_afk = await self.table.find_first( - where={"member_id": member_id, "guild_id": guild_id, "perma_afk": True}, + where={"member_id": member_id, "guild_id": guild_id, "perm_afk": True}, ) return is_user_perm_afk is not None From cdd8e23fbc3e32b2eba1060f866b2d601417c6c7 Mon Sep 17 00:00:00 2001 From: kzndotsh Date: Thu, 21 Nov 2024 21:46:47 -0500 Subject: [PATCH 8/8] docs(permafk.py): update permafk command description for clarity Clarify that the permafk status remains until the command is rerun. Add spacing for improved readability and maintainability of the code. --- tux/cogs/utility/permafk.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tux/cogs/utility/permafk.py b/tux/cogs/utility/permafk.py index 8818ac05..7ac0d9dd 100644 --- a/tux/cogs/utility/permafk.py +++ b/tux/cogs/utility/permafk.py @@ -23,7 +23,7 @@ async def remove_afk(self, target: int) -> None: @commands.guild_only() async def permafk(self, ctx: commands.Context[Tux], *, reason: str = "No reason.") -> discord.Message: """ - Set yourself permanently AFK so it doesnt remove your afk status if you send a message. + Set yourself permanently AFK until you rerun the command. Parameters ---------- @@ -32,16 +32,21 @@ async def permafk(self, ctx: commands.Context[Tux], *, reason: str = "No reason. reason : str, optional The reason you are AFK. """ + target = ctx.author + assert ctx.guild assert isinstance(target, discord.Member) + if await self.db.is_afk(target.id, guild_id=ctx.guild.id): await self.remove_afk(target.id) + return await ctx.send("Welcome back!") if len(target.display_name) >= CONST.NICKNAME_MAX_LENGTH - 6: truncated_name = f"{target.display_name[: CONST.NICKNAME_MAX_LENGTH - 9]}..." new_name = f"[AFK] {truncated_name}" + else: new_name = f"[AFK] {target.display_name}" @@ -50,6 +55,7 @@ async def permafk(self, ctx: commands.Context[Tux], *, reason: str = "No reason. with contextlib.suppress(discord.Forbidden): await target.edit(nick=new_name) + return await ctx.send( content="\N{SLEEPING SYMBOL} || You are now permanently afk! To remove afk run this command again. " + f"Reason: `{shortened_reason}`",