import discord from cogs import FeatureCog from discord import option from discord.ext import commands, bridge from setup.config import Config from setup.logger import LOGGER class RolesCog(FeatureCog): def __init__(self, bot: discord.Bot): super().__init__(bot, feature_name="roles") @bridge.bridge_command() async def roles(self, ctx: discord.ApplicationContext, category: bridge.BridgeOption(name="category", description="The category to manipulate", input_type=str, required=True)): if not ctx.guild: await ctx.respond("This command must be used in a guild.", ephemeral=True) return guild_id = ctx.guild.id if not self.is_enabled(guild_id): await ctx.respond("Roles feature is disabled for this guild.", ephemeral=True) return guild_cfg = Config.GUILD_CONFIGS.get(guild_id) if not guild_cfg: await ctx.respond("No configuration for this guild.", ephemeral=True) return categories = guild_cfg.get("configs", {}).get("roles", {}).get("categories", []) filtered = [c for c in categories if c.get("category_id") == category] if not filtered: await ctx.respond("Category not found.", ephemeral=True) return await ctx.defer() config_category = filtered.pop() embed = discord.Embed( title=config_category.get("category_name", ""), description=config_category.get("message_header", ""), color=discord.Color.blue() ) roles_list = [ ctx.guild.get_role(role_config.get("role_id")) for role_config in config_category.get("roles", []) ] for role_instance, role_config in zip(roles_list, config_category.get("roles", [])): mention = role_instance.mention if role_instance else "(role missing)" embed.add_field(name=role_config.get("reaction", ""), value=mention) message = await ctx.send(embed=embed) if message: config_category["message_id"] = message.id # persist the updated guild config Config.save_guild_config(guild_id) for config_role in config_category.get("roles", []): reaction = config_role.get("reaction") if reaction: await message.add_reaction(reaction) await ctx.followup.send("Role message generated", ephemeral=True) @commands.Cog.listener() async def on_raw_reaction_add(self, payload: discord.RawReactionActionEvent): if payload.user_id == self.bot.user.id: return guild_id = payload.guild_id guild_cfg = Config.GUILD_CONFIGS.get(guild_id) if not guild_cfg: return if not self.is_enabled(guild_id): return categories = guild_cfg.get("configs", {}).get("roles", {}).get("categories", []) filtered = [c for c in categories if c.get("message_id") == payload.message_id] if not filtered: return config_category = filtered.pop() role_ids = [config_role.get("role_id") for config_role in config_category.get("roles", []) if config_role.get("reaction") == payload.emoji.name] if not role_ids: return role_id = role_ids.pop() guild = self.bot.get_guild(guild_id) if not guild: return role = guild.get_role(role_id) if not role: return user = guild.get_member(payload.user_id) if not user: return if "parent_role_id" in config_category: parent_role = guild.get_role(config_category.get("parent_role_id")) if parent_role: await user.add_roles(parent_role, role) return await user.add_roles(role) @commands.Cog.listener() async def on_raw_reaction_remove(self, payload: discord.RawReactionActionEvent): if payload.user_id == self.bot.user.id: return guild_id = payload.guild_id guild_cfg = Config.GUILD_CONFIGS.get(guild_id) if not guild_cfg: return if not self.is_enabled(guild_id): return categories = guild_cfg.get("configs", {}).get("roles", {}).get("categories", []) filtered = [c for c in categories if c.get("message_id") == payload.message_id] if not filtered: return config_category = filtered.pop() role_ids = [config_role.get("role_id") for config_role in config_category.get("roles", []) if config_role.get("reaction") == payload.emoji.name] if not role_ids: return role_id = role_ids.pop() guild = self.bot.get_guild(guild_id) if not guild: return role = guild.get_role(role_id) if not role: return user = guild.get_member(payload.user_id) if not user: return if "parent_role_id" in config_category: parent_role = guild.get_role(config_category.get("parent_role_id")) if parent_role: await user.remove_roles(parent_role, role) return await user.remove_roles(role)