Browse Source
This is missing a lot of functionality right now, such as two gateway events and all the HTTP CRUD endpoints.feature/threads
9 changed files with 504 additions and 12 deletions
@ -0,0 +1,244 @@ |
|||
""" |
|||
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 Optional, TYPE_CHECKING |
|||
|
|||
from .mixins import Hashable |
|||
from .abc import Messageable |
|||
from .enums import ChannelType, try_enum |
|||
from . import utils |
|||
|
|||
__all__ = ( |
|||
'Thread', |
|||
'ThreadMember', |
|||
) |
|||
|
|||
if TYPE_CHECKING: |
|||
from .types.threads import ( |
|||
Thread as ThreadPayload, |
|||
ThreadMember as ThreadMemberPayload, |
|||
ThreadMetadata, |
|||
) |
|||
from .guild import Guild |
|||
from .channel import TextChannel |
|||
from .member import Member |
|||
|
|||
|
|||
class Thread(Messageable, Hashable): |
|||
"""Represents a Discord thread. |
|||
|
|||
.. container:: operations |
|||
|
|||
.. describe:: x == y |
|||
|
|||
Checks if two threads are equal. |
|||
|
|||
.. describe:: x != y |
|||
|
|||
Checks if two threads are not equal. |
|||
|
|||
.. describe:: hash(x) |
|||
|
|||
Returns the thread's hash. |
|||
|
|||
.. describe:: str(x) |
|||
|
|||
Returns the thread's name. |
|||
|
|||
.. versionadded:: 2.0 |
|||
|
|||
Attributes |
|||
----------- |
|||
name: :class:`str` |
|||
The thread name. |
|||
guild: :class:`Guild` |
|||
The guild the thread belongs to. |
|||
id: :class:`int` |
|||
The thread ID. |
|||
parent_id: :class:`int` |
|||
The parent :class:`TextChannel` ID this thread belongs to. |
|||
owner_id: :class:`int` |
|||
The user's ID that created this thread. |
|||
last_message_id: Optional[:class:`int`] |
|||
The last message ID of the message sent to this thread. It may |
|||
*not* point to an existing or valid message. |
|||
message_count: :class:`int` |
|||
An approximate number of messages in this thread. This caps at 50. |
|||
member_count: :class:`int` |
|||
An approximate number of members in this thread. This caps at 50. |
|||
me: Optional[:class:`ThreadMember`] |
|||
A thread member representing yourself, if you've joined the thread. |
|||
This could not be available. |
|||
archived: :class:`bool` |
|||
Whether the thread is archived. |
|||
archiver_id: Optional[:class:`int`] |
|||
The user's ID that archived this thread. |
|||
auto_archive_duration: :class:`int` |
|||
The duration in minutes until the thread is automatically archived due to inactivity. |
|||
Usually a value of 60, 1440, 4320 and 10080. |
|||
archive_timestamp: :class:`datetime.datetime` |
|||
An aware timestamp of when the thread's archived status was last updated in UTC. |
|||
""" |
|||
|
|||
__slots__ = ( |
|||
'name', |
|||
'id', |
|||
'guild', |
|||
'_type', |
|||
'_state', |
|||
'owner_id', |
|||
'last_message_id', |
|||
'message_count', |
|||
'member_count', |
|||
'me', |
|||
'archived', |
|||
'archiver_id', |
|||
'auto_archive_duration', |
|||
'archive_timestamp', |
|||
) |
|||
|
|||
def __init__(self, *, guild: Guild, data: ThreadPayload): |
|||
self._state = guild._state |
|||
self.guild = guild |
|||
self._from_data(data) |
|||
|
|||
async def _get_channel(self): |
|||
return self |
|||
|
|||
def _from_data(self, data: ThreadPayload): |
|||
self.id = int(data['id']) |
|||
self.parent_id = int(data['parent_id']) |
|||
self.owner_id = int(data['owner_id']) |
|||
self.name = data['name'] |
|||
self.type = try_enum(ChannelType, data['type']) |
|||
self.last_message_id = utils._get_as_snowflake(data, 'last_message_id') |
|||
self._unroll_metadata(data['thread_metadata']) |
|||
|
|||
try: |
|||
member = data['member'] |
|||
except KeyError: |
|||
self.me = None |
|||
else: |
|||
self.me = ThreadMember(member, self._state) |
|||
|
|||
def _unroll_metadata(self, data: ThreadMetadata): |
|||
self.archived = data['archived'] |
|||
self.archiver_id = utils._get_as_snowflake(data, 'archiver_id') |
|||
self.auto_archive_duration = data['auto_archive_duration'] |
|||
self.archive_timestamp = utils.parse_time(data['archive_timestamp']) |
|||
|
|||
def _update(self, data): |
|||
try: |
|||
self.name = data['name'] |
|||
except KeyError: |
|||
pass |
|||
|
|||
try: |
|||
self._unroll_metadata(data['thread_metadata']) |
|||
except KeyError: |
|||
pass |
|||
|
|||
@property |
|||
def parent(self) -> Optional[TextChannel]: |
|||
"""Optional[:class:`TextChannel`]: The parent channel this thread belongs to.""" |
|||
return self.guild.get_channel(self.parent_id) |
|||
|
|||
@property |
|||
def owner(self) -> Optional[Member]: |
|||
"""Optional[:class:`Member`]: The member this thread belongs to.""" |
|||
return self.guild.get_member(self.owner_id) |
|||
|
|||
@property |
|||
def last_message(self): |
|||
"""Fetches the last message from this channel in cache. |
|||
|
|||
The message might not be valid or point to an existing message. |
|||
|
|||
.. admonition:: Reliable Fetching |
|||
:class: helpful |
|||
|
|||
For a slightly more reliable method of fetching the |
|||
last message, consider using either :meth:`history` |
|||
or :meth:`fetch_message` with the :attr:`last_message_id` |
|||
attribute. |
|||
|
|||
Returns |
|||
--------- |
|||
Optional[:class:`Message`] |
|||
The last message in this channel or ``None`` if not found. |
|||
""" |
|||
return self._state._get_message(self.last_message_id) if self.last_message_id else None |
|||
|
|||
|
|||
class ThreadMember(Hashable): |
|||
"""Represents a Discord thread member. |
|||
|
|||
.. container:: operations |
|||
|
|||
.. describe:: x == y |
|||
|
|||
Checks if two thread members are equal. |
|||
|
|||
.. describe:: x != y |
|||
|
|||
Checks if two thread members are not equal. |
|||
|
|||
.. describe:: hash(x) |
|||
|
|||
Returns the thread member's hash. |
|||
|
|||
.. describe:: str(x) |
|||
|
|||
Returns the thread member's name. |
|||
|
|||
.. versionadded:: 2.0 |
|||
|
|||
Attributes |
|||
----------- |
|||
id: :class:`int` |
|||
The thread member's ID. |
|||
thread_id: :class:`int` |
|||
The thread's ID. |
|||
joined_at: :class:`datetime.datetime` |
|||
The time the member joined the thread in UTC. |
|||
""" |
|||
|
|||
__slots__ = ( |
|||
'id', |
|||
'thread_id', |
|||
'joined_at', |
|||
'flags', |
|||
'_state', |
|||
) |
|||
|
|||
def __init__(self, data: ThreadMemberPayload, state): |
|||
self._state = state |
|||
self._from_data(data) |
|||
|
|||
def _from_data(self, data: ThreadMemberPayload): |
|||
self.id = int(data['user_id']) |
|||
self.thread_id = int(data['id']) |
|||
self.joined_at = utils.parse_time(data['join_timestamp']) |
|||
self.flags = data['flags'] |
Loading…
Reference in new issue