Skip to content

feat: soundboard forward port #10859

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/discord.js/src/managers/GuildManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,8 @@ class GuildManager extends CachedManager {

/**
* @typedef {Object} FetchSoundboardSoundsOptions
* @param {Snowflake[]} guildIds The ids of the guilds to fetch soundboard sounds for
* @param {number} [time=10_000] The timeout for receipt of the soundboard sounds
* @property {Snowflake[]} guildIds The ids of the guilds to fetch soundboard sounds for
* @property {number} [time=10_000] The timeout for receipt of the soundboard sounds
*/

/**
Expand Down
58 changes: 40 additions & 18 deletions packages/discord.js/src/managers/GuildSoundboardSoundManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class GuildSoundboardSoundManager extends CachedManager {
* Data for editing a soundboard sound.
* @typedef {Object} GuildSoundboardSoundEditOptions
* @property {string} [name] The name of the soundboard sound
* @property {?number} [volume] The volume of the soundboard sound, from 0 to 1
* @property {?number} [volume] The volume (a double) of the soundboard sound, from 0 (inclusive) to 1
* @property {?Snowflake} [emojiId] The emoji id of the soundboard sound
* @property {?string} [emojiName] The emoji name of the soundboard sound
* @property {string} [reason] The reason for editing the soundboard sound
Expand Down Expand Up @@ -157,35 +157,57 @@ class GuildSoundboardSoundManager extends CachedManager {
await this.client.rest.delete(Routes.guildSoundboardSound(this.guild.id, soundId), { reason });
}

/**
* Options used to fetch a soundboard sound.
* @typedef {BaseFetchOptions} FetchSoundboardSoundOptions
* @property {SoundboardSoundResolvable} soundboardSound The soundboard sound to fetch
*/

/**
* Options used to fetch soundboard sounds from Discord
* @typedef {Object} FetchGuildSoundboardSoundsOptions
* @property {boolean} [cache] Whether to cache the fetched soundboard sounds
*/

/* eslint-disable max-len */
/**
* Obtains one or more soundboard sounds from Discord, or the soundboard sound cache if they're already available.
* @param {Snowflake} [id] The soundboard sound's id
* @param {BaseFetchOptions} [options] Additional options for this fetch
* @param {SoundboardSoundResolvable|FetchSoundboardSoundOptions|FetchGuildSoundboardSoundsOptions} [options] Options for fetching soundboard sound(s)
* @returns {Promise<SoundboardSound|Collection<Snowflake, SoundboardSound>>}
* @example
* // Fetch all soundboard sounds from the guild
* guild.soundboardSounds.fetch()
* .then(sounds => console.log(`There are ${sounds.size} soundboard sounds.`))
* .catch(console.error);
* @example
* // Fetch a single soundboard sound
* guild.soundboardSounds.fetch('222078108977594368')
* .then(sound => console.log(`The soundboard sound name is: ${sound.name}`))
* .catch(console.error);
* @example
* // Fetch all soundboard sounds from the guild
* guild.soundboardSounds.fetch()
* .then(sounds => console.log(`There are ${sounds.size} soundboard sounds.`))
* .catch(console.error);
*/
async fetch(id, { cache = true, force = false } = {}) {
if (id) {
if (!force) {
const existing = this.cache.get(id);
if (existing) return existing;
}

const sound = await this.client.rest.get(Routes.guildSoundboardSound(this.guild.id, id));
return this._add(sound, cache);
/* eslint-enable max-len */
async fetch(options) {
if (!options) return this._fetchMany();
const { cache, force, soundboardSound } = options;
const resolvedSoundboardSound = this.resolveId(soundboardSound ?? options);
if (resolvedSoundboardSound) return this._fetchSingle({ cache, force, soundboardSound: resolvedSoundboardSound });
return this._fetchMany({ cache });
}

async _fetchSingle({ cache, force, soundboardSound } = {}) {
if (!force) {
const existing = this.cache.get(soundboardSound);
if (existing) return existing;
}

const data = await this.client.rest.get(Routes.guildSoundboardSound(this.guild.id, soundboardSound));
return this._add(data, cache);
}

async _fetchMany({ cache } = {}) {
const data = await this.client.rest.get(Routes.guildSoundboardSounds(this.guild.id));
return new Collection(data.map(sound => [sound.sound_id, this._add(sound, cache)]));

return data.items.reduce((coll, sound) => coll.set(sound.sound_id, this._add(sound, cache)), new Collection());
}
}

Expand Down
7 changes: 7 additions & 0 deletions packages/discord.js/src/structures/Guild.js
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,13 @@ class Guild extends AnonymousGuild {
} else {
this.incidentsData ??= null;
}

if (data.soundboard_sounds) {
this.soundboardSounds.cache.clear();
for (const soundboardSound of data.soundboard_sounds) {
this.soundboardSounds._add(soundboardSound);
}
}
}

/**
Expand Down
8 changes: 4 additions & 4 deletions packages/discord.js/src/structures/SoundboardSound.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ class SoundboardSound extends Base {
this.available === other.available &&
this.name === other.name &&
this.volume === other.volume &&
this.emojiId === other.emojiId &&
this.emojiName === other.emojiName &&
this._emoji?.id === other._emoji?.id &&
this._emoji?.name === other._emoji?.name &&
this.guildId === other.guildId &&
this.user?.id === other.user?.id
);
Expand All @@ -193,8 +193,8 @@ class SoundboardSound extends Base {
this.available === other.available &&
this.name === other.name &&
this.volume === other.volume &&
this.emojiId === other.emoji_id &&
this.emojiName === other.emoji_name &&
(this._emoji?.id ?? null) === other.emoji_id &&
(this._emoji?.name ?? null) === other.emoji_name &&
this.guildId === other.guild_id &&
this.user?.id === other.user?.id
);
Expand Down
10 changes: 8 additions & 2 deletions packages/discord.js/typings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4290,8 +4290,15 @@ export interface GuildSoundboardSoundEditOptions {
volume?: number | null;
emojiId?: Snowflake | null;
emojiName?: string | null;
reason?: string;
}

export interface FetchGuildSoundboardSoundOptions extends BaseFetchOptions {
soundboardSound: SoundboardSoundResolvable;
}

export interface FetchGuildSoundboardSoundsOptions extends Pick<BaseFetchOptions, 'cache'> {}

export class GuildSoundboardSoundManager extends CachedManager<Snowflake, SoundboardSound, SoundboardSoundResolvable> {
private constructor(guild: Guild, iterable?: Iterable<APISoundboardSound>);
public guild: Guild;
Expand Down Expand Up @@ -5804,8 +5811,7 @@ export interface GuildAuditLogsEntryTargetField<TAction extends AuditLogEvent> {
ApplicationCommand: ApplicationCommand | { id: Snowflake };
AutoModeration: AutoModerationRule;
GuildOnboardingPrompt: GuildOnboardingPrompt | { id: Snowflake; [x: string]: unknown };
// TODO: Update when https://github.com/discordjs/discord.js/pull/10590 is merged
SoundboardSound: { id: Snowflake };
SoundboardSound: SoundboardSound | { id: Snowflake };
}

export interface GuildAuditLogsFetchOptions<Event extends GuildAuditLogsResolvable> {
Expand Down