diff --git a/main.py b/main.py old mode 100644 new mode 100755 index e69de29..52a9db2 --- a/main.py +++ b/main.py @@ -0,0 +1,83 @@ +#!/bin/env python3 +from typing import Literal, Optional +from emoji import emojize +from yaml import safe_load + +import discord +from discord.ext import commands +from discord.ext.commands import Greedy, Context +from discord import app_commands + +from src.roles import AddRoleButton, RemoveRoleButton + +class Bot(commands.Bot): + with open('config.yaml', 'r') as file: + config = safe_load(file) + +# Bot +intents=discord.Intents.default() +intents.message_content = True +client = Bot(intents=intents, command_prefix=",") + +# Command Groups +roles = app_commands.Group(name="roles", description="Manage role dialogues") + +# Commands +## Group: roles +@roles.command(name="create") +async def roles_create_button(interaction: discord.Interaction): + view = discord.ui.View() + view.add_item( + AddRoleButton( + style=discord.ButtonStyle.primary, + label="Add Roles", + emoji=discord.PartialEmoji.from_str(emojize(":check_mark_button:")) + ) + ) + view.add_item( + RemoveRoleButton( + style=discord.ButtonStyle.secondary, + label="Remove Roles", + emoji=discord.PartialEmoji.from_str(emojize(":cross_mark:")) + ) + ) + await interaction.response.send_message(view=view) + +# Sync using ,sync ~ +@client.command() +@commands.guild_only() +@commands.is_owner() +async def sync( + ctx: Context, guilds: Greedy[discord.Object], spec: Optional[Literal["~", "*", "^"]] = None) -> None: + if not guilds: + if spec == "~": + synced = await ctx.bot.tree.sync(guild=ctx.guild) + elif spec == "*": + ctx.bot.tree.copy_global_to(guild=ctx.guild) + synced = await ctx.bot.tree.sync(guild=ctx.guild) + elif spec == "^": + ctx.bot.tree.clear_commands(guild=ctx.guild) + await ctx.bot.tree.sync(guild=ctx.guild) + synced = [] + else: + synced = await ctx.bot.tree.sync() + + await ctx.send( + f"Synced {len(synced)} commands {'globally' if spec is None else 'to the current guild.'}" + ) + return + + ret = 0 + for guild in guilds: + try: + await ctx.bot.tree.sync(guild=guild) + except discord.HTTPException: + pass + else: + ret += 1 + + await ctx.send(f"Synced the tree to {ret}/{len(guilds)}.") + +if __name__ == "__main__": + client.tree.add_command(roles) + client.run(client.config['auth']['token']) diff --git a/src/roles.py b/src/roles.py new file mode 100644 index 0000000..ccf8d68 --- /dev/null +++ b/src/roles.py @@ -0,0 +1,82 @@ +from discord import Interaction, SelectOption +from discord.ui import Button, Select, View + +class AddRoleSelect(Select): + async def callback(self, interaction: Interaction): + added_roles = [ + role for role in [ interaction.guild.get_role(int(role_id)) for role_id in interaction.data['values'] ] + if role not in interaction.user.roles + ] + + print(added_roles) + for role in added_roles: + await interaction.user.add_roles(role) + + await interaction.response.send_message( + ephemeral=True, + content="Added Roles: " + ", ".join([ role.mention for role in added_roles ]) + ) + +class RemoveRoleSelect(Select): + async def callback(self, interaction: Interaction): + removed_roles = [ + role for role in [ interaction.guild.get_role(int(role_id)) for role_id in interaction.data['values'] ] + if role in interaction.user.roles + ] + + for role in removed_roles: + await interaction.user.remove_roles(role) + + await interaction.response.send_message( + ephemeral=True, + content="Removed Roles: " + ", ".join([ role.mention for role in removed_roles ]) + ) + +class AddRoleButton(Button): + async def callback(self, interaction: Interaction): + view=View() + view.add_item( + AddRoleSelect( + min_values=0, + max_values=len(interaction.client.config['roles']) if len(interaction.client.config['roles']) <= 25 else 25, + placeholder="Select roles to add:", + options = [ + SelectOption( + label=f"@{interaction.guild.get_role(role['id']).name}", + value=role['id'], + description=role['description'], + emoji=interaction.client.get_emoji(role['emoji']) + ) + for role in interaction.client.config['roles'] + if role['id'] in [ role.id for role in list(interaction.guild.roles) ] + ] + ) + ) + await interaction.response.send_message( + ephemeral=True, + view=view + ) + +class RemoveRoleButton(Button): + async def callback(self, interaction: Interaction): + view=View() + view.add_item( + RemoveRoleSelect( + min_values=0, + max_values=len(interaction.client.config['roles']) if len(interaction.client.config['roles']) <= 25 else 25, + placeholder="Select roles to remove:", + options = [ + SelectOption( + label=f"@{interaction.guild.get_role(role['id']).name}", + value=role['id'], + description=role['description'], + emoji=interaction.client.get_emoji(role['emoji']) + ) + for role in interaction.client.config['roles'] + ] + ) + ) + await interaction.response.send_message( + ephemeral=True, + view=view + )