mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-04-20 16:00:29 +00:00
Implement StageInstance
This commit is contained in:
parent
90a28d48d5
commit
9f98a9a87f
@ -55,6 +55,7 @@ from .audit_logs import *
|
||||
from .raw_models import *
|
||||
from .team import *
|
||||
from .sticker import *
|
||||
from .stage_instance import *
|
||||
from .interactions import *
|
||||
from .components import *
|
||||
|
||||
|
@ -30,11 +30,12 @@ from typing import Callable, Dict, List, Optional, TYPE_CHECKING, Union, overloa
|
||||
|
||||
import discord.abc
|
||||
from .permissions import PermissionOverwrite, Permissions
|
||||
from .enums import ChannelType, try_enum, VoiceRegion, VideoQualityMode
|
||||
from .enums import ChannelType, StagePrivacyLevel, try_enum, VoiceRegion, VideoQualityMode
|
||||
from .mixins import Hashable
|
||||
from . import utils
|
||||
from .asset import Asset
|
||||
from .errors import ClientException, NoMoreItems, InvalidArgument
|
||||
from .stage_instance import StageInstance
|
||||
|
||||
__all__ = (
|
||||
'TextChannel',
|
||||
@ -49,7 +50,7 @@ __all__ = (
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .role import Role
|
||||
from .member import Member
|
||||
from .member import Member, VoiceState
|
||||
from .abc import Snowflake
|
||||
from .message import Message
|
||||
from .webhook import Webhook
|
||||
@ -611,7 +612,7 @@ class VocalGuildChannel(discord.abc.Connectable, discord.abc.GuildChannel, Hasha
|
||||
return ChannelType.voice.value
|
||||
|
||||
@property
|
||||
def members(self):
|
||||
def members(self) -> List[Member]:
|
||||
"""List[:class:`Member`]: Returns all members that are currently inside this voice channel."""
|
||||
ret = []
|
||||
for user_id, state in self.guild._voice_states.items():
|
||||
@ -622,7 +623,7 @@ class VocalGuildChannel(discord.abc.Connectable, discord.abc.GuildChannel, Hasha
|
||||
return ret
|
||||
|
||||
@property
|
||||
def voice_states(self):
|
||||
def voice_states(self) -> Dict[int, VoiceState]:
|
||||
"""Returns a mapping of member IDs who have voice states in this channel.
|
||||
|
||||
.. versionadded:: 1.3
|
||||
@ -640,7 +641,7 @@ class VocalGuildChannel(discord.abc.Connectable, discord.abc.GuildChannel, Hasha
|
||||
return {key: value for key, value in self.guild._voice_states.items() if value.channel.id == self.id}
|
||||
|
||||
@utils.copy_doc(discord.abc.GuildChannel.permissions_for)
|
||||
def permissions_for(self, member):
|
||||
def permissions_for(self, member: Union[Role, Member], /) -> Permissions:
|
||||
base = super().permissions_for(member)
|
||||
|
||||
# voice channels cannot be edited by people who can't connect to them
|
||||
@ -875,10 +876,35 @@ class StageChannel(VocalGuildChannel):
|
||||
self.topic = data.get('topic')
|
||||
|
||||
@property
|
||||
def requesting_to_speak(self):
|
||||
def requesting_to_speak(self) -> List[Member]:
|
||||
"""List[:class:`Member`]: A list of members who are requesting to speak in the stage channel."""
|
||||
return [member for member in self.members if member.voice.requested_to_speak_at is not None]
|
||||
|
||||
@property
|
||||
def speakers(self) -> List[Member]:
|
||||
"""List[:class:`Member`]: A list of members who have been permitted to speak in the stage channel.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
"""
|
||||
return [member for member in self.members if not member.voice.suppress and member.voice.requested_to_speak_at is None]
|
||||
|
||||
@property
|
||||
def listeners(self) -> List[Member]:
|
||||
"""List[:class:`Member`]: A list of members who are listening in the stage channel.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
"""
|
||||
return [member for member in self.members if member.voice.suppress]
|
||||
|
||||
@property
|
||||
def moderators(self) -> List[Member]:
|
||||
"""List[:class:`Member`]: A list of members who are moderating the stage channel.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
"""
|
||||
required_permissions = Permissions.stage_moderator()
|
||||
return [member for member in self.members if self.permissions_for(member) >= required_permissions]
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
""":class:`ChannelType`: The channel's Discord type."""
|
||||
@ -886,9 +912,83 @@ class StageChannel(VocalGuildChannel):
|
||||
|
||||
@utils.copy_doc(discord.abc.GuildChannel.clone)
|
||||
async def clone(self, *, name: str = None, reason: Optional[str] = None) -> StageChannel:
|
||||
return await self._clone_impl({
|
||||
'topic': self.topic,
|
||||
}, name=name, reason=reason)
|
||||
return await self._clone_impl({}, name=name, reason=reason)
|
||||
|
||||
@property
|
||||
def instance(self) -> Optional[StageInstance]:
|
||||
"""Optional[:class:`StageInstance`]: The running stage instance of the stage channel.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
"""
|
||||
return utils.get(self.guild.stage_instances, channel_id=self.id)
|
||||
|
||||
async def create_instance(self, *, topic: str, privacy_level: StagePrivacyLevel = utils.MISSING) -> StageInstance:
|
||||
"""|coro|
|
||||
|
||||
Create a stage instance.
|
||||
|
||||
You must have the :attr:`~Permissions.manage_channels` permission to
|
||||
use this.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
topic: :class:`str`
|
||||
The stage instance's topic.
|
||||
privacy_level: :class:`StagePrivacyLevel`
|
||||
The stage instance's privacy level. Defaults to :attr:`PrivacyLevel.guild_only`.
|
||||
|
||||
Raises
|
||||
------
|
||||
InvalidArgument
|
||||
If the ``privacy_level`` parameter is not the proper type.
|
||||
Forbidden
|
||||
You do not have permissions to create a stage instance.
|
||||
HTTPException
|
||||
Creating a stage instance failed.
|
||||
|
||||
Returns
|
||||
--------
|
||||
:class:`StageInstance`
|
||||
The newly created stage instance.
|
||||
"""
|
||||
|
||||
payload = {
|
||||
'channel_id': self.id,
|
||||
'topic': topic
|
||||
}
|
||||
|
||||
if privacy_level is not utils.MISSING:
|
||||
if not isinstance(privacy_level, StagePrivacyLevel):
|
||||
raise InvalidArgument('privacy_level field must be of type PrivacyLevel')
|
||||
|
||||
payload['privacy_level'] = privacy_level.value
|
||||
|
||||
data = await self._state.http.create_stage_instance(**payload)
|
||||
return StageInstance(guild=self.guild, state=self._state, data=data)
|
||||
|
||||
async def fetch_instance(self) -> StageInstance:
|
||||
"""|coro|
|
||||
|
||||
Gets the running :class:`StageInstance`.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
Raises
|
||||
-------
|
||||
:exc:`.NotFound`
|
||||
The stage instance or channel could not be found.
|
||||
:exc:`.HTTPException`
|
||||
Getting the stage instance failed.
|
||||
|
||||
Returns
|
||||
--------
|
||||
:class:`StageInstance`
|
||||
The stage instance.
|
||||
"""
|
||||
data = await self._state.http.get_stage_instance(self.id)
|
||||
return StageInstance(guild=self.guild, state=self._state, data=data)
|
||||
|
||||
@overload
|
||||
async def edit(
|
||||
@ -918,12 +1018,13 @@ class StageChannel(VocalGuildChannel):
|
||||
You must have the :attr:`~Permissions.manage_channels` permission to
|
||||
use this.
|
||||
|
||||
.. versionchanged:: 2.0
|
||||
The ``topic`` parameter must now be set via :attr:`create_instance`.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name: :class:`str`
|
||||
The new channel's name.
|
||||
topic: Optional[:class:`str`]
|
||||
The new channel's topic.
|
||||
position: :class:`int`
|
||||
The new channel's position.
|
||||
sync_permissions: :class:`bool`
|
||||
|
@ -29,7 +29,7 @@ import logging
|
||||
import signal
|
||||
import sys
|
||||
import traceback
|
||||
from typing import Any, List, Optional, TYPE_CHECKING, Union
|
||||
from typing import Any, Generator, List, Optional, TYPE_CHECKING, TypeVar, Union
|
||||
|
||||
import aiohttp
|
||||
|
||||
@ -56,6 +56,7 @@ from .webhook import Webhook
|
||||
from .iterators import GuildIterator
|
||||
from .appinfo import AppInfo
|
||||
from .ui.view import View
|
||||
from .stage_instance import StageInstance
|
||||
|
||||
__all__ = (
|
||||
'Client',
|
||||
@ -693,6 +694,28 @@ class Client:
|
||||
"""
|
||||
return self._connection.get_channel(id)
|
||||
|
||||
def get_stage_instance(self, id) -> Optional[StageInstance]:
|
||||
"""Returns a stage instance with the given stage channel ID.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
id: :class:`int`
|
||||
The ID to search for.
|
||||
|
||||
Returns
|
||||
--------
|
||||
Optional[:class:`StageInstance`]
|
||||
The returns stage instance of ``None`` if not found.
|
||||
"""
|
||||
from .channel import StageChannel
|
||||
|
||||
channel = self._connection.get_channel(id)
|
||||
|
||||
if isinstance(channel, StageChannel):
|
||||
return channel.instance
|
||||
|
||||
def get_guild(self, id):
|
||||
"""Returns a guild with the given ID.
|
||||
|
||||
@ -1136,6 +1159,34 @@ class Client:
|
||||
data = await self.http.create_guild(name, region_value, icon)
|
||||
return Guild(data=data, state=self._connection)
|
||||
|
||||
async def fetch_stage_instance(self, channel_id: int) -> StageInstance:
|
||||
"""|coro|
|
||||
|
||||
Gets a :class:`StageInstance` for a stage channel id.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
channel_id: :class:`int`
|
||||
The stage channel ID.
|
||||
|
||||
Raises
|
||||
-------
|
||||
:exc:`.NotFound`
|
||||
The stage instance or channel could not be found.
|
||||
:exc:`.HTTPException`
|
||||
Getting the stage instance failed.
|
||||
|
||||
Returns
|
||||
--------
|
||||
:class:`StageInstance`
|
||||
The stage instance from the stage channel ID.
|
||||
"""
|
||||
data = await self.http.get_stage_instance(channel_id)
|
||||
guild = self.get_guild(int(data['guild_id']))
|
||||
return StageInstance(guild=guild, state=self._connection, data=data) # type: ignore
|
||||
|
||||
# Invite management
|
||||
|
||||
async def fetch_invite(self, url: Union[Invite, str], *, with_counts: bool = True, with_expiration: bool = True) -> Invite:
|
||||
@ -1261,7 +1312,7 @@ class Client:
|
||||
async def fetch_user(self, user_id):
|
||||
"""|coro|
|
||||
|
||||
Retrieves a :class:`~discord.User` based on their ID.
|
||||
Retrieves a :class:`~discord.User` based on their ID.
|
||||
You do not have to share any guilds with the user to get this information,
|
||||
however many operations do require that you do.
|
||||
|
||||
|
@ -50,6 +50,7 @@ __all__ = (
|
||||
'VideoQualityMode',
|
||||
'ComponentType',
|
||||
'ButtonStyle',
|
||||
'StagePrivacyLevel',
|
||||
)
|
||||
|
||||
def _create_value_cls(name):
|
||||
@ -480,6 +481,11 @@ class ButtonStyle(Enum):
|
||||
def __int__(self):
|
||||
return self.value
|
||||
|
||||
class StagePrivacyLevel(Enum):
|
||||
public = 1
|
||||
closed = 2
|
||||
guild_only = 2
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
def create_unknown_value(cls: Type[T], val: Any) -> T:
|
||||
|
@ -46,6 +46,7 @@ from .widget import Widget
|
||||
from .asset import Asset
|
||||
from .flags import SystemChannelFlags
|
||||
from .integrations import Integration, _integration_factory
|
||||
from .stage_instance import StageInstance
|
||||
|
||||
__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', 'nsfw')
|
||||
'_public_updates_channel_id', '_stage_instances', 'nsfw')
|
||||
|
||||
_PREMIUM_GUILD_LIMITS = {
|
||||
None: _GuildLimit(emoji=50, bitrate=96e3, filesize=8388608),
|
||||
@ -319,6 +320,11 @@ class Guild(Hashable):
|
||||
self._public_updates_channel_id = utils._get_as_snowflake(guild, 'public_updates_channel_id')
|
||||
self.nsfw = guild.get('nsfw', False)
|
||||
|
||||
self._stage_instances = {}
|
||||
for s in guild.get('stage_instances', []):
|
||||
stage_instance = StageInstance(guild=self, data=s, state=state)
|
||||
self._stage_instances[stage_instance.id] = stage_instance
|
||||
|
||||
cache_joined = self._state.member_cache_flags.joined
|
||||
self_id = self._state.self_id
|
||||
for mdata in guild.get('members', []):
|
||||
@ -613,6 +619,32 @@ class Guild(Hashable):
|
||||
return role
|
||||
return None
|
||||
|
||||
@property
|
||||
def stage_instances(self) -> List[StageInstance]:
|
||||
"""List[:class:`StageInstance`]: Returns a :class:`list` of the guild's stage instances that
|
||||
are currently running.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
"""
|
||||
return list(self._stage_instances.values())
|
||||
|
||||
def get_stage_instance(self, stage_instance_id: int) -> Optional[StageInstance]:
|
||||
"""Returns a stage instance with the given ID.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
stage_instance_id: :class:`int`
|
||||
The ID to search for.
|
||||
|
||||
Returns
|
||||
--------
|
||||
Optional[:class:`StageInstance`]
|
||||
The stage instance or ``None`` if not found.
|
||||
"""
|
||||
return self._stage_instances.get(stage_instance_id)
|
||||
|
||||
@property
|
||||
def owner(self):
|
||||
"""Optional[:class:`Member`]: The member that owns the guild."""
|
||||
@ -1801,7 +1833,7 @@ class Guild(Hashable):
|
||||
The list of integrations that are attached to the guild.
|
||||
"""
|
||||
data = await self._state.http.get_all_integrations(self.id)
|
||||
|
||||
|
||||
def convert(d):
|
||||
factory, _ = _integration_factory(d['type'])
|
||||
if factory is None:
|
||||
|
@ -44,7 +44,9 @@ if TYPE_CHECKING:
|
||||
from .types import (
|
||||
interactions,
|
||||
invite,
|
||||
stage_instance,
|
||||
)
|
||||
from .types.snowflake import Snowflake
|
||||
|
||||
T = TypeVar('T')
|
||||
Response = Coroutine[Any, Any, T]
|
||||
@ -1080,6 +1082,33 @@ class HTTPClient:
|
||||
def move_member(self, user_id, guild_id, channel_id, *, reason=None):
|
||||
return self.edit_member(guild_id=guild_id, user_id=user_id, channel_id=channel_id, reason=reason)
|
||||
|
||||
# Stage instance management
|
||||
|
||||
def get_stage_instance(self, channel_id: Snowflake) -> Response[stage_instance.StageInstance]:
|
||||
return self.request(Route('GET', '/stage-instances/{channel_id}', channel_id=channel_id))
|
||||
|
||||
def create_stage_instance(self, **payload) -> Response[stage_instance.StageInstance]:
|
||||
valid_keys = (
|
||||
'channel_id',
|
||||
'topic',
|
||||
'privacy_level',
|
||||
)
|
||||
payload = {k: v for k, v in payload.items() if k in valid_keys}
|
||||
|
||||
return self.request(Route('POST', '/stage-instances'), json=payload)
|
||||
|
||||
def edit_stage_instance(self, channel_id: Snowflake, **payload) -> Response[None]:
|
||||
valid_keys = (
|
||||
'topic',
|
||||
'privacy_level',
|
||||
)
|
||||
payload = {k: v for k, v in payload.items() if k in valid_keys}
|
||||
|
||||
return self.request(Route('PATCH', '/stage-instances/{channel_id}', channel_id=channel_id), json=payload)
|
||||
|
||||
def delete_stage_instance(self, channel_id: Snowflake) -> Response[None]:
|
||||
return self.request(Route('DELETE', '/stage-instances/{channel_id}', channel_id=channel_id))
|
||||
|
||||
# Application commands (global)
|
||||
|
||||
def get_global_commands(self, application_id) -> Response[List[interactions.ApplicationCommand]]:
|
||||
|
168
discord/stage_instance.py
Normal file
168
discord/stage_instance.py
Normal file
@ -0,0 +1,168 @@
|
||||
"""
|
||||
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 .utils import MISSING, cached_slot_property
|
||||
from .mixins import Hashable
|
||||
from .errors import InvalidArgument
|
||||
from .enums import StagePrivacyLevel, try_enum
|
||||
|
||||
__all__ = (
|
||||
'StageInstance',
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .types.channel import StageInstance as StageInstancePayload
|
||||
from .state import ConnectionState
|
||||
from .channel import StageChannel
|
||||
from .guild import Guild
|
||||
|
||||
|
||||
class StageInstance(Hashable):
|
||||
"""Represents a stage instance of a stage channel in a guild.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
.. container:: operations
|
||||
|
||||
.. describe:: x == y
|
||||
|
||||
Checks if two stagea instances are equal.
|
||||
|
||||
.. describe:: x != y
|
||||
|
||||
Checks if two stage instances are not equal.
|
||||
|
||||
.. describe:: hash(x)
|
||||
|
||||
Returns the stage instance's hash.
|
||||
|
||||
Attributes
|
||||
-----------
|
||||
id: :class:`int`
|
||||
The stage instance's ID.
|
||||
guild: :class:`Guild`
|
||||
The guild that the stage instance is running in.
|
||||
channel_id: :class:`int`
|
||||
The ID of the channel that the stage instance is running in.
|
||||
topic: :class:`str`
|
||||
The topic of the stage instance.
|
||||
privacy_level: :class:`StagePrivacyLevel`
|
||||
The privacy level of the stage instance.
|
||||
discoverable_disabled: :class:`bool`
|
||||
Whether the stage instance is discoverable.
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
'_state',
|
||||
'id',
|
||||
'guild',
|
||||
'channel_id',
|
||||
'topic',
|
||||
'privacy_level',
|
||||
'discoverable_disabled',
|
||||
'_cs_channel',
|
||||
)
|
||||
|
||||
def __init__(self, *, state: ConnectionState, guild: Guild, data: StageInstancePayload) -> None:
|
||||
self._state = state
|
||||
self.guild = guild
|
||||
self._update(data)
|
||||
|
||||
def _update(self, data: StageInstancePayload):
|
||||
self.id: int = int(data['id'])
|
||||
self.channel_id: int = int(data['channel_id'])
|
||||
self.topic: str = data['topic']
|
||||
self.privacy_level = try_enum(StagePrivacyLevel, data['privacy_level'])
|
||||
self.discoverable_disabled = data['discoverable_disabled']
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f'<StageInstance id={self.id} guild={self.guild!r} channel_id={self.channel_id} topic={self.topic!r}>'
|
||||
|
||||
@cached_slot_property('_cs_channel')
|
||||
def channel(self) -> Optional[StageChannel]:
|
||||
"""Optional[:class:`StageChannel`: The guild that stage instance is running in."""
|
||||
return self._state.get_channel(self.channel_id)
|
||||
|
||||
def is_public(self) -> bool:
|
||||
return self.privacy_level is StagePrivacyLevel.public
|
||||
|
||||
async def edit(self, *, topic: str = MISSING, privacy_level: StagePrivacyLevel = MISSING) -> None:
|
||||
"""|coro|
|
||||
|
||||
Edits the stage instance.
|
||||
|
||||
You must have the :attr:`~Permissions.manage_channels` permission to
|
||||
use this.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
topic: :class:`str`
|
||||
The stage instance's new topic.
|
||||
privacy_level: :class:`StagePrivacyLevel`
|
||||
The stage instance's new privacy level.
|
||||
|
||||
Raises
|
||||
------
|
||||
InvalidArgument
|
||||
If the ``privacy_level`` parameter is not the proper type.
|
||||
Forbidden
|
||||
You do not have permissions to edit the stage instance.
|
||||
HTTPException
|
||||
Editing a stage instance failed.
|
||||
"""
|
||||
|
||||
payload = {}
|
||||
|
||||
if topic is not MISSING:
|
||||
payload['topic'] = topic
|
||||
|
||||
if privacy_level is not MISSING:
|
||||
if not isinstance(privacy_level, StagePrivacyLevel):
|
||||
raise InvalidArgument('privacy_level field must be of type PrivacyLevel')
|
||||
|
||||
payload['privacy_level'] = privacy_level.value
|
||||
|
||||
if payload:
|
||||
await self._state.http.edit_stage_instance(self.channel_id, **payload)
|
||||
|
||||
async def delete(self) -> None:
|
||||
"""|coro|
|
||||
|
||||
Deletes the stage instance.
|
||||
|
||||
You must have the :attr:`~Permissions.manage_channels` permission to
|
||||
use this.
|
||||
|
||||
Raises
|
||||
------
|
||||
Forbidden
|
||||
You do not have permissions to delete the stage instance.
|
||||
HTTPException
|
||||
Deleting the stage instance failed.
|
||||
"""
|
||||
await self._state.http.delete_stage_instance(self.channel_id)
|
@ -53,6 +53,7 @@ from .object import Object
|
||||
from .invite import Invite
|
||||
from .interactions import Interaction
|
||||
from .ui.view import ViewStore
|
||||
from .stage_instance import StageInstance
|
||||
|
||||
class ChunkRequest:
|
||||
def __init__(self, guild_id, loop, resolver, *, cache=True):
|
||||
@ -956,6 +957,40 @@ class ConnectionState:
|
||||
else:
|
||||
log.debug('WEBHOOKS_UPDATE referencing an unknown channel ID: %s. Discarding.', data['channel_id'])
|
||||
|
||||
def parse_stage_instance_create(self, data):
|
||||
guild = self._get_guild(int(data['guild_id']))
|
||||
if guild is not None:
|
||||
stage_instance = StageInstance(guild=guild, state=self, data=data)
|
||||
guild._stage_instances[stage_instance.id] = stage_instance
|
||||
self.dispatch('stage_instance_create', stage_instance)
|
||||
else:
|
||||
log.debug('STAGE_INSTANCE_CREATE referencing unknown guild ID: %s. Discarding.', data['guild_id'])
|
||||
|
||||
def parse_stage_instance_update(self, data):
|
||||
guild = self._get_guild(int(data['guild_id']))
|
||||
if guild is not None:
|
||||
stage_instance = guild._stage_instances.get(int(data['id']))
|
||||
if stage_instance is not None:
|
||||
old_stage_instance = copy.copy(stage_instance)
|
||||
stage_instance._update(data)
|
||||
self.dispatch('stage_instance_update', old_stage_instance, stage_instance)
|
||||
else:
|
||||
log.debug('STAGE_INSTANCE_UPDATE referencing unknown stage instance ID: %s. Discarding.', data['id'])
|
||||
else:
|
||||
log.debug('STAGE_INSTANCE_UPDATE referencing unknown guild ID: %s. Discarding.', data['guild_id'])
|
||||
|
||||
def parse_stage_instance_delete(self, data):
|
||||
guild = self._get_guild(int(data['guild_id']))
|
||||
if guild is not None:
|
||||
try:
|
||||
stage_instance = guild._stage_instances.pop(int(data['id']))
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
self.dispatch('stage_instance_delete', stage_instance)
|
||||
else:
|
||||
log.debug('STAGE_INSTANCE_DELETE referencing unknown guild ID: %s. Discarding.', data['guild_id'])
|
||||
|
||||
def parse_voice_state_update(self, data):
|
||||
guild = self._get_guild(utils._get_as_snowflake(data, 'guild_id'))
|
||||
channel_id = utils._get_as_snowflake(data, 'channel_id')
|
||||
|
@ -89,3 +89,15 @@ class DMChannel(PartialChannel):
|
||||
class GroupDMChannel(DMChannel):
|
||||
icon: Optional[str]
|
||||
owner_id: Snowflake
|
||||
|
||||
|
||||
PrivacyLevel = Literal[1, 2]
|
||||
|
||||
|
||||
class StageInstance(TypedDict):
|
||||
id: Snowflake
|
||||
guild_id: Snowflake
|
||||
channel_id: Snowflake
|
||||
topic: str
|
||||
privacy_level: PrivacyLevel
|
||||
discoverable_disabled: bool
|
||||
|
52
docs/api.rst
52
docs/api.rst
@ -835,6 +835,32 @@ to handle it, which defaults to print a traceback and ignoring the exception.
|
||||
:param after: The voice state after the changes.
|
||||
:type after: :class:`VoiceState`
|
||||
|
||||
.. function:: on_stage_instance_create(stage_instance)
|
||||
on_stage_instance_delete(stage_instance)
|
||||
|
||||
Called when a :class:`StageInstance` is created or deleted for a :class:`StageChannel`.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
:param stage_instance: The stage instance that was created or deleted.
|
||||
:type stage_instance: :class:`StageInstance`
|
||||
|
||||
.. function:: on_stage_instance_update(before, after)
|
||||
|
||||
Called when a :class:`StageInstance` is updated.
|
||||
|
||||
The following, but not limited to, examples illustrate when this event is called:
|
||||
|
||||
- The topic is changed.
|
||||
- The privacy level is changed.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
:param before: The stage instance before the update.
|
||||
:type before: :class:`StageInstance`
|
||||
:param after: The stage instance after the update.
|
||||
:type after: :class:`StageInstance`
|
||||
|
||||
.. function:: on_member_ban(guild, user)
|
||||
|
||||
Called when user gets banned from a :class:`Guild`.
|
||||
@ -2120,6 +2146,23 @@ of :class:`enum.Enum`.
|
||||
|
||||
Represents full camera video quality.
|
||||
|
||||
.. class:: PrivacyLevel
|
||||
|
||||
Represents a stage instance's privacy level.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
.. attribute:: public
|
||||
|
||||
The stage instance can be joined by external users.
|
||||
|
||||
.. attribute:: closed
|
||||
|
||||
The stage instance can only be joined by members of the guild.
|
||||
|
||||
.. attribute:: guild_only
|
||||
|
||||
Alias for :attr:`.closed`
|
||||
|
||||
Async Iterator
|
||||
----------------
|
||||
@ -3126,6 +3169,15 @@ StageChannel
|
||||
:members:
|
||||
:inherited-members:
|
||||
|
||||
|
||||
StageInstance
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
.. attributetable:: StageInstance
|
||||
|
||||
.. autoclass:: StageInstance()
|
||||
:members:
|
||||
|
||||
CategoryChannel
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user