mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-09-07 10:22:59 +00:00
Support for Soundboard and VC effects
This commit is contained in:
172
discord/guild.py
172
discord/guild.py
@ -94,6 +94,7 @@ from .object import OLDEST_OBJECT, Object
|
||||
from .welcome_screen import WelcomeScreen, WelcomeChannel
|
||||
from .automod import AutoModRule, AutoModTrigger, AutoModRuleAction
|
||||
from .partial_emoji import _EmojiTag, PartialEmoji
|
||||
from .soundboard import SoundboardSound
|
||||
|
||||
|
||||
__all__ = (
|
||||
@ -328,6 +329,7 @@ class Guild(Hashable):
|
||||
'_safety_alerts_channel_id',
|
||||
'max_stage_video_users',
|
||||
'_incidents_data',
|
||||
'_soundboard_sounds',
|
||||
)
|
||||
|
||||
_PREMIUM_GUILD_LIMITS: ClassVar[Dict[Optional[int], _GuildLimit]] = {
|
||||
@ -345,6 +347,7 @@ class Guild(Hashable):
|
||||
self._threads: Dict[int, Thread] = {}
|
||||
self._stage_instances: Dict[int, StageInstance] = {}
|
||||
self._scheduled_events: Dict[int, ScheduledEvent] = {}
|
||||
self._soundboard_sounds: Dict[int, SoundboardSound] = {}
|
||||
self._state: ConnectionState = state
|
||||
self._member_count: Optional[int] = None
|
||||
self._from_data(data)
|
||||
@ -390,6 +393,12 @@ class Guild(Hashable):
|
||||
del self._threads[k]
|
||||
return to_remove
|
||||
|
||||
def _add_soundboard_sound(self, sound: SoundboardSound, /) -> None:
|
||||
self._soundboard_sounds[sound.id] = sound
|
||||
|
||||
def _remove_soundboard_sound(self, sound: SoundboardSound, /) -> None:
|
||||
self._soundboard_sounds.pop(sound.id, None)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name or ''
|
||||
|
||||
@ -547,6 +556,11 @@ class Guild(Hashable):
|
||||
scheduled_event = ScheduledEvent(data=s, state=self._state)
|
||||
self._scheduled_events[scheduled_event.id] = scheduled_event
|
||||
|
||||
if 'soundboard_sounds' in guild:
|
||||
for s in guild['soundboard_sounds']:
|
||||
soundboard_sound = SoundboardSound(guild=self, data=s, state=self._state)
|
||||
self._add_soundboard_sound(soundboard_sound)
|
||||
|
||||
@property
|
||||
def channels(self) -> Sequence[GuildChannel]:
|
||||
"""Sequence[:class:`abc.GuildChannel`]: A list of channels that belongs to this guild."""
|
||||
@ -996,6 +1010,37 @@ class Guild(Hashable):
|
||||
"""
|
||||
return self._scheduled_events.get(scheduled_event_id)
|
||||
|
||||
@property
|
||||
def soundboard_sounds(self) -> Sequence[SoundboardSound]:
|
||||
"""Sequence[:class:`SoundboardSound`]: Returns a sequence of the guild's soundboard sounds.
|
||||
|
||||
.. versionadded:: 2.5
|
||||
"""
|
||||
return utils.SequenceProxy(self._soundboard_sounds.values())
|
||||
|
||||
def get_soundboard_sound(self, sound_id: int, /) -> Optional[SoundboardSound]:
|
||||
"""Returns a soundboard sound with the given ID.
|
||||
|
||||
.. versionadded:: 2.5
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
sound_id: :class:`int`
|
||||
The ID to search for.
|
||||
|
||||
Returns
|
||||
--------
|
||||
Optional[:class:`SoundboardSound`]
|
||||
The soundboard sound or ``None`` if not found.
|
||||
"""
|
||||
return self._soundboard_sounds.get(sound_id)
|
||||
|
||||
def _resolve_soundboard_sound(self, id: Optional[int], /) -> Optional[SoundboardSound]:
|
||||
if id is None:
|
||||
return
|
||||
|
||||
return self._soundboard_sounds.get(id)
|
||||
|
||||
@property
|
||||
def owner(self) -> Optional[Member]:
|
||||
"""Optional[:class:`Member`]: The member that owns the guild."""
|
||||
@ -4496,3 +4541,130 @@ class Guild(Hashable):
|
||||
return False
|
||||
|
||||
return self.raid_detected_at > utils.utcnow()
|
||||
|
||||
async def fetch_soundboard_sound(self, sound_id: int, /) -> SoundboardSound:
|
||||
"""|coro|
|
||||
|
||||
Retrieves a :class:`SoundboardSound` with the specified ID.
|
||||
|
||||
.. versionadded:: 2.5
|
||||
|
||||
.. note::
|
||||
|
||||
Using this, in order to receive :attr:`SoundboardSound.user`, you must have :attr:`~Permissions.create_expressions`
|
||||
or :attr:`~Permissions.manage_expressions`.
|
||||
|
||||
.. note::
|
||||
|
||||
This method is an API call. For general usage, consider :attr:`get_soundboard_sound` instead.
|
||||
|
||||
Raises
|
||||
-------
|
||||
NotFound
|
||||
The sound requested could not be found.
|
||||
HTTPException
|
||||
Retrieving the sound failed.
|
||||
|
||||
Returns
|
||||
--------
|
||||
:class:`SoundboardSound`
|
||||
The retrieved sound.
|
||||
"""
|
||||
data = await self._state.http.get_soundboard_sound(self.id, sound_id)
|
||||
return SoundboardSound(guild=self, state=self._state, data=data)
|
||||
|
||||
async def fetch_soundboard_sounds(self) -> List[SoundboardSound]:
|
||||
"""|coro|
|
||||
|
||||
Retrieves a list of all soundboard sounds for the guild.
|
||||
|
||||
.. versionadded:: 2.5
|
||||
|
||||
.. note::
|
||||
|
||||
Using this, in order to receive :attr:`SoundboardSound.user`, you must have :attr:`~Permissions.create_expressions`
|
||||
or :attr:`~Permissions.manage_expressions`.
|
||||
|
||||
.. note::
|
||||
|
||||
This method is an API call. For general usage, consider :attr:`soundboard_sounds` instead.
|
||||
|
||||
Raises
|
||||
-------
|
||||
HTTPException
|
||||
Retrieving the sounds failed.
|
||||
|
||||
Returns
|
||||
--------
|
||||
List[:class:`SoundboardSound`]
|
||||
The retrieved soundboard sounds.
|
||||
"""
|
||||
data = await self._state.http.get_soundboard_sounds(self.id)
|
||||
return [SoundboardSound(guild=self, state=self._state, data=sound) for sound in data['items']]
|
||||
|
||||
async def create_soundboard_sound(
|
||||
self,
|
||||
*,
|
||||
name: str,
|
||||
sound: bytes,
|
||||
volume: float = 1,
|
||||
emoji: Optional[EmojiInputType] = None,
|
||||
reason: Optional[str] = None,
|
||||
) -> SoundboardSound:
|
||||
"""|coro|
|
||||
|
||||
Creates a :class:`SoundboardSound` for the guild.
|
||||
You must have :attr:`Permissions.create_expressions` to do this.
|
||||
|
||||
.. versionadded:: 2.5
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name: :class:`str`
|
||||
The name of the sound. Must be between 2 and 32 characters.
|
||||
sound: :class:`bytes`
|
||||
The :term:`py:bytes-like object` representing the sound data.
|
||||
Only MP3 and OGG sound files that don't exceed the duration of 5.2s are supported.
|
||||
volume: :class:`float`
|
||||
The volume of the sound. Must be between 0 and 1. Defaults to ``1``.
|
||||
emoji: Optional[Union[:class:`Emoji`, :class:`PartialEmoji`, :class:`str`]]
|
||||
The emoji of the sound.
|
||||
reason: Optional[:class:`str`]
|
||||
The reason for creating the sound. Shows up on the audit log.
|
||||
|
||||
Raises
|
||||
-------
|
||||
Forbidden
|
||||
You do not have permissions to create a soundboard sound.
|
||||
HTTPException
|
||||
Creating the soundboard sound failed.
|
||||
|
||||
Returns
|
||||
-------
|
||||
:class:`SoundboardSound`
|
||||
The newly created soundboard sound.
|
||||
"""
|
||||
payload: Dict[str, Any] = {
|
||||
'name': name,
|
||||
'sound': utils._bytes_to_base64_data(sound, audio=True),
|
||||
'volume': volume,
|
||||
'emoji_id': None,
|
||||
'emoji_name': None,
|
||||
}
|
||||
|
||||
if emoji is not None:
|
||||
if isinstance(emoji, _EmojiTag):
|
||||
partial_emoji = emoji._to_partial()
|
||||
elif isinstance(emoji, str):
|
||||
partial_emoji = PartialEmoji.from_str(emoji)
|
||||
else:
|
||||
partial_emoji = None
|
||||
|
||||
if partial_emoji is not None:
|
||||
if partial_emoji.id is None:
|
||||
payload['emoji_name'] = partial_emoji.name
|
||||
else:
|
||||
payload['emoji_id'] = partial_emoji.id
|
||||
|
||||
data = await self._state.http.create_soundboard_sound(self.id, reason=reason, **payload)
|
||||
return SoundboardSound(guild=self, state=self._state, data=data)
|
||||
|
Reference in New Issue
Block a user