Refactor modal usage and error handling in views
Replaced custom Modal class with BaseModal in embed_builder.py for consistency and maintainability. Updated modal instantiation to use custom_id and improved value handling. Removed redundant on_error methods from help.py, pagination.py, and search.py, and delegated error handling to superclass in controller.py for cleaner error management.
This commit is contained in:
@@ -484,10 +484,6 @@ class InteractiveController(discord.ui.View):
|
||||
async def on_error(self, interaction: discord.Interaction, error: Exception, item: discord.ui.Item) -> None:
|
||||
if isinstance(error, ButtonOnCooldown):
|
||||
sec = int(error.retry_after)
|
||||
await interaction.response.send_message(f"You're on cooldown for {sec} second{'' if sec == 1 else 's'}!", ephemeral=True)
|
||||
return await interaction.response.send_message(f"You're on cooldown for {sec} second{'' if sec == 1 else 's'}!", ephemeral=True)
|
||||
|
||||
elif isinstance(error, Exception):
|
||||
traceback.print_exception(error)
|
||||
await interaction.response.send_message(error)
|
||||
|
||||
return
|
||||
super().on_error(interaction, error, item)
|
||||
@@ -24,26 +24,12 @@ SOFTWARE.
|
||||
import discord
|
||||
import copy
|
||||
|
||||
from typing import List
|
||||
from discord.ext import commands
|
||||
|
||||
from .utils import BaseModal
|
||||
from ..mongodb import MongoDBHandler
|
||||
from ..placeholders import PlayerPlaceholder
|
||||
|
||||
class Modal(discord.ui.Modal):
|
||||
def __init__(self, items: List[discord.ui.Item], *args, **kwargs) -> None:
|
||||
super().__init__(*args, **kwargs)
|
||||
for item in items:
|
||||
self.add_item(item)
|
||||
|
||||
self.values: dict = {}
|
||||
|
||||
async def on_submit(self, interaction: discord.Interaction) -> None:
|
||||
await interaction.response.defer()
|
||||
for children in self.children:
|
||||
self.values[children.label.lower()] = children.value
|
||||
|
||||
self.stop()
|
||||
|
||||
class Dropdown(discord.ui.Select):
|
||||
def __init__(self):
|
||||
@@ -90,42 +76,47 @@ class EmbedBuilderView(discord.ui.View):
|
||||
@discord.ui.button(label="Edit Content", style=discord.ButtonStyle.blurple)
|
||||
async def edit_content(self, interaction: discord.Interaction, button: discord.ui.Button):
|
||||
data = self.data.get(self.embed_type, {})
|
||||
items = [
|
||||
discord.ui.TextInput(
|
||||
label="Title",
|
||||
placeholder="The title of the embed",
|
||||
style=discord.TextStyle.paragraph,
|
||||
max_length=1000,
|
||||
default=data.get("title", {}).get("name"),
|
||||
required=False
|
||||
),
|
||||
discord.ui.TextInput(
|
||||
label="Url",
|
||||
placeholder="The url of the title",
|
||||
style=discord.TextStyle.short,
|
||||
max_length=100,
|
||||
default=data.get("title", {}).get("url"),
|
||||
required=False
|
||||
),
|
||||
discord.ui.TextInput(
|
||||
label="Color",
|
||||
placeholder="The color of the embed",
|
||||
style=discord.TextStyle.short,
|
||||
max_length=100,
|
||||
default=data.get("color"),
|
||||
required=False
|
||||
),
|
||||
discord.ui.TextInput(
|
||||
label="Description",
|
||||
placeholder="The description of the title",
|
||||
style=discord.TextStyle.paragraph,
|
||||
max_length=200,
|
||||
default=data.get("description"),
|
||||
required=False
|
||||
)
|
||||
]
|
||||
|
||||
modal = Modal(items, title="Edit Content")
|
||||
modal = BaseModal(
|
||||
title="Edit Content",
|
||||
custom_id="edit_content",
|
||||
items=[
|
||||
discord.ui.TextInput(
|
||||
label="Title",
|
||||
placeholder="The title of the embed",
|
||||
style=discord.TextStyle.paragraph,
|
||||
custom_id="title",
|
||||
max_length=1000,
|
||||
default=data.get("title", {}).get("name"),
|
||||
required=False
|
||||
),
|
||||
discord.ui.TextInput(
|
||||
label="Url",
|
||||
placeholder="The url of the title",
|
||||
style=discord.TextStyle.short,
|
||||
custom_id="url",
|
||||
max_length=100,
|
||||
default=data.get("title", {}).get("url"),
|
||||
required=False
|
||||
),
|
||||
discord.ui.TextInput(
|
||||
label="Color",
|
||||
placeholder="The color of the embed",
|
||||
style=discord.TextStyle.short,
|
||||
custom_id="color",
|
||||
max_length=100,
|
||||
default=data.get("color"),
|
||||
required=False
|
||||
),
|
||||
discord.ui.TextInput(
|
||||
label="Description",
|
||||
placeholder="The description of the title",
|
||||
style=discord.TextStyle.paragraph,
|
||||
custom_id="description",
|
||||
max_length=200,
|
||||
default=data.get("description"),
|
||||
required=False
|
||||
)
|
||||
])
|
||||
await interaction.response.send_modal(modal)
|
||||
await modal.wait()
|
||||
|
||||
@@ -142,112 +133,120 @@ class EmbedBuilderView(discord.ui.View):
|
||||
except:
|
||||
pass
|
||||
|
||||
return await interaction.edit_original_response(embed=self.build_embed())
|
||||
return await self.response.edit(embed=self.build_embed())
|
||||
|
||||
@discord.ui.button(label="Edit Author",)
|
||||
async def edit_author(self, interaction: discord.Interaction, button: discord.ui.Button):
|
||||
data = self.data.get(self.embed_type, {})
|
||||
items = [
|
||||
discord.ui.TextInput(
|
||||
label="Name",
|
||||
placeholder="The name of the author",
|
||||
style=discord.TextStyle.paragraph,
|
||||
max_length=200,
|
||||
default=data.get("author", {}).get("name"),
|
||||
required=False
|
||||
),
|
||||
discord.ui.TextInput(
|
||||
label="Url",
|
||||
placeholder="The url of the author",
|
||||
style=discord.TextStyle.short,
|
||||
max_length=100,
|
||||
default=data.get("author", {}).get("url"),
|
||||
required=False
|
||||
),
|
||||
discord.ui.TextInput(
|
||||
label="Icon Url",
|
||||
placeholder="The icon url of the author",
|
||||
style=discord.TextStyle.short,
|
||||
max_length=100,
|
||||
default=data.get("author", {}).get("icon_url"),
|
||||
required=False
|
||||
),
|
||||
]
|
||||
|
||||
modal = Modal(items, title="Edit Author")
|
||||
modal = BaseModal(
|
||||
title="Edit Author",
|
||||
custom_id="edit_author",
|
||||
items=[
|
||||
discord.ui.TextInput(
|
||||
label="Name",
|
||||
placeholder="The name of the author",
|
||||
style=discord.TextStyle.paragraph,
|
||||
custom_id="name",
|
||||
max_length=200,
|
||||
default=data.get("author", {}).get("name"),
|
||||
required=False
|
||||
),
|
||||
discord.ui.TextInput(
|
||||
label="Url",
|
||||
placeholder="The url of the author",
|
||||
style=discord.TextStyle.short,
|
||||
custom_id="url",
|
||||
max_length=100,
|
||||
default=data.get("author", {}).get("url"),
|
||||
required=False
|
||||
),
|
||||
discord.ui.TextInput(
|
||||
label="Icon Url",
|
||||
placeholder="The icon url of the author",
|
||||
style=discord.TextStyle.short,
|
||||
custom_id="icon_url",
|
||||
max_length=100,
|
||||
default=data.get("author", {}).get("icon_url"),
|
||||
required=False
|
||||
),
|
||||
])
|
||||
await interaction.response.send_modal(modal)
|
||||
await modal.wait()
|
||||
|
||||
v = modal.values
|
||||
|
||||
if v['name'] != "":
|
||||
if "author" not in data:
|
||||
data["author"] = {}
|
||||
|
||||
data["author"]["name"] = v['name']
|
||||
data["author"]["url"] = v['url']
|
||||
data["author"]["icon_url"] = v['icon url']
|
||||
data["author"]["icon_url"] = v['icon_url']
|
||||
else:
|
||||
del data["author"]
|
||||
|
||||
return await interaction.edit_original_response(embed=self.build_embed())
|
||||
return await self.response.edit(embed=self.build_embed())
|
||||
|
||||
@discord.ui.button(label="Edit Image")
|
||||
async def edit_image(self, interaction: discord.Interaction, button: discord.ui.Button):
|
||||
data = self.data.get(self.embed_type, {})
|
||||
items = [
|
||||
discord.ui.TextInput(
|
||||
label="Thumbnail",
|
||||
placeholder="The url of the thumbnail",
|
||||
style=discord.TextStyle.short,
|
||||
max_length=200,
|
||||
default=data.get("thumbnail"),
|
||||
required=False
|
||||
),
|
||||
discord.ui.TextInput(
|
||||
label="Image",
|
||||
placeholder="The url of the image",
|
||||
style=discord.TextStyle.short,
|
||||
max_length=100,
|
||||
default=data.get("image"),
|
||||
required=False
|
||||
)
|
||||
]
|
||||
|
||||
modal = Modal(items, title="Edit Image")
|
||||
modal = BaseModal(
|
||||
title="Edit Image",
|
||||
custom_id="edit_image",
|
||||
items=[
|
||||
discord.ui.TextInput(
|
||||
label="Thumbnail",
|
||||
placeholder="The url of the thumbnail",
|
||||
style=discord.TextStyle.short,
|
||||
custom_id="thumbnail",
|
||||
max_length=200,
|
||||
default=data.get("thumbnail"),
|
||||
required=False
|
||||
),
|
||||
discord.ui.TextInput(
|
||||
label="Image",
|
||||
placeholder="The url of the image",
|
||||
style=discord.TextStyle.short,
|
||||
custom_id="image",
|
||||
max_length=100,
|
||||
default=data.get("image"),
|
||||
required=False
|
||||
)
|
||||
])
|
||||
await interaction.response.send_modal(modal)
|
||||
await modal.wait()
|
||||
|
||||
v = modal.values
|
||||
|
||||
data["thumbnail"] = v['thumbnail']
|
||||
data["image"] = v['image']
|
||||
|
||||
return await interaction.edit_original_response(embed=self.build_embed())
|
||||
return await self.response.edit(embed=self.build_embed())
|
||||
|
||||
@discord.ui.button(label="Edit Footer")
|
||||
async def edit_footer(self, interaction: discord.Interaction, button: discord.ui.Button):
|
||||
data = self.data.get(self.embed_type, {})
|
||||
items = [
|
||||
discord.ui.TextInput(
|
||||
label="Text",
|
||||
placeholder="The text of the footer",
|
||||
style=discord.TextStyle.paragraph,
|
||||
max_length=200,
|
||||
default=data.get("footer", {}).get("text"),
|
||||
required=False
|
||||
),
|
||||
discord.ui.TextInput(
|
||||
label="Icon Url",
|
||||
placeholder="The url of the icon",
|
||||
style=discord.TextStyle.short,
|
||||
max_length=100,
|
||||
default=data.get("footer", {}).get("icon_url"),
|
||||
required=False
|
||||
)
|
||||
]
|
||||
|
||||
modal = Modal(items, title="Edit Footer")
|
||||
modal = BaseModal(
|
||||
title="Edit Footer",
|
||||
custom_id="edit_footer",
|
||||
items=[
|
||||
discord.ui.TextInput(
|
||||
label="Text",
|
||||
placeholder="The text of the footer",
|
||||
style=discord.TextStyle.paragraph,
|
||||
custom_id="text",
|
||||
max_length=200,
|
||||
default=data.get("footer", {}).get("text"),
|
||||
required=False
|
||||
),
|
||||
discord.ui.TextInput(
|
||||
label="Icon Url",
|
||||
placeholder="The url of the icon",
|
||||
style=discord.TextStyle.short,
|
||||
custom_id="icon_url",
|
||||
max_length=100,
|
||||
default=data.get("footer", {}).get("icon_url"),
|
||||
required=False
|
||||
)
|
||||
])
|
||||
await interaction.response.send_modal(modal)
|
||||
await modal.wait()
|
||||
|
||||
@@ -256,40 +255,44 @@ class EmbedBuilderView(discord.ui.View):
|
||||
data["footer"] = {}
|
||||
|
||||
data["footer"]["text"] = v['text']
|
||||
data["footer"]["icon_url"] = v['icon url']
|
||||
data["footer"]["icon_url"] = v['icon_url']
|
||||
|
||||
return await interaction.edit_original_response(embed=self.build_embed())
|
||||
return await self.response.edit(embed=self.build_embed())
|
||||
|
||||
@discord.ui.button(label="Add Field", style=discord.ButtonStyle.green, row=1)
|
||||
async def add_field(self, interaction: discord.Interaction, button: discord.ui.Button):
|
||||
data = self.data.get(self.embed_type)
|
||||
items = [
|
||||
discord.ui.TextInput(
|
||||
label="Name",
|
||||
placeholder="The name of the field",
|
||||
style=discord.TextStyle.paragraph,
|
||||
max_length=256
|
||||
),
|
||||
discord.ui.TextInput(
|
||||
label="Value",
|
||||
placeholder="The value of the field",
|
||||
style=discord.TextStyle.long,
|
||||
max_length=1024
|
||||
),
|
||||
discord.ui.TextInput(
|
||||
label="Inline",
|
||||
placeholder="The inline of the field, e.g. True or False",
|
||||
style=discord.TextStyle.short
|
||||
)
|
||||
]
|
||||
|
||||
if "fields" not in data:
|
||||
data["fields"] = []
|
||||
|
||||
if len(data["fields"]) >= 25:
|
||||
return await interaction.response.send_message("You have already reached the maximum of fields!", ephemeral=True)
|
||||
|
||||
modal = Modal(items, title="Add Field")
|
||||
modal = BaseModal(
|
||||
title="Add Field",
|
||||
custom_id="add_field",
|
||||
items=[
|
||||
discord.ui.TextInput(
|
||||
label="Name",
|
||||
placeholder="The name of the field",
|
||||
style=discord.TextStyle.paragraph,
|
||||
custom_id="name",
|
||||
max_length=256
|
||||
),
|
||||
discord.ui.TextInput(
|
||||
label="Value",
|
||||
placeholder="The value of the field",
|
||||
style=discord.TextStyle.long,
|
||||
custom_id="value",
|
||||
max_length=1024
|
||||
),
|
||||
discord.ui.TextInput(
|
||||
label="Inline",
|
||||
placeholder="The inline of the field, e.g. True or False",
|
||||
style=discord.TextStyle.short,
|
||||
custom_id="inline",
|
||||
)
|
||||
])
|
||||
await interaction.response.send_modal(modal)
|
||||
await modal.wait()
|
||||
|
||||
@@ -300,18 +303,10 @@ class EmbedBuilderView(discord.ui.View):
|
||||
"inline": True if v["inline"].lower() == "true" else False
|
||||
})
|
||||
|
||||
return await interaction.edit_original_response(embed=self.build_embed())
|
||||
return await self.response.edit(embed=self.build_embed())
|
||||
|
||||
@discord.ui.button(label="Remove Field", style=discord.ButtonStyle.red, row=1)
|
||||
async def remove_field(self, interaction: discord.Interaction, button: discord.ui.Button):
|
||||
items = [
|
||||
discord.ui.TextInput(
|
||||
label="Index",
|
||||
placeholder="The number of fields to remove, e.g. 1",
|
||||
style=discord.TextStyle.short
|
||||
)
|
||||
]
|
||||
|
||||
data = self.data.get(self.embed_type)
|
||||
if "fields" not in data:
|
||||
data["fields"] = []
|
||||
@@ -319,7 +314,17 @@ class EmbedBuilderView(discord.ui.View):
|
||||
if len(data["fields"]) == 0:
|
||||
return await interaction.response.send_message("There are no fields to remove!", ephemeral=True)
|
||||
|
||||
modal = Modal(items, title="Remove Field")
|
||||
modal = BaseModal(
|
||||
title="Remove Field",
|
||||
custom_id="remove_field",
|
||||
items = [
|
||||
discord.ui.TextInput(
|
||||
label="Index",
|
||||
placeholder="The number of fields to remove, e.g. 1",
|
||||
style=discord.TextStyle.short,
|
||||
custom_id="index",
|
||||
)
|
||||
])
|
||||
await interaction.response.send_modal(modal)
|
||||
await modal.wait()
|
||||
|
||||
@@ -328,7 +333,7 @@ class EmbedBuilderView(discord.ui.View):
|
||||
except:
|
||||
return await interaction.followup.send("Can't found the field", ephemeral=True)
|
||||
|
||||
return await interaction.edit_original_response(embed=self.build_embed())
|
||||
return await self.response.edit(embed=self.build_embed())
|
||||
|
||||
@discord.ui.button(label="Apply", style=discord.ButtonStyle.green, row=1)
|
||||
async def apply(self, interaction: discord.Interaction, button: discord.ui.Button):
|
||||
|
||||
@@ -61,9 +61,6 @@ class HelpView(discord.ui.View):
|
||||
self.add_item(discord.ui.Button(label='Github', emoji=':github:1098265017268322406', url='https://github.com/ChocoMeow/Vocard'))
|
||||
self.add_item(discord.ui.Button(label='Donate', emoji=':patreon:913397909024800878', url='https://www.patreon.com/Vocard'))
|
||||
self.add_item(HelpDropdown(self.categories))
|
||||
|
||||
async def on_error(self, error, item, interaction) -> None:
|
||||
return
|
||||
|
||||
async def on_timeout(self) -> None:
|
||||
for child in self.children:
|
||||
|
||||
@@ -73,9 +73,6 @@ class PaginationView(discord.ui.View):
|
||||
child.disabled = state.get("disabled", False)
|
||||
child.label = state.get("label")
|
||||
|
||||
async def on_error(self, error: Exception, item: discord.ui.Item, interaction: discord.Interaction) -> None:
|
||||
return
|
||||
|
||||
async def update_message(self, interaction: discord.Interaction) -> None:
|
||||
"""Update the view and edit the message."""
|
||||
|
||||
|
||||
@@ -54,9 +54,6 @@ class SearchView(discord.ui.View):
|
||||
self.values: list[str] = None
|
||||
self.add_item(SearchDropdown(tracks, texts))
|
||||
|
||||
async def on_error(self, error, item, interaction):
|
||||
return
|
||||
|
||||
async def on_timeout(self):
|
||||
for child in self.children:
|
||||
child.disabled = True
|
||||
|
||||
Reference in New Issue
Block a user