From 40b347c875bdbdfca69c8791949df70d22d6a2f7 Mon Sep 17 00:00:00 2001 From: Vegard Berg Date: Thu, 4 Aug 2022 00:56:46 +0200 Subject: [PATCH] Added updating role group messages and exclusive roles Added a context menu for messages for updating a role group message. Ideally this would be done automatically, but this works fine for now. Alternatively, this may be ideal if one doesn't want changes to immediately propagate. Added the option for some role groups to have their roles be mutually exclusive. I.e. one would only be able to pick one role from the group. --- commands/self_roles.py | 172 ++++++++++++++++++++++++++++++++++++----- database.py | 2 + 2 files changed, 153 insertions(+), 21 deletions(-) diff --git a/commands/self_roles.py b/commands/self_roles.py index 0e3ad59..acaea6e 100644 --- a/commands/self_roles.py +++ b/commands/self_roles.py @@ -16,7 +16,9 @@ from naff import ( Select, SelectOption, listen, - component_callback, + context_menu, + CommandTypes, + Message, ) from naff.api import events from naff import components @@ -124,8 +126,18 @@ class SelfRoles(Extension): required=False, opt_type=OptionTypes.STRING, ) + @slash_option( + name="exclusive", + description="Whether each role in this group is exclusive", + required=False, + opt_type=OptionTypes.BOOLEAN, + ) async def role_group_add_group( - self, ctx: InteractionContext, group: str, description: str = None + self, + ctx: InteractionContext, + group: str, + description: str = None, + exclusive: bool = False, ): await ctx.defer(ephemeral=True) @@ -133,6 +145,7 @@ class SelfRoles(Extension): guild_id=int(ctx.guild_id), group_name=group, group_description=description, + exclusive=exclusive, ).on_conflict_replace().execute() await ctx.send( @@ -391,18 +404,28 @@ class SelfRoles(Extension): autocomplete=True, ) async def role_group_generate(self, ctx: InteractionContext, group: str): - await ctx.defer(ephemeral=False) + await ctx.defer(ephemeral=True) roles_q: List[SelfRolesModel] = ( - SelfRolesModel.select(SelfRolesModel.role_name, SelfRolesModel.role_id, SelfRolesModel.role_description) - .join(SelfRoleGroupRelationsModel, on=(SelfRolesModel.role_id == SelfRoleGroupRelationsModel.role_id)) + SelfRolesModel.select( + SelfRolesModel.role_name, + SelfRolesModel.role_id, + SelfRolesModel.role_description, + ) + .join( + SelfRoleGroupRelationsModel, + on=(SelfRolesModel.role_id == SelfRoleGroupRelationsModel.role_id), + ) .where( SelfRoleGroupRelationsModel.guild_id == int(ctx.guild_id), SelfRoleGroupRelationsModel.group_name == group, - ).objects() + ) + .objects() ) - group_q = SelfRoleGroupsModel.get(SelfRoleGroupsModel.group_name == group) + group_q: SelfRoleGroupsModel = SelfRoleGroupsModel.get( + SelfRoleGroupsModel.group_name == group + ) options = [] for role in roles_q: @@ -413,15 +436,17 @@ class SelfRoles(Extension): ) options.append(opt) + max_vals = 1 if group_q.exclusive else len(options) + select = Select( options=options, placeholder=f"Select roles from the group {group}", custom_id=f"role-group-assign:{group}", min_values=0, - max_values=len(options), + max_values=max_vals, ) - await ctx.send( + msg = await ctx.channel.send( embed=Embed( title=f"{group}", description=group_q.group_description, @@ -429,7 +454,11 @@ class SelfRoles(Extension): components=select, ) - + if msg is not None: + await ctx.send("Created!", ephemeral=True) + else: + await ctx.send("Failed to create message!", ephemeral=True) + @role_group_generate.autocomplete("group") async def role_group_generate_group_autocomplete( self, ctx: AutocompleteContext, group: str @@ -457,12 +486,21 @@ class SelfRoles(Extension): role_ids = [int(r) for r in ctx.values] roles_q: List[SelfRolesModel] = ( - SelfRolesModel.select(SelfRolesModel.role_name, SelfRolesModel.role_id, SelfRolesModel.requires, SelfRoleGroupRelationsModel.group_name) - .join(SelfRoleGroupRelationsModel, on=(SelfRolesModel.role_id == SelfRoleGroupRelationsModel.role_id)) + SelfRolesModel.select( + SelfRolesModel.role_name, + SelfRolesModel.role_id, + SelfRolesModel.requires, + SelfRoleGroupRelationsModel.group_name, + ) + .join( + SelfRoleGroupRelationsModel, + on=(SelfRolesModel.role_id == SelfRoleGroupRelationsModel.role_id), + ) .where( SelfRoleGroupRelationsModel.guild_id == int(ctx.guild_id), SelfRoleGroupRelationsModel.group_name == group, - ).objects() + ) + .objects() ) actions = [] @@ -471,7 +509,9 @@ class SelfRoles(Extension): if not ctx.author.has_role(role.role_id): if not role.requires is None: if not ctx.author.has_role(role.requires): - actions.append(f"{role.role_name} requires {role.requires} and was not added.") + actions.append( + f"{role.role_name} requires {role.requires} and was not added." + ) continue await ctx.author.add_role(role.role_id) @@ -480,20 +520,110 @@ class SelfRoles(Extension): if ctx.author.has_role(role.role_id): if not role.requires is None: if not ctx.author.has_role(role.requires): - actions.append(f"{role.role_name} requires {role.requires} to be managed, and was therefore not removed.") + actions.append( + f"{role.role_name} requires {role.requires} to be managed, and was therefore not removed." + ) continue await ctx.author.remove_role(role.role_id) actions.append(f"Removed role {role.role_name}") - await ctx.send( - content="\n".join(actions), - ephemeral=True, + if len(actions) == 0: + await ctx.send("No roles were added or removed.") + else: + await ctx.send( + content="\n".join(actions), + ephemeral=True, + ) + + @context_menu( + name="Regenerate group", + context_type=CommandTypes.MESSAGE, + dm_permission=False, + default_member_permissions=Permissions.MANAGE_ROLES, + ) + async def role_group_regenerate(self, ctx: InteractionContext): + await ctx.defer(ephemeral=True) + msg: Message = ctx.target + + if msg.author.id != self.client.user.id: + await ctx.send("This message is not from the bot!", ephemeral=True) + return + + if ( + len(msg.embeds) < 1 + or msg.embeds[0].title is None + or len(msg.components) < 1 + or len(msg.components[0].components) < 1 + or not isinstance(msg.components[0].components[0], Select) + or not msg.components[0].components[0].custom_id.startswith("role-group-assign") + ): + await ctx.send("Could not identify this as a role-group message!", ephemeral=True) + return + + embed = msg.embeds[0] + group = msg.components[0].components[0].custom_id.split(":")[1] + if ( + group is None + or group == "" + or embed.title != group + ): + await ctx.send("Could not identify this as a role-group message!", ephemeral=True) + return + + roles_q: List[SelfRolesModel] = ( + SelfRolesModel.select( + SelfRolesModel.role_name, + SelfRolesModel.role_id, + SelfRolesModel.role_description, + ) + .join( + SelfRoleGroupRelationsModel, + on=(SelfRolesModel.role_id == SelfRoleGroupRelationsModel.role_id), + ) + .where( + SelfRoleGroupRelationsModel.guild_id == int(ctx.guild_id), + SelfRoleGroupRelationsModel.group_name == group, + ) + .objects() ) + group_q: SelfRoleGroupsModel = SelfRoleGroupsModel.get( + SelfRoleGroupsModel.group_name == group + ) + + options = [] + for role in roles_q: + opt = SelectOption( + label=role.role_name, + value=str(role.role_id), + description=role.role_description, + ) + options.append(opt) + + max_vals = 1 if group_q.exclusive else len(options) + + select = Select( + options=options, + placeholder=f"Select roles from the group {group}", + custom_id=f"role-group-assign:{group}", + min_values=0, + max_values=max_vals, + ) + + msg = await msg.edit( + embed=Embed( + title=f"{group}", + description=group_q.group_description, + ), + components=select, + ) + + await ctx.send("Role group message regenerated!", ephemeral=True) + + + - - - + @slash_command( name="role", diff --git a/database.py b/database.py index 4c1c9a6..e443044 100644 --- a/database.py +++ b/database.py @@ -122,6 +122,8 @@ class SelfRoleGroups(Model): """The name of the self-role group.""" group_description = TextField(null=True) """The description of the self-role group.""" + exclusive = BooleanField(default=False) + """Whether the self-role group is exclusive.""" class Meta: primary_key = CompositeKey("guild_id", "group_name")