# db - msg_id, user_id, guild_id import asyncio import discord import os import json import pickle from dotenv import load_dotenv from discord.ui import Modal, InputText from discord.utils import get from discord.ext import commands from dbutil import MessageDB from dbutil import StartButtonDB from dbutil import GuildAppDB from action import Action, ActionInteraction, actions usable_actions = actions load_dotenv() TOKEN = os.getenv("TOKEN") bot = discord.Bot(intents=discord.Intents.all()) @bot.event async def on_ready(): bot.add_view(ApplicationButtonsView()) bot.add_view(ApplicationStartButtonView()) activity = discord.Activity(name=f"{len(bot.guilds)} guilds", type=discord.ActivityType.listening) await bot.change_presence(activity=activity, status = discord.Status.online) print(f"Logged in as {bot.user}") await bot.sync_commands(force=True) for i in bot.guilds: if str(i.id) not in GuildAppDB.get_all_guilds(): GuildAppDB.create_guild(str(i.id), i.name) print(f"Entry for {i.id} created") @bot.event async def on_guild_join(guild): activity = discord.Activity(name=f"{len(bot.guilds)} guilds", type=discord.ActivityType.listening) await bot.change_presence(activity=activity, status = discord.Status.online) GuildAppDB.create_guild(str(guild.id), guild.name) print(f"Joined guild {guild.name}: {guild.id}") @bot.event async def on_guild_remove(guild): activity = discord.Activity(name=f"{len(bot.guilds)} guilds", type=discord.ActivityType.listening) await bot.change_presence(activity=activity, status = discord.Status.online) print(f"Removed from guild {guild.name}: {guild.id}") @commands.has_permissions(administrator=True) @bot.slash_command(description = "Command used to set up the application prompt") async def start_button(ctx): view = discord.ui.View() options = SelectApplicationStartButton(max_values=1, placeholder="Select application") for i in GuildAppDB.get_applications(str(ctx.guild.id)): options.add_option(label=i, value=i) view.add_item(options) await ctx.response.send_message(view=view, ephemeral=True) @start_button.error async def on_application_command_error(ctx, error): if isinstance(error, commands.MissingPermissions): await ctx.respond("You need Administrator permissions to use this command", ephemeral=True) else: raise error application = discord.SlashCommandGroup("application", "The main command to manage applications") @commands.has_permissions(administrator=True) @application.command(description="Create application") async def create(ctx, application): if len(application) < 40: result = GuildAppDB.add_application_entry(str(ctx.guild.id), application) if result == "success": await ctx.response.send_message(f"Successfully created application: {application}\n\nDon't forget to set the response channel!", ephemeral=True) # create a new application, modal with name ask else: await ctx.response.send_message(f"please choose shorter name", ephemeral=True) @commands.has_permissions(administrator=True) @application.command(description="Remove application") async def remove(ctx, application): result = GuildAppDB.remove_application_entry(str(ctx.guild.id), application) if result == "success": await ctx.response.send_message(f"Successfully removed application: {application}", ephemeral=True) else: await ctx.response.send_message(f"Application {application} not found", ephemeral=True) @commands.has_permissions(administrator=True) @application.command(description="List all applications") async def list(ctx): applications = GuildAppDB.get_applications(str(ctx.guild.id)) embed = discord.Embed(title="**List of applications**") embed.set_footer(text="Made by @anorak01", icon_url="https://cdn.discordapp.com/avatars/269164865480949760/a1af9962da20d5ddaa136043cf45d015?size=1024") for i, app in enumerate(applications): embed.add_field(value=f"**{i+1}. {app}**", name="", inline=False) await ctx.response.send_message(embed=embed, ephemeral=True) @commands.has_permissions(administrator=True) @application.command(description="Opens editor for selected application") async def editor(ctx): view = discord.ui.View() options = SelectApplicationOptionsEditor(max_values=1, placeholder="Select application") for i in GuildAppDB.get_applications(str(ctx.guild.id)): options.add_option(label=i, value=i) view.add_item(options) await ctx.response.send_message(view=view, ephemeral=True) @commands.has_permissions(administrator=True) @application.command(description="Opens Actions™ editor") async def actions(ctx): view = discord.ui.View() options = SelectActionOptionsEditor(max_values=1, placeholder="Select application") for i in GuildAppDB.get_applications(str(ctx.guild.id)): options.add_option(label=i, value=i) view.add_item(options) await ctx.response.send_message(view=view, ephemeral=True) @commands.has_permissions(administrator=True) @application.command(description="Select response channel for application") async def response_channel(ctx): view = discord.ui.View() options = SelectApplicationOptionsRespChannel(max_values=1, placeholder="Select application") for i in GuildAppDB.get_applications(str(ctx.guild.id)): options.add_option(label=i, value=i) view.add_item(options) await ctx.response.send_message(view=view, ephemeral=True) bot.add_application_command(application) # add application group commands def get_questions_embed(guild_id, application) -> discord.Embed: embed = discord.Embed(title=f"Application: {application}") questions, length = GuildAppDB.get_questions(str(guild_id), application) for i, que in enumerate(questions): embed.add_field(value=f"**{i+1}. {que}**", name="", inline=False) embed.set_footer(text="Made by @anorak01", icon_url="https://cdn.discordapp.com/avatars/269164865480949760/a1af9962da20d5ddaa136043cf45d015?size=1024") return embed class SelectApplicationStartButton(discord.ui.Select): async def callback(self, interaction: discord.Interaction): self.disabled = True embed = discord.Embed(title="**Start your application!**") embed.add_field(name=f"Click the button below to start your application for: {self.values[0]}", value="", inline=False) embed.set_footer(text="Made by @anorak01", icon_url="https://cdn.discordapp.com/avatars/269164865480949760/a1af9962da20d5ddaa136043cf45d015?size=1024") appStartView = ApplicationStartButtonView() await interaction.response.edit_message(embed=None, content="Application button created", view=None) message = await interaction.channel.send(embed = embed, view=appStartView) StartButtonDB.add_start_msg(str(message.id), str(self.values[0]), str(interaction.guild.id)) class SelectResponseChannelView(discord.ui.View): @discord.ui.select( select_type=discord.ComponentType.channel_select, channel_types=[discord.ChannelType.text], max_values=1 ) async def select_callback(self, select, interaction: discord.Interaction): self.disable_all_items() GuildAppDB.set_response_channel(interaction.guild.id, ) await interaction.response.edit_message(content=f"Selected channel: {select.values[0].mention}", view=None) class SelectApplicationOptionsEditor(discord.ui.Select): async def callback(self, interaction: discord.Interaction): self.disabled = True editor = ApplicationEditorView(str(interaction.guild.id), self.values[0]) embed = get_questions_embed(str(interaction.guild.id), self.values[0]) await interaction.response.edit_message(embed = embed, view=editor) class SelectApplicationOptionsRespChannel(discord.ui.Select): async def callback(self, interaction: discord.Interaction): self.disabled = True view = discord.ui.View() options = SelectResponseChannel(select_type=discord.ComponentType.channel_select, channel_types=[discord.ChannelType.text], max_values=1, placeholder="Select channel") options.set_app_name(self.values[0]) view.add_item(options) await interaction.response.edit_message(view=view) class SelectResponseChannel(discord.ui.Select): def set_app_name(self, app_name): self.app_name = app_name async def callback(self, interaction: discord.Interaction): self.disabled = True GuildAppDB.set_response_channel(str(interaction.guild.id), self.app_name, str(self.values[0].id)) await interaction.response.edit_message(content=f"Selected channel: {self.values[0].mention} for application: {self.app_name}", view=None) class ApplicationEditorView(discord.ui.View): def __init__(self, guild_id, application_name): super().__init__(timeout=180) self.guild_id = guild_id self.application_name = application_name @discord.ui.button( label="New", style=discord.ButtonStyle.green, custom_id="editor:add", row=0 ) async def add_question(self, button: discord.ui.Button, interaction: discord.Interaction): modal = AddQuestionModal(self.application_name) await interaction.response.send_modal(modal) @discord.ui.button( label="Remove", style=discord.ButtonStyle.red, custom_id="editor:remove", row=0 ) async def remove_question(self, button, interaction: discord.Interaction): view = ApplicationEditorView(str(interaction.guild.id), self.application_name) options = RemoveQuestionSelect(max_values=1, placeholder="Select question to remove") options.set_app_name(self.application_name) questions, length = GuildAppDB.get_questions(str(interaction.guild.id), self.application_name) for i, que in enumerate(questions): options.add_option(label=f"{str(i+1)}. {que}", value=str(i)) view.add_item(options) await interaction.response.edit_message(view=view) @discord.ui.button( label="Edit", style=discord.ButtonStyle.primary, custom_id="editor:edit", row=0 ) async def edit_question(self, button, interaction: discord.Interaction): view = ApplicationEditorView(str(interaction.guild.id), self.application_name) options = EditQuestionSelect(max_values=1, placeholder="Select question to edit") options.set_app_name(self.application_name) questions, length = GuildAppDB.get_questions(str(interaction.guild.id), self.application_name) for i, que in enumerate(questions): options.add_option(label=f"{str(i+1)}. {que}", value=str(i)) view.add_item(options) await interaction.response.edit_message(view=view) @discord.ui.button( label="Move", style=discord.ButtonStyle.gray, custom_id="editor:move", row=0 ) async def move_question(self, button, interaction: discord.Interaction): view = ApplicationEditorView(str(interaction.guild.id), self.application_name) options = MoveQuestionSelect(max_values=1, placeholder="Select question to move") options.set_app_name(self.application_name) questions, length = GuildAppDB.get_questions(str(interaction.guild.id), self.application_name) for i, que in enumerate(questions): options.add_option(label=f"{str(i+1)}. {que}", value=str(i)) view.add_item(options) await interaction.response.edit_message(view=view) class AddQuestionModal(discord.ui.Modal): def __init__(self, app_name): self.app_name = app_name super().__init__(discord.ui.InputText(label=f"New Question: "), title = "") async def callback(self, interaction: discord.Interaction): question = self.children[0].value GuildAppDB.add_question(str(interaction.guild.id), self.app_name, question) embed = get_questions_embed(str(interaction.guild.id), self.app_name) await interaction.response.edit_message(embed=embed) class RemoveQuestionSelect(discord.ui.Select): def set_app_name(self, app_name): self.app_name = app_name async def callback(self, interaction: discord.Interaction): self.disabled = True GuildAppDB.remove_question(str(interaction.guild.id), self.app_name, int(self.values[0])+1) editor = ApplicationEditorView(str(interaction.guild.id), self.app_name) embed = get_questions_embed(str(interaction.guild.id), self.app_name) await interaction.response.edit_message(embed = embed, view = editor) class EditQuestionSelect(discord.ui.Select): def set_app_name(self, app_name): self.app_name = app_name async def callback(self, interaction: discord.Interaction): self.disabled = True editor = ApplicationEditorView(str(interaction.guild.id), self.app_name) modal = EditQuestionModal(self.app_name, int(self.values[0])+1) await interaction.response.send_modal(modal) await interaction.followup.edit_message(view = editor, message_id=interaction.message.id) class EditQuestionModal(discord.ui.Modal): def __init__(self, app_name, question_index): self.app_name = app_name self.question_index = question_index super().__init__(discord.ui.InputText(label=f"Edited Question: "), title = "") async def callback(self, interaction: discord.Interaction): question = self.children[0].value GuildAppDB.edit_question(str(interaction.guild.id), self.app_name, self.question_index, question) embed = get_questions_embed(str(interaction.guild.id), self.app_name) await interaction.response.edit_message(embed=embed) class MoveQuestionSelect(discord.ui.Select): def set_app_name(self, app_name): self.app_name = app_name async def callback(self, interaction: discord.Interaction): self.disabled = True view = ApplicationEditorView(str(interaction.guild.id), self.app_name) options = MoveQuestionSelectNum(max_values=1, placeholder="Select place for move") options.set_app_name(self.app_name) options.set_init_index(int(self.values[0])+1) questions, length = GuildAppDB.get_questions(str(interaction.guild.id), self.app_name) for i in range(length): options.add_option(label=str(i+1), value=str(i+1)) view.add_item(options) await interaction.response.edit_message(view = view) class MoveQuestionSelectNum(discord.ui.Select): def set_app_name(self, app_name): self.app_name = app_name def set_init_index(self, init_index: int): self.init_index = init_index async def callback(self, interaction: discord.Interaction): self.disabled = True editor = ApplicationEditorView(str(interaction.guild.id), self.app_name) GuildAppDB.move_question(str(interaction.guild.id), self.app_name, int(self.init_index), int(self.values[0])) embed = get_questions_embed(str(interaction.guild.id), self.app_name) await interaction.response.edit_message(view = editor, embed=embed) def get_actions_embed(guild_id, application, action_type: ActionInteraction) -> discord.Embed: embed = discord.Embed(title=f"Application: {application}", description=f"Actions happening on: {action_type.value}") actions = GuildAppDB.get_actions(str(guild_id), application, action_type) for i, que in enumerate(actions): if que["action_type"] == "add_role": role = bot.get_guild(int(guild_id)).get_role(que["data"]["role_id"]).name embed.add_field(value=f"**{i+1}. {que['display_type']}: {role}**", name="", inline=False) else: embed.add_field(value=f"**{i+1}. {que['display_type']}**", name="", inline=False) embed.set_footer(text="Made by @anorak01", icon_url="https://cdn.discordapp.com/avatars/269164865480949760/a1af9962da20d5ddaa136043cf45d015?size=1024") return embed class ActionAcceptEditorView(discord.ui.View): def __init__(self, guild_id, application_name): super().__init__(timeout=180) self.guild_id = guild_id self.application_name = application_name @discord.ui.button( label="New", style=discord.ButtonStyle.green, custom_id="action_accept_editor:add", row=0 ) async def add_action(self, button: discord.ui.Button, interaction: discord.Interaction): view = ActionAcceptEditorView(str(interaction.guild.id), self.application_name) options = AddActionSelect(max_values=1, placeholder="Select action to add") options.set_app_name(self.application_name) options.set_action_type(ActionInteraction.ACCEPT) for i, que in enumerate(usable_actions): options.add_option(label=f"{str(i+1)}. {que}", value=str(usable_actions[que])) view.add_item(options) await interaction.response.edit_message(view=view) @discord.ui.button( label="Remove", style=discord.ButtonStyle.red, custom_id="action_accept_editor:remove", row=0 ) async def remove_action(self, button, interaction: discord.Interaction): view = ActionAcceptEditorView(str(interaction.guild.id), self.application_name) options = RemoveActionSelect(max_values=1, placeholder="Select action to remove") options.set_app_name(self.application_name) actions = GuildAppDB.get_actions(str(interaction.guild.id), self.application_name, action_type=ActionInteraction.ACCEPT) options.set_action_type(ActionInteraction.ACCEPT) for i, que in enumerate(actions): options.add_option(label=f"{str(i+1)}. {que}", value=str(i)) view.add_item(options) await interaction.response.edit_message(view=view) class ActionDeclineEditorView(discord.ui.View): def __init__(self, guild_id, application_name): super().__init__(timeout=180) self.guild_id = guild_id self.application_name = application_name @discord.ui.button( label="New", style=discord.ButtonStyle.green, custom_id="action_decline_editor:add", row=0 ) async def add_action(self, button: discord.ui.Button, interaction: discord.Interaction): view = ActionDeclineEditorView(str(interaction.guild.id), self.application_name) options = AddActionSelect(max_values=1, placeholder="Select action to add") options.set_app_name(self.application_name) options.set_action_type(ActionInteraction.DECLINE) for i, que in enumerate(usable_actions): options.add_option(label=f"{str(i+1)}. {que}", value=str(usable_actions[que])) view.add_item(options) await interaction.response.edit_message(view=view) @discord.ui.button( label="Remove", style=discord.ButtonStyle.red, custom_id="action_decline_editor:remove", row=0 ) async def remove_action(self, button, interaction: discord.Interaction): view = ActionDeclineEditorView(str(interaction.guild.id), self.application_name) options = RemoveActionSelect(max_values=1, placeholder="Select action to remove") options.set_app_name(self.application_name) actions = GuildAppDB.get_actions(str(interaction.guild.id), self.application_name, action_type=ActionInteraction.DECLINE) options.set_action_type(ActionInteraction.DECLINE) for i, que in enumerate(actions): options.add_option(label=f"{str(i+1)}. {que}", value=str(i)) view.add_item(options) await interaction.response.edit_message(view=view) class AddActionSelect(discord.ui.Select): def set_app_name(self, app_name): self.app_name = app_name def set_action_type(self, action_type): self.action_type = action_type async def callback(self, interaction: discord.Interaction): self.disabled = True action = self.values[0] if action == "add_role": view = discord.ui.View() options = SelectRoleToAdd(select_type=discord.ComponentType.role_select, max_values=1, placeholder="Select role to add") options.set_app_name(self.app_name) options.set_action_type(self.action_type) view.add_item(options) await interaction.response.edit_message(view=view) class SelectRoleToAdd(discord.ui.Select): def set_app_name(self, app_name): self.app_name = app_name def set_action_type(self, action_type): self.action_type = action_type async def callback(self, interaction: discord.Interaction): self.disabled = True role = self.values[0] action = {"result": self.action_type, "action_type": "add_role", "display_type": "Add Role", "data": {"role_id": role.id}} GuildAppDB.add_action(str(interaction.guild.id), self.app_name, action) if self.action_type == ActionInteraction.ACCEPT: editor = ActionAcceptEditorView(str(interaction.guild.id), self.app_name) embed = get_actions_embed(str(interaction.guild.id), self.app_name, ActionInteraction.ACCEPT) if self.action_type == ActionInteraction.DECLINE: editor = ActionDeclineEditorView(str(interaction.guild.id), self.app_name) embed = get_actions_embed(str(interaction.guild.id), self.app_name, ActionInteraction.DECLINE) await interaction.response.edit_message(embed = embed, view = editor) class RemoveActionSelect(discord.ui.Select): def set_app_name(self, app_name): self.app_name = app_name def set_action_type(self, action_type: ActionInteraction): self.action_type = action_type async def callback(self, interaction: discord.Interaction): self.disabled = True GuildAppDB.remove_action(str(interaction.guild.id), self.app_name, int(self.values[0])+1) if self.action_type == ActionInteraction.ACCEPT: editor = ActionAcceptEditorView(str(interaction.guild.id), self.app_name) embed = get_actions_embed(str(interaction.guild.id), self.app_name, ActionInteraction.ACCEPT) if self.action_type == ActionInteraction.DECLINE: editor = ActionDeclineEditorView(str(interaction.guild.id), self.app_name) embed = get_actions_embed(str(interaction.guild.id), self.app_name, ActionInteraction.DECLINE) await interaction.response.edit_message(embed = embed, view = editor) class SelectActionOptionsEditor(discord.ui.Select): async def callback(self, interaction: discord.Interaction): self.disabled = True view = discord.ui.View() options = SelectActionType(max_values=1, placeholder="Select Action™ type") options.add_option(label="Accept", value="accept") options.add_option(label="Decline", value="decline") options.set_app_name(self.values[0]) view.add_item(options) await interaction.response.edit_message(view=view) class SelectActionType(discord.ui.Select): def set_app_name(self, app_name): self.app_name = app_name async def callback(self, interaction: discord.Interaction): self.disabled = True if self.values[0] == "accept": editor = ActionAcceptEditorView(str(interaction.guild.id), self.app_name) embed = get_actions_embed(str(interaction.guild.id), self.app_name, ActionInteraction.ACCEPT) if self.values[0] == "decline": editor = ActionDeclineEditorView(str(interaction.guild.id), self.app_name) embed = get_actions_embed(str(interaction.guild.id), self.app_name, ActionInteraction.DECLINE) await interaction.response.edit_message(embed = embed, view=editor) # View with button that starts the application process class ApplicationStartButtonView(discord.ui.View): def __init__(self): super().__init__(timeout=None) @discord.ui.button( label="Start application!", style=discord.ButtonStyle.green, custom_id=f"persistent:start_application", ) async def start_app(self, button: discord.ui.Button, interaction: discord.Interaction): app_name, guild_id = StartButtonDB.get_start_msg(interaction.message.id) questions, max_questions=GuildAppDB.get_questions(guild_id, app_name) if questions == "error on get questions: application not found": await interaction.response.send_message(content="Application no longer exists", ephemeral=True) return response_channel = GuildAppDB.get_response_channel(guild_id, app_name) user = await interaction.user.create_dm() embedd = discord.Embed(title=f'{interaction.guild.name} application: {app_name}', description="Hey! Your application has started. You have 300 seconds to complete it.") embedd.add_field(value=f'You can cancel the application by answering "cancel" to any of the questions', name="", inline=False) embedd.set_footer(text="Made by @anorak01", icon_url="https://cdn.discordapp.com/avatars/269164865480949760/a1af9962da20d5ddaa136043cf45d015?size=1024") try: await user.send(embed=embedd) except discord.Forbidden: await interaction.response.send_message(content="Can't start application. Please allow direct messages from server members in your privacy settings.", ephemeral=True) return await interaction.response.send_message(content="Application started", ephemeral=True) application = {'userId': interaction.user.id} for i in range(0, max_questions): try: embed = discord.Embed(title=f'Question [{i+1}/{max_questions}]', description=questions[i]) await user.send(embed=embed) response = await bot.wait_for('message', check=lambda m: m.author == interaction.user and m.channel == user, timeout=300) if response.content.startswith("cancel"): await user.send("Your application has been cancelled") return else: application[f'question{i}'] = response.content except asyncio.TimeoutError: await user.send(content="As you haven't replied in 300 seconds, your application has been cancelled") return try: with open('applications.json', 'r') as f: data = json.load(f) except (FileNotFoundError, json.JSONDecodeError): data = [] data.append(application) with open('applications.json', 'w') as f: json.dump(data, f) channel = bot.get_channel(int(response_channel)) embed = discord.Embed(title=f"Application: {app_name}\nUser: {interaction.user.display_name}") for i in range(0, max_questions): embed.add_field(name=f'{questions[i]}', value=application[f'question{i}'], inline=False) embed.set_footer(text=f"Applicant ID: {interaction.user.id}") appView = ApplicationButtonsView() msg = await channel.send(embed=embed, view=appView) MessageDB.add_application_msg(msg.id, interaction.user.id, interaction.guild.id) await user.send('Thank you for applying!') # View containing accept and decline buttons for each application class ApplicationButtonsView(discord.ui.View): def __init__(self): super().__init__(timeout=None) @discord.ui.button( label="Accept", style=discord.ButtonStyle.green, custom_id=f"persistent:accept", ) async def accept(self, button: discord.ui.Button, interaction: discord.Interaction): msg_id = str(interaction.message.id) user_id, guild_id = MessageDB.get_application_msg(msg_id) modal = ApplicationModal(title=f"Accepting: {bot.get_user(user_id).display_name}") modal.set_action("acc") modal.add_item(discord.ui.InputText(label=f"Reason: ")) await interaction.response.send_modal(modal) @discord.ui.button( label="Decline", style=discord.ButtonStyle.red, custom_id=f"persistent:decline", ) async def decline(self, button: discord.ui.Button, interaction: discord.Interaction): msg_id = str(interaction.message.id) user_id, guild_id = MessageDB.get_application_msg(msg_id) modal = ApplicationModal(title=f"Declining: {bot.get_user(user_id).display_name}") modal.set_action("dec") modal.add_item(discord.ui.InputText(label=f"Reason: ")) await interaction.response.send_modal(modal) # Modal functioning as a callback for Accepting/Declining application class ApplicationModal(discord.ui.Modal): def set_action(self, action): self.action = action async def callback(self, interaction: discord.Interaction): reason = self.children[0].value msg_id = str(interaction.message.id) user_id, guild_id = MessageDB.get_application_msg(msg_id) if self.action == "acc": user = await bot.get_user(user_id).create_dm() await user.send(f"Your application has been accepted!") await user.send(f"Reason: {reason}") await interaction.response.send_message(content="Application accepted", ephemeral=True) role = get(interaction.message.guild.roles, name="CreatTopian") #await discord.utils.get(interaction.message.guild.members, id=int(user_id)).add_roles(role) emb = interaction.message.embeds[0] emb.colour = discord.Colour.green() embed = discord.Embed(title='Accepted') embed.add_field(name=f'Reason:', value=reason, inline=False) embed.colour = discord.Colour.green() await interaction.followup.edit_message(message_id = interaction.message.id, embeds=[emb, embed]) view = discord.ui.View.from_message(interaction.message) view.disable_all_items() await interaction.followup.edit_message(message_id = interaction.message.id, view = view) if self.action == "dec": user = await bot.get_user(user_id).create_dm() await user.send(f"Your application has been declined.") await user.send(f"Reason: {reason}") await interaction.response.send_message(content="Application declined", ephemeral=True) emb = interaction.message.embeds[0] emb.colour = discord.Colour.red() embed = discord.Embed(title='Declined') embed.add_field(name=f'Reason:', value=reason, inline=False) embed.colour = discord.Colour.red() await interaction.followup.edit_message(message_id = interaction.message.id, embeds=[emb, embed]) view = discord.ui.View.from_message(interaction.message) view.disable_all_items() await interaction.followup.edit_message(message_id = interaction.message.id, view = view) # end bot.run(TOKEN)