Implement StageInstance

This commit is contained in:
Nadir Chowdhury
2021-05-30 18:51:52 +01:00
committed by GitHub
parent 90a28d48d5
commit 9f98a9a87f
10 changed files with 502 additions and 15 deletions

View File

@@ -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`