Browse Source

Fix interactions

pull/10109/head
dolfies 4 years ago
parent
commit
a86d42ce55
  1. 24
      discord/commands.py
  2. 10
      discord/components.py
  3. 2
      discord/interactions.py
  4. 4
      discord/state.py
  5. 10
      discord/utils.py

24
discord/commands.py

@ -29,7 +29,7 @@ from typing import Any, Dict, List, Optional, Protocol, Tuple, runtime_checkable
from .enums import CommandType, ChannelType, OptionType, try_enum from .enums import CommandType, ChannelType, OptionType, try_enum
from .errors import InvalidData, InvalidArgument from .errors import InvalidData, InvalidArgument
from .utils import time_snowflake from .utils import _generate_session_id, time_snowflake
if TYPE_CHECKING: if TYPE_CHECKING:
from .abc import Messageable, Snowflake from .abc import Messageable, Snowflake
@ -99,6 +99,7 @@ class ApplicationCommand(Protocol):
'channel_id': str(channel.id), 'channel_id': str(channel.id),
'data': data, 'data': data,
'nonce': str(time_snowflake(datetime.utcnow())), 'nonce': str(time_snowflake(datetime.utcnow())),
'session_id': state.session_id or _generate_session_id(),
'type': 2, # Should be an enum but eh 'type': 2, # Should be an enum but eh
} }
if getattr(channel, 'guild', None) is not None: if getattr(channel, 'guild', None) is not None:
@ -143,19 +144,21 @@ class BaseCommand(ApplicationCommand):
'version', 'version',
'type', 'type',
'default_permission', 'default_permission',
'_dm_permission', '_data',
'_default_member_permissions',
'_state', '_state',
'_channel', '_channel',
'_application_id' '_application_id',
'_dm_permission',
'_default_member_permissions',
) )
def __init__( def __init__(
self, *, state: ConnectionState, data: Dict[str, Any], channel: Optional[Messageable] = None self, *, state: ConnectionState, data: Dict[str, Any], channel: Optional[Messageable] = None
) -> None: ) -> None:
self._state = state
self._data = data
self.name = data['name'] self.name = data['name']
self.description = data['description'] self.description = data['description']
self._state = state
self._channel = channel self._channel = channel
self._application_id: int = int(data['application_id']) self._application_id: int = int(data['application_id'])
self.id: int = int(data['id']) self.id: int = int(data['id'])
@ -202,7 +205,7 @@ class BaseCommand(ApplicationCommand):
self._channel = value self._channel = value
class SlashMixin(ApplicationCommand): class SlashMixin(ApplicationCommand, Protocol):
if TYPE_CHECKING: if TYPE_CHECKING:
_parent: SlashCommand _parent: SlashCommand
options: List[Option] options: List[Option]
@ -210,7 +213,10 @@ class SlashMixin(ApplicationCommand):
async def __call__(self, options, channel=None): async def __call__(self, options, channel=None):
obj = self._parent obj = self._parent
command = obj._data
command['name_localized'] = command['name']
data = { data = {
'application_command': command,
'attachments': [], 'attachments': [],
'id': str(obj.id), 'id': str(obj.id),
'name': obj.name, 'name': obj.name,
@ -299,7 +305,10 @@ class UserCommand(BaseCommand):
if user is None: if user is None:
raise TypeError('__call__() missing 1 required positional argument: \'user\'') raise TypeError('__call__() missing 1 required positional argument: \'user\'')
command = self._data
command['name_localized'] = command['name']
data = { data = {
'application_command': command,
'attachments': [], 'attachments': [],
'id': str(self.id), 'id': str(self.id),
'name': self.name, 'name': self.name,
@ -367,7 +376,10 @@ class MessageCommand(BaseCommand):
if message is None: if message is None:
raise TypeError('__call__() missing 1 required positional argument: \'message\'') raise TypeError('__call__() missing 1 required positional argument: \'message\'')
command = self._data
command['name_localized'] = command['name']
data = { data = {
'application_command': command,
'attachments': [], 'attachments': [],
'id': str(self.id), 'id': str(self.id),
'name': self.name, 'name': self.name,

10
discord/components.py

@ -30,7 +30,7 @@ from typing import Any, ClassVar, Dict, List, Optional, TYPE_CHECKING, Tuple, Ty
from .enums import try_enum, ComponentType, ButtonStyle from .enums import try_enum, ComponentType, ButtonStyle
from .errors import InvalidData from .errors import InvalidData
from .utils import get_slots, MISSING, time_snowflake from .utils import _generate_session_id, get_slots, MISSING, time_snowflake
from .partial_emoji import PartialEmoji, _EmojiTag from .partial_emoji import PartialEmoji, _EmojiTag
if TYPE_CHECKING: if TYPE_CHECKING:
@ -228,7 +228,7 @@ class Button(Component):
message = self.message message = self.message
state = message._state state = message._state
payload = { payload = {
'application_id': str(message.application_id), 'application_id': str(message.application_id or message.author.id),
'channel_id': str(message.channel.id), 'channel_id': str(message.channel.id),
'data': { 'data': {
'component_type': 2, 'component_type': 2,
@ -237,12 +237,13 @@ class Button(Component):
'message_flags': message.flags.value, 'message_flags': message.flags.value,
'message_id': str(message.id), 'message_id': str(message.id),
'nonce': str(time_snowflake(datetime.utcnow())), 'nonce': str(time_snowflake(datetime.utcnow())),
'session_id': state.session_id or _generate_session_id(),
'type': 3, # Should be an enum but eh 'type': 3, # Should be an enum but eh
} }
if message.guild: if message.guild:
payload['guild_id'] = str(message.guild.id) payload['guild_id'] = str(message.guild.id)
state._interactions[payload['nonce']] = 3 state._interactions[payload['nonce']] = (3, None)
await state.http.interact(payload) await state.http.interact(payload)
try: try:
i = await state.client.wait_for( i = await state.client.wait_for(
@ -354,12 +355,13 @@ class SelectMenu(Component):
'message_flags': message.flags.value, 'message_flags': message.flags.value,
'message_id': str(message.id), 'message_id': str(message.id),
'nonce': str(time_snowflake(datetime.utcnow())), 'nonce': str(time_snowflake(datetime.utcnow())),
'session_id': state.session_id or _generate_session_id(),
'type': 3, # Should be an enum but eh 'type': 3, # Should be an enum but eh
} }
if message.guild: if message.guild:
payload['guild_id'] = str(message.guild.id) payload['guild_id'] = str(message.guild.id)
state._interactions[payload['nonce']] = 3 state._interactions[payload['nonce']] = (3, None)
await state.http.interact(payload) await state.http.interact(payload)
try: try:
i = await state.client.wait_for( i = await state.client.wait_for(

2
discord/interactions.py

@ -76,7 +76,7 @@ class Interaction:
@classmethod @classmethod
def _from_self( def _from_self(
cls, *, id: Snowflake, type: int, nonce: Optional[Snowflake] = None, user: ClientUser, name: str cls, *, id: Snowflake, type: int, nonce: Optional[Snowflake] = None, user: ClientUser, name: Optional[str]
) -> Interaction: ) -> Interaction:
return cls(int(id), type, nonce, user=user, name=name) return cls(int(id), type, nonce, user=user, name=name)

4
discord/state.py

@ -262,7 +262,7 @@ class ConnectionState:
self._voice_clients: Dict[int, VoiceProtocol] = {} self._voice_clients: Dict[int, VoiceProtocol] = {}
self._voice_states: Dict[int, VoiceState] = {} self._voice_states: Dict[int, VoiceState] = {}
self._interactions: Dict[Union[int, str], Union[Tuple[int, str], Interaction]] = {} self._interactions: Dict[Union[int, str], Union[Tuple[int, Optional[str]], Interaction]] = {}
self._relationships: Dict[int, Relationship] = {} self._relationships: Dict[int, Relationship] = {}
self._private_channels: Dict[int, PrivateChannel] = {} self._private_channels: Dict[int, PrivateChannel] = {}
self._private_channels_by_user: Dict[int, DMChannel] = {} self._private_channels_by_user: Dict[int, DMChannel] = {}
@ -1722,7 +1722,7 @@ class ConnectionState:
self.dispatch('relationship_remove', old) self.dispatch('relationship_remove', old)
def parse_interaction_create(self, data) -> None: def parse_interaction_create(self, data) -> None:
type, name = self._interactions.pop(data['nonce'], (0, '')) type, name = self._interactions.pop(data['nonce'], (0, None))
i = Interaction._from_self(type=type, user=self.user, name=name, **data) # type: ignore i = Interaction._from_self(type=type, user=self.user, name=name, **data) # type: ignore
self._interactions[i.id] = i self._interactions[i.id] = i
self.dispatch('interaction_create', i) self.dispatch('interaction_create', i)

10
discord/utils.py

@ -59,7 +59,9 @@ import json
import logging import logging
import os import os
import platform import platform
import random
import re import re
import string
import subprocess import subprocess
import sys import sys
import tempfile import tempfile
@ -1067,6 +1069,14 @@ def set_target(
except AttributeError: except AttributeError:
pass pass
def _generate_session_id() -> str:
return ''.join(
random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits)
for _ in range(16)
)
class ExpiringQueue(asyncio.Queue): # Inspired from https://github.com/NoahCardoza/CaptchaHarvester class ExpiringQueue(asyncio.Queue): # Inspired from https://github.com/NoahCardoza/CaptchaHarvester
def __init__(self, timeout: int, maxsize: int = 0) -> None: def __init__(self, timeout: int, maxsize: int = 0) -> None:
super().__init__(maxsize) super().__init__(maxsize)

Loading…
Cancel
Save