Skip to content

Instantly share code, notes, and snippets.

@i-am-unknown-81514525
Created May 28, 2025 00:48
Show Gist options
  • Select an option

  • Save i-am-unknown-81514525/8d84ed916f3943119759354a76bf1677 to your computer and use it in GitHub Desktop.

Select an option

Save i-am-unknown-81514525/8d84ed916f3943119759354a76bf1677 to your computer and use it in GitHub Desktop.
d.py DynamicItem Base Class implementation
from typing import Callable, Coroutine, Type, TypeVar, Self, overload, Any, Optional, Generic, ParamSpec
K = TypeVar("K", bound=Item)
R = TypeVar("R", bound="BaseOnboardingDynamicItem")
P = ParamSpec("P")
class BaseOnboardingDynamicItem(DynamicItem[K], Generic[K], template=r"onboarding::(\d+)::(\d+)::[a-zA-Z\d_]*::(\d+)"):
ACTIONS: dict[Type["BaseOnboardingDynamicItem"], str] = {}
generate_appearance: Callable[[P], ...]
def __init_subclass__(cls, action_name: str):
if any(map(lambda x: x not in string.ascii_letters + string.digits + "_", action_name)):
raise ValueError(f"Contain invalid {action_name=}, only alphanumerical character and underscore allowed")
template = (
r"onboarding::(\d+)::(\d+)::" + action_name + r"::(\d+)"
) # prefix::current_page::next_page::action_name::author
BaseOnboardingDynamicItem.ACTIONS[cls] = action_name
super().__init_subclass__(template=template)
def __init__(self, current_page: int, next_page: int, author_id: int, *args: P.args, **kwargs: P.kwargs):
self.current_page = current_page
self.next_page = next_page
self.author_id = author_id
super().__init__(item=self.generate_appearance(*args, **kwargs))
def generate_appearance(self, *args, **kwargs) -> K:
raise NotImplementedError("Require custom implement")
@property
def custom_id(self) -> str:
return f"onboarding::{self.current_page}::{self.next_page}::{BaseOnboardingDynamicItem.ACTIONS[self.__class__]}::{self.author_id}"
@classmethod
async def from_custom_id(
cls: Type[Self], interaction: Interaction[ClientT], item: Item[Any], match: re.Match[str], /
) -> Self:
return cls(int(match.group(1)), int(match.group(2)), int(match.group(3)))
async def update(
self, interaction: discord.Interaction[AutoShardedBot], db: Optional[DB] = None, hasDefer: bool = True
):
if not hasDefer:
await interaction.response.defer()
if not db:
db = await db_manager.get_config(interaction.guild_id, bot=interaction.client)
embed, view = page_generator(db, self.next_page, self.author_id)
message = interaction.message
if message:
view.set_message(message)
await self.content_update(interaction, embed, view)
async def content_update(self, interaction: discord.Interaction, embed: Embed | None, view: View | None):
if not embed and not view:
return
if embed and view:
return await interaction.edit_original_response(embed=embed, view=view)
if embed and not view:
return await interaction.edit_original_response(embed=embed)
if view and not embed:
return await interaction.edit_original_response(view=view)
async def callback(self, interaction: Interaction[AutoShardedBot]) -> Any:
await self.update(interaction, hasDefer=False)
return
def loader(bot: Bot | AutoShardedBot):
for cls in BaseOnboardingDynamicItem.ACTIONS:
bot.add_dynamic_items(cls)
def unloader(bot: Bot | AutoShardedBot):
for cls in BaseOnboardingDynamicItem.ACTIONS:
bot.remove_dynamic_items(cls)
@i-am-unknown-81514525
Copy link
Author

Btw GPL-3.0 license applied

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment