aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bot/exts/info/subscribe.py128
1 files changed, 62 insertions, 66 deletions
diff --git a/bot/exts/info/subscribe.py b/bot/exts/info/subscribe.py
index 1aec0e3a0..333f33b50 100644
--- a/bot/exts/info/subscribe.py
+++ b/bot/exts/info/subscribe.py
@@ -55,72 +55,18 @@ ASSIGNABLE_ROLES = (
)
ITEMS_PER_ROW = 3
-DELETE_MESSAGE_AFTER = 300 # Seconds
+DELETE_MESSAGE_AFTER = 20 # Seconds
log = get_logger(__name__)
-class AllSelfAssignableRolesView(discord.ui.View):
- """A view that'll hold one button allowing interactors to get all available self-assignable roles."""
-
- def __init__(self):
- super(AllSelfAssignableRolesView, self).__init__(timeout=None)
-
-
-class ClaimAllSelfAssignableRolesButton(discord.ui.Button):
- """A button that adds all self assignable roles to the interactor."""
-
- CUSTOM_ID = "gotta-claim-them-all"
-
- def __init__(self, assignable_roles: list[AssignableRole]):
- super().__init__(
- style=discord.ButtonStyle.success,
- label="Claim all available roles",
- custom_id=self.CUSTOM_ID,
- row=1
- )
- self.assignable_roles = assignable_roles
-
- async def callback(self, interaction: Interaction) -> t.Any:
- """Assigns all missing available roles to the interactor."""
- await interaction.response.defer()
-
- if isinstance(interaction.user, discord.User):
- log.trace("User %s is not a member", interaction.user)
- await interaction.message.delete()
- self.view.stop()
- return
-
- author_roles = [role.id for role in interaction.user.roles]
- assigned_roles = []
-
- for role in self.assignable_roles:
- if role.role_id in author_roles:
- continue
- if not role.is_currently_available():
- continue
-
- log.debug(f"Assigning role {role.name} to {interaction.user.display_name}")
- await members.handle_role_change(
- interaction.user,
- interaction.user.add_roles,
- discord.Object(role.role_id),
- )
-
- assigned_roles.append(role.name)
-
- if assigned_roles:
- await interaction.followup.send(
- f"The following roles have been assigned to you: {', '.join(assigned_roles)}",
- ephemeral=True,
- )
-
-
class RoleButtonView(discord.ui.View):
"""A list of SingleRoleButtons to show to the member."""
def __init__(self, member: discord.Member):
- super().__init__()
+ super().__init__(timeout=DELETE_MESSAGE_AFTER)
+ # We can't obtain the reference to the message before the view is sent
+ self.original_message = None
self.interaction_owner = member
async def interaction_check(self, interaction: Interaction) -> bool:
@@ -133,6 +79,10 @@ class RoleButtonView(discord.ui.View):
return False
return True
+ async def on_timeout(self) -> None:
+ """Delete the original message that the view was sent along with."""
+ await self.original_message.delete()
+
class SingleRoleButton(discord.ui.Button):
"""A button that adds or removes a role from the member depending on it's current state."""
@@ -196,6 +146,38 @@ class SingleRoleButton(discord.ui.Button):
self.view.stop()
+class AllSelfAssignableRolesView(discord.ui.View):
+ """A view that'll hold one button allowing interactors to get all available self-assignable roles."""
+
+ def __init__(self):
+ super(AllSelfAssignableRolesView, self).__init__(timeout=None)
+
+
+class ClaimAllSelfAssignableRolesButton(discord.ui.Button):
+ """A button that adds all self assignable roles to the interactor."""
+
+ CUSTOM_ID = "gotta-claim-them-all"
+
+ def __init__(self, assignable_roles: list[AssignableRole]):
+ super().__init__(
+ style=discord.ButtonStyle.success,
+ label="Claim all available roles",
+ custom_id=self.CUSTOM_ID,
+ row=1
+ )
+ self.assignable_roles = assignable_roles
+
+ async def callback(self, interaction: Interaction) -> t.Any:
+ """Assigns all missing available roles to the interactor."""
+ await interaction.response.defer()
+ view = prepare_available_role_subscription_view(interaction, self.assignable_roles)
+ message = await interaction.followup.send(
+ view=view,
+ )
+ # Keep reference of the message that contains the view to be deleted
+ view.original_message = message
+
+
class Subscribe(commands.Cog):
"""Cog to allow user to self-assign & remove the roles present in ASSIGNABLE_ROLES."""
@@ -239,17 +221,14 @@ class Subscribe(commands.Cog):
)
async def subscribe_command(self, ctx: commands.Context, *_) -> None: # We don't actually care about the args
"""Display the member's current state for each role, and allow them to add/remove the roles."""
- button_view = RoleButtonView(ctx.author)
- author_roles = [role.id for role in ctx.author.roles]
- for index, role in enumerate(self.assignable_roles):
- row = index // ITEMS_PER_ROW
- button_view.add_item(SingleRoleButton(role, role.role_id in author_roles, row))
+ view = prepare_available_role_subscription_view(ctx, self.assignable_roles)
- await ctx.send(
+ message = await ctx.send(
"Click the buttons below to add or remove your roles!",
- view=button_view,
- delete_after=DELETE_MESSAGE_AFTER,
+ view=view,
)
+ # Keep reference of the message that contains the view to be deleted
+ view.original_message = message
async def __search_for_self_assignable_roles_message(self) -> discord.Message:
"""
@@ -281,6 +260,23 @@ class Subscribe(commands.Cog):
self.bot.add_view(view, message_id=message.id)
+def prepare_available_role_subscription_view(
+ trigger_action: commands.Context | Interaction,
+ assignable_roles: list[AssignableRole]
+) -> discord.ui.View:
+ """Prepares the view containing the self assignable roles before its sent."""
+ author = trigger_action.author if isinstance(trigger_action, commands.Context) else trigger_action.user
+ author_roles = [role.id for role in author.roles]
+ button_view = RoleButtonView(member=author)
+ button_view.original_message = trigger_action.message
+
+ for index, role in enumerate(assignable_roles):
+ row = index // ITEMS_PER_ROW
+ button_view.add_item(SingleRoleButton(role, role.role_id in author_roles, row))
+
+ return button_view
+
+
async def setup(bot: Bot) -> None:
"""Load the Subscribe cog."""
if len(ASSIGNABLE_ROLES) > ITEMS_PER_ROW*5: # Discord limits views to 5 rows of buttons.