From e05c80b963065bb3602d5fbf1ff3af49c69321f4 Mon Sep 17 00:00:00 2001 From: Josh Date: Fri, 18 Feb 2022 18:22:40 +1000 Subject: [PATCH] [types] Refactor and add Application Command types --- discord/http.py | 40 +++--- discord/types/command.py | 220 ++++++++++++++++++++++++++++++ discord/types/interactions.py | 245 +++++++++++++++++----------------- 3 files changed, 361 insertions(+), 144 deletions(-) create mode 100644 discord/types/command.py diff --git a/discord/http.py b/discord/http.py index 58f91ce6d..84d9e7a9e 100644 --- a/discord/http.py +++ b/discord/http.py @@ -25,7 +25,6 @@ DEALINGS IN THE SOFTWARE. from __future__ import annotations import asyncio -import json import logging import sys from typing import ( @@ -68,6 +67,7 @@ if TYPE_CHECKING: appinfo, audit_log, channel, + command, components, emoji, embed, @@ -1699,12 +1699,12 @@ class HTTPClient: # Application commands (global) - def get_global_commands(self, application_id: Snowflake) -> Response[List[interactions.ApplicationCommand]]: + def get_global_commands(self, application_id: Snowflake) -> Response[List[command.ApplicationCommand]]: return self.request(Route('GET', '/applications/{application_id}/commands', application_id=application_id)) def get_global_command( self, application_id: Snowflake, command_id: Snowflake - ) -> Response[interactions.ApplicationCommand]: + ) -> Response[command.ApplicationCommand]: r = Route( 'GET', '/applications/{application_id}/commands/{command_id}', @@ -1713,7 +1713,7 @@ class HTTPClient: ) return self.request(r) - def upsert_global_command(self, application_id: Snowflake, payload) -> Response[interactions.ApplicationCommand]: + def upsert_global_command(self, application_id: Snowflake, payload) -> Response[command.ApplicationCommand]: r = Route('POST', '/applications/{application_id}/commands', application_id=application_id) return self.request(r, json=payload) @@ -1721,8 +1721,8 @@ class HTTPClient: self, application_id: Snowflake, command_id: Snowflake, - payload: interactions.EditApplicationCommand, - ) -> Response[interactions.ApplicationCommand]: + payload: Dict[str, Any], + ) -> Response[command.ApplicationCommand]: valid_keys = ( 'name', 'description', @@ -1748,7 +1748,7 @@ class HTTPClient: def bulk_upsert_global_commands( self, application_id: Snowflake, payload - ) -> Response[List[interactions.ApplicationCommand]]: + ) -> Response[List[command.ApplicationCommand]]: r = Route('PUT', '/applications/{application_id}/commands', application_id=application_id) return self.request(r, json=payload) @@ -1756,7 +1756,7 @@ class HTTPClient: def get_guild_commands( self, application_id: Snowflake, guild_id: Snowflake - ) -> Response[List[interactions.ApplicationCommand]]: + ) -> Response[List[command.ApplicationCommand]]: r = Route( 'GET', '/applications/{application_id}/guilds/{guild_id}/commands', @@ -1770,7 +1770,7 @@ class HTTPClient: application_id: Snowflake, guild_id: Snowflake, command_id: Snowflake, - ) -> Response[interactions.ApplicationCommand]: + ) -> Response[command.ApplicationCommand]: r = Route( 'GET', '/applications/{application_id}/guilds/{guild_id}/commands/{command_id}', @@ -1784,8 +1784,8 @@ class HTTPClient: self, application_id: Snowflake, guild_id: Snowflake, - payload: interactions.EditApplicationCommand, - ) -> Response[interactions.ApplicationCommand]: + payload: Dict[str, Any], + ) -> Response[command.ApplicationCommand]: r = Route( 'POST', '/applications/{application_id}/guilds/{guild_id}/commands', @@ -1799,8 +1799,8 @@ class HTTPClient: application_id: Snowflake, guild_id: Snowflake, command_id: Snowflake, - payload: interactions.EditApplicationCommand, - ) -> Response[interactions.ApplicationCommand]: + payload: Dict[str, Any], + ) -> Response[command.ApplicationCommand]: valid_keys = ( 'name', 'description', @@ -1835,8 +1835,8 @@ class HTTPClient: self, application_id: Snowflake, guild_id: Snowflake, - payload: List[interactions.EditApplicationCommand], - ) -> Response[List[interactions.ApplicationCommand]]: + payload: List[Dict[str, Any]], + ) -> Response[List[command.ApplicationCommand]]: r = Route( 'PUT', '/applications/{application_id}/guilds/{guild_id}/commands', @@ -1889,7 +1889,7 @@ class HTTPClient: token: str, *, type: InteractionResponseType, - data: Optional[interactions.InteractionApplicationCommandCallbackData] = None, + data: Optional[Dict[str, Any]] = None, ) -> Response[None]: r = Route( 'POST', @@ -2003,7 +2003,7 @@ class HTTPClient: self, application_id: Snowflake, guild_id: Snowflake, - ) -> Response[List[interactions.GuildApplicationCommandPermissions]]: + ) -> Response[List[command.GuildApplicationCommandPermissions]]: r = Route( 'GET', '/applications/{application_id}/guilds/{guild_id}/commands/permissions', @@ -2017,7 +2017,7 @@ class HTTPClient: application_id: Snowflake, guild_id: Snowflake, command_id: Snowflake, - ) -> Response[interactions.GuildApplicationCommandPermissions]: + ) -> Response[command.GuildApplicationCommandPermissions]: r = Route( 'GET', '/applications/{application_id}/guilds/{guild_id}/commands/{command_id}/permissions', @@ -2032,7 +2032,7 @@ class HTTPClient: application_id: Snowflake, guild_id: Snowflake, command_id: Snowflake, - payload: interactions.BaseGuildApplicationCommandPermissions, + payload: Dict[str, Any], ) -> Response[None]: r = Route( 'PUT', @@ -2047,7 +2047,7 @@ class HTTPClient: self, application_id: Snowflake, guild_id: Snowflake, - payload: List[interactions.PartialGuildApplicationCommandPermissions], + payload: List[Dict[str, Any]], ) -> Response[None]: r = Route( 'PUT', diff --git a/discord/types/command.py b/discord/types/command.py new file mode 100644 index 000000000..04207aa55 --- /dev/null +++ b/discord/types/command.py @@ -0,0 +1,220 @@ +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +from __future__ import annotations + +from typing import List, Literal, TypedDict, Union + +from discord.types.channel import ChannelType +from discord.types.snowflake import Snowflake + +ApplicationCommandType = Literal[1, 2, 3] +ApplicationCommandOptionType = Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] + + +class _BaseApplicationCommandOption(TypedDict): + name: str + description: str + + +class _SubCommandCommandOption(_BaseApplicationCommandOption): + type: Literal[1] + options: List[_ValueApplicationCommandOption] + + +class _SubCommandGroupCommandOption(_BaseApplicationCommandOption): + type: Literal[2] + options: List[_SubCommandCommandOption] + + +class _BaseValueApplicationCommandOption(_BaseApplicationCommandOption, total=False): + required: bool + + +class _StringApplicationCommandOptionChoice(TypedDict, total=False): + name: str + value: str + + +class _StringApplicationCommandOptionOptional(_BaseValueApplicationCommandOption, total=False): + choices: List[_StringApplicationCommandOptionChoice] + autocomplete: bool + + +class _StringApplicationCommandOption(_StringApplicationCommandOptionOptional): + type: Literal[3] + + +class _IntegerApplicationCommandOptionChoice(TypedDict, total=False): + name: str + value: int + + +class _IntegerApplicationCommandOptionOptional(_BaseValueApplicationCommandOption, total=False): + min_value: int + max_value: int + choices: List[_IntegerApplicationCommandOptionChoice] + autocomplete: bool + + +class _IntegerApplicationCommandOption(_IntegerApplicationCommandOptionOptional): + type: Literal[4] + + +class _BooleanApplicationCommandOption(_BaseValueApplicationCommandOption): + type: Literal[5] + + +class _ChannelApplicationCommandOptionChoiceOptional(_BaseApplicationCommandOption, total=False): + channel_types: List[ChannelType] + + +class _ChannelApplicationCommandOptionChoice(_ChannelApplicationCommandOptionChoiceOptional): + type: Literal[7] + + +class _NonChannelSnowflakeApplicationCommandOptionChoice(_BaseValueApplicationCommandOption): + type: Literal[6, 8, 9, 11] + + +_SnowflakeApplicationCommandOptionChoice = Union[ + _ChannelApplicationCommandOptionChoice, + _NonChannelSnowflakeApplicationCommandOptionChoice, +] + + +class _NumberApplicationCommandOptionChoice(TypedDict, total=False): + name: str + value: float + + +class _NumberApplicationCommandOptionOptional(_BaseValueApplicationCommandOption, total=False): + min_value: float + max_value: float + choices: List[_NumberApplicationCommandOptionChoice] + autocomplete: bool + + +class _NumberApplicationCommandOption(_NumberApplicationCommandOptionOptional): + type: Literal[10] + + +_ValueApplicationCommandOption = Union[ + _StringApplicationCommandOption, + _IntegerApplicationCommandOption, + _BooleanApplicationCommandOption, + _SnowflakeApplicationCommandOptionChoice, + _NumberApplicationCommandOption, +] + +ApplicationCommandOption = Union[ + _SubCommandGroupCommandOption, + _SubCommandCommandOption, + _ValueApplicationCommandOption, +] + +ApplicationCommandOptionChoice = Union[ + _StringApplicationCommandOptionChoice, + _IntegerApplicationCommandOptionChoice, + _NumberApplicationCommandOptionChoice, +] + + +class _BaseApplicationCommand(TypedDict): + id: Snowflake + application_id: Snowflake + name: str + version: Snowflake + + +class _ChatInputApplicationCommandOptional(_BaseApplicationCommand, total=False): + type: Literal[1] + options: Union[ + List[_ValueApplicationCommandOption], + List[Union[_SubCommandCommandOption, _SubCommandGroupCommandOption]], + ] + + +class _ChatInputApplicationCommand(_ChatInputApplicationCommandOptional): + description: str + + +class _BaseContextMenuApplicationCommand(_BaseApplicationCommand): + description: Literal[""] + + +class _UserApplicationCommand(_BaseContextMenuApplicationCommand): + type: Literal[2] + + +class _MessageApplicationCommand(_BaseContextMenuApplicationCommand): + type: Literal[3] + + +GlobalApplicationCommand = Union[ + _ChatInputApplicationCommand, + _UserApplicationCommand, + _MessageApplicationCommand, +] + + +class _GuildChatInputApplicationCommand(_ChatInputApplicationCommand): + guild_id: Snowflake + + +class _GuildUserApplicationCommand(_UserApplicationCommand): + guild_id: Snowflake + + +class _GuildMessageApplicationCommand(_MessageApplicationCommand): + guild_id: Snowflake + + +GuildApplicationCommand = Union[ + _GuildChatInputApplicationCommand, + _GuildUserApplicationCommand, + _GuildMessageApplicationCommand, +] + + +ApplicationCommand = Union[ + GlobalApplicationCommand, + GuildApplicationCommand, +] + + +ApplicationCommandPermissionType = Literal[1, 2] + + +class ApplicationCommandPermissions(TypedDict): + id: Snowflake + type: ApplicationCommandPermissionType + permission: bool + + +class GuildApplicationCommandPermissions(TypedDict): + id: Snowflake + application_id: Snowflake + guild_id: Snowflake + permissions: List[ApplicationCommandPermissions] diff --git a/discord/types/interactions.py b/discord/types/interactions.py index b0ce156b1..672c4940c 100644 --- a/discord/types/interactions.py +++ b/discord/types/interactions.py @@ -24,195 +24,206 @@ DEALINGS IN THE SOFTWARE. from __future__ import annotations -from typing import Optional, TYPE_CHECKING, Dict, TypedDict, Union, List, Literal -from .snowflake import Snowflake -from .components import Component, ComponentType -from .embed import Embed -from .channel import ChannelType +from typing import TYPE_CHECKING, Dict, List, Literal, TypedDict, Union + +from .channel import ChannelType, ThreadMetadata from .member import Member +from .message import Attachment from .role import Role +from .snowflake import Snowflake from .user import User if TYPE_CHECKING: - from .message import AllowedMentions, Message + from .message import Message -ApplicationCommandType = Literal[1, 2, 3] - -class _ApplicationCommandOptional(TypedDict, total=False): - options: List[ApplicationCommandOption] - type: ApplicationCommandType +InteractionType = Literal[1, 2, 3, 4, 5] -class ApplicationCommand(_ApplicationCommandOptional): +class PartialChannel(TypedDict): id: Snowflake - application_id: Snowflake name: str - description: str + type: ChannelType + permissions: str -class _ApplicationCommandOptionOptional(TypedDict, total=False): - choices: List[ApplicationCommandOptionChoice] - options: List[ApplicationCommandOption] +class PartialThread(PartialChannel): + thread_metadata: ThreadMetadata + parent_id: Snowflake -ApplicationCommandOptionType = Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +class ResolvedData(TypedDict, total=False): + users: Dict[Snowflake, User] + members: Dict[Snowflake, Member] + roles: Dict[Snowflake, Role] + channels: Dict[Snowflake, Union[PartialChannel, PartialThread]] + messages: Dict[Snowflake, Message] + attachments: Dict[Snowflake, Attachment] -class ApplicationCommandOption(_ApplicationCommandOptionOptional): - type: ApplicationCommandOptionType - name: str - description: str - required: bool - - -class ApplicationCommandOptionChoice(TypedDict): - name: str - value: Union[str, int] - - -ApplicationCommandPermissionType = Literal[1, 2] - - -class ApplicationCommandPermissions(TypedDict): - id: Snowflake - type: ApplicationCommandPermissionType - permission: bool - - -class BaseGuildApplicationCommandPermissions(TypedDict): - permissions: List[ApplicationCommandPermissions] - - -class PartialGuildApplicationCommandPermissions(BaseGuildApplicationCommandPermissions): - id: Snowflake - - -class GuildApplicationCommandPermissions(PartialGuildApplicationCommandPermissions): - application_id: Snowflake - guild_id: Snowflake - - -InteractionType = Literal[1, 2, 3] - - -class _ApplicationCommandInteractionDataOption(TypedDict): +class _BaseApplicationCommandInteractionDataOption(TypedDict): name: str -class _ApplicationCommandInteractionDataOptionSubcommand(_ApplicationCommandInteractionDataOption): +class _CommandGroupApplicationCommandInteractionDataOption(_BaseApplicationCommandInteractionDataOption): type: Literal[1, 2] options: List[ApplicationCommandInteractionDataOption] -class _ApplicationCommandInteractionDataOptionString(_ApplicationCommandInteractionDataOption): +class _BaseValueApplicationCommandInteractionDataOption(_BaseApplicationCommandInteractionDataOption, total=False): + focused: bool + + +class _StringValueApplicationCommandInteractionDataOption(_BaseValueApplicationCommandInteractionDataOption): type: Literal[3] value: str -class _ApplicationCommandInteractionDataOptionInteger(_ApplicationCommandInteractionDataOption): +class _IntegerValueApplicationCommandInteractionDataOption(_BaseValueApplicationCommandInteractionDataOption): type: Literal[4] value: int -class _ApplicationCommandInteractionDataOptionBoolean(_ApplicationCommandInteractionDataOption): +class _BooleanValueApplicationCommandInteractionDataOption(_BaseValueApplicationCommandInteractionDataOption): type: Literal[5] value: bool -class _ApplicationCommandInteractionDataOptionSnowflake(_ApplicationCommandInteractionDataOption): - type: Literal[6, 7, 8, 9] +class _SnowflakeValueApplicationCommandInteractionDataOption(_BaseValueApplicationCommandInteractionDataOption): + type: Literal[6, 7, 8, 9, 11] value: Snowflake -class _ApplicationCommandInteractionDataOptionNumber(_ApplicationCommandInteractionDataOption): +class _NumberValueApplicationCommandInteractionDataOption(_BaseValueApplicationCommandInteractionDataOption): type: Literal[10] value: float -ApplicationCommandInteractionDataOption = Union[ - _ApplicationCommandInteractionDataOptionString, - _ApplicationCommandInteractionDataOptionInteger, - _ApplicationCommandInteractionDataOptionSubcommand, - _ApplicationCommandInteractionDataOptionBoolean, - _ApplicationCommandInteractionDataOptionSnowflake, - _ApplicationCommandInteractionDataOptionNumber, +_ValueApplicationCommandInteractionDataOption = Union[ + _StringValueApplicationCommandInteractionDataOption, + _IntegerValueApplicationCommandInteractionDataOption, + _BooleanValueApplicationCommandInteractionDataOption, + _SnowflakeValueApplicationCommandInteractionDataOption, + _NumberValueApplicationCommandInteractionDataOption, ] -class ApplicationCommandResolvedPartialChannel(TypedDict): +ApplicationCommandInteractionDataOption = Union[ + _CommandGroupApplicationCommandInteractionDataOption, + _ValueApplicationCommandInteractionDataOption, +] + + +class _BaseApplicationCommandInteractionDataOptional(TypedDict): + resolved: ResolvedData + + +class _BaseApplicationCommandInteractionData(_BaseApplicationCommandInteractionDataOptional): id: Snowflake - type: ChannelType - permissions: str name: str -class ApplicationCommandInteractionDataResolved(TypedDict, total=False): - users: Dict[Snowflake, User] - members: Dict[Snowflake, Member] - roles: Dict[Snowflake, Role] - channels: Dict[Snowflake, ApplicationCommandResolvedPartialChannel] - - -class _ApplicationCommandInteractionDataOptional(TypedDict, total=False): +class ChatInputApplicationCommandInteractionData(_BaseApplicationCommandInteractionData, total=False): + type: Literal[1] options: List[ApplicationCommandInteractionDataOption] - resolved: ApplicationCommandInteractionDataResolved + + +class _BaseNonChatInputApplicationCommandInteractionData(_BaseApplicationCommandInteractionData): target_id: Snowflake - type: ApplicationCommandType -class ApplicationCommandInteractionData(_ApplicationCommandInteractionDataOptional): - id: Snowflake - name: str +class UserApplicationCommandInteractionData(_BaseNonChatInputApplicationCommandInteractionData): + type: Literal[2] -class _ComponentInteractionDataOptional(TypedDict, total=False): +class MessageApplicationCommandInteractionData(_BaseNonChatInputApplicationCommandInteractionData): + type: Literal[3] + + +ApplicationCommandInteractionData = Union[ + ChatInputApplicationCommandInteractionData, + UserApplicationCommandInteractionData, + MessageApplicationCommandInteractionData, +] + + +class _BaseMessageComponentInteractionData(TypedDict): + custom_id: str + + +class ButtonMessageComponentInteractionData(_BaseMessageComponentInteractionData): + type: Literal[2] + + +class SelectMessageComponentInteractionData(_BaseMessageComponentInteractionData): + component_type: Literal[3] values: List[str] -class ComponentInteractionData(_ComponentInteractionDataOptional): +MessageComponentInteractionData = Union[ButtonMessageComponentInteractionData, SelectMessageComponentInteractionData] + + +class ModalSubmitInputTextInteractionData(TypedDict): + type: Literal[4] custom_id: str - component_type: ComponentType + value: str -InteractionData = Union[ApplicationCommandInteractionData, ComponentInteractionData] +ModalSubmitComponentItemInteractionData = ModalSubmitInputTextInteractionData -class _InteractionOptional(TypedDict, total=False): - data: InteractionData +class ModalSubmitActionRowInteractionData(TypedDict): + type: Literal[1] + components: List[ModalSubmitComponentItemInteractionData] + + +ModalSubmitComponentInteractionData = Union[ModalSubmitActionRowInteractionData, ModalSubmitComponentItemInteractionData] + + +class ModalSubmitInteractionData(TypedDict): + custom_id: str + components: List[ModalSubmitActionRowInteractionData] + + +InteractionData = Union[ + ApplicationCommandInteractionData, + MessageComponentInteractionData, + ModalSubmitInteractionData, +] + + +class _BaseInteractionOptional(TypedDict, total=False): guild_id: Snowflake channel_id: Snowflake - member: Member - user: User - message: Message -class Interaction(_InteractionOptional): +class _BaseInteraction(_BaseInteractionOptional): id: Snowflake application_id: Snowflake - type: InteractionType token: str - version: int + version: Literal[1] -class InteractionApplicationCommandCallbackData(TypedDict, total=False): - tts: bool - content: str - embeds: List[Embed] - allowed_mentions: AllowedMentions - flags: int - components: List[Component] +class PingInteraction(_BaseInteraction): + type: Literal[1] -InteractionResponseType = Literal[1, 4, 5, 6, 7] +class ApplicationCommandInteraction(_BaseInteraction): + type: Literal[2, 4] + data: ApplicationCommandInteractionData -class _InteractionResponseOptional(TypedDict, total=False): - data: InteractionApplicationCommandCallbackData +class MessageComponentInteraction(_BaseInteraction): + type: Literal[3] + data: MessageComponentInteractionData -class InteractionResponse(_InteractionResponseOptional): - type: InteractionResponseType +class ModalSubmitInteraction(_BaseInteraction): + type: Literal[5] + data: ModalSubmitInteractionData + + +Interaction = Union[PingInteraction, ApplicationCommandInteraction, MessageComponentInteraction, ModalSubmitInteraction] class MessageInteraction(TypedDict): @@ -220,17 +231,3 @@ class MessageInteraction(TypedDict): type: InteractionType name: str user: User - - - - - -class _EditApplicationCommandOptional(TypedDict, total=False): - description: str - options: Optional[List[ApplicationCommandOption]] - type: ApplicationCommandType - - -class EditApplicationCommand(_EditApplicationCommandOptional): - name: str - default_permission: bool