@@ -4,8 +4,9 @@ const process = require('node:process');
4
4
const { setTimeout, clearTimeout } = require ( 'node:timers' ) ;
5
5
const { Collection } = require ( '@discordjs/collection' ) ;
6
6
const { makeURLSearchParams } = require ( '@discordjs/rest' ) ;
7
- const { Routes, RouteBases } = require ( 'discord-api-types/v10' ) ;
7
+ const { GatewayOpcodes , Routes, RouteBases } = require ( 'discord-api-types/v10' ) ;
8
8
const { CachedManager } = require ( './CachedManager.js' ) ;
9
+ const { DiscordjsError, ErrorCodes } = require ( '../errors/index.js' ) ;
9
10
const { ShardClientUtil } = require ( '../sharding/ShardClientUtil.js' ) ;
10
11
const { Guild } = require ( '../structures/Guild.js' ) ;
11
12
const { GuildChannel } = require ( '../structures/GuildChannel.js' ) ;
@@ -282,6 +283,71 @@ class GuildManager extends CachedManager {
282
283
return data . reduce ( ( coll , guild ) => coll . set ( guild . id , new OAuth2Guild ( this . client , guild ) ) , new Collection ( ) ) ;
283
284
}
284
285
286
+ /**
287
+ * @typedef {Object } FetchSoundboardSoundsOptions
288
+ * @param {Snowflake[] } guildIds The ids of the guilds to fetch soundboard sounds for
289
+ * @param {number } [time=10_000] The timeout for receipt of the soundboard sounds
290
+ */
291
+
292
+ /**
293
+ * Fetches soundboard sounds for the specified guilds.
294
+ * @param {FetchSoundboardSoundsOptions } options The options for fetching soundboard sounds
295
+ * @returns {Promise<Collection<Snowflake, Collection<string, SoundboardSound>>> }
296
+ * @example
297
+ * // Fetch soundboard sounds for multiple guilds
298
+ * const soundboardSounds = await client.guilds.fetchSoundboardSounds({
299
+ * guildIds: ['1234567890', '9876543210'],
300
+ * })
301
+ *
302
+ * console.log(soundboardSounds.get('1234567890'));
303
+ */
304
+ async fetchSoundboardSounds ( { guildIds, time = 10_000 } ) {
305
+ const shardCount = await this . client . ws . getShardCount ( ) ;
306
+ const shardIds = Map . groupBy ( guildIds , guildId => ShardClientUtil . shardIdForGuildId ( guildId , shardCount ) ) ;
307
+
308
+ for ( const [ shardId , shardGuildIds ] of shardIds ) {
309
+ this . client . ws . send ( shardId , {
310
+ op : GatewayOpcodes . RequestSoundboardSounds ,
311
+ d : {
312
+ guild_ids : shardGuildIds ,
313
+ } ,
314
+ } ) ;
315
+ }
316
+
317
+ return new Promise ( ( resolve , reject ) => {
318
+ const remainingGuildIds = new Set ( guildIds ) ;
319
+
320
+ const fetchedSoundboardSounds = new Collection ( ) ;
321
+
322
+ const handler = ( soundboardSounds , guild ) => {
323
+ if ( ! remainingGuildIds . has ( guild . id ) ) return ;
324
+
325
+ timeout . refresh ( ) ;
326
+
327
+ fetchedSoundboardSounds . set ( guild . id , soundboardSounds ) ;
328
+
329
+ remainingGuildIds . delete ( guild . id ) ;
330
+
331
+ if ( remainingGuildIds . size === 0 ) {
332
+ clearTimeout ( timeout ) ;
333
+ this . client . removeListener ( Events . SoundboardSounds , handler ) ;
334
+ this . client . decrementMaxListeners ( ) ;
335
+
336
+ resolve ( fetchedSoundboardSounds ) ;
337
+ }
338
+ } ;
339
+
340
+ const timeout = setTimeout ( ( ) => {
341
+ this . client . removeListener ( Events . SoundboardSounds , handler ) ;
342
+ this . client . decrementMaxListeners ( ) ;
343
+ reject ( new DiscordjsError ( ErrorCodes . GuildSoundboardSoundsTimeout ) ) ;
344
+ } , time ) . unref ( ) ;
345
+
346
+ this . client . incrementMaxListeners ( ) ;
347
+ this . client . on ( Events . SoundboardSounds , handler ) ;
348
+ } ) ;
349
+ }
350
+
285
351
/**
286
352
* Options used to set incident actions. Supplying `null` to any option will disable the action.
287
353
* @typedef {Object } IncidentActionsEditOptions
0 commit comments