|
|
|
@ -36,6 +36,7 @@ from typing import ( |
|
|
|
List, |
|
|
|
MutableMapping, |
|
|
|
Optional, |
|
|
|
Sequence, |
|
|
|
Set, |
|
|
|
TYPE_CHECKING, |
|
|
|
Tuple, |
|
|
|
@ -48,7 +49,7 @@ from typing import ( |
|
|
|
import re |
|
|
|
from copy import copy as shallow_copy |
|
|
|
|
|
|
|
from ..enums import AppCommandOptionType, AppCommandType, ChannelType, Locale |
|
|
|
from ..enums import AppCommandOptionType, AppCommandType, ChannelType, Locale, FileType |
|
|
|
from .installs import AppCommandContext, AppInstallationType |
|
|
|
from .models import Choice |
|
|
|
from .transformers import annotation_to_parameter, CommandParameter, NoneType |
|
|
|
@ -67,6 +68,7 @@ from ..utils import ( |
|
|
|
_iscoroutinefunction, |
|
|
|
_shorten, |
|
|
|
_to_kebab_case, |
|
|
|
_validate_discord_file_types, |
|
|
|
) |
|
|
|
|
|
|
|
if TYPE_CHECKING: |
|
|
|
@ -107,6 +109,7 @@ __all__ = ( |
|
|
|
'user_install', |
|
|
|
'allowed_installs', |
|
|
|
'default_permissions', |
|
|
|
'set_file_types', |
|
|
|
) |
|
|
|
|
|
|
|
if TYPE_CHECKING: |
|
|
|
@ -373,6 +376,26 @@ def _populate_autocomplete(params: Dict[str, CommandParameter], autocomplete: Di |
|
|
|
raise TypeError(f'unknown parameter given: {first}') |
|
|
|
|
|
|
|
|
|
|
|
def _populate_file_types(params: Dict[str, CommandParameter], file_types: Dict[str, Sequence[Union[str, FileType]]]) -> None: |
|
|
|
for name, param in params.items(): |
|
|
|
types = file_types.pop(name, MISSING) |
|
|
|
if types is MISSING: |
|
|
|
continue |
|
|
|
|
|
|
|
if param.type is not AppCommandOptionType.attachment: |
|
|
|
raise TypeError('file_types is only supported for attachment option types') |
|
|
|
|
|
|
|
if not isinstance(types, (list, tuple)) or not all(isinstance(ft, (str, FileType)) for ft in types): |
|
|
|
raise TypeError('file_types must be a list of strings and FileType enums') |
|
|
|
|
|
|
|
_validate_discord_file_types(types) |
|
|
|
param.file_types = types |
|
|
|
|
|
|
|
if file_types: |
|
|
|
first = next(iter(file_types)) |
|
|
|
raise TypeError(f'unknown parameter given: {first}') |
|
|
|
|
|
|
|
|
|
|
|
def _extract_parameters_from_callback(func: Callable[..., Any], globalns: Dict[str, Any]) -> Dict[str, CommandParameter]: |
|
|
|
params = inspect.signature(func).parameters |
|
|
|
cache = {} |
|
|
|
@ -428,6 +451,13 @@ def _extract_parameters_from_callback(func: Callable[..., Any], globalns: Dict[s |
|
|
|
else: |
|
|
|
_populate_autocomplete(result, autocomplete.copy()) |
|
|
|
|
|
|
|
try: |
|
|
|
file_types = func.__discord_app_commands_param_file_types__ |
|
|
|
except AttributeError: |
|
|
|
pass |
|
|
|
else: |
|
|
|
_populate_file_types(result, file_types.copy()) |
|
|
|
|
|
|
|
return result |
|
|
|
|
|
|
|
|
|
|
|
@ -497,6 +527,12 @@ class Parameter: |
|
|
|
The minimum supported value for this parameter. |
|
|
|
max_value: Optional[Union[:class:`int`, :class:`float`]] |
|
|
|
The maximum supported value for this parameter. |
|
|
|
file_types: Optional[Sequence[Union[:class:`str`, :class:`.FileType`]]] |
|
|
|
A list of file types that are allowed to be uploaded for this parameter. |
|
|
|
|
|
|
|
Only applicable for :class:`~discord.AppCommandOptionType.attachment` parameters. |
|
|
|
|
|
|
|
.. versionadded:: 2.8 |
|
|
|
default: Any |
|
|
|
The default value of the parameter, if given. |
|
|
|
If not given then this is :data:`~discord.utils.MISSING`. |
|
|
|
@ -574,6 +610,10 @@ class Parameter: |
|
|
|
def max_value(self) -> Optional[Union[int, float]]: |
|
|
|
return self.__parent.max_value |
|
|
|
|
|
|
|
@property |
|
|
|
def file_types(self) -> Optional[Sequence[Union[str, FileType]]]: |
|
|
|
return self.__parent.file_types |
|
|
|
|
|
|
|
|
|
|
|
class Command(Generic[GroupT, P, T]): |
|
|
|
"""A class that implements an application command. |
|
|
|
@ -2905,3 +2945,59 @@ def default_permissions(perms_obj: Optional[Permissions] = None, /, **perms: Unp |
|
|
|
return func |
|
|
|
|
|
|
|
return decorator |
|
|
|
|
|
|
|
|
|
|
|
def set_file_types(**parameters: Sequence[Union[str, FileType]]) -> Callable[[T], T]: |
|
|
|
r"""Sets the file types for the given parameters by their name using the key of the keyword argument |
|
|
|
as the name. |
|
|
|
|
|
|
|
.. versionadded:: 2.8 |
|
|
|
|
|
|
|
.. warning:: |
|
|
|
|
|
|
|
The actual file is not guaranteed to be of the specified type. The client only |
|
|
|
checks the file extension, so users can easily bypass this check by renaming the file. |
|
|
|
|
|
|
|
Example: |
|
|
|
|
|
|
|
.. code-block:: python3 |
|
|
|
|
|
|
|
@app_commands.command(description='Uploads a file') |
|
|
|
@app_commands.set_file_types(file=['.png', discord.FileType.video]) |
|
|
|
async def upload(interaction: discord.Interaction, file: discord.Attachment): |
|
|
|
await interaction.response.send_message(f'Uploaded {file.filename}') |
|
|
|
|
|
|
|
Parameters |
|
|
|
----------- |
|
|
|
\*\*parameters: Sequence[Union[:class:`str`, :class:`.FileType`]] |
|
|
|
A list of up to 10 file types that are allowed to be uploaded for each attachment parameter. |
|
|
|
The type of the parameter must be :class:`discord.Attachment`. |
|
|
|
|
|
|
|
You can mix and match strings and :class:`.FileType` enums in the list. |
|
|
|
|
|
|
|
If a string is provided, make sure to prefix it with a period (``.``) (e.g. ``.png``). |
|
|
|
This is required. |
|
|
|
You may provide any string you want, but (if you are specifying only extensions) you must |
|
|
|
include ``.jpg`` for image uploads, and both ``.mp4`` and ``.mov`` for video uploads. |
|
|
|
|
|
|
|
Must be between 0 and 10. Defaults to allowing all file types. |
|
|
|
|
|
|
|
Raises |
|
|
|
-------- |
|
|
|
TypeError |
|
|
|
The parameter name is not found or the parameter type is not :class:`discord.Attachment`. |
|
|
|
""" |
|
|
|
|
|
|
|
def decorator(inner: T) -> T: |
|
|
|
unwrapped = getattr(inner, '__discord_app_commands_unwrap__', inner) or inner |
|
|
|
if isinstance(unwrapped, Command): |
|
|
|
_populate_file_types(unwrapped._params, parameters) |
|
|
|
else: |
|
|
|
try: |
|
|
|
inner.__discord_app_commands_param_file_types__.update(parameters) # type: ignore # Runtime attribute access |
|
|
|
except AttributeError: |
|
|
|
inner.__discord_app_commands_param_file_types__ = parameters # type: ignore # Runtime attribute assignment |
|
|
|
|
|
|
|
return inner |
|
|
|
|
|
|
|
return decorator |
|
|
|
|