2525
2626from __future__ import annotations
2727
28- from typing import TYPE_CHECKING
28+ from typing import TYPE_CHECKING , Any , Coroutine
2929
30- from typing_extensions import reveal_type
30+ from typing_extensions import override , reveal_type
3131
3232from .asset import Asset
3333from .emoji import PartialEmoji
3434from .mixins import Hashable
3535from .types .channel import (
3636 VoiceChannelEffectSendEvent as VoiceChannelEffectSendEventPayload ,
3737)
38- from .types .soundboard import PartialSoundboardSound as PartialSoundboardSoundPayload
3938from .types .soundboard import SoundboardSound as SoundboardSoundPayload
4039from .utils import cached_slot_property
4140
4241if TYPE_CHECKING :
4342 from .guild import Guild
4443 from .http import HTTPClient
45- from .member import Member
4644 from .state import ConnectionState
4745
4846
4947__all__ = (
5048 "PartialSoundboardSound" ,
5149 "SoundboardSound" ,
52- "DefaultSoundboardSound" ,
5350)
5451
5552
@@ -66,45 +63,54 @@ class PartialSoundboardSound(Hashable):
6663 The sound's emoji.
6764 """
6865
69- __slots__ = ("id" , "volume" , "emoji" , "_http" , "emoji" )
66+ __slots__ = ("id" , "volume" , "emoji" , "_http" )
7067
7168 def __init__ (
7269 self ,
73- data : PartialSoundboardSoundPayload | VoiceChannelEffectSendEventPayload ,
70+ data : SoundboardSoundPayload | VoiceChannelEffectSendEventPayload ,
7471 http : HTTPClient ,
7572 ):
7673 self ._http = http
7774 self ._from_data (data )
7875
79- def __eq__ (self , other : PartialSoundboardSound ) -> bool :
76+ def _from_data (
77+ self , data : SoundboardSoundPayload | VoiceChannelEffectSendEventPayload
78+ ) -> None :
79+ self .id = int (data .get ("sound_id" , 0 ))
80+ self .volume = (
81+ float (data .get ("volume" , 0 ) or data .get ("sound_volume" , 0 )) or None
82+ )
83+ if raw_emoji := data .get (
84+ "emoji"
85+ ): # From gateway event (VoiceChannelEffectSendEventPayload)
86+ self .emoji = PartialEmoji .from_dict (raw_emoji )
87+ else : # From HTTP response (SoundboardSoundPayload)
88+ self .emoji = PartialEmoji (
89+ name = data .get ("emoji_name" ),
90+ id = int (data .get ("emoji_id" , 0 ) or 0 ) or None ,
91+ )
92+
93+ @override
94+ def __eq__ (
95+ self , other : PartialSoundboardSound
96+ ) -> bool : # pyright: ignore[reportIncompatibleMethodOverride]
8097 if isinstance (other , self , __class__ ):
8198 return self .id == other .id
8299 return NotImplemented
83100
84- def __ne__ (self , other : PartialSoundboardSound ) -> bool :
101+ @override
102+ def __ne__ (
103+ self , other : PartialSoundboardSound
104+ ) -> bool : # pyright: ignore[reportIncompatibleMethodOverride]
85105 return not self .__eq__ (other )
86106
87107 @property
88108 def file (self ) -> Asset :
89109 """:class:`Asset`: Returns the sound's file."""
90110 return Asset ._from_soundboard_sound (self , sound_id = self .id )
91111
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- )
112+ def __repr__ (self ) -> str :
113+ return f"<PartialSoundboardSound id={ self .id } volume={ self .volume } emoji={ self .emoji !r} >"
108114
109115
110116class SoundboardSound (PartialSoundboardSound ):
@@ -129,17 +135,12 @@ class SoundboardSound(PartialSoundboardSound):
129135 """
130136
131137 __slots__ = (
132- "id" ,
133- "volume" ,
134138 "name" ,
135139 "available" ,
136- "emoji" ,
137140 "guild_id" ,
138- "_cs_guild" ,
139141 "user" ,
140- "_http " ,
142+ "_cs_guild " ,
141143 "_state" ,
142- "emoji" ,
143144 )
144145
145146 def __init__ (
@@ -152,59 +153,42 @@ def __init__(
152153 self ._state = state
153154 super ().__init__ (data , http )
154155
155- def _from_data (self , data : SoundboardSoundPayload ) -> None :
156+ @override
157+ def _from_data (
158+ self , data : SoundboardSoundPayload
159+ ) -> None : # pyright: ignore[reportIncompatibleMethodOverride]
156160 super ()._from_data (data )
157161 self .name = data ["name" ]
158162 self .available : bool = data ["available" ]
159- self .guild_id = int (data [ "guild_id" ])
163+ self .guild_id = int (data . get ( "guild_id" , 0 ) or 0 ) or None
160164 user = data .get ("user" )
161-
162165 self .user = self ._state .store_user (user ) if user else None
163166
164167 @cached_slot_property ("_cs_guild" )
165- def guild (self ) -> Guild :
168+ def guild (self ) -> Guild | None :
166169 """:class:`Guild`: The guild the sound belongs to.
167170
168171 The :class:`Guild` object representing the guild the sound belongs to.
169172 .. versionadded:: 2.7
170173 """
171- return self ._state ._get_guild (self .guild_id )
174+ return self ._state ._get_guild (self .guild_id ) if self . guild_id else None
172175
173- def __eq__ (self , other : SoundboardSound ) -> bool :
176+ @override
177+ def __eq__ (
178+ self , other : SoundboardSound
179+ ) -> bool : # pyright: ignore[reportIncompatibleMethodOverride]
174180 return isinstance (other , SoundboardSound ) and self .__dict__ == other .__dict__
175181
176- def delete (self ):
177- return self ._http .delete_sound (self )
178-
179- def _update (self , data : PartialSoundboardSound ) -> None :
180- super ()._update (data )
181- self .name = data ["name" ]
182- self .available = bool (data .get ("available" , True ))
183-
184-
185- class DefaultSoundboardSound (PartialSoundboardSound ):
186- """Represents a default soundboard sound.
187-
188- Attributes
189- ----------
190- id: :class:`int`
191- The sound's ID.
192- volume: :class:`float`
193- The sound's volume.
194- name: :class:`str`
195- The sound's name.
196- emoji: :class:`PartialEmoji`
197- The sound's emoji.
198- """
199-
200- __slots__ = ("id" , "volume" , "name" , "emoji" , "_http" )
201-
202- def __init__ (self , * , http : HTTPClient , data : SoundboardSoundPayload ) -> None :
203- super ().__init__ (data , http )
204- self .name = data ["name" ]
205-
206- def __eq__ (self , other : DefaultSoundboardSound ) -> bool :
207- return (
208- isinstance (other , DefaultSoundboardSound )
209- and self .__dict__ == other .__dict__
210- )
182+ @property
183+ def is_default_sound (self ) -> bool :
184+ """:class:`bool`: Whether the sound is a default sound."""
185+ return self .guild_id is None
186+
187+ def delete (self , * , reason : str | None = None ) -> Coroutine [Any , Any , None ]:
188+ if self .is_default_sound :
189+ raise ValueError ("Cannot delete a default sound." )
190+ return self ._http .delete_sound (self , reason = reason )
191+
192+ @override
193+ def __repr__ (self ) -> str :
194+ return f"<SoundboardSound id={ self .id } name={ self .name !r} volume={ self .volume } emoji={ self .emoji !r} guild={ self .guild !r} user={ self .user !r} available={ self .available } default={ self .is_default_sound } >"
0 commit comments