Discord.py passing variables into modal to be used in on_submit()

2k views Asked by At

I have written a discord bot that presents a view on the command "!send_view". This view will have 3 buttons, one for each role. When a user clicks a button, a modal pops up asking for a response. Once the user submits their response the modal assigns them the role they chose. It also inserts a new record into a database to store information about the interaction. I'd like to pass additional variables (like a role ID) into the modal class so it can be used in the "on_submit()" method.

My working code so far is:

import discord
from discord.ext import commands
from discord import ui # modals

intents = discord.Intents.default()
intents.members = True # required for removing roles
intents.message_content = True # required for slash commands

# create connection
bot = commands.Bot(command_prefix="!", intents=intents)

@bot.event # decorator
async def on_ready():
    bot.add_view(ViewAllianceSelection())
    await bot.tree.sync()

# views
class ViewAllianceSelection(discord.ui.View):
    def __init__(self):
        super().__init__(timeout = None)
    @discord.ui.button(label = "test", custom_id = "Role 1", style = discord.ButtonStyle.green)
    async def test(self, interaction: discord.Interaction, button:discord.Button):
        await interaction.response.send_modal(ModalApplicationForm())

# modals
class ModalApplicationForm(discord.ui.Modal, title='Alliance Application Form'):

    submittedUN = ui.TextInput(label='Enter your username.', style=discord.TextStyle.short)
    async def on_submit(self, interaction: discord.Interaction):
        print('add the information to database')
        await interaction.response.send_message(f'Thank you **{self.submittedUN}**, your application has been submitted.', ephemeral=True)        

@bot.command()
async def send_view(ctx):
    embed = discord.Embed(
        title='this is a test'
    )
    await ctx.send(embed=embed, view=ViewAllianceSelection())


bot.run('my token')

In order to pass variables into the on_submit() I've tried doing the following but am getting an error:

async def test(self, interaction: discord.Interaction, button:discord.Button):
        await interaction.response.send_modal(ModalApplicationForm(var='abc')) # variable to pass into modal

# modals
class ModalApplicationForm(discord.ui.Modal, title='Alliance Application Form'):
    def __init__(self, var):
        self.var = var # init variable
        print(var)
    submittedUN = ui.TextInput(label='Enter your travian username.', style=discord.TextStyle.short)
    async def on_submit(self, interaction: discord.Interaction):
    print('add the information to database')

The error I am getting is:

AttributeError: 'ModalApplicationForm' object has no attribute 'custom_id'

I am very new to using classes and am struggling to find a solution to what I'd like to do. Any help or ideas would be greatly appreciated.

1

There are 1 answers

0
Hazzu On

Note that you need to call the __init__ method from discord.ui.Modal for the modal to be prepared.

When you use ModalApplicationForm() in the first code, you are calling the nearest __init__ method in the class hierarchy. As you have not defined a __init__ method in the ModalApplicationForm class, the __init__ method of the super class (discord.ui.Modal) will be called.

In the second code, as you defined a __init__ method for ModalApplicationForm, it will be called when you use ModalApplicationForm().

In this scenario, for the super class to be initialized, you need to make an explicit call to super().__init__():

# modals
class ModalApplicationForm(discord.ui.Modal):
    submitted_un = ui.TextInput(
        label='Enter your travian username.',
        style=discord.TextStyle.short
    )

    def __init__(self, var):
        self.var = var
        super().__init__(title='Alliance Application Form')


    async def on_submit(self, interaction: discord.Interaction):
        print(self.var)