From e4b1cfec31fc49448db5f9dfb06f3a6a952c59e3 Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Mon, 14 Apr 2025 15:08:51 +0100 Subject: [PATCH 01/28] implement get strikes command --- cogs/strike.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/cogs/strike.py b/cogs/strike.py index 94faa470e..0247c277e 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -865,6 +865,48 @@ async def strike(self, ctx: "TeXBotApplicationContext", str_strike_member_id: st await self._command_perform_strike(ctx, strike_member) + @discord.slash_command( # type: ignore[misc, no-untyped-call] + name="get-strikes", + description="Get the number of strikes a user has.", + ) + @discord.option( # type: ignore[misc, no-untyped-call] + name="user", + description="The user to give a strike to.", + input_type=str, + autocomplete=discord.utils.basic_autocomplete(autocomplete_get_members), # type: ignore[arg-type] + required=True, + parameter_name="str_strike_member_id", + ) + @CommandChecks.check_interaction_user_has_committee_role + @CommandChecks.check_interaction_user_in_main_guild + async def get_strikes( + self, ctx: "TeXBotApplicationContext", str_strike_member_id: str + ) -> None: # type: ignore[misc] + """ + Define method and callback response of of the "get-strikes" command. + + Returns the number of strikes a user has. + """ + member_id_not_integer_error: ValueError + try: + strike_member: discord.Member = await self.bot.get_member_from_str_id( + str_strike_member_id, + ) + except ValueError as member_id_not_integer_error: + await self.command_send_error(ctx, message=member_id_not_integer_error.args[0]) + return + + member_strikes = [ + strike + async for strike in await DiscordMemberStrikes.objects.afilter( + discord_id=str(strike_member.id), + ) + ] + + await ctx.respond( + f"User {strike_member.mention} has the following strikes: {member_strikes}" + ) + class StrikeContextCommandsCog(BaseStrikeCog): """Cog class that defines the context menu strike command and its call-back method.""" From 62b1e84c4465ff783df38f1328a85e2f68bbf109 Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Mon, 14 Apr 2025 15:11:00 +0100 Subject: [PATCH 02/28] move the ignore --- cogs/strike.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cogs/strike.py b/cogs/strike.py index 0247c277e..c2f9c23a6 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -879,9 +879,9 @@ async def strike(self, ctx: "TeXBotApplicationContext", str_strike_member_id: st ) @CommandChecks.check_interaction_user_has_committee_role @CommandChecks.check_interaction_user_in_main_guild - async def get_strikes( + async def get_strikes( # type: ignore[misc] self, ctx: "TeXBotApplicationContext", str_strike_member_id: str - ) -> None: # type: ignore[misc] + ) -> None: """ Define method and callback response of of the "get-strikes" command. From 0503c78e1578f6ef4c0f4895587ced310105de1f Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Mon, 14 Apr 2025 15:27:49 +0100 Subject: [PATCH 03/28] Fix this --- cogs/strike.py | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/cogs/strike.py b/cogs/strike.py index c2f9c23a6..27b4a9ef0 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -10,6 +10,7 @@ import discord from asyncstdlib.builtins import any as asyncany from discord.ui import View +from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist from config import settings from db.core.models import DiscordMemberStrikes @@ -896,15 +897,30 @@ async def get_strikes( # type: ignore[misc] await self.command_send_error(ctx, message=member_id_not_integer_error.args[0]) return - member_strikes = [ - strike - async for strike in await DiscordMemberStrikes.objects.afilter( - discord_id=str(strike_member.id), + logger.debug(DiscordMemberStrikes.objects) + + try: + member_strike_object: DiscordMemberStrikes = ( + await DiscordMemberStrikes.objects.select_related().aget( + discord_id=str(strike_member.id), + ) ) - ] + except ObjectDoesNotExist: + await ctx.respond(f"User {strike_member.mention} does not have any strikes.") + return + except MultipleObjectsReturned: + await self.command_send_error( + ctx=ctx, + message=( + "Multiple objects returned when trying to get strikes for user! " + "This should never happen!" + ), + ) + return await ctx.respond( - f"User {strike_member.mention} has the following strikes: {member_strikes}" + f"User {strike_member.mention} has the following strikes: " + f"{member_strike_object.strikes}" ) From d094358bcb01fd1489133f33aca5e460a7e54101 Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Mon, 14 Apr 2025 15:30:58 +0100 Subject: [PATCH 04/28] Fix using wrong field --- cogs/strike.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cogs/strike.py b/cogs/strike.py index 27b4a9ef0..b7b7ea6c5 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -902,7 +902,7 @@ async def get_strikes( # type: ignore[misc] try: member_strike_object: DiscordMemberStrikes = ( await DiscordMemberStrikes.objects.select_related().aget( - discord_id=str(strike_member.id), + discord_member_id=str(strike_member.id), ) ) except ObjectDoesNotExist: From 826a25b424f3d928fb9baa146d42bdc086d4e891 Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Mon, 14 Apr 2025 15:43:03 +0100 Subject: [PATCH 05/28] try something else --- cogs/strike.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/cogs/strike.py b/cogs/strike.py index b7b7ea6c5..c99464eb1 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -13,7 +13,7 @@ from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist from config import settings -from db.core.models import DiscordMemberStrikes +from db.core.models import DiscordMember, DiscordMemberStrikes from exceptions import ( GuildDoesNotExistError, NoAuditLogsStrikeTrackingError, @@ -876,12 +876,12 @@ async def strike(self, ctx: "TeXBotApplicationContext", str_strike_member_id: st input_type=str, autocomplete=discord.utils.basic_autocomplete(autocomplete_get_members), # type: ignore[arg-type] required=True, - parameter_name="str_strike_member_id", + parameter_name="str_user_id", ) @CommandChecks.check_interaction_user_has_committee_role @CommandChecks.check_interaction_user_in_main_guild async def get_strikes( # type: ignore[misc] - self, ctx: "TeXBotApplicationContext", str_strike_member_id: str + self, ctx: "TeXBotApplicationContext", str_user_id: str ) -> None: """ Define method and callback response of of the "get-strikes" command. @@ -891,18 +891,17 @@ async def get_strikes( # type: ignore[misc] member_id_not_integer_error: ValueError try: strike_member: discord.Member = await self.bot.get_member_from_str_id( - str_strike_member_id, + str_user_id, ) + logger.debug("Found user: %s", strike_member) except ValueError as member_id_not_integer_error: await self.command_send_error(ctx, message=member_id_not_integer_error.args[0]) return - logger.debug(DiscordMemberStrikes.objects) - try: member_strike_object: DiscordMemberStrikes = ( await DiscordMemberStrikes.objects.select_related().aget( - discord_member_id=str(strike_member.id), + discord_member=DiscordMember.hash_discord_id(strike_member.id), ) ) except ObjectDoesNotExist: From a0d3d22c4c31e0bdc04743b545a85f03078e1ac7 Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Mon, 14 Apr 2025 15:56:11 +0100 Subject: [PATCH 06/28] Add some debug --- cogs/strike.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/cogs/strike.py b/cogs/strike.py index c99464eb1..69794c898 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -898,6 +898,21 @@ async def get_strikes( # type: ignore[misc] await self.command_send_error(ctx, message=member_id_not_integer_error.args[0]) return + all_strike_objects: list[DiscordMemberStrikes] = [ + strike_object + async for strike_object in DiscordMemberStrikes.objects.select_related().all() + ] + + strike_obj: DiscordMemberStrikes = next( + strike_object + for strike_object in all_strike_objects + if str(strike_object.discord_member) + == DiscordMember.hash_discord_id(strike_member.id) + ) + + logger.debug(all_strike_objects) + logger.debug(strike_obj) + try: member_strike_object: DiscordMemberStrikes = ( await DiscordMemberStrikes.objects.select_related().aget( From 92100dfd6392d29ac09f0315064d351183ecdcc2 Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Mon, 14 Apr 2025 15:57:05 +0100 Subject: [PATCH 07/28] fix mypy --- cogs/strike.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cogs/strike.py b/cogs/strike.py index 69794c898..9737d64e7 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -888,7 +888,7 @@ async def get_strikes( # type: ignore[misc] Returns the number of strikes a user has. """ - member_id_not_integer_error: ValueError + member_id_not_integer_error: ValueError # type: ignore[misc] try: strike_member: discord.Member = await self.bot.get_member_from_str_id( str_user_id, @@ -906,7 +906,7 @@ async def get_strikes( # type: ignore[misc] strike_obj: DiscordMemberStrikes = next( strike_object for strike_object in all_strike_objects - if str(strike_object.discord_member) + if str(strike_object.discord_member) # type: ignore[has-type] == DiscordMember.hash_discord_id(strike_member.id) ) From e5b5ffe43732cffaae2a9f4eff4f165f98817425 Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Mon, 14 Apr 2025 16:04:48 +0100 Subject: [PATCH 08/28] getting better --- cogs/strike.py | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/cogs/strike.py b/cogs/strike.py index 9737d64e7..8d790192a 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -10,7 +10,6 @@ import discord from asyncstdlib.builtins import any as asyncany from discord.ui import View -from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist from config import settings from db.core.models import DiscordMember, DiscordMemberStrikes @@ -913,28 +912,8 @@ async def get_strikes( # type: ignore[misc] logger.debug(all_strike_objects) logger.debug(strike_obj) - try: - member_strike_object: DiscordMemberStrikes = ( - await DiscordMemberStrikes.objects.select_related().aget( - discord_member=DiscordMember.hash_discord_id(strike_member.id), - ) - ) - except ObjectDoesNotExist: - await ctx.respond(f"User {strike_member.mention} does not have any strikes.") - return - except MultipleObjectsReturned: - await self.command_send_error( - ctx=ctx, - message=( - "Multiple objects returned when trying to get strikes for user! " - "This should never happen!" - ), - ) - return - await ctx.respond( - f"User {strike_member.mention} has the following strikes: " - f"{member_strike_object.strikes}" + f"User {strike_member.mention} has the following strikes: {strike_obj.strikes}" ) From bfab1d26df87adf85b225a93ad3386aac03b1c0e Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Mon, 14 Apr 2025 16:31:45 +0100 Subject: [PATCH 09/28] i literally hate these precommits --- cogs/strike.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cogs/strike.py b/cogs/strike.py index 8d790192a..23d0bf784 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -904,9 +904,12 @@ async def get_strikes( # type: ignore[misc] strike_obj: DiscordMemberStrikes = next( strike_object - for strike_object in all_strike_objects + for strike_object in [ + all_strike_object + async for all_strike_object in DiscordMemberStrikes.objects.select_related().all() # noqa: E501 # NOTE: I tried to reformat this to avoid the ruff error but the stupid fucking reformat put it all back on one line again + ] if str(strike_object.discord_member) # type: ignore[has-type] - == DiscordMember.hash_discord_id(strike_member.id) + == (DiscordMember.hash_discord_id(strike_member.id)) ) logger.debug(all_strike_objects) From c265d582a1bd067b5dad9c23d12369ebba246143 Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Mon, 14 Apr 2025 16:37:38 +0100 Subject: [PATCH 10/28] minor refactor --- cogs/strike.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/cogs/strike.py b/cogs/strike.py index 23d0bf784..52530e6ea 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -897,11 +897,6 @@ async def get_strikes( # type: ignore[misc] await self.command_send_error(ctx, message=member_id_not_integer_error.args[0]) return - all_strike_objects: list[DiscordMemberStrikes] = [ - strike_object - async for strike_object in DiscordMemberStrikes.objects.select_related().all() - ] - strike_obj: DiscordMemberStrikes = next( strike_object for strike_object in [ @@ -912,11 +907,8 @@ async def get_strikes( # type: ignore[misc] == (DiscordMember.hash_discord_id(strike_member.id)) ) - logger.debug(all_strike_objects) - logger.debug(strike_obj) - await ctx.respond( - f"User {strike_member.mention} has the following strikes: {strike_obj.strikes}" + f"User {strike_member.mention} has {strike_obj.strikes or 0} strikes." ) From 6795cef7dccf4446ae144d79bd0f274f15588ed1 Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Mon, 14 Apr 2025 16:48:47 +0100 Subject: [PATCH 11/28] Add delete-all strikes command --- cogs/delete_all.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/cogs/delete_all.py b/cogs/delete_all.py index d89572dc1..b5c5e2d20 100644 --- a/cogs/delete_all.py +++ b/cogs/delete_all.py @@ -4,7 +4,12 @@ import discord -from db.core.models import AssignedCommitteeAction, DiscordReminder, GroupMadeMember +from db.core.models import ( + AssignedCommitteeAction, + DiscordMemberStrikes, + DiscordReminder, + GroupMadeMember, +) from utils import CommandChecks, TeXBotBaseCog if TYPE_CHECKING: @@ -88,3 +93,18 @@ async def delete_all_actions(self, ctx: "TeXBotApplicationContext") -> None: to delete all `Action` instance objects stored in the database. """ await self._delete_all(ctx, delete_model=AssignedCommitteeAction) + + @delete_all.command( + name="strikes", + description="Deletes all the Strikes from the backend database.", + ) + @CommandChecks.check_interaction_user_has_committee_role + @CommandChecks.check_interaction_user_in_main_guild + async def delete_all_strikes(self, ctx: "TeXBotApplicationContext") -> None: + """ + Definition & callback response of the "delete-all-strikes" command. + + The "delete-all-strikes" command uses the _delete_all() function + to delete all `Strike` instance objects stored in the database. + """ + await self._delete_all(ctx, delete_model=DiscordMemberStrikes) From 0ab4fa44ddc09f3dde3e71bffadb964edabc8218 Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Mon, 14 Apr 2025 16:58:16 +0100 Subject: [PATCH 12/28] refactor to handle exceptions --- cogs/strike.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/cogs/strike.py b/cogs/strike.py index 52530e6ea..2c80b0d27 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -897,18 +897,23 @@ async def get_strikes( # type: ignore[misc] await self.command_send_error(ctx, message=member_id_not_integer_error.args[0]) return - strike_obj: DiscordMemberStrikes = next( - strike_object - for strike_object in [ - all_strike_object - async for all_strike_object in DiscordMemberStrikes.objects.select_related().all() # noqa: E501 # NOTE: I tried to reformat this to avoid the ruff error but the stupid fucking reformat put it all back on one line again - ] - if str(strike_object.discord_member) # type: ignore[has-type] - == (DiscordMember.hash_discord_id(strike_member.id)) - ) + strike_obj: DiscordMemberStrikes | None = None + try: + strike_obj = next( + strike_object + for strike_object in [ + all_strike_object + async for all_strike_object in DiscordMemberStrikes.objects.select_related().all() # noqa: E501 # NOTE: I tried to reformat this to avoid the ruff error but the stupid fucking reformat put it all back on one line again + ] + if str(strike_object.discord_member) # type: ignore[has-type] + == (DiscordMember.hash_discord_id(strike_member.id)) + ) + except StopIteration: + logger.debug("No strikes found for user %s", strike_member) await ctx.respond( - f"User {strike_member.mention} has {strike_obj.strikes or 0} strikes." + f"User {strike_member.mention} has " + f"{strike_obj.strikes if strike_obj else 0} strikes." ) From 08ec83f5d8d221206e8d7fa55078683df94a9c31 Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Mon, 14 Apr 2025 17:03:13 +0100 Subject: [PATCH 13/28] make response ephemeral --- cogs/strike.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cogs/strike.py b/cogs/strike.py index 2c80b0d27..7de0ea312 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -892,7 +892,6 @@ async def get_strikes( # type: ignore[misc] strike_member: discord.Member = await self.bot.get_member_from_str_id( str_user_id, ) - logger.debug("Found user: %s", strike_member) except ValueError as member_id_not_integer_error: await self.command_send_error(ctx, message=member_id_not_integer_error.args[0]) return @@ -912,8 +911,11 @@ async def get_strikes( # type: ignore[misc] logger.debug("No strikes found for user %s", strike_member) await ctx.respond( - f"User {strike_member.mention} has " - f"{strike_obj.strikes if strike_obj else 0} strikes." + content=( + f"User {strike_member.mention} has " + f"{strike_obj.strikes if strike_obj else 0} strikes." + ), + ephemeral=True, ) From caa2a66bece6ddbe452b3055deb27f4d678ad6b0 Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Mon, 14 Apr 2025 17:10:15 +0100 Subject: [PATCH 14/28] Implement decrement strike command --- cogs/strike.py | 59 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/cogs/strike.py b/cogs/strike.py index 7de0ea312..15f97b31a 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -871,7 +871,7 @@ async def strike(self, ctx: "TeXBotApplicationContext", str_strike_member_id: st ) @discord.option( # type: ignore[misc, no-untyped-call] name="user", - description="The user to give a strike to.", + description="The user to check the number of strikes for.", input_type=str, autocomplete=discord.utils.basic_autocomplete(autocomplete_get_members), # type: ignore[arg-type] required=True, @@ -887,7 +887,6 @@ async def get_strikes( # type: ignore[misc] Returns the number of strikes a user has. """ - member_id_not_integer_error: ValueError # type: ignore[misc] try: strike_member: discord.Member = await self.bot.get_member_from_str_id( str_user_id, @@ -918,6 +917,62 @@ async def get_strikes( # type: ignore[misc] ephemeral=True, ) + @discord.slash_command( # type: ignore[misc, no-untyped-call] + name="decrease-strikes", + description="Decrement the number of strikes a user has by 1.", + ) + @discord.option( # type: ignore[misc, no-untyped-call] + name="user", + description="The user to remove a strike from.", + input_type=str, + autocomplete=discord.utils.basic_autocomplete(autocomplete_get_members), # type: ignore[arg-type] + required=True, + parameter_name="str_user_id", + ) + async def decrement_strikes( + self, ctx: "TeXBotApplicationContext", str_user_id: str + ) -> None: # type: ignore[misc, no-untyped-call] + """ + Definition & callback response of the "decrease-strikes" command. + + The "decrease-strikes" command removes a strike from the given member. + """ + try: + strike_member: discord.Member = await self.bot.get_member_from_str_id( + str_user_id, + ) + except ValueError as member_id_not_integer_error: + await self.command_send_error(ctx, message=member_id_not_integer_error.args[0]) + return + + strike_obj: DiscordMemberStrikes | None = None + try: + strike_obj = next( + strike_object + for strike_object in [ + all_strike_object + async for all_strike_object in DiscordMemberStrikes.objects.select_related().all() # noqa: E501 # NOTE: I tried to reformat this to avoid the ruff error but the stupid fucking reformat put it all back on one line again + ] + if str(strike_object.discord_member) # type: ignore[has-type] + == (DiscordMember.hash_discord_id(strike_member.id)) + ) + except StopIteration: + await self.command_send_error( + ctx=ctx, + message="Cannot decrement strikes of user that has no strikes.", + ) + return + + if strike_obj.strikes == 1: + await strike_obj.adelete() + await ctx.respond( + content=f"Successfully removed all strikes from {strike_member.mention}." + ) + return + + strike_obj.strikes -= 1 + await strike_obj.asave() + class StrikeContextCommandsCog(BaseStrikeCog): """Cog class that defines the context menu strike command and its call-back method.""" From b0ac12dfef889455001977e87d339c502730a7c3 Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Mon, 14 Apr 2025 17:10:47 +0100 Subject: [PATCH 15/28] fix mypy --- cogs/strike.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cogs/strike.py b/cogs/strike.py index 15f97b31a..0f13101ef 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -929,9 +929,9 @@ async def get_strikes( # type: ignore[misc] required=True, parameter_name="str_user_id", ) - async def decrement_strikes( + async def decrement_strikes( # type: ignore[misc] self, ctx: "TeXBotApplicationContext", str_user_id: str - ) -> None: # type: ignore[misc, no-untyped-call] + ) -> None: """ Definition & callback response of the "decrease-strikes" command. From 0de9e424b4ff9849490a2d86a15246b93c82a7b5 Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Mon, 14 Apr 2025 17:28:29 +0100 Subject: [PATCH 16/28] Add response for decremenet --- cogs/strike.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/cogs/strike.py b/cogs/strike.py index 0f13101ef..12ae552ff 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -918,7 +918,7 @@ async def get_strikes( # type: ignore[misc] ) @discord.slash_command( # type: ignore[misc, no-untyped-call] - name="decrease-strikes", + name="decrement-strikes", description="Decrement the number of strikes a user has by 1.", ) @discord.option( # type: ignore[misc, no-untyped-call] @@ -933,9 +933,10 @@ async def decrement_strikes( # type: ignore[misc] self, ctx: "TeXBotApplicationContext", str_user_id: str ) -> None: """ - Definition & callback response of the "decrease-strikes" command. + Definition & callback response of the "decrement-strikes" command. - The "decrease-strikes" command removes a strike from the given member. + The "decrement-strikes" command removes a strike from the given member. + If the user only has one strike, the object will be deleted from the database. """ try: strike_member: discord.Member = await self.bot.get_member_from_str_id( @@ -972,6 +973,12 @@ async def decrement_strikes( # type: ignore[misc] strike_obj.strikes -= 1 await strike_obj.asave() + await ctx.respond( + content=( + f"Successfully removed a strike from {strike_member.mention}. " + f"User now has {strike_obj.strikes} strikes." + ) + ) class StrikeContextCommandsCog(BaseStrikeCog): From 4fefdb0828fe16579d7b9a2d9577288ec01581b9 Mon Sep 17 00:00:00 2001 From: Matty Widdop <18513864+MattyTheHacker@users.noreply.github.com> Date: Mon, 14 Apr 2025 17:37:29 +0100 Subject: [PATCH 17/28] Update strike.py --- cogs/strike.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cogs/strike.py b/cogs/strike.py index 12ae552ff..7094fd696 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -901,7 +901,7 @@ async def get_strikes( # type: ignore[misc] strike_object for strike_object in [ all_strike_object - async for all_strike_object in DiscordMemberStrikes.objects.select_related().all() # noqa: E501 # NOTE: I tried to reformat this to avoid the ruff error but the stupid fucking reformat put it all back on one line again + async for all_strike_object in DiscordMemberStrikes.objects.select_related().all() # noqa: E501 ] if str(strike_object.discord_member) # type: ignore[has-type] == (DiscordMember.hash_discord_id(strike_member.id)) From a7fae4d98d3e1f0ca893d0058a9251ab1fbda01f Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Sat, 10 May 2025 13:36:20 +0100 Subject: [PATCH 18/28] improve fetching of strike object --- cogs/strike.py | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/cogs/strike.py b/cogs/strike.py index d608f7566..6fc7b42a7 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -900,26 +900,16 @@ async def get_strikes( # type: ignore[misc] await self.command_send_error(ctx, message=member_id_not_integer_error.args[0]) return - strike_obj: DiscordMemberStrikes | None = None + strikes_count: int = 0 try: - strike_obj = next( - strike_object - for strike_object in [ - all_strike_object - async for all_strike_object in DiscordMemberStrikes.objects.select_related().all() # noqa: E501 - ] - if str(strike_object.discord_member) # type: ignore[has-type] - == (DiscordMember.hash_discord_id(strike_member.id)) - ) - except StopIteration: + strikes_count = ( + await DiscordMemberStrikes.objects.aget(discord_id=strike_member.id) + ).strikes + except DiscordMemberStrikes.DoesNotExist: logger.debug("No strikes found for user %s", strike_member) await ctx.respond( - content=( - f"User {strike_member.mention} has " - f"{strike_obj.strikes if strike_obj else 0} strikes." - ), - ephemeral=True, + content=(f"User {strike_member.mention} has {strikes_count} strikes.") ) @discord.slash_command( # type: ignore[misc, no-untyped-call] From 62786d78668b6b1731b7a8a96b800f0fe6f649cd Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Sat, 10 May 2025 15:39:10 +0100 Subject: [PATCH 19/28] add logging --- cogs/strike.py | 57 +++++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/cogs/strike.py b/cogs/strike.py index 6fc7b42a7..fd723e742 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -890,11 +890,11 @@ async def get_strikes( # type: ignore[misc] """ Define method and callback response of of the "get-strikes" command. - Returns the number of strikes a user has. + Responds with the number of strikes a user has. """ try: strike_member: discord.Member = await self.bot.get_member_from_str_id( - str_user_id, + str_user_id ) except ValueError as member_id_not_integer_error: await self.command_send_error(ctx, message=member_id_not_integer_error.args[0]) @@ -931,7 +931,8 @@ async def decrement_strikes( # type: ignore[misc] Definition & callback response of the "decrement-strikes" command. The "decrement-strikes" command removes a strike from the given member. - If the user only has one strike, the object will be deleted from the database. + If the member only has one strike, the corresponding `DiscordMemberStrikes` + object will be deleted from the database. """ try: strike_member: discord.Member = await self.bot.get_member_from_str_id( @@ -941,39 +942,53 @@ async def decrement_strikes( # type: ignore[misc] await self.command_send_error(ctx, message=member_id_not_integer_error.args[0]) return - strike_obj: DiscordMemberStrikes | None = None try: - strike_obj = next( - strike_object - for strike_object in [ - all_strike_object - async for all_strike_object in DiscordMemberStrikes.objects.select_related().all() # noqa: E501 # NOTE: I tried to reformat this to avoid the ruff error but the stupid fucking reformat put it all back on one line again - ] - if str(strike_object.discord_member) # type: ignore[has-type] - == (DiscordMember.hash_discord_id(strike_member.id)) + discord_member_strikes: DiscordMemberStrikes = ( + await DiscordMemberStrikes.objects.select_related().aget( + discord_id=strike_member.id + ) ) - except StopIteration: - await self.command_send_error( - ctx=ctx, - message="Cannot decrement strikes of user that has no strikes.", + except DiscordMemberStrikes.DoesNotExist: + await ctx.respond( + content=( + ":information_source: No action taken." + f"User {strike_member.mention} does not have any strikes to remove!" + ), + ephemeral=True, + ) + logger.info( + "%s attempted to remove a strike from user %s, but they had none", + ctx.user, + strike_member, ) return - if strike_obj.strikes == 1: - await strike_obj.adelete() + if discord_member_strikes.strikes == 1: + await discord_member_strikes.adelete() await ctx.respond( content=f"Successfully removed all strikes from {strike_member.mention}." ) + logger.info( + "%s removed all strikes from user %s", + ctx.user, + strike_member, + ) return - strike_obj.strikes -= 1 - await strike_obj.asave() + discord_member_strikes.strikes -= 1 + await discord_member_strikes.asave() await ctx.respond( content=( f"Successfully removed a strike from {strike_member.mention}. " - f"User now has {strike_obj.strikes} strikes." + f"User now has {discord_member_strikes.strikes} strikes." ) ) + logger.info( + "%s removed 1 strike from user %s, they now have %s", + ctx.user, + strike_member, + discord_member_strikes.strikes, + ) class StrikeContextCommandsCog(BaseStrikeCog): From ef7d3ab0245f45372712d68ec69af4cd28842cc4 Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Sat, 10 May 2025 15:56:15 +0100 Subject: [PATCH 20/28] minor fixes --- cogs/strike.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/cogs/strike.py b/cogs/strike.py index fd723e742..3571ea05a 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -10,9 +10,10 @@ import discord from asyncstdlib.builtins import any as asyncany from discord.ui import View +from django.db.models import F from config import settings -from db.core.models import DiscordMember, DiscordMemberStrikes +from db.core.models import DiscordMemberStrikes from exceptions import ( GuildDoesNotExistError, NoAuditLogsStrikeTrackingError, @@ -880,12 +881,12 @@ async def strike(self, ctx: "TeXBotApplicationContext", str_strike_member_id: st input_type=str, autocomplete=discord.utils.basic_autocomplete(autocomplete_get_members), # type: ignore[arg-type] required=True, - parameter_name="str_user_id", + parameter_name="str_strike_member_id", ) @CommandChecks.check_interaction_user_has_committee_role @CommandChecks.check_interaction_user_in_main_guild async def get_strikes( # type: ignore[misc] - self, ctx: "TeXBotApplicationContext", str_user_id: str + self, ctx: "TeXBotApplicationContext", str_strike_member_id: str ) -> None: """ Define method and callback response of of the "get-strikes" command. @@ -894,7 +895,7 @@ async def get_strikes( # type: ignore[misc] """ try: strike_member: discord.Member = await self.bot.get_member_from_str_id( - str_user_id + str_member_id=str_strike_member_id ) except ValueError as member_id_not_integer_error: await self.command_send_error(ctx, message=member_id_not_integer_error.args[0]) @@ -914,7 +915,7 @@ async def get_strikes( # type: ignore[misc] @discord.slash_command( # type: ignore[misc, no-untyped-call] name="decrement-strikes", - description="Decrement the number of strikes a user has by 1.", + description="Remove a single strike from a user.", ) @discord.option( # type: ignore[misc, no-untyped-call] name="user", @@ -922,10 +923,10 @@ async def get_strikes( # type: ignore[misc] input_type=str, autocomplete=discord.utils.basic_autocomplete(autocomplete_get_members), # type: ignore[arg-type] required=True, - parameter_name="str_user_id", + parameter_name="str_strike_member_id", ) async def decrement_strikes( # type: ignore[misc] - self, ctx: "TeXBotApplicationContext", str_user_id: str + self, ctx: "TeXBotApplicationContext", str_strike_member_id: str ) -> None: """ Definition & callback response of the "decrement-strikes" command. @@ -936,7 +937,7 @@ async def decrement_strikes( # type: ignore[misc] """ try: strike_member: discord.Member = await self.bot.get_member_from_str_id( - str_user_id, + str_member_id=str_strike_member_id, ) except ValueError as member_id_not_integer_error: await self.command_send_error(ctx, message=member_id_not_integer_error.args[0]) @@ -963,7 +964,7 @@ async def decrement_strikes( # type: ignore[misc] ) return - if discord_member_strikes.strikes == 1: + if discord_member_strikes.strikes <= 1: await discord_member_strikes.adelete() await ctx.respond( content=f"Successfully removed all strikes from {strike_member.mention}." @@ -975,8 +976,7 @@ async def decrement_strikes( # type: ignore[misc] ) return - discord_member_strikes.strikes -= 1 - await discord_member_strikes.asave() + await discord_member_strikes.aupdate(strikes=F("strikes") - 1) await ctx.respond( content=( f"Successfully removed a strike from {strike_member.mention}. " From fd5f42fd9ab25613a2f1740df9ccd4e997f185f7 Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Sat, 10 May 2025 16:34:14 +0100 Subject: [PATCH 21/28] fix decrement object fetch --- cogs/strike.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cogs/strike.py b/cogs/strike.py index 3571ea05a..4f0650359 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -945,7 +945,7 @@ async def decrement_strikes( # type: ignore[misc] try: discord_member_strikes: DiscordMemberStrikes = ( - await DiscordMemberStrikes.objects.select_related().aget( + await DiscordMemberStrikes.objects.aget( discord_id=strike_member.id ) ) From a945af93b20786b2c0f7aa852271e318b344f968 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Sat, 10 May 2025 15:35:00 +0000 Subject: [PATCH 22/28] [pre-commit.ci lite] apply automatic fixes --- cogs/strike.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cogs/strike.py b/cogs/strike.py index 4f0650359..1466d8e31 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -945,9 +945,7 @@ async def decrement_strikes( # type: ignore[misc] try: discord_member_strikes: DiscordMemberStrikes = ( - await DiscordMemberStrikes.objects.aget( - discord_id=strike_member.id - ) + await DiscordMemberStrikes.objects.aget(discord_id=strike_member.id) ) except DiscordMemberStrikes.DoesNotExist: await ctx.respond( From 186fee68ed860212d8fb51f6f7b300c4de9a50c6 Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Sun, 11 May 2025 00:51:06 +0100 Subject: [PATCH 23/28] update old method too --- cogs/strike.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cogs/strike.py b/cogs/strike.py index 1466d8e31..f3c4f460a 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -356,8 +356,7 @@ async def _confirm_increase_strike( raise TypeError(STRIKE_USER_TYPE_ERROR_MESSAGE) if member_strikes.strikes < 3: - member_strikes.strikes += 1 - await member_strikes.asave() + await member_strikes.aupdate(strikes=F("strikes") + 1) await self._send_strike_user_message(strike_user, member_strikes) From e6b7f114eb3dfb02f1328d90d0959048f4df7f13 Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Sun, 11 May 2025 14:35:56 +0100 Subject: [PATCH 24/28] fix ephemerality --- cogs/strike.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cogs/strike.py b/cogs/strike.py index f3c4f460a..fa4922ab1 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -909,7 +909,8 @@ async def get_strikes( # type: ignore[misc] logger.debug("No strikes found for user %s", strike_member) await ctx.respond( - content=(f"User {strike_member.mention} has {strikes_count} strikes.") + content=(f"User {strike_member.mention} has {strikes_count} strikes."), + ephemeral=True, ) @discord.slash_command( # type: ignore[misc, no-untyped-call] @@ -964,7 +965,8 @@ async def decrement_strikes( # type: ignore[misc] if discord_member_strikes.strikes <= 1: await discord_member_strikes.adelete() await ctx.respond( - content=f"Successfully removed all strikes from {strike_member.mention}." + content=f"Successfully removed all strikes from {strike_member.mention}.", + ephemeral=True, ) logger.info( "%s removed all strikes from user %s", @@ -978,7 +980,7 @@ async def decrement_strikes( # type: ignore[misc] content=( f"Successfully removed a strike from {strike_member.mention}. " f"User now has {discord_member_strikes.strikes} strikes." - ) + ), ephemeral=True ) logger.info( "%s removed 1 strike from user %s, they now have %s", From b60617f8ce08fce8ea842dd50ef6d058d3a451bd Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Sun, 11 May 2025 13:36:48 +0000 Subject: [PATCH 25/28] [pre-commit.ci lite] apply automatic fixes --- cogs/strike.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cogs/strike.py b/cogs/strike.py index fa4922ab1..4e8140067 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -980,7 +980,8 @@ async def decrement_strikes( # type: ignore[misc] content=( f"Successfully removed a strike from {strike_member.mention}. " f"User now has {discord_member_strikes.strikes} strikes." - ), ephemeral=True + ), + ephemeral=True, ) logger.info( "%s removed 1 strike from user %s, they now have %s", From 1837306b6bf8664e1c9a7c7776de2c079f9944d2 Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Sun, 11 May 2025 22:00:48 +0100 Subject: [PATCH 26/28] fix the f string stuff --- cogs/strike.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cogs/strike.py b/cogs/strike.py index 4e8140067..d8c499366 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -356,7 +356,7 @@ async def _confirm_increase_strike( raise TypeError(STRIKE_USER_TYPE_ERROR_MESSAGE) if member_strikes.strikes < 3: - await member_strikes.aupdate(strikes=F("strikes") + 1) + await member_strikes.aupdate(strikes=member_strikes.strikes + 1) await self._send_strike_user_message(strike_user, member_strikes) @@ -950,7 +950,7 @@ async def decrement_strikes( # type: ignore[misc] except DiscordMemberStrikes.DoesNotExist: await ctx.respond( content=( - ":information_source: No action taken." + ":information_source: No action taken. " f"User {strike_member.mention} does not have any strikes to remove!" ), ephemeral=True, @@ -975,7 +975,7 @@ async def decrement_strikes( # type: ignore[misc] ) return - await discord_member_strikes.aupdate(strikes=F("strikes") - 1) + await discord_member_strikes.aupdate(strikes=discord_member_strikes.strikes - 1) await ctx.respond( content=( f"Successfully removed a strike from {strike_member.mention}. " From ac2520737fafc1550361e13bb0c745cc4087a993 Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Mon, 12 May 2025 09:50:16 +0100 Subject: [PATCH 27/28] yeet the import --- cogs/strike.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cogs/strike.py b/cogs/strike.py index d8c499366..b61d3a637 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -10,7 +10,6 @@ import discord from asyncstdlib.builtins import any as asyncany from discord.ui import View -from django.db.models import F from config import settings from db.core.models import DiscordMemberStrikes From 32934784375e6cdbd4056dccc4853ecc01595cc8 Mon Sep 17 00:00:00 2001 From: MattyTheHacker <18513864+MattyTheHacker@users.noreply.github.com> Date: Mon, 12 May 2025 18:00:40 +0100 Subject: [PATCH 28/28] revert to use `asave` --- cogs/strike.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cogs/strike.py b/cogs/strike.py index b61d3a637..c4a9db299 100644 --- a/cogs/strike.py +++ b/cogs/strike.py @@ -355,7 +355,8 @@ async def _confirm_increase_strike( raise TypeError(STRIKE_USER_TYPE_ERROR_MESSAGE) if member_strikes.strikes < 3: - await member_strikes.aupdate(strikes=member_strikes.strikes + 1) + member_strikes.strikes += 1 + await member_strikes.asave() await self._send_strike_user_message(strike_user, member_strikes) @@ -974,7 +975,8 @@ async def decrement_strikes( # type: ignore[misc] ) return - await discord_member_strikes.aupdate(strikes=discord_member_strikes.strikes - 1) + discord_member_strikes.strikes -= 1 + await discord_member_strikes.asave() await ctx.respond( content=( f"Successfully removed a strike from {strike_member.mention}. "