Browse Source

Add raw typing event and fix typing event not working for DMs

pull/7927/head
Lilly Rose Berner 3 years ago
committed by GitHub
parent
commit
277d35c9b2
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 34
      discord/raw_models.py
  2. 25
      discord/state.py
  3. 23
      docs/api.rst

34
discord/raw_models.py

@ -24,9 +24,11 @@ DEALINGS IN THE SOFTWARE.
from __future__ import annotations from __future__ import annotations
import datetime
from typing import TYPE_CHECKING, Optional, Set, List, Tuple, Union from typing import TYPE_CHECKING, Optional, Set, List, Tuple, Union
from .enums import ChannelType, try_enum from .enums import ChannelType, try_enum
from .utils import _get_as_snowflake
if TYPE_CHECKING: if TYPE_CHECKING:
from .types.gateway import ( from .types.gateway import (
@ -39,11 +41,13 @@ if TYPE_CHECKING:
MessageUpdateEvent, MessageUpdateEvent,
IntegrationDeleteEvent, IntegrationDeleteEvent,
ThreadDeleteEvent, ThreadDeleteEvent,
TypingStartEvent,
) )
from .message import Message from .message import Message
from .partial_emoji import PartialEmoji from .partial_emoji import PartialEmoji
from .member import Member from .member import Member
from .threads import Thread from .threads import Thread
from .user import User
ReactionActionEvent = Union[MessageReactionAddEvent, MessageReactionRemoveEvent] ReactionActionEvent = Union[MessageReactionAddEvent, MessageReactionRemoveEvent]
@ -57,6 +61,7 @@ __all__ = (
'RawReactionClearEmojiEvent', 'RawReactionClearEmojiEvent',
'RawIntegrationDeleteEvent', 'RawIntegrationDeleteEvent',
'RawThreadDeleteEvent', 'RawThreadDeleteEvent',
'RawTypingEvent',
) )
@ -314,3 +319,32 @@ class RawThreadDeleteEvent(_RawReprMixin):
self.guild_id: int = int(data['guild_id']) self.guild_id: int = int(data['guild_id'])
self.parent_id: int = int(data['parent_id']) self.parent_id: int = int(data['parent_id'])
self.thread: Optional[Thread] = None self.thread: Optional[Thread] = None
class RawTypingEvent(_RawReprMixin):
"""Represents the payload for a :func:`on_raw_typing` event.
.. versionadded:: 2.0
Attributes
----------
channel_id: :class:`int`
The ID of the channel the user started typing in.
user_id: :class:`int`
The ID of the user that started typing.
user: Optional[Union[:class:`discord.User`, :class:`discord.Member`]]
The user that started typing, if they could be found in the internal cache.
timestamp: :class:`datetime.datetime`
When the typing started as an aware datetime in UTC.
guild_id: Optional[:class:`int`]
The ID of the guild the user started typing in, if applicable.
"""
__slots__ = ('channel_id', 'user_id', 'user', 'timestamp', 'guild_id')
def __init__(self, data: TypingStartEvent, /) -> None:
self.channel_id: int = int(data['channel_id'])
self.user_id: int = int(data['user_id'])
self.user: Optional[Union[User, Member]] = None
self.timestamp: datetime.datetime = datetime.datetime.fromtimestamp(data['timestamp'], tz=datetime.timezone.utc)
self.guild_id: Optional[int] = _get_as_snowflake(data, 'guild_id')

25
discord/state.py

@ -27,7 +27,6 @@ from __future__ import annotations
import asyncio import asyncio
from collections import deque, OrderedDict from collections import deque, OrderedDict
import copy import copy
import datetime
import itertools import itertools
import logging import logging
from typing import ( from typing import (
@ -1443,27 +1442,25 @@ class ConnectionState:
asyncio.create_task(logging_coroutine(coro, info='Voice Protocol voice server update handler')) asyncio.create_task(logging_coroutine(coro, info='Voice Protocol voice server update handler'))
def parse_typing_start(self, data: gw.TypingStartEvent) -> None: def parse_typing_start(self, data: gw.TypingStartEvent) -> None:
raw = RawTypingEvent(data)
raw.user = self.get_user(raw.user_id)
channel, guild = self._get_guild_channel(data) channel, guild = self._get_guild_channel(data)
if channel is not None: if channel is not None:
member = None
user_id = int(data['user_id'])
if isinstance(channel, DMChannel): if isinstance(channel, DMChannel):
member = channel.recipient channel.recipient = raw.user
elif guild is not None:
elif isinstance(channel, (Thread, TextChannel)) and guild is not None: raw.user = guild.get_member(raw.user_id)
member = guild.get_member(user_id)
if member is None: if raw.user is None:
member_data = data.get('member') member_data = data.get('member')
if member_data: if member_data:
member = Member(data=member_data, state=self, guild=guild) raw.user = Member(data=member_data, state=self, guild=guild)
elif isinstance(channel, GroupChannel): if raw.user is not None:
member = utils.find(lambda x: x.id == user_id, channel.recipients) self.dispatch('typing', channel, raw.user, raw.timestamp)
if member is not None: self.dispatch('raw_typing', raw)
timestamp = datetime.datetime.fromtimestamp(data['timestamp'], tz=datetime.timezone.utc)
self.dispatch('typing', channel, member, timestamp)
def _get_reaction_user(self, channel: MessageableChannel, user_id: int) -> Optional[Union[User, Member]]: def _get_reaction_user(self, channel: MessageableChannel, user_id: int) -> Optional[Union[User, Member]]:
if isinstance(channel, TextChannel): if isinstance(channel, TextChannel):

23
docs/api.rst

@ -273,6 +273,9 @@ Channels
If the ``channel`` is a :class:`TextChannel` then the ``user`` parameter If the ``channel`` is a :class:`TextChannel` then the ``user`` parameter
is a :class:`Member`, otherwise it is a :class:`User`. is a :class:`Member`, otherwise it is a :class:`User`.
If the channel or user could not be found in the internal cache this event
will not be called, you may use :func:`on_raw_typing` instead.
This requires :attr:`Intents.typing` to be enabled. This requires :attr:`Intents.typing` to be enabled.
:param channel: The location where the typing originated from. :param channel: The location where the typing originated from.
@ -282,6 +285,18 @@ Channels
:param when: When the typing started as an aware datetime in UTC. :param when: When the typing started as an aware datetime in UTC.
:type when: :class:`datetime.datetime` :type when: :class:`datetime.datetime`
.. function:: on_raw_typing(payload)
Called when someone begins typing a message. Unlike :func:`on_typing` this
is called regardless of the channel and user being in the internal cache.
This requires :attr:`Intents.typing` to be enabled.
.. versionadded:: 2.0
:param payload: The raw event payload data.
:type payload: :class:`RawTypingEvent`
Connection Connection
~~~~~~~~~~~ ~~~~~~~~~~~
@ -4015,6 +4030,14 @@ RawThreadDeleteEvent
.. autoclass:: RawThreadDeleteEvent() .. autoclass:: RawThreadDeleteEvent()
:members: :members:
RawTypingEvent
~~~~~~~~~~~~~~~~
.. attributetable:: RawTypingEvent
.. autoclass:: RawTypingEvent()
:members:
PartialWebhookGuild PartialWebhookGuild
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~

Loading…
Cancel
Save