Last active
March 4, 2022 20:32
-
-
Save JeyyGit/2618ca611a2ac2955d2d193b68c214b7 to your computer and use it in GitHub Desktop.
Rough implementation of modal in discord.py 2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import discord, secrets | |
class TextInput: | |
"""for storing our text input data""" | |
def __init__(self, payload): | |
self.type = payload['type'] | |
self.custom_id = payload['custom_id'] | |
self.style = payload['style'] | |
self.label = payload['label'] | |
self.min_length = payload.get('min_length') | |
self.max_length = payload.get('max_length') | |
self.required = payload.get('required') | |
self.value = payload.get('value') | |
self.placeholder = payload.get('placeholder') | |
class Modal: | |
def __init__(self, bot: commands.Bot, title): | |
self.bot = bot | |
self.title = title | |
self.custom_id = secrets.token_urlsafe(16) | |
self.payload = { | |
'title': title, | |
'custom_id': self.custom_id, | |
'components': [] | |
} | |
self.adapter = discord.webhook.async_.async_context.get() | |
self.fields = [] | |
def add_field(self, style, label, min_length=None, max_length=None, required=False, value=None, placeholder=None): | |
"""method to add new text input field | |
styles: | |
1 : single-line input | |
2 : multi-line input | |
""" | |
component = { | |
'type': 4, | |
'custom_id': secrets.token_urlsafe(16), | |
'style': style, | |
'label': label, | |
'required': str(required), | |
} | |
if min_length: | |
component['min_length'] = min_length | |
if max_length: | |
component['max_length'] = max_length | |
if value: | |
component['value'] = value | |
if placeholder: | |
component['placeholder'] = placeholder | |
self.payload['components'].append({ | |
'type': 1, | |
'components': [component] | |
}) | |
self.fields.append(TextInput(component)) | |
async def send_modal(self, interaction: discord.Interaction): | |
interaction.response._responded = True | |
await self.adapter.create_interaction_response( | |
interaction_id = interaction.id, | |
token = interaction.token, | |
session = interaction._session, | |
data = self.payload, | |
type = 9 | |
) | |
async def wait(self, timeout=180): | |
def interaction_check(interaction: discord.Interaction): | |
return interaction.data.get('custom_id') == self.custom_id | |
# this is probably a bad implementation but its working | |
try: | |
# wait for interaction with that match this modal instance custom_id | |
interaction = await self.bot.wait_for('interaction', check=interaction_check, timeout=timeout) | |
except asyncio.TimeoutError: | |
# return None if user didn't respond to the modal | |
return None, [] | |
components = interaction.data['components'] | |
# match each result field with corresponding TextInput field | |
# because interaction data doesn't hold all of text input data | |
result = [] | |
for component in components: | |
for field in self.fields: | |
if component['components'][0]['custom_id'] == field.custom_id: | |
field.value = component['components'][0]['value'] | |
result.append(field) | |
# returns modal interactions and list of TextInput filled. | |
return interaction, result |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@commands.command() | |
async def test_modal(self, ctx): | |
class View(discord.ui.View): # create a subclass of discord.ui.View | |
def __init__(self): | |
super().__init__(timeout=None) | |
self.submiter = [] | |
@discord.ui.button(label='Form-aline', style=discord.ButtonStyle.success) | |
async def btn(self, button, interaction): | |
form = Modal(ctx.bot, f'Form for {interaction.user}') # initate Modal | |
# add text input fields | |
form.add_field(1, 'Name', max_length=100, placeholder='ur stopid name', required=True) # single-line text input | |
form.add_field(2, 'reason why ur dumb', max_length=200, placeholder='what is it') # paragraph input | |
form.add_field(1, 'ur age', max_length=100) # single-line input | |
await form.send_modal(interaction) | |
# wait for user to submit the modal | |
interacted, result = await form.wait() | |
if not interacted: | |
return | |
if interacted.user.id in self.submiter: # check if they have submited to this modal before | |
return await interacted.response.send_message('you have filled this form.', ephemeral=True) | |
# add it to list of people who have submited their modal | |
self.submiter.append(interacted.user.id) | |
fields = [f'`{field.label}` : {field.value}' for field in result] # get them text input data | |
embed = discord.Embed(title=form.title, description='\n'.join(fields)) | |
await interacted.response.send_message(embed=embed) | |
await ctx.reply('STUPIDITY SURVEY 2022', view=View(), mention_author=False) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment