Skip to content

Commit 67f9b5f

Browse files
committed
Guild.fetch_sounds
1 parent 97628fe commit 67f9b5f

File tree

4 files changed

+89
-36
lines changed

4 files changed

+89
-36
lines changed

discord/client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2293,7 +2293,7 @@ def get_sound(self, sound_id: int) -> SoundboardSound | None:
22932293
def sounds(self) -> list[SoundboardSound]:
22942294
"""A list of all the sounds the bot can see.
22952295
2296-
.. versionadded:: 2.4
2296+
.. versionadded:: 2.7
22972297
"""
22982298
return self._connection.sounds
22992299

@@ -2302,7 +2302,7 @@ async def fetch_default_sounds(self) -> list[SoundboardSound]:
23022302
23032303
Fetches the bot's default sounds.
23042304
2305-
.. versionadded:: 2.4
2305+
.. versionadded:: 2.7
23062306
23072307
Returns
23082308
-------

discord/guild.py

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -565,9 +565,7 @@ def _from_data(self, guild: GuildPayload) -> None:
565565
self._update_voice_state(obj, int(obj["channel_id"]))
566566

567567
for sound in guild.get("soundboard_sounds", []):
568-
sound = SoundboardSound(
569-
state=state, http=state.http, data=sound, guild=self
570-
)
568+
sound = SoundboardSound(state=state, http=state.http, data=sound)
571569
self._add_sound(sound)
572570

573571
def _add_sound(self, sound: SoundboardSound) -> None:
@@ -577,12 +575,33 @@ def _add_sound(self, sound: SoundboardSound) -> None:
577575
def _remove_sound(self, sound_id: int) -> None:
578576
self._sounds.pop(sound_id, None)
579577

578+
async def fetch_sounds(self) -> list[SoundboardSound]:
579+
"""|coro|
580+
Fetches all the soundboard sounds in the guild.
581+
582+
.. versionadded:: 2.7
583+
584+
Returns
585+
-------
586+
List[:class:`SoundboardSound`]
587+
The sounds in the guild.
588+
"""
589+
data = await self._state.http.get_all_guild_sounds(self.id)
590+
return [
591+
SoundboardSound(
592+
state=self._state,
593+
http=self._state.http,
594+
data=sound,
595+
)
596+
for sound in data["items"]
597+
]
598+
580599
async def create_sound(
581600
self,
582601
name: str,
583602
sound: bytes,
584603
volume: float = 1.0,
585-
emoji: PartialEmoji | Emoji | str | None = None,
604+
emoji: PartialEmoji | GuildEmoji | str | None = None,
586605
reason: str | None = None,
587606
):
588607
"""|coro|
@@ -600,7 +619,7 @@ async def create_sound(
600619
Only MP3 sound files that don't exceed the duration of 5.2s are supported.
601620
volume: :class:`float`
602621
The volume of the sound. Defaults to 1.0.
603-
emoji: Union[:class:`PartialEmoji`, :class:`Emoji`, :class:`str`]
622+
emoji: Union[:class:`PartialEmoji`, :class:`GuildEmoji`, :class:`str`]
604623
The emoji of the sound.
605624
reason: Optional[:class:`str`]
606625
The reason for creating this sound. Shows up on the audit log.
@@ -640,13 +659,13 @@ async def create_sound(
640659
else:
641660
payload["emoji_id"] = partial_emoji.id
642661

643-
data = await self._state.http.create_sound(self.id, reason=reason, **payload)
662+
data = await self._state.http.create_guild_sound(
663+
self.id, reason=reason, **payload
664+
)
644665
return SoundboardSound(
645666
state=self._state,
646667
http=self._state.http,
647668
data=data,
648-
guild=self,
649-
owner_id=self._state.self_id,
650669
)
651670

652671
# TODO: refactor/remove?

discord/http.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3191,10 +3191,12 @@ def delete_sound(
31913191
def get_default_sounds(self):
31923192
return self.request(Route("GET", "/soundboard-default-sounds"))
31933193

3194-
def create_sound(self, guild_id: Snowflake, reason: str | None, **payload):
3194+
def create_guild_sound(
3195+
self, guild_id: Snowflake, reason: str | None, **payload
3196+
) -> Response[SoundboardSoundPayload]:
31953197
keys = (
31963198
"name",
3197-
"suond",
3199+
"sound",
31983200
"volume",
31993201
"emoji_id",
32003202
"emoji_name",
@@ -3208,6 +3210,13 @@ def create_sound(self, guild_id: Snowflake, reason: str | None, **payload):
32083210
reason=reason,
32093211
)
32103212

3213+
def get_all_guild_sounds(
3214+
self, guild_id: Snowflake
3215+
) -> Response[list[SoundboardSoundPayload]]:
3216+
return self.request(
3217+
Route("GET", "/guilds/{guild_id}/soundboard-sounds", guild_id=guild_id)
3218+
)
3219+
32113220
def edit_sound(
32123221
self, guild_id: Snowflake, sound_Id: Snowflake, *, reason: str | None, **payload
32133222
):

discord/soundboard.py

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,17 @@
2727

2828
from typing import TYPE_CHECKING
2929

30+
from typing_extensions import reveal_type
31+
3032
from .asset import Asset
3133
from .emoji import PartialEmoji
3234
from .mixins import Hashable
35+
from .types.channel import (
36+
VoiceChannelEffectSendEvent as VoiceChannelEffectSendEventPayload,
37+
)
3338
from .types.soundboard import PartialSoundboardSound as PartialSoundboardSoundPayload
3439
from .types.soundboard import SoundboardSound as SoundboardSoundPayload
40+
from .utils import cached_slot_property
3541

3642
if TYPE_CHECKING:
3743
from .guild import Guild
@@ -62,16 +68,13 @@ class PartialSoundboardSound(Hashable):
6268

6369
__slots__ = ("id", "volume", "emoji", "_http", "emoji")
6470

65-
def __init__(self, data: PartialSoundboardSoundPayload, http: HTTPClient):
71+
def __init__(
72+
self,
73+
data: PartialSoundboardSoundPayload | VoiceChannelEffectSendEventPayload,
74+
http: HTTPClient,
75+
):
6676
self._http = http
67-
self.id = int(data["sound_id"])
68-
self.volume = (
69-
float(data["volume"]) if data.get("volume") else data["sound_volume"]
70-
)
71-
self.emoji = PartialEmoji(
72-
name=data.get("emoji_name"),
73-
id=int(data["emoji_id"]) if data.get("emoji_id") else None,
74-
)
77+
self._from_data(data)
7578

7679
def __eq__(self, other: PartialSoundboardSound) -> bool:
7780
if isinstance(other, self, __class__):
@@ -84,14 +87,24 @@ def __ne__(self, other: PartialSoundboardSound) -> bool:
8487
@property
8588
def file(self) -> Asset:
8689
""":class:`Asset`: Returns the sound's file."""
87-
return Asset._from_soundboard_sound(self)
90+
return Asset._from_soundboard_sound(self, sound_id=self.id)
8891

89-
def _update(self, data: PartialSoundboardSoundPayload) -> None:
90-
self.volume = float(data["volume"])
91-
self.emoji = PartialEmoji(
92-
name=data.get("emoji_name"),
93-
id=int(data["emoji_id"]) if data.get("emoji_id") else None,
94-
)
92+
def _from_data(
93+
self, data: PartialSoundboardSoundPayload | VoiceChannelEffectSendEventPayload
94+
) -> None:
95+
self.id = int(data["sound_id"])
96+
self.volume = float(data.get("volume", 0)) or data.get("sound_volume")
97+
if raw_emoji := data.get(
98+
"emoji"
99+
): # From gateway event (VoiceChannelEffectSendEventPayload)
100+
self.emoji = PartialEmoji.from_dict(raw_emoji)
101+
elif emoji_id := data.get(
102+
"emoji_id", 0
103+
): # From HTTP response (PartialSoundboardSoundPayload)
104+
self.emoji = PartialEmoji(
105+
name=data.get("emoji_name"),
106+
id=int(emoji_id) or None,
107+
)
95108

96109

97110
class SoundboardSound(PartialSoundboardSound):
@@ -121,8 +134,9 @@ class SoundboardSound(PartialSoundboardSound):
121134
"name",
122135
"available",
123136
"emoji",
124-
"guild",
125-
"owner",
137+
"guild_id",
138+
"_cs_guild",
139+
"user",
126140
"_http",
127141
"_state",
128142
"emoji",
@@ -134,16 +148,27 @@ def __init__(
134148
state: ConnectionState,
135149
http: HTTPClient,
136150
data: SoundboardSoundPayload,
137-
guild_id: int = None,
138-
owner_id: Member = None,
139-
guild: Guild = None,
140151
) -> None:
141152
self._state = state
142153
super().__init__(data, http)
154+
155+
def _from_data(self, data: SoundboardSoundPayload) -> None:
156+
super()._from_data(data)
143157
self.name = data["name"]
144-
self.available = bool(data.get("available", True))
145-
self.guild: Guild = guild or state._get_guild(guild_id)
146-
self.owner: Member = self.guild.get_member(owner_id)
158+
self.available: bool = data["available"]
159+
self.guild_id = int(data["guild_id"])
160+
user = data.get("user")
161+
162+
self.user = self._state.store_user(user) if user else None
163+
164+
@cached_slot_property("_cs_guild")
165+
def guild(self) -> Guild:
166+
""":class:`Guild`: The guild the sound belongs to.
167+
168+
The :class:`Guild` object representing the guild the sound belongs to.
169+
.. versionadded:: 2.7
170+
"""
171+
return self._state._get_guild(self.guild_id)
147172

148173
def __eq__(self, other: SoundboardSound) -> bool:
149174
return isinstance(other, SoundboardSound) and self.__dict__ == other.__dict__

0 commit comments

Comments
 (0)