Skip to content

Commit 33bfded

Browse files
sdanialrazaalmeidxkodiakhq[bot]
authored andcommitted
feat(Client): add request soundboard sounds (#10608)
* feat(Client): add request soundboard sounds * docs: add `guildId` to example Co-authored-by: Almeida <github@almeidx.dev> * refactor: remove `groupBy` polyfill --------- Co-authored-by: Almeida <github@almeidx.dev> Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
1 parent caa7833 commit 33bfded

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed

packages/core/src/client.ts

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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';
8688
import type { Gateway } from './Gateway.js';
8789
import { 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

Comments
 (0)