@@ -82,6 +82,8 @@ import {
8282 type GatewayVoiceStateUpdateData ,
8383 type GatewayVoiceStateUpdateDispatchData ,
8484 type GatewayWebhooksUpdateDispatchData ,
85+ type GatewayRequestSoundboardSoundsData ,
86+ type GatewaySoundboardSoundsDispatchData ,
8587} from 'discord-api-types/v10' ;
8688import type { Gateway } from './Gateway.js' ;
8789import { API } from './api/index.js' ;
@@ -143,6 +145,7 @@ export interface MappedEvents {
143145 [ GatewayDispatchEvents . GuildSoundboardSoundDelete ] : [ ToEventProps < GatewayGuildSoundboardSoundDeleteDispatch > ] ;
144146 [ GatewayDispatchEvents . GuildSoundboardSoundUpdate ] : [ ToEventProps < GatewayGuildSoundboardSoundUpdateDispatch > ] ;
145147 [ GatewayDispatchEvents . GuildSoundboardSoundsUpdate ] : [ ToEventProps < GatewayGuildSoundboardSoundsUpdateDispatch > ] ;
148+ [ GatewayDispatchEvents . SoundboardSounds ] : [ ToEventProps < GatewaySoundboardSoundsDispatchData > ] ;
146149 [ GatewayDispatchEvents . GuildStickersUpdate ] : [ ToEventProps < GatewayGuildStickersUpdateDispatchData > ] ;
147150 [ GatewayDispatchEvents . GuildUpdate ] : [ ToEventProps < GatewayGuildUpdateDispatchData > ] ;
148151 [ GatewayDispatchEvents . IntegrationCreate ] : [ ToEventProps < GatewayIntegrationCreateDispatchData > ] ;
@@ -334,6 +337,105 @@ export class Client extends AsyncEventEmitter<MappedEvents> {
334337 return { members, nonce, notFound, presences } ;
335338 }
336339
340+ /**
341+ * Requests soundboard sounds from the gateway and returns an async iterator that yields the data from each soundboard sounds event.
342+ *
343+ * @see {@link https://discord.com/developers/docs/topics/gateway-events#request-soundboard-sounds }
344+ * @param options - The options for the request
345+ * @param timeout - The timeout for waiting for each soundboard sounds
346+ * @example
347+ * Requesting soundboard sounds for specific guilds
348+ * ```ts
349+ * for await (const { guildId, soundboardSounds } of this.requestSoundboardSoundsIterator({
350+ * guild_ids: ['1234567890', '9876543210'],
351+ * })) {
352+ * console.log(`Soundboard sounds for guild ${guildId}:`, soundboardSounds);
353+ * }
354+ * ```
355+ */
356+ public async * requestSoundboardSoundsIterator ( options : GatewayRequestSoundboardSoundsData , timeout = 10_000 ) {
357+ const shardCount = await this . gateway . getShardCount ( ) ;
358+ const shardIds = Map . groupBy ( options . guild_ids , ( guildId ) => calculateShardId ( guildId , shardCount ) ) ;
359+
360+ const controller = new AbortController ( ) ;
361+
362+ let timer : NodeJS . Timeout | undefined = createTimer ( controller , timeout ) ;
363+
364+ for ( const [ shardId , guildIds ] of shardIds ) {
365+ await this . gateway . send ( shardId , {
366+ op : GatewayOpcodes . RequestSoundboardSounds ,
367+ // eslint-disable-next-line id-length
368+ d : {
369+ ...options ,
370+ guild_ids : guildIds ,
371+ } ,
372+ } ) ;
373+ }
374+
375+ try {
376+ const iterator = AsyncEventEmitter . on ( this , GatewayDispatchEvents . SoundboardSounds , {
377+ signal : controller . signal ,
378+ } ) ;
379+
380+ const guildIds = new Set ( options . guild_ids ) ;
381+
382+ for await ( const [ { data } ] of iterator ) {
383+ if ( ! guildIds . has ( data . guild_id ) ) continue ;
384+
385+ clearTimeout ( timer ) ;
386+ timer = undefined ;
387+
388+ yield {
389+ guildId : data . guild_id ,
390+ soundboardSounds : data . soundboard_sounds ,
391+ } ;
392+
393+ guildIds . delete ( data . guild_id ) ;
394+
395+ if ( guildIds . size === 0 ) break ;
396+
397+ timer = createTimer ( controller , timeout ) ;
398+ }
399+ } catch ( error ) {
400+ if ( error instanceof Error && error . name === 'AbortError' ) {
401+ throw new Error ( 'Request timed out' ) ;
402+ }
403+
404+ throw error ;
405+ } finally {
406+ if ( timer ) {
407+ clearTimeout ( timer ) ;
408+ }
409+ }
410+ }
411+
412+ /**
413+ * Requests soundboard sounds from the gateway.
414+ *
415+ * @see {@link https://discord.com/developers/docs/topics/gateway-events#request-soundboard-sounds }
416+ * @param options - The options for the request
417+ * @param timeout - The timeout for waiting for each soundboard sounds event
418+ * @example
419+ * Requesting soundboard sounds for specific guilds
420+ * ```ts
421+ * const soundboardSounds = await client.requestSoundboardSounds({ guild_ids: ['1234567890', '9876543210'], });
422+ *
423+ * console.log(soundboardSounds.get('1234567890'));
424+ * ```
425+ */
426+ public async requestSoundboardSounds ( options : GatewayRequestSoundboardSoundsData , timeout = 10_000 ) {
427+ const soundboardSounds = new Map <
428+ GatewaySoundboardSoundsDispatchData [ 'guild_id' ] ,
429+ GatewaySoundboardSoundsDispatchData [ 'soundboard_sounds' ]
430+ > ( ) ;
431+
432+ for await ( const data of this . requestSoundboardSoundsIterator ( options , timeout ) ) {
433+ soundboardSounds . set ( data . guildId , data . soundboardSounds ) ;
434+ }
435+
436+ return soundboardSounds ;
437+ }
438+
337439 /**
338440 * Updates the voice state of the bot user
339441 *
0 commit comments