Skip to content

Commit 3b010f9

Browse files
DasupergrasskakjdDorukyum
authored andcommitted
Original work at #2321
Co-authored-by: Dasupergrasskakjd <[email protected]> Co-authored-by: Dorukyum <[email protected]>
1 parent 9a6cbff commit 3b010f9

File tree

14 files changed

+631
-7
lines changed

14 files changed

+631
-7
lines changed

discord/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
from .role import *
6565
from .scheduled_events import *
6666
from .shard import *
67+
from .soundboard import *
6768
from .stage_instance import *
6869
from .sticker import *
6970
from .team import *

discord/asset.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,14 @@ def _from_scheduled_event_image(
300300
animated=False,
301301
)
302302

303+
@classmethod
304+
def _from_soundboard_sound(cls, state, sound_id: int) -> Asset:
305+
return cls(
306+
state,
307+
url=f"{cls.BASE}/soundboard-sounds/{sound_id}",
308+
key=str(sound_id),
309+
)
310+
303311
def __str__(self) -> str:
304312
return self._url
305313

discord/channel.py

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,16 @@
2626
from __future__ import annotations
2727

2828
import datetime
29-
from typing import TYPE_CHECKING, Any, Callable, Iterable, Mapping, TypeVar, overload
29+
from typing import (
30+
TYPE_CHECKING,
31+
Any,
32+
Callable,
33+
Iterable,
34+
Mapping,
35+
NamedTuple,
36+
TypeVar,
37+
overload,
38+
)
3039

3140
import discord.abc
3241

@@ -40,6 +49,7 @@
4049
SortOrder,
4150
StagePrivacyLevel,
4251
VideoQualityMode,
52+
VoiceChannelEffectAnimationType,
4353
VoiceRegion,
4454
try_enum,
4555
)
@@ -52,6 +62,7 @@
5262
from .object import Object
5363
from .partial_emoji import PartialEmoji, _EmojiTag
5464
from .permissions import PermissionOverwrite, Permissions
65+
from .soundboard import PartialSoundboardSound, SoundboardSound
5566
from .stage_instance import StageInstance
5667
from .threads import Thread
5768
from .utils import MISSING
@@ -66,6 +77,8 @@
6677
"PartialMessageable",
6778
"ForumChannel",
6879
"ForumTag",
80+
# "VoiceChannelEffect",
81+
"VoiceChannelEffectSendEvent",
6982
)
7083

7184
if TYPE_CHECKING:
@@ -84,6 +97,7 @@
8497
from .types.channel import StageChannel as StageChannelPayload
8598
from .types.channel import TextChannel as TextChannelPayload
8699
from .types.channel import VoiceChannel as VoiceChannelPayload
100+
from .types.channel import VoiceChannelEffectSendEvent as VoiceChannelEffectSend
87101
from .types.snowflake import SnowflakeList
88102
from .types.threads import ThreadArchiveDuration
89103
from .user import BaseUser, ClientUser, User
@@ -3220,6 +3234,79 @@ def get_partial_message(self, message_id: int, /) -> PartialMessage:
32203234
return PartialMessage(channel=self, id=message_id)
32213235

32223236

3237+
class VoiceChannelEffectAnimation(NamedTuple):
3238+
id: int
3239+
type: VoiceChannelEffectAnimationType
3240+
3241+
3242+
class VoiceChannelSoundEffect(PartialSoundboardSound): ...
3243+
3244+
3245+
class VoiceChannelEffectSendEvent:
3246+
"""Represents the payload for an :func:`on_voice_channel_effect_send`
3247+
3248+
.. versionadded:: 2.4
3249+
3250+
Attributes
3251+
----------
3252+
animation_type: :class:`int`
3253+
The type of animation that is being sent.
3254+
animation_id: :class:`int`
3255+
The ID of the animation that is being sent.
3256+
sound: Optional[:class:`SoundboardSound`]
3257+
The sound that is being sent, might be None if the effect is not a sound effect.
3258+
guild: :class:`Guild`
3259+
The guild that the sound is being sent in.
3260+
user: :class:`Member`
3261+
The member that is sending the sound.
3262+
channel: :class:`VoiceChannel`
3263+
The voice channel that the sound is being sent in.
3264+
data: :class:`dict`
3265+
The raw data sent by the gateway([#6025](https://github.com/discord/discord-api-docs/pull/6025)).
3266+
"""
3267+
3268+
__slots__ = (
3269+
"_state",
3270+
"animation_type",
3271+
"animation_id",
3272+
"sound",
3273+
"guild",
3274+
"user",
3275+
"channel",
3276+
"data",
3277+
"emoji",
3278+
)
3279+
3280+
def __init__(
3281+
self,
3282+
data: VoiceChannelEffectSend,
3283+
state: ConnectionState,
3284+
sound: SoundboardSound | PartialSoundboardSound | None = None,
3285+
) -> None:
3286+
self._state = state
3287+
channel_id = int(data["channel_id"])
3288+
user_id = int(data["user_id"])
3289+
guild_id = int(data["guild_id"])
3290+
self.animation_type: VoiceChannelEffectAnimationType = try_enum(
3291+
VoiceChannelEffectAnimationType, data["animation_type"]
3292+
)
3293+
self.animation_id = int(data["animation_id"])
3294+
self.sound = sound
3295+
self.guild = state._get_guild(guild_id)
3296+
self.user = self.guild.get_member(user_id)
3297+
self.channel = self.guild.get_channel(channel_id)
3298+
self.emoji = (
3299+
PartialEmoji(
3300+
name=data["emoji"]["name"],
3301+
animated=data["emoji"]["animated"],
3302+
id=data["emoji"]["id"],
3303+
)
3304+
if data.get("emoji", None)
3305+
else None
3306+
)
3307+
self.data = data
3308+
3309+
32233310
def _guild_channel_factory(channel_type: int):
32243311
value = try_enum(ChannelType, channel_type)
32253312
if value is ChannelType.text:

discord/client.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
from .mentions import AllowedMentions
5454
from .monetization import SKU, Entitlement
5555
from .object import Object
56+
from .soundboard import DefaultSoundboardSound
5657
from .stage_instance import StageInstance
5758
from .state import ConnectionState
5859
from .sticker import GuildSticker, StandardSticker, StickerPack, _sticker_factory
@@ -71,6 +72,7 @@
7172
from .member import Member
7273
from .message import Message
7374
from .poll import Poll
75+
from .soundboard import SoundboardSound
7476
from .voice_client import VoiceProtocol
7577

7678
__all__ = ("Client",)
@@ -2269,3 +2271,43 @@ async def delete_emoji(self, emoji: Snowflake) -> None:
22692271
)
22702272
if self._connection.cache_app_emojis and self._connection.get_emoji(emoji.id):
22712273
self._connection.remove_emoji(emoji)
2274+
2275+
def get_sound(self, sound_id: int) -> SoundboardSound | None:
2276+
"""Gets a :class:`.Sound` from the bot's sound cache.
2277+
2278+
.. versionadded:: 2.4
2279+
2280+
Parameters
2281+
----------
2282+
sound_id: :class:`int`
2283+
The ID of the sound to get.
2284+
2285+
Returns
2286+
-------
2287+
:class:`.Sound`
2288+
The sound from the ID.
2289+
"""
2290+
return self._connection._get_sound(sound_id)
2291+
2292+
@property
2293+
def sounds(self) -> list[SoundboardSound]:
2294+
"""A list of all the sounds the bot can see.
2295+
2296+
.. versionadded:: 2.4
2297+
"""
2298+
return self._connection.sounds
2299+
2300+
async def fetch_default_sounds(self) -> list[SoundboardSound]:
2301+
"""|coro|
2302+
2303+
Fetches the bot's default sounds.
2304+
2305+
.. versionadded:: 2.4
2306+
2307+
Returns
2308+
-------
2309+
List[:class:`.Sound`]
2310+
The bot's default sounds.
2311+
"""
2312+
data = await self._connection.http.get_default_sounds()
2313+
return [DefaultSoundboardSound(self.http, s) for s in data]

discord/enums.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
"PromptType",
7272
"OnboardingMode",
7373
"ReactionType",
74+
"VoiceChannelEffectAnimationType",
7475
"SKUType",
7576
"EntitlementType",
7677
"EntitlementOwnerType",
@@ -1053,6 +1054,13 @@ class PollLayoutType(Enum):
10531054
default = 1
10541055

10551056

1057+
class VoiceChannelEffectAnimationType(Enum):
1058+
"""Voice channel effect animation type"""
1059+
1060+
premium = 0
1061+
basic = 1
1062+
1063+
10561064
T = TypeVar("T")
10571065

10581066

discord/gateway.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ class DiscordWebSocket:
284284
HELLO = 10
285285
HEARTBEAT_ACK = 11
286286
GUILD_SYNC = 12
287+
REQUEST_SOUNDBOARD_SOUNDS = 31
287288

288289
def __init__(self, socket, *, loop):
289290
self.socket = socket
@@ -713,6 +714,15 @@ async def voice_state(self, guild_id, channel_id, self_mute=False, self_deaf=Fal
713714
_log.debug("Updating our voice state to %s.", payload)
714715
await self.send_as_json(payload)
715716

717+
async def request_soundboard_sounds(self, guild_ids):
718+
payload = {
719+
"op": self.REQUEST_SOUNDBOARD_SOUNDS,
720+
"d": {"guild_ids": guild_ids},
721+
}
722+
723+
_log.debug("Requesting soundboard sounds for guilds %s.", guild_ids)
724+
await self.send_as_json(payload)
725+
716726
async def close(self, code=4000):
717727
if self._keep_alive:
718728
self._keep_alive.stop()

0 commit comments

Comments
 (0)