First pass at preliminary thread support
This is missing a lot of functionality right now, such as two gateway events and all the HTTP CRUD endpoints.
This commit is contained in:
parent
6c79714b42
commit
68c7c538f5
@ -58,6 +58,7 @@ from .sticker import *
|
||||
from .stage_instance import *
|
||||
from .interactions import *
|
||||
from .components import *
|
||||
from .threads import *
|
||||
|
||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro releaselevel serial')
|
||||
|
||||
|
@ -173,6 +173,14 @@ class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable):
|
||||
"""List[:class:`Member`]: Returns all members that can see this channel."""
|
||||
return [m for m in self.guild.members if self.permissions_for(m).read_messages]
|
||||
|
||||
@property
|
||||
def threads(self):
|
||||
"""List[:class:`Thread`]: Returns all the threads that you can see.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
"""
|
||||
return [thread for thread in self.guild.threads if thread.parent_id == self.id]
|
||||
|
||||
def is_nsfw(self):
|
||||
""":class:`bool`: Checks if the channel is NSFW."""
|
||||
return self.nsfw
|
||||
|
@ -155,14 +155,16 @@ else:
|
||||
return value
|
||||
|
||||
class ChannelType(Enum):
|
||||
text = 0
|
||||
private = 1
|
||||
voice = 2
|
||||
group = 3
|
||||
category = 4
|
||||
news = 5
|
||||
store = 6
|
||||
stage_voice = 13
|
||||
text = 0
|
||||
private = 1
|
||||
voice = 2
|
||||
group = 3
|
||||
category = 4
|
||||
news = 5
|
||||
store = 6
|
||||
public_thread = 11
|
||||
private_thread = 12
|
||||
stage_voice = 13
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
@ -186,8 +188,10 @@ class MessageType(Enum):
|
||||
guild_discovery_requalified = 15
|
||||
guild_discovery_grace_period_initial_warning = 16
|
||||
guild_discovery_grace_period_final_warning = 17
|
||||
thread_created = 18
|
||||
reply = 19
|
||||
application_command = 20
|
||||
thread_starter_message = 21
|
||||
guild_invite_reminder = 22
|
||||
|
||||
class VoiceRegion(Enum):
|
||||
|
@ -279,6 +279,13 @@ class MessageFlags(BaseFlags):
|
||||
"""
|
||||
return 16
|
||||
|
||||
@flag_value
|
||||
def has_thread(self):
|
||||
""":class:`bool`: Returns ``True`` if the source message is associated with a thread.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
"""
|
||||
return 32
|
||||
|
||||
@fill_with_flags()
|
||||
class PublicUserFlags(BaseFlags):
|
||||
|
@ -47,6 +47,7 @@ from .asset import Asset
|
||||
from .flags import SystemChannelFlags
|
||||
from .integrations import Integration, _integration_factory
|
||||
from .stage_instance import StageInstance
|
||||
from .threads import Thread
|
||||
|
||||
__all__ = (
|
||||
'Guild',
|
||||
@ -182,7 +183,7 @@ class Guild(Hashable):
|
||||
'description', 'max_presences', 'max_members', 'max_video_channel_users',
|
||||
'premium_tier', 'premium_subscription_count', '_system_channel_flags',
|
||||
'preferred_locale', '_discovery_splash', '_rules_channel_id',
|
||||
'_public_updates_channel_id', '_stage_instances', 'nsfw_level')
|
||||
'_public_updates_channel_id', '_stage_instances', 'nsfw_level', '_threads')
|
||||
|
||||
_PREMIUM_GUILD_LIMITS = {
|
||||
None: _GuildLimit(emoji=50, bitrate=96e3, filesize=8388608),
|
||||
@ -196,6 +197,7 @@ class Guild(Hashable):
|
||||
self._channels = {}
|
||||
self._members = {}
|
||||
self._voice_states = {}
|
||||
self._threads = {}
|
||||
self._state = state
|
||||
self._from_data(data)
|
||||
|
||||
@ -214,6 +216,12 @@ class Guild(Hashable):
|
||||
def _remove_member(self, member):
|
||||
self._members.pop(member.id, None)
|
||||
|
||||
def _add_thread(self, thread):
|
||||
self._threads[thread.id] = thread
|
||||
|
||||
def _remove_thread(self, thread):
|
||||
self._threads.pop(thread.id, None)
|
||||
|
||||
def __str__(self):
|
||||
return self.name or ''
|
||||
|
||||
@ -360,11 +368,24 @@ class Guild(Hashable):
|
||||
if factory:
|
||||
self._add_channel(factory(guild=self, data=c, state=self._state))
|
||||
|
||||
if 'threads' in data:
|
||||
threads = data['threads']
|
||||
for thread in threads:
|
||||
self._add_thread(Thread(guild=self, data=thread))
|
||||
|
||||
@property
|
||||
def channels(self):
|
||||
"""List[:class:`abc.GuildChannel`]: A list of channels that belongs to this guild."""
|
||||
return list(self._channels.values())
|
||||
|
||||
@property
|
||||
def threads(self):
|
||||
"""List[:class:`Thread`]: A list of threads that you have permission to view.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
"""
|
||||
return list(self._threads.values())
|
||||
|
||||
@property
|
||||
def large(self):
|
||||
""":class:`bool`: Indicates if the guild is a 'large' guild.
|
||||
@ -484,6 +505,23 @@ class Guild(Hashable):
|
||||
"""
|
||||
return self._channels.get(channel_id)
|
||||
|
||||
def get_thread(self, thread_id):
|
||||
"""Returns a thread with the given ID.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
thread_id: :class:`int`
|
||||
The ID to search for.
|
||||
|
||||
Returns
|
||||
--------
|
||||
Optional[:class:`Thread`]
|
||||
The returned thread or ``None`` if not found.
|
||||
"""
|
||||
return self._threads.get(thread_id)
|
||||
|
||||
@property
|
||||
def system_channel(self):
|
||||
"""Optional[:class:`TextChannel`]: Returns the guild's channel used for system messages.
|
||||
@ -2377,7 +2415,7 @@ class Guild(Hashable):
|
||||
data = await self._state.http.get_widget(self.id)
|
||||
|
||||
return Widget(state=self._state, data=data)
|
||||
|
||||
|
||||
async def edit_widget(self, *, enabled: bool = utils.MISSING, channel: Optional[abc.Snowflake] = utils.MISSING) -> None:
|
||||
"""|coro|
|
||||
|
||||
|
@ -695,6 +695,8 @@ class HTTPClient:
|
||||
'type',
|
||||
'rtc_region',
|
||||
'video_quality_mode',
|
||||
'archived',
|
||||
'auto_archive_duration',
|
||||
)
|
||||
payload = {k: v for k, v in options.items() if k in valid_keys}
|
||||
return self.request(r, reason=reason, json=payload)
|
||||
@ -720,6 +722,7 @@ class HTTPClient:
|
||||
'rate_limit_per_user',
|
||||
'rtc_region',
|
||||
'video_quality_mode',
|
||||
'auto_archive_duration',
|
||||
)
|
||||
payload.update({k: v for k, v in options.items() if k in valid_keys and v is not None})
|
||||
|
||||
@ -728,6 +731,80 @@ class HTTPClient:
|
||||
def delete_channel(self, channel_id, *, reason=None):
|
||||
return self.request(Route('DELETE', '/channels/{channel_id}', channel_id=channel_id), reason=reason)
|
||||
|
||||
# Thread management
|
||||
|
||||
def start_public_thread(
|
||||
self,
|
||||
channel_id: int,
|
||||
message_id: int,
|
||||
*,
|
||||
name: str,
|
||||
auto_archive_duration: int,
|
||||
type: int,
|
||||
):
|
||||
payload = {
|
||||
'name': name,
|
||||
'auto_archive_duration': auto_archive_duration,
|
||||
'type': type,
|
||||
}
|
||||
|
||||
route = Route(
|
||||
'POST', '/channels/{channel_id}/messages/{message_id}/threads', channel_id=channel_id, message_id=message_id
|
||||
)
|
||||
return self.request(route, json=payload)
|
||||
|
||||
def start_private_thread(
|
||||
self,
|
||||
channel_id: int,
|
||||
*,
|
||||
name: str,
|
||||
auto_archive_duration: int,
|
||||
type: int,
|
||||
):
|
||||
payload = {
|
||||
'name': name,
|
||||
'auto_archive_duration': auto_archive_duration,
|
||||
'type': type,
|
||||
}
|
||||
|
||||
route = Route('POST', '/channels/{channel_id}/threads', channel_id=channel_id)
|
||||
return self.request(route, json=payload)
|
||||
|
||||
def join_thread(self, channel_id: int):
|
||||
return self.request(Route('POST', '/channels/{channel_id}/thread-members/@me', channel_id=channel_id))
|
||||
|
||||
def add_user_to_thread(self, channel_id: int, user_id: int):
|
||||
return self.request(
|
||||
Route('POST', '/channels/{channel_id}/thread-members/{user_id}', channel_id=channel_id, user_id=user_id)
|
||||
)
|
||||
|
||||
def leave_thread(self, channel_id: int):
|
||||
return self.request(Route('DELETE', '/channels/{channel_id}/thread-members/@me', channel_id=channel_id))
|
||||
|
||||
def remove_user_from_thread(self, channel_id: int, user_id: int):
|
||||
route = Route('DELETE', '/channels/{channel_id}/thread-members/{user_id}', channel_id=channel_id, user_id=user_id)
|
||||
return self.request(route)
|
||||
|
||||
def get_archived_threads(self, channel_id: int, before=None, limit: int = 50, public: bool = True):
|
||||
if public:
|
||||
route = Route('GET', '/channels/{channel_id}/threads/archived/public', channel_id=channel_id)
|
||||
else:
|
||||
route = Route('GET', '/channels/{channel_id}/threads/archived/private', channel_id=channel_id)
|
||||
|
||||
params = {}
|
||||
if before:
|
||||
params['before'] = before
|
||||
params['limit'] = limit
|
||||
return self.request(route, params=params)
|
||||
|
||||
def get_joined_private_archived_threads(self, channel_id, before=None, limit: int = 50):
|
||||
route = Route('GET', '/channels/{channel_id}/users/@me/threads/archived/private', channel_id=channel_id)
|
||||
params = {}
|
||||
if before:
|
||||
params['before'] = before
|
||||
params['limit'] = limit
|
||||
return self.request(route, params=params)
|
||||
|
||||
# Webhook management
|
||||
|
||||
def create_webhook(self, channel_id, *, name, avatar=None, reason=None):
|
||||
|
@ -55,6 +55,7 @@ from .integrations import _integration_factory
|
||||
from .interactions import Interaction
|
||||
from .ui.view import ViewStore
|
||||
from .stage_instance import StageInstance
|
||||
from .threads import Thread, ThreadMember
|
||||
|
||||
class ChunkRequest:
|
||||
def __init__(self, guild_id, loop, resolver, *, cache=True):
|
||||
@ -483,7 +484,7 @@ class ConnectionState:
|
||||
self.dispatch('message', message)
|
||||
if self._messages is not None:
|
||||
self._messages.append(message)
|
||||
if channel and channel.__class__ is TextChannel:
|
||||
if channel and channel.__class__ in (TextChannel, Thread):
|
||||
channel.last_message_id = message.id
|
||||
|
||||
def parse_message_delete(self, data):
|
||||
@ -704,6 +705,44 @@ class ConnectionState:
|
||||
else:
|
||||
self.dispatch('guild_channel_pins_update', channel, last_pin)
|
||||
|
||||
def parse_thread_create(self, data):
|
||||
guild_id = int(data['guild_id'])
|
||||
guild = self._get_guild(guild_id)
|
||||
if guild is None:
|
||||
log.debug('THREAD_CREATE referencing an unknown guild ID: %s. Discarding', guild_id)
|
||||
return
|
||||
|
||||
thread = Thread(guild=guild, data=data)
|
||||
guild._add_thread(thread)
|
||||
self.dispatch('thread_create', thread)
|
||||
|
||||
def parse_thread_update(self, data):
|
||||
guild_id = int(data['guild_id'])
|
||||
guild = self._get_guild(guild_id)
|
||||
if guild is None:
|
||||
log.debug('THREAD_UPDATE referencing an unknown guild ID: %s. Discarding', guild_id)
|
||||
return
|
||||
|
||||
thread_id = int(data['id'])
|
||||
thread = guild._get_thread(thread_id)
|
||||
if thread is not None:
|
||||
old = copy.copy(thread)
|
||||
thread._update(data)
|
||||
self.dispatch('thread_update', old, thread)
|
||||
|
||||
def parse_thread_delete(self, data):
|
||||
guild_id = int(data['guild_id'])
|
||||
guild = self._get_guild(guild_id)
|
||||
if guild is None:
|
||||
log.debug('THREAD_UPDATE referencing an unknown guild ID: %s. Discarding', guild_id)
|
||||
return
|
||||
|
||||
thread_id = int(data['id'])
|
||||
thread = guild._get_thread(thread_id)
|
||||
if thread is not None:
|
||||
guild._remove_thread(thread)
|
||||
self.dispatch('thread_delete', thread)
|
||||
|
||||
def parse_guild_member_add(self, data):
|
||||
guild = self._get_guild(int(data['guild_id']))
|
||||
if guild is None:
|
||||
|
244
discord/threads.py
Normal file
244
discord/threads.py
Normal file
@ -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']
|
76
docs/api.rst
76
docs/api.rst
@ -658,6 +658,33 @@ to handle it, which defaults to print a traceback and ignoring the exception.
|
||||
:param last_pin: The latest message that was pinned as an aware datetime in UTC. Could be ``None``.
|
||||
:type last_pin: Optional[:class:`datetime.datetime`]
|
||||
|
||||
.. function:: on_thread_delete(thread)
|
||||
on_thread_create(thread)
|
||||
|
||||
Called whenever a thread is deleted or created.
|
||||
|
||||
Note that you can get the guild from :attr:`Thread.guild`.
|
||||
|
||||
This requires :attr:`Intents.guilds` to be enabled.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
:param thread: The thread that got created or deleted.
|
||||
:type thread: :class:`Thread`
|
||||
|
||||
.. function:: on_thread_update(before, after)
|
||||
|
||||
Called whenever a thread is updated.
|
||||
|
||||
This requires :attr:`Intents.guilds` to be enabled.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
:param before: The updated thread's old info.
|
||||
:type before: :class:`Thread`
|
||||
:param after: The updated thread's new info.
|
||||
:type after: :class:`Thread`
|
||||
|
||||
.. function:: on_guild_integrations_update(guild)
|
||||
|
||||
Called whenever an integration is created, modified, or removed from a guild.
|
||||
@ -1038,6 +1065,18 @@ of :class:`enum.Enum`.
|
||||
|
||||
.. versionadded:: 1.7
|
||||
|
||||
.. attribute:: public_thread
|
||||
|
||||
A public thread
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
.. attribute:: private_thread
|
||||
|
||||
A private thread
|
||||
|
||||
.. versionadded:: 1.8
|
||||
|
||||
.. class:: MessageType
|
||||
|
||||
Specifies the type of :class:`Message`. This is used to denote if a message
|
||||
@ -1129,9 +1168,14 @@ of :class:`enum.Enum`.
|
||||
Discovery requirements for 3 weeks in a row.
|
||||
|
||||
.. versionadded:: 1.7
|
||||
.. attribute:: thread_created
|
||||
|
||||
The system message denoting that a thread has been created
|
||||
|
||||
.. versionadded:: 2.0
|
||||
.. attribute:: reply
|
||||
|
||||
The message type denoting that the author is replying to a message.
|
||||
The system message denoting that the author is replying to a message.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
.. attribute:: application_command
|
||||
@ -1143,6 +1187,12 @@ of :class:`enum.Enum`.
|
||||
|
||||
The system message sent as a reminder to invite people to the guild.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
.. attribute:: thread_starter_message
|
||||
|
||||
The system message denoting that this message is the one that started a thread's
|
||||
conversation topic.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
.. class:: UserFlags
|
||||
@ -3197,6 +3247,30 @@ TextChannel
|
||||
.. automethod:: typing
|
||||
:async-with:
|
||||
|
||||
Thread
|
||||
~~~~~~~~
|
||||
|
||||
.. attributetable:: Thread
|
||||
|
||||
.. autoclass:: Thread()
|
||||
:members:
|
||||
:inherited-members:
|
||||
:exclude-members: history, typing
|
||||
|
||||
.. automethod:: history
|
||||
:async-for:
|
||||
|
||||
.. automethod:: typing
|
||||
:async-with:
|
||||
|
||||
ThreadMember
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
.. attributetable:: ThreadMember
|
||||
|
||||
.. autoclass:: ThreadMember()
|
||||
:members:
|
||||
|
||||
StoreChannel
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user