Skip to content

Commit

Permalink
feat: add soundboard_sounds caching from guild_create
Browse files Browse the repository at this point in the history
  • Loading branch information
shiftinv committed Aug 9, 2024
1 parent f508548 commit e808867
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 3 deletions.
28 changes: 26 additions & 2 deletions disnake/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
from .mentions import AllowedMentions
from .object import Object
from .sku import SKU
from .soundboard import SoundboardSound
from .soundboard import GuildSoundboardSound, SoundboardSound
from .stage_instance import StageInstance
from .state import ConnectionState
from .sticker import GuildSticker, StandardSticker, StickerPack, _sticker_factory
Expand Down Expand Up @@ -572,6 +572,14 @@ def stickers(self) -> List[GuildSticker]:
"""
return self._connection.stickers

@property
def soundboard_sounds(self) -> List[GuildSoundboardSound]:
"""List[:class:`.GuildSoundboardSound`]: The soundboard sounds that the connected client has.
.. versionadded:: 2.10
"""
return self._connection.soundboard_sounds

@property
def cached_messages(self) -> Sequence[Message]:
"""Sequence[:class:`.Message`]: Read-only list of messages the connected client has cached.
Expand Down Expand Up @@ -1497,7 +1505,7 @@ def get_sticker(self, id: int, /) -> Optional[GuildSticker]:
.. note::
To retrieve standard stickers, use :meth:`.fetch_sticker`.
To retrieve standard stickers, use :meth:`.fetch_sticker`
or :meth:`.fetch_sticker_packs`.
Returns
Expand All @@ -1507,6 +1515,22 @@ def get_sticker(self, id: int, /) -> Optional[GuildSticker]:
"""
return self._connection.get_sticker(id)

def get_soundboard_sounds(self, id: int, /) -> Optional[GuildSoundboardSound]:
"""Returns a guild soundboard sound with the given ID.
.. versionadded:: 2.10
.. note::
To retrieve standard soundboard sounds, use :meth:`.fetch_default_soundboard_sounds`.
Returns
-------
Optional[:class:`.GuildSoundboardSound`]
The soundboard sound or ``None`` if not found.
"""
return self._connection.get_soundboard_sound(id)

def get_all_channels(self) -> Generator[GuildChannel, None, None]:
"""A generator that retrieves every :class:`.abc.GuildChannel` the client can 'access'.
Expand Down
10 changes: 10 additions & 0 deletions disnake/guild.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,11 @@ class Guild(Hashable):
.. versionadded:: 2.0
soundboard_sounds: Tuple[:class:`GuildSoundboardSound`, ...]
All soundboard sounds that the guild owns.
.. versionadded:: 2.10
afk_timeout: :class:`int`
The timeout to get sent to the AFK channel.
afk_channel: Optional[:class:`VoiceChannel`]
Expand Down Expand Up @@ -325,6 +330,7 @@ class Guild(Hashable):
"mfa_level",
"emojis",
"stickers",
"soundboard_sounds",
"features",
"verification_level",
"explicit_content_filter",
Expand Down Expand Up @@ -558,6 +564,10 @@ def _from_data(self, guild: GuildPayload) -> None:
self.stickers: Tuple[GuildSticker, ...] = tuple(
state.store_sticker(self, d) for d in guild.get("stickers", [])
)
# TODO: rest methods
self.soundboard_sounds: Tuple[GuildSoundboardSound, ...] = tuple(
state.store_soundboard_sound(self, d) for d in guild.get("soundboard_sounds", [])
)
self.features: List[GuildFeature] = guild.get("features", [])
self._splash: Optional[str] = guild.get("splash")
self._system_channel_id: Optional[int] = utils._get_as_snowflake(guild, "system_channel_id")
Expand Down
23 changes: 23 additions & 0 deletions disnake/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
from .types.emoji import Emoji as EmojiPayload, PartialEmoji as PartialEmojiPayload
from .types.guild import Guild as GuildPayload, UnavailableGuild as UnavailableGuildPayload
from .types.message import Message as MessagePayload
from .types.soundboard import GuildSoundboardSound as GuildSoundboardSoundPayload
from .types.sticker import GuildSticker as GuildStickerPayload
from .types.user import User as UserPayload
from .types.webhook import Webhook as WebhookPayload
Expand Down Expand Up @@ -308,6 +309,7 @@ def clear(
self._users: weakref.WeakValueDictionary[int, User] = weakref.WeakValueDictionary()
self._emojis: Dict[int, Emoji] = {}
self._stickers: Dict[int, GuildSticker] = {}
self._soundboard_sounds: Dict[int, GuildSoundboardSound] = {}
self._guilds: Dict[int, Guild] = {}

if application_commands:
Expand Down Expand Up @@ -418,6 +420,15 @@ def store_sticker(self, guild: Guild, data: GuildStickerPayload) -> GuildSticker
self._stickers[sticker_id] = sticker = GuildSticker(state=self, data=data)
return sticker

def store_soundboard_sound(
self, guild: Guild, data: GuildSoundboardSoundPayload
) -> GuildSoundboardSound:
sticker_id = int(data["sound_id"])
self._soundboard_sounds[sticker_id] = sound = GuildSoundboardSound(
state=self, data=data, guild_id=guild.id
)
return sound

def store_view(self, view: View, message_id: Optional[int] = None) -> None:
self._view_store.add_view(view, message_id)

Expand Down Expand Up @@ -453,6 +464,9 @@ def _remove_guild(self, guild: Guild) -> None:
for sticker in guild.stickers:
self._stickers.pop(sticker.id, None)

for sound in guild.soundboard_sounds:
self._soundboard_sounds.pop(sound.id, None)

del guild

def _get_global_application_command(
Expand Down Expand Up @@ -528,6 +542,10 @@ def emojis(self) -> List[Emoji]:
def stickers(self) -> List[GuildSticker]:
return list(self._stickers.values())

@property
def soundboard_sounds(self) -> List[GuildSoundboardSound]:
return list(self._soundboard_sounds.values())

def get_emoji(self, emoji_id: Optional[int]) -> Optional[Emoji]:
# the keys of self._emojis are ints
return self._emojis.get(emoji_id) # type: ignore
Expand All @@ -536,6 +554,10 @@ def get_sticker(self, sticker_id: Optional[int]) -> Optional[GuildSticker]:
# the keys of self._stickers are ints
return self._stickers.get(sticker_id) # type: ignore

def get_soundboard_sound(self, sound_id: Optional[int]) -> Optional[GuildSoundboardSound]:
# the keys of self._soundboard_sounds are ints
return self._soundboard_sounds.get(sound_id) # type: ignore

@property
def private_channels(self) -> List[PrivateChannel]:
return list(self._private_channels.values())
Expand Down Expand Up @@ -1960,6 +1982,7 @@ def parse_entitlement_delete(self, data: gateway.EntitlementDelete) -> None:
entitlement = Entitlement(data=data, state=self)
self.dispatch("entitlement_delete", entitlement)

# TODO: update cache, add non-raw events
def parse_guild_soundboard_sound_create(self, data: gateway.GuildSoundboardSoundCreate) -> None:
guild_id = utils._get_as_snowflake(data, "guild_id")
guild = self._get_guild(guild_id)
Expand Down
2 changes: 2 additions & 0 deletions disnake/types/guild.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from .member import Member
from .role import CreateRole, Role
from .snowflake import Snowflake
from .soundboard import GuildSoundboardSound
from .sticker import GuildSticker
from .threads import Thread
from .user import User
Expand Down Expand Up @@ -149,6 +150,7 @@ class Guild(_BaseGuildPreview):
presences: NotRequired[List[PartialPresenceUpdate]]
stage_instances: NotRequired[List[StageInstance]]
guild_scheduled_events: NotRequired[List[GuildScheduledEvent]]
soundboard_sounds: NotRequired[List[GuildSoundboardSound]]


class InviteGuild(Guild, total=False):
Expand Down
2 changes: 1 addition & 1 deletion disnake/types/soundboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ class SoundboardSound(PartialSoundboardSound):

class GuildSoundboardSound(SoundboardSound):
guild_id: NotRequired[Snowflake]
user: NotRequired[User]
user: NotRequired[User] # only available via REST, given appropriate permissions

0 comments on commit e808867

Please sign in to comment.