rewrite: Refactor ui utils, add pagers.
This commit is contained in:
91
bot/utils/ui/transformed.py
Normal file
91
bot/utils/ui/transformed.py
Normal file
@@ -0,0 +1,91 @@
|
||||
from typing import Any, Type, TYPE_CHECKING
|
||||
from enum import Enum
|
||||
|
||||
import discord
|
||||
import discord.app_commands as appcmd
|
||||
from discord.app_commands.transformers import AppCommandOptionType
|
||||
|
||||
|
||||
__all__ = (
|
||||
'ChoicedEnum',
|
||||
'ChoicedEnumTransformer',
|
||||
'Transformed',
|
||||
)
|
||||
|
||||
|
||||
class ChoicedEnum(Enum):
|
||||
@property
|
||||
def choice_name(self):
|
||||
return self.name
|
||||
|
||||
@property
|
||||
def choice_value(self):
|
||||
return self.value
|
||||
|
||||
@property
|
||||
def choice(self):
|
||||
return appcmd.Choice(
|
||||
name=self.choice_name, value=self.choice_value
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def choices(self):
|
||||
return [item.choice for item in self]
|
||||
|
||||
@classmethod
|
||||
def make_choice_map(cls):
|
||||
return {item.choice_value: item for item in cls}
|
||||
|
||||
@classmethod
|
||||
async def transform(cls, transformer: 'ChoicedEnumTransformer', interaction: discord.Interaction, value: Any):
|
||||
return transformer._choice_map[value]
|
||||
|
||||
@classmethod
|
||||
def option_type(cls) -> AppCommandOptionType:
|
||||
return AppCommandOptionType.string
|
||||
|
||||
@classmethod
|
||||
def transformer(cls, *args) -> appcmd.Transformer:
|
||||
return ChoicedEnumTransformer(cls, *args)
|
||||
|
||||
|
||||
class ChoicedEnumTransformer(appcmd.Transformer):
|
||||
# __discord_app_commands_is_choice__ = True
|
||||
|
||||
def __init__(self, enum: Type[ChoicedEnum], opt_type) -> None:
|
||||
super().__init__()
|
||||
|
||||
self._type = opt_type
|
||||
self._enum = enum
|
||||
self._choices = enum.choices()
|
||||
self._choice_map = enum.make_choice_map()
|
||||
|
||||
@property
|
||||
def _error_display_name(self) -> str:
|
||||
return self._enum.__name__
|
||||
|
||||
@property
|
||||
def type(self) -> AppCommandOptionType:
|
||||
return self._type
|
||||
|
||||
@property
|
||||
def choices(self):
|
||||
return self._choices
|
||||
|
||||
async def transform(self, interaction: discord.Interaction, value: Any, /) -> Any:
|
||||
return await self._enum.transform(self, interaction, value)
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing_extensions import Annotated as Transformed
|
||||
else:
|
||||
|
||||
class Transformed:
|
||||
def __class_getitem__(self, items):
|
||||
cls = items[0]
|
||||
options = items[1:]
|
||||
|
||||
if not hasattr(cls, 'transformer'):
|
||||
raise ValueError("Tranformed class must have a transformer classmethod.")
|
||||
transformer = cls.transformer(*options)
|
||||
return appcmd.Transform[cls, transformer]
|
||||
Reference in New Issue
Block a user