From 356176560fde9a692fd0f6e0d7b58b0fd85d8539 Mon Sep 17 00:00:00 2001 From: Kasen Engel <86841460+FluxC0@users.noreply.github.com> Date: Mon, 23 Sep 2024 16:45:12 +0000 Subject: [PATCH 01/12] add pollban command cog --- tux/cogs/moderation/pollban.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tux/cogs/moderation/pollban.py diff --git a/tux/cogs/moderation/pollban.py b/tux/cogs/moderation/pollban.py new file mode 100644 index 000000000..e69de29bb From 06dfab430410a9f8ffe6c7bce949b39867948c03 Mon Sep 17 00:00:00 2001 From: Kasen Engel <86841460+FluxC0@users.noreply.github.com> Date: Mon, 23 Sep 2024 17:28:19 +0000 Subject: [PATCH 02/12] update flags.py to include pollban/unban --- tux/utils/flags.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tux/utils/flags.py b/tux/utils/flags.py index 43785b6bb..f876dc26a 100644 --- a/tux/utils/flags.py +++ b/tux/utils/flags.py @@ -309,3 +309,33 @@ class SnippetUnbanFlags(commands.FlagConverter, case_insensitive=True, delimiter aliases=["s", "quiet"], default=False, ) + + +class PollBanFlags(commands.FlagConverter, case_insensitive=True, delimiter=" ", prefix="-"): + reason: str = commands.flag( + name="reason", + description="Reason for the poll ban.", + aliases=["r"], + default=MISSING, + ) + silent: bool = commands.flag( + name="silent", + description="Do not send a DM to the target.", + aliases=["s", "quiet"], + default=False, + ) + + +class PollUnbanFlags(commands.FlagConverter, case_insensitive=True, delimiter=" ", prefix="-"): + reason: str = commands.flag( + name="reason", + description="Reason for the poll unban", + aliases=["r"], + default=MISSING, + ) + silent: bool = commands.flag( + name="silent", + description="Do not send a DM to the target.", + aliases=["s", "quiet"], + default=False, + ) From 1b5b8c5f483f947090de317c2a98c3ed2a7d73d8 Mon Sep 17 00:00:00 2001 From: Kasen Engel <86841460+FluxC0@users.noreply.github.com> Date: Mon, 23 Sep 2024 17:31:11 +0000 Subject: [PATCH 03/12] update schema.prisma casetype --- prisma/schema.prisma | 2 ++ 1 file changed, 2 insertions(+) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index f5cd1b4fb..cc45cd98a 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -170,4 +170,6 @@ enum CaseType { UNJAIL SNIPPETUNBAN UNTEMPBAN + POLLBAN + POLLUNBAN } From 65466b5b25c6dd98c3487a83140c01c32cbfbd0a Mon Sep 17 00:00:00 2001 From: Kasen Engel <86841460+FluxC0@users.noreply.github.com> Date: Mon, 23 Sep 2024 17:39:32 +0000 Subject: [PATCH 04/12] Added the code, heavily derived off of the snippet ban code. gonna integrate with polls next. --- tux/cogs/moderation/pollban.py | 96 ++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/tux/cogs/moderation/pollban.py b/tux/cogs/moderation/pollban.py index e69de29bb..ac1463932 100644 --- a/tux/cogs/moderation/pollban.py +++ b/tux/cogs/moderation/pollban.py @@ -0,0 +1,96 @@ +import discord +from discord.ext import commands +from loguru import logger + +from prisma.enums import CaseType +from tux.bot import Tux +from tux.database.controllers.case import CaseController +from tux.utils import checks +from tux.utils.flags import PollBanFlags, generate_usage + +from . import ModerationCogBase + + +class PollBan(ModerationCogBase): + def __init__(self, bot: Tux) -> None: + super().__init__(bot) + self.case_controller = CaseController() + self.poll_ban.usage = generate_usage(self.poll_ban, PollBanFlags) + + @commands.hybrid_command( + name="pollban", + aliases=["pb"], + ) + @commands.guild_only() + @checks.has_pl(3) + async def poll_ban( + self, + ctx: commands.Context[Tux], + member: discord.Member, + *, + flags: PollBanFlags, + ) -> None: + """ + Ban a user from creating polls using tux.. + + Parameters + ---------- + ctx : commands.Context[Tux] + The context object. + member : discord.Member + The member to poll ban. + flags : PollBanFlags + The flags for the command. (reason: str, silent: bool) + """ + + assert ctx.guild + + if await self.is_pollbanned(ctx.guild.id, member.id): + await ctx.send("User is already poll banned.", delete_after=30, ephemeral=True) + return + + try: + case = await self.db.case.insert_case( + case_user_id=member.id, + case_moderator_id=ctx.author.id, + case_type=CaseType.POLLBAN, + case_reason=flags.reason, + guild_id=ctx.guild.id, + ) + + except Exception as e: + logger.error(f"Failed to ban {member}. {e}") + await ctx.send(f"Failed to ban {member}. {e}", delete_after=30) + return + + dm_sent = await self.send_dm(ctx, flags.silent, member, flags.reason, "poll banned") + await self.handle_case_response(ctx, CaseType.POLLBAN, case.case_number, flags.reason, member, dm_sent) + + async def is_pollbanned(self, guild_id: int, user_id: int) -> bool: + """ + Check if a user is poll banned. + + Parameters + ---------- + guild_id : int + The ID of the guild to check in. + user_id : int + The ID of the user to check. + + Returns + ------- + bool + True if the user is poll banned, False otherwise. + """ + + ban_cases = await self.case_controller.get_all_cases_by_type(guild_id, CaseType.POLLBAN) + unban_cases = await self.case_controller.get_all_cases_by_type(guild_id, CaseType.POLLUNBAN) + + ban_count = sum(case.case_user_id == user_id for case in ban_cases) + unban_count = sum(case.case_user_id == user_id for case in unban_cases) + + return ban_count > unban_count + + +async def setup(bot: Tux) -> None: + await bot.add_cog(PollBan(bot)) From 7fe7b85f186edcc5c2a61d0de2dd0b6b19b240d0 Mon Sep 17 00:00:00 2001 From: Kasen Engel <86841460+FluxC0@users.noreply.github.com> Date: Mon, 23 Sep 2024 17:58:27 +0000 Subject: [PATCH 05/12] integrate poll banning into poll code, gonna see if this code is working --- tux/cogs/utility/poll.py | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/tux/cogs/utility/poll.py b/tux/cogs/utility/poll.py index 119d53e4b..d26d7df6c 100644 --- a/tux/cogs/utility/poll.py +++ b/tux/cogs/utility/poll.py @@ -3,7 +3,9 @@ from discord.ext import commands from loguru import logger +from prisma.enums import CaseType from tux.bot import Tux +from tux.database.controllers import CaseController from tux.ui.embeds import EmbedCreator # TODO: Create option inputs for the poll command instead of using a comma separated string @@ -12,6 +14,16 @@ class Poll(commands.Cog): def __init__(self, bot: Tux) -> None: self.bot = bot + self.case_controller = CaseController() + + async def is_pollbanned(self, guild_id: int, user_id: int) -> bool: + ban_cases = await self.case_controller.get_all_cases_by_type(guild_id, CaseType.POLLBAN) + unban_cases = await self.case_controller.get_all_cases_by_type(guild_id, CaseType.POLLUNBAN) + + ban_count = sum(case.case_user_id == user_id for case in ban_cases) + unban_count = sum(case.case_user_id == user_id for case in unban_cases) + + return ban_count > unban_count @commands.Cog.listener() # listen for messages async def on_message(self, message: discord.Message) -> None: @@ -40,7 +52,8 @@ async def on_message(self, message: discord.Message) -> None: @commands.Cog.listener() async def on_reaction_add(self, reaction: discord.Reaction, user: discord.User) -> None: # Block any reactions that are not numbers for the poll - + # NOTE: Today we observed in amazing detail that the pure will of 1 too many dedicated discord members can make + # the bot freak out whenever trying to remove reactions. Is there a better solution for this? if reaction.message.embeds: embed = reaction.message.embeds[0] if ( @@ -52,7 +65,13 @@ async def on_reaction_add(self, reaction: discord.Reaction, user: discord.User) @app_commands.command(name="poll", description="Creates a poll.") @app_commands.describe(title="Title of the poll", options="Poll options, comma separated") - async def poll(self, interaction: discord.Interaction, title: str, options: str) -> None: + async def poll( + self, + interaction: discord.Interaction, + title: str, + options: str, + ctx: commands.Context[Tux], + ) -> None: """ Create a poll with a title and options. @@ -65,6 +84,7 @@ async def poll(self, interaction: discord.Interaction, title: str, options: str) options : str The options for the poll, separated by commas. """ + assert ctx.guild # Split the options by comma options_list = options.split(",") @@ -72,6 +92,9 @@ async def poll(self, interaction: discord.Interaction, title: str, options: str) # Remove any leading or trailing whitespaces from the options options_list = [option.strip() for option in options_list] + if await self.is_pollbanned(ctx.guild.id, ctx.author.id): + await ctx.send("You are banned from making polls.") + return # Check if the options count is between 2-9 if len(options_list) < 2 or len(options_list) > 9: embed = EmbedCreator.create_embed( From ce6515782b7818ba7e1a8cc37fb33881a831a39d Mon Sep 17 00:00:00 2001 From: Kasen Engel Date: Mon, 23 Sep 2024 16:25:01 -0500 Subject: [PATCH 06/12] Finish up Pollban code and fix some bugs --- tux/cogs/moderation/pollban.py | 2 +- tux/cogs/utility/poll.py | 23 +++++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/tux/cogs/moderation/pollban.py b/tux/cogs/moderation/pollban.py index ac1463932..131c4d85b 100644 --- a/tux/cogs/moderation/pollban.py +++ b/tux/cogs/moderation/pollban.py @@ -31,7 +31,7 @@ async def poll_ban( flags: PollBanFlags, ) -> None: """ - Ban a user from creating polls using tux.. + Ban a user from creating polls using tux. Parameters ---------- diff --git a/tux/cogs/utility/poll.py b/tux/cogs/utility/poll.py index d26d7df6c..73e8ed09b 100644 --- a/tux/cogs/utility/poll.py +++ b/tux/cogs/utility/poll.py @@ -65,13 +65,7 @@ async def on_reaction_add(self, reaction: discord.Reaction, user: discord.User) @app_commands.command(name="poll", description="Creates a poll.") @app_commands.describe(title="Title of the poll", options="Poll options, comma separated") - async def poll( - self, - interaction: discord.Interaction, - title: str, - options: str, - ctx: commands.Context[Tux], - ) -> None: + async def poll(self, interaction: discord.Interaction, title: str, options: str) -> None: """ Create a poll with a title and options. @@ -83,8 +77,9 @@ async def poll( The title of the poll. options : str The options for the poll, separated by commas. + + """ - assert ctx.guild # Split the options by comma options_list = options.split(",") @@ -92,8 +87,16 @@ async def poll( # Remove any leading or trailing whitespaces from the options options_list = [option.strip() for option in options_list] - if await self.is_pollbanned(ctx.guild.id, ctx.author.id): - await ctx.send("You are banned from making polls.") + if await self.is_pollbanned(interaction.guild_id, interaction.user.id): + embed = EmbedCreator.create_embed( + bot=self.bot, + embed_type=EmbedCreator.ERROR, + user_name=interaction.user.name, + user_display_avatar=interaction.user.display_avatar.url, + title="Poll Banned", + description="you are banned from making polls. think about what you have done.", + ) + await interaction.response.send_message(embed=embed, ephemeral=True) return # Check if the options count is between 2-9 if len(options_list) < 2 or len(options_list) > 9: From 7e1bb4f934f801a88b8d7445bf117505189c2b4b Mon Sep 17 00:00:00 2001 From: Kasen Engel Date: Mon, 23 Sep 2024 16:38:19 -0500 Subject: [PATCH 07/12] make unbanning people possible. --- tux/cogs/moderation/pollunban.py | 96 ++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 tux/cogs/moderation/pollunban.py diff --git a/tux/cogs/moderation/pollunban.py b/tux/cogs/moderation/pollunban.py new file mode 100644 index 000000000..c486caf4b --- /dev/null +++ b/tux/cogs/moderation/pollunban.py @@ -0,0 +1,96 @@ +import discord +from discord.ext import commands +from loguru import logger + +from prisma.enums import CaseType +from tux.bot import Tux +from tux.database.controllers.case import CaseController +from tux.utils import checks +from tux.utils.flags import PollUnbanFlags, generate_usage + +from . import ModerationCogBase + + +class PollUnban(ModerationCogBase): + def __init__(self, bot: Tux) -> None: + super().__init__(bot) + self.case_controller = CaseController() + self.poll_unban.usage = generate_usage(self.poll_unban, PollUnbanFlags) + + @commands.hybrid_command( + name="pollunban", + aliases=["pub"], + ) + @commands.guild_only() + @checks.has_pl(3) + async def poll_unban( + self, + ctx: commands.Context[Tux], + member: discord.Member, + *, + flags: PollUnbanFlags, + ): + """ + Unban a user from creating snippets. + + Parameters + ---------- + ctx : commands.Context[Tux] + The context object. + member : discord.Member + The member to snippet unban. + flags : PollUnbanFlags + The flags for the command. (reason: str, silent: bool) + """ + + assert ctx.guild + + if not await self.is_pollbanned(ctx.guild.id, member.id): + await ctx.send("User is not poll banned.", delete_after=30, ephemeral=True) + return + + try: + case = await self.db.case.insert_case( + case_user_id=member.id, + case_moderator_id=ctx.author.id, + case_type=CaseType.POLLUNBAN, + case_reason=flags.reason, + guild_id=ctx.guild.id, + ) + + except Exception as e: + logger.error(f"Failed to poll unban {member}. {e}") + await ctx.send(f"Failed to poll unban {member}. {e}", delete_after=30, ephemeral=True) + return + + dm_sent = await self.send_dm(ctx, flags.silent, member, flags.reason, "poll unbanned") + await self.handle_case_response(ctx, CaseType.POLLUNBAN, case.case_number, flags.reason, member, dm_sent) + + async def is_pollbanned(self, guild_id: int, user_id: int) -> bool: + """ + Check if a user is poll banned. + + Parameters + ---------- + guild_id : int + The ID of the guild to check in. + user_id : int + The ID of the user to check. + + Returns + ------- + bool + True if the user is snippet banned, False otherwise. + """ + + ban_cases = await self.case_controller.get_all_cases_by_type(guild_id, CaseType.POLLBAN) + unban_cases = await self.case_controller.get_all_cases_by_type(guild_id, CaseType.POLLUNBAN) + + ban_count = sum(case.case_user_id == user_id for case in ban_cases) + unban_count = sum(case.case_user_id == user_id for case in unban_cases) + + return ban_count > unban_count + + +async def setup(bot: Tux) -> None: + await bot.add_cog(PollUnban(bot)) From 6022a1d33dff0a738dd51665e73a404b4afb883d Mon Sep 17 00:00:00 2001 From: Kasen Engel Date: Mon, 23 Sep 2024 16:43:17 -0500 Subject: [PATCH 08/12] add assertation to poll.py --- tux/cogs/utility/poll.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tux/cogs/utility/poll.py b/tux/cogs/utility/poll.py index 73e8ed09b..d5f6a3fd8 100644 --- a/tux/cogs/utility/poll.py +++ b/tux/cogs/utility/poll.py @@ -80,7 +80,7 @@ async def poll(self, interaction: discord.Interaction, title: str, options: str) """ - + assert interaction # Split the options by comma options_list = options.split(",") From 6241e2199fa60fda911bee71fee0ac810689b965 Mon Sep 17 00:00:00 2001 From: Kasen Engel Date: Mon, 23 Sep 2024 16:46:18 -0500 Subject: [PATCH 09/12] add assertation (another) to poll.py --- tux/cogs/utility/poll.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tux/cogs/utility/poll.py b/tux/cogs/utility/poll.py index d5f6a3fd8..836a26df1 100644 --- a/tux/cogs/utility/poll.py +++ b/tux/cogs/utility/poll.py @@ -80,7 +80,9 @@ async def poll(self, interaction: discord.Interaction, title: str, options: str) """ - assert interaction + assert interaction.guild_id is int + assert interaction.user.id is int + # Split the options by comma options_list = options.split(",") From 887ad4710f7aa0ed34ec3e60d3be22e472f2b6e4 Mon Sep 17 00:00:00 2001 From: electron271 <66094410+electron271@users.noreply.github.com> Date: Thu, 26 Sep 2024 20:33:23 -0500 Subject: [PATCH 10/12] fix(poll.py) update poll banned message for consistency and professionalism --- tux/cogs/utility/poll.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tux/cogs/utility/poll.py b/tux/cogs/utility/poll.py index 836a26df1..1e40d1e21 100644 --- a/tux/cogs/utility/poll.py +++ b/tux/cogs/utility/poll.py @@ -96,7 +96,7 @@ async def poll(self, interaction: discord.Interaction, title: str, options: str) user_name=interaction.user.name, user_display_avatar=interaction.user.display_avatar.url, title="Poll Banned", - description="you are banned from making polls. think about what you have done.", + description="You are poll banned and cannot create a poll.", ) await interaction.response.send_message(embed=embed, ephemeral=True) return From 83b028b5b8a386430db58603dd8107c59506df0c Mon Sep 17 00:00:00 2001 From: electron271 <66094410+electron271@users.noreply.github.com> Date: Thu, 26 Sep 2024 20:37:00 -0500 Subject: [PATCH 11/12] note(poll.py) address note (see commit desc) this is just part of discord rate limiting, at the end of the day the reactions are still removed --- tux/cogs/utility/poll.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tux/cogs/utility/poll.py b/tux/cogs/utility/poll.py index 1e40d1e21..67436b2f4 100644 --- a/tux/cogs/utility/poll.py +++ b/tux/cogs/utility/poll.py @@ -52,8 +52,6 @@ async def on_message(self, message: discord.Message) -> None: @commands.Cog.listener() async def on_reaction_add(self, reaction: discord.Reaction, user: discord.User) -> None: # Block any reactions that are not numbers for the poll - # NOTE: Today we observed in amazing detail that the pure will of 1 too many dedicated discord members can make - # the bot freak out whenever trying to remove reactions. Is there a better solution for this? if reaction.message.embeds: embed = reaction.message.embeds[0] if ( From afb937783d62c794abdd078174351a9d62a3091f Mon Sep 17 00:00:00 2001 From: electron271 <66094410+electron271@users.noreply.github.com> Date: Thu, 26 Sep 2024 20:59:50 -0500 Subject: [PATCH 12/12] finish pollban --- tux/cogs/moderation/__init__.py | 28 ++++++++++++++++++++++++++++ tux/cogs/moderation/pollban.py | 25 ------------------------- tux/cogs/moderation/pollunban.py | 25 ------------------------- tux/cogs/utility/poll.py | 26 +++++++++++++++++++++++--- 4 files changed, 51 insertions(+), 53 deletions(-) diff --git a/tux/cogs/moderation/__init__.py b/tux/cogs/moderation/__init__.py index e0bc92921..04d61de54 100644 --- a/tux/cogs/moderation/__init__.py +++ b/tux/cogs/moderation/__init__.py @@ -250,3 +250,31 @@ async def handle_case_response( await self.send_embed(ctx, embed, log_type="mod") await ctx.send(embed=embed, delete_after=30, ephemeral=True) + + async def is_pollbanned(self, guild_id: int, user_id: int) -> bool: + """ + Check if a user is poll banned. + + Parameters + ---------- + guild_id : int + The ID of the guild to check in. + user_id : int + The ID of the user to check. + + Returns + ------- + bool + True if the user is poll banned, False otherwise. + """ + + # ban_cases = await self.case_controller.get_all_cases_by_type(guild_id, CaseType.POLLBAN) + # unban_cases = await self.case_controller.get_all_cases_by_type(guild_id, CaseType.POLLUNBAN) + + ban_cases = await self.db.case.get_all_cases_by_type(guild_id, CaseType.POLLBAN) + unban_cases = await self.db.case.get_all_cases_by_type(guild_id, CaseType.POLLUNBAN) + + ban_count = sum(case.case_user_id == user_id for case in ban_cases) + unban_count = sum(case.case_user_id == user_id for case in unban_cases) + + return ban_count > unban_count diff --git a/tux/cogs/moderation/pollban.py b/tux/cogs/moderation/pollban.py index 131c4d85b..6afbabdae 100644 --- a/tux/cogs/moderation/pollban.py +++ b/tux/cogs/moderation/pollban.py @@ -66,31 +66,6 @@ async def poll_ban( dm_sent = await self.send_dm(ctx, flags.silent, member, flags.reason, "poll banned") await self.handle_case_response(ctx, CaseType.POLLBAN, case.case_number, flags.reason, member, dm_sent) - async def is_pollbanned(self, guild_id: int, user_id: int) -> bool: - """ - Check if a user is poll banned. - - Parameters - ---------- - guild_id : int - The ID of the guild to check in. - user_id : int - The ID of the user to check. - - Returns - ------- - bool - True if the user is poll banned, False otherwise. - """ - - ban_cases = await self.case_controller.get_all_cases_by_type(guild_id, CaseType.POLLBAN) - unban_cases = await self.case_controller.get_all_cases_by_type(guild_id, CaseType.POLLUNBAN) - - ban_count = sum(case.case_user_id == user_id for case in ban_cases) - unban_count = sum(case.case_user_id == user_id for case in unban_cases) - - return ban_count > unban_count - async def setup(bot: Tux) -> None: await bot.add_cog(PollBan(bot)) diff --git a/tux/cogs/moderation/pollunban.py b/tux/cogs/moderation/pollunban.py index c486caf4b..dcf3ff267 100644 --- a/tux/cogs/moderation/pollunban.py +++ b/tux/cogs/moderation/pollunban.py @@ -66,31 +66,6 @@ async def poll_unban( dm_sent = await self.send_dm(ctx, flags.silent, member, flags.reason, "poll unbanned") await self.handle_case_response(ctx, CaseType.POLLUNBAN, case.case_number, flags.reason, member, dm_sent) - async def is_pollbanned(self, guild_id: int, user_id: int) -> bool: - """ - Check if a user is poll banned. - - Parameters - ---------- - guild_id : int - The ID of the guild to check in. - user_id : int - The ID of the user to check. - - Returns - ------- - bool - True if the user is snippet banned, False otherwise. - """ - - ban_cases = await self.case_controller.get_all_cases_by_type(guild_id, CaseType.POLLBAN) - unban_cases = await self.case_controller.get_all_cases_by_type(guild_id, CaseType.POLLUNBAN) - - ban_count = sum(case.case_user_id == user_id for case in ban_cases) - unban_count = sum(case.case_user_id == user_id for case in unban_cases) - - return ban_count > unban_count - async def setup(bot: Tux) -> None: await bot.add_cog(PollUnban(bot)) diff --git a/tux/cogs/utility/poll.py b/tux/cogs/utility/poll.py index 67436b2f4..513b006d5 100644 --- a/tux/cogs/utility/poll.py +++ b/tux/cogs/utility/poll.py @@ -16,14 +16,33 @@ def __init__(self, bot: Tux) -> None: self.bot = bot self.case_controller = CaseController() + # TODO: for the moment this is duplicated code from ModerationCogBase in a attempt to get the code out sooner async def is_pollbanned(self, guild_id: int, user_id: int) -> bool: + """ + Check if a user is poll banned. + + Parameters + ---------- + guild_id : int + The ID of the guild to check in. + user_id : int + The ID of the user to check. + + Returns + ------- + bool + True if the user is poll banned, False otherwise. + """ + ban_cases = await self.case_controller.get_all_cases_by_type(guild_id, CaseType.POLLBAN) unban_cases = await self.case_controller.get_all_cases_by_type(guild_id, CaseType.POLLUNBAN) ban_count = sum(case.case_user_id == user_id for case in ban_cases) unban_count = sum(case.case_user_id == user_id for case in unban_cases) - return ban_count > unban_count + return ( + ban_count > unban_count + ) # TODO: this implementation is flawed, if someone bans and unbans the same user multiple times, this will not work as expected @commands.Cog.listener() # listen for messages async def on_message(self, message: discord.Message) -> None: @@ -78,8 +97,9 @@ async def poll(self, interaction: discord.Interaction, title: str, options: str) """ - assert interaction.guild_id is int - assert interaction.user.id is int + if interaction.guild_id is None: + await interaction.response.send_message("This command can only be used in a server.", ephemeral=True) + return # Split the options by comma options_list = options.split(",")