From 44c872de71546bfca0820f3eb02f66bcc347a591 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Susa=C3=B1a?= Date: Tue, 1 Oct 2024 12:57:44 -0400 Subject: [PATCH] feat: Soundboard API (#267) * feat(discord): soundboard api * chore: apply formatting * fix(gateway): events * feat(events): soundboard * chore: apply formatting * fix: xd * feat(api): soundboard routes * chore: apply formatting --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: MARCROCK22 <57925328+MARCROCK22@users.noreply.github.com> --- src/api/Router.ts | 8 ++-- src/api/Routes/cdn.ts | 5 +- src/api/Routes/index.ts | 1 + src/api/Routes/soundboard.ts | 36 +++++++++++++++ src/api/utils/constants.ts | 2 + src/cache/index.ts | 4 +- src/common/shorters/emojis.ts | 6 +-- src/common/shorters/guilds.ts | 6 +-- src/events/hooks/index.ts | 1 + src/events/hooks/soundboard.ts | 39 ++++++++++++++++ src/types/gateway.ts | 79 +++++++++++++++++++++++++++++++- src/types/payloads/guild.ts | 8 ++++ src/types/payloads/index.ts | 1 + src/types/payloads/soundboard.ts | 25 ++++++++++ src/types/rest/index.ts | 1 + src/types/rest/soundboard.ts | 70 ++++++++++++++++++++++++++++ src/types/utils/index.ts | 12 ++++- src/websocket/SharedTypes.ts | 16 ++++++- 18 files changed, 303 insertions(+), 17 deletions(-) create mode 100644 src/api/Routes/soundboard.ts create mode 100644 src/events/hooks/soundboard.ts create mode 100644 src/types/payloads/soundboard.ts create mode 100644 src/types/rest/soundboard.ts diff --git a/src/api/Router.ts b/src/api/Router.ts index 430c446..64fdfbc 100644 --- a/src/api/Router.ts +++ b/src/api/Router.ts @@ -1,6 +1,6 @@ import { CDN_URL } from '../common'; import type { APIRoutes, ApiHandler, CDNRoute } from './index'; -import type { HttpMethods, ImageExtension, ImageSize, StickerExtension } from './shared'; +import type { HttpMethods, ImageExtension, ImageSize, SoundExtension, StickerExtension } from './shared'; export enum ProxyRequestMethod { Delete = 'delete', @@ -63,7 +63,7 @@ export const CDNRouter = { }; export interface BaseCDNUrlOptions { - extension?: ImageExtension | StickerExtension | undefined; + extension?: ImageExtension | StickerExtension | SoundExtension; size?: ImageSize; } @@ -75,7 +75,9 @@ export function parseCDNURL(route: string, options: CDNUrlOptions = {}) { if (options.forceStatic && route.includes('a_')) options.extension = 'png'; if (!options.extension && route.includes('a_')) options.extension = 'gif'; - const url = new URL(`${route}.${options.extension || 'png'}`); + options.extension ||= route.includes('soundboard') ? 'ogg' : 'png'; + + const url = new URL(`${route}.${options.extension}`); if (options.size) url.searchParams.set('size', `${options.size}`); diff --git a/src/api/Routes/cdn.ts b/src/api/Routes/cdn.ts index 98b9cd6..2d5a541 100644 --- a/src/api/Routes/cdn.ts +++ b/src/api/Routes/cdn.ts @@ -1,5 +1,5 @@ import type { BaseCDNUrlOptions, CDNUrlOptions } from '../..'; -import type { StickerExtension } from '../shared'; +import type { SoundExtension, StickerExtension } from '../shared'; export interface CDNRoute { embed: { @@ -67,6 +67,9 @@ export interface CDNRoute { 'guild-events'(id: string): { get(cover: string, options?: BaseCDNUrlOptions): string; }; + 'soundboard-sounds': { + get(id: string, options?: { extension: SoundExtension }): string; + }; } export interface CDNRoute { diff --git a/src/api/Routes/index.ts b/src/api/Routes/index.ts index 9c5be88..2b71bf5 100644 --- a/src/api/Routes/index.ts +++ b/src/api/Routes/index.ts @@ -9,6 +9,7 @@ import type { StickerRoutes } from './stickers'; import type { UserRoutes } from './users'; import type { VoiceRoutes } from './voice'; import type { WebhookRoutes } from './webhooks'; +export type { SoundboardRoutes } from './soundboard'; export * from './cdn'; diff --git a/src/api/Routes/soundboard.ts b/src/api/Routes/soundboard.ts new file mode 100644 index 0000000..5e9eafc --- /dev/null +++ b/src/api/Routes/soundboard.ts @@ -0,0 +1,36 @@ +import type { + RESTGetAPIDefaultsSoundboardSoundsResult, + RESTGetAPIGuildSoundboardSoundsResult, + RESTPatchAPIGuildSoundboardSound, + RESTPatchAPIGuildSoundboardSoundResult, + RESTPostAPIGuildSoundboardSound, + RESTPostAPIGuildSoundboardSoundResult, + RESTPostAPISendSoundboardSound, +} from '../../types'; +import type { RestArguments, RestArgumentsNoBody } from '../api'; + +export interface SoundboardRoutes { + channels(id: string): { + 'send-soundboard-sound': { + post(args: RestArguments): Promise; + }; + }; + 'soundboard-default-sounds': { + get(args?: RestArgumentsNoBody): Promise; + }; + guilds(id: string): { + get(args?: RestArgumentsNoBody): Promise; + 'soundboard-sounds': { + post( + args: RestArguments, + ): Promise; + ( + id: string, + ): { + get(args?: RestArgumentsNoBody): Promise; + patch(args?: RestArguments): Promise; + delete(args?: RestArgumentsNoBody): Promise; + }; + }; + }; +} diff --git a/src/api/utils/constants.ts b/src/api/utils/constants.ts index 288290b..95fcd45 100644 --- a/src/api/utils/constants.ts +++ b/src/api/utils/constants.ts @@ -2,7 +2,9 @@ export const DefaultUserAgent = 'DiscordBot (https://seyfert.dev, v2.1.0)'; export const ALLOWED_EXTENSIONS = ['webp', 'png', 'jpg', 'jpeg', 'gif'] as const; export const ALLOWED_STICKER_EXTENSIONS = ['png', 'json', 'gif'] as const; export const ALLOWED_SIZES = [16, 32, 64, 100, 128, 256, 512, 1_024, 2_048, 4_096] as const; +export const ALLOWED_SOUNDS_EXTENSIONS = ['mp3', 'ogg'] as const; export type ImageExtension = (typeof ALLOWED_EXTENSIONS)[number]; export type StickerExtension = (typeof ALLOWED_STICKER_EXTENSIONS)[number]; export type ImageSize = (typeof ALLOWED_SIZES)[number]; +export type SoundExtension = (typeof ALLOWED_SOUNDS_EXTENSIONS)[number]; diff --git a/src/cache/index.ts b/src/cache/index.ts index d411598..f2feb55 100644 --- a/src/cache/index.ts +++ b/src/cache/index.ts @@ -224,8 +224,8 @@ export class Cache { return this.hasIntent('GuildMembers'); } - get hasEmojisAndStickersIntent() { - return this.hasIntent('GuildEmojisAndStickers'); + get hasGuildExpressionsIntent() { + return this.hasIntent('GuildExpressions'); } get hasVoiceStatesIntent() { diff --git a/src/common/shorters/emojis.ts b/src/common/shorters/emojis.ts index cd8bb65..d87f338 100644 --- a/src/common/shorters/emojis.ts +++ b/src/common/shorters/emojis.ts @@ -40,7 +40,7 @@ export class EmojiShorter extends BaseShorter { body: bodyResolved, }); - await this.client.cache.emojis?.setIfNI('GuildEmojisAndStickers', emoji.id!, guildId, emoji); + await this.client.cache.emojis?.setIfNI('GuildExpressions', emoji.id!, guildId, emoji); return Transformers.GuildEmoji(this.client, emoji, guildId); } @@ -70,7 +70,7 @@ export class EmojiShorter extends BaseShorter { */ async delete(guildId: string, emojiId: string, reason?: string) { await this.client.proxy.guilds(guildId).emojis(emojiId).delete({ reason }); - await this.client.cache.emojis?.removeIfNI('GuildEmojisAndStickers', emojiId, guildId); + await this.client.cache.emojis?.removeIfNI('GuildExpressions', emojiId, guildId); } /** @@ -83,7 +83,7 @@ export class EmojiShorter extends BaseShorter { */ async edit(guildId: string, emojiId: string, body: RESTPatchAPIGuildEmojiJSONBody, reason?: string) { const emoji = await this.client.proxy.guilds(guildId).emojis(emojiId).patch({ body, reason }); - await this.client.cache.emojis?.setIfNI('GuildEmojisAndStickers', emoji.id!, guildId, emoji); + await this.client.cache.emojis?.setIfNI('GuildExpressions', emoji.id!, guildId, emoji); return Transformers.GuildEmoji(this.client, emoji, guildId); } } diff --git a/src/common/shorters/guilds.ts b/src/common/shorters/guilds.ts index be0ed50..1ae9475 100644 --- a/src/common/shorters/guilds.ts +++ b/src/common/shorters/guilds.ts @@ -299,7 +299,7 @@ export class GuildShorter extends BaseShorter { const sticker = await this.client.proxy .guilds(guildId) .stickers.post({ reason, body: json, files: [{ ...fileResolve[0], key: 'file' }], appendToFormData: true }); - await this.client.cache.stickers?.setIfNI('GuildEmojisAndStickers', sticker.id, guildId, sticker); + await this.client.cache.stickers?.setIfNI('GuildExpressions', sticker.id, guildId, sticker); return Transformers.Sticker(this.client, sticker); }, @@ -313,7 +313,7 @@ export class GuildShorter extends BaseShorter { */ edit: async (guildId: string, stickerId: string, body: RESTPatchAPIGuildStickerJSONBody, reason?: string) => { const sticker = await this.client.proxy.guilds(guildId).stickers(stickerId).patch({ body, reason }); - await this.client.cache.stickers?.setIfNI('GuildEmojisAndStickers', stickerId, guildId, sticker); + await this.client.cache.stickers?.setIfNI('GuildExpressions', stickerId, guildId, sticker); return Transformers.Sticker(this.client, sticker); }, @@ -344,7 +344,7 @@ export class GuildShorter extends BaseShorter { */ delete: async (guildId: string, stickerId: string, reason?: string) => { await this.client.proxy.guilds(guildId).stickers(stickerId).delete({ reason }); - await this.client.cache.stickers?.removeIfNI('GuildEmojisAndStickers', stickerId, guildId); + await this.client.cache.stickers?.removeIfNI('GuildExpressions', stickerId, guildId); }, }; } diff --git a/src/events/hooks/index.ts b/src/events/hooks/index.ts index 56175fc..70f8adf 100644 --- a/src/events/hooks/index.ts +++ b/src/events/hooks/index.ts @@ -16,6 +16,7 @@ export * from './typing'; export * from './user'; export * from './voice'; export * from './webhook'; +export * from './soundboard'; import type { CamelCase } from '../../common'; import type * as RawEvents from './index'; diff --git a/src/events/hooks/soundboard.ts b/src/events/hooks/soundboard.ts new file mode 100644 index 0000000..5eb4adb --- /dev/null +++ b/src/events/hooks/soundboard.ts @@ -0,0 +1,39 @@ +import { Transformers } from '../../client'; +import type { UsingClient } from '../../commands'; +import { toCamelCase } from '../../common'; +import type { + GatewayGuildSoundboardSoundCreateDispatchData, + GatewayGuildSoundboardSoundDeleteDispatchData, + GatewayGuildSoundboardSoundUpdateDispatchData, + GatewayGuildSoundboardSoundsUpdateDispatchData, + GatewaySoundboardSoundsDispatchData, +} from '../../types'; + +export const GUILD_SOUNDBOARD_SOUND_CREATE = ( + self: UsingClient, + data: GatewayGuildSoundboardSoundCreateDispatchData, +) => { + return data.user ? { ...toCamelCase(data), user: Transformers.User(self, data.user) } : toCamelCase(data); +}; + +export const GUILD_SOUNDBOARD_SOUND_UPDATE = ( + self: UsingClient, + data: GatewayGuildSoundboardSoundUpdateDispatchData, +) => { + return data.user ? { ...toCamelCase(data), user: Transformers.User(self, data.user) } : toCamelCase(data); +}; + +export const GUILD_SOUNDBOARD_SOUNDS_UPDATE = ( + self: UsingClient, + data: GatewayGuildSoundboardSoundsUpdateDispatchData, +) => { + return data.map(d => (d.user ? { ...toCamelCase(d), user: Transformers.User(self, d.user) } : toCamelCase(d))); +}; + +export const GUILD_SOUNDBOARD_SOUND_DELETE = (_: UsingClient, data: GatewayGuildSoundboardSoundDeleteDispatchData) => { + return toCamelCase(data); +}; + +export const SOUNDBOARD_SOUNDS = (_: UsingClient, data: GatewaySoundboardSoundsDispatchData) => { + return toCamelCase(data); +}; diff --git a/src/types/gateway.ts b/src/types/gateway.ts index 9a77e0f..bd0500a 100644 --- a/src/types/gateway.ts +++ b/src/types/gateway.ts @@ -35,6 +35,7 @@ import type { GatewayThreadListSync as RawGatewayThreadListSync, GatewayThreadMembersUpdate as RawGatewayThreadMembersUpdate, } from './payloads/index'; +import type { APISoundBoard } from './payloads/soundboard'; import type { ReactionType } from './rest/index'; import type { AnimationTypes, Nullable } from './utils'; @@ -57,7 +58,8 @@ export type GatewaySendPayload = | GatewayRequestGuildMembers | GatewayResume | GatewayUpdatePresence - | GatewayVoiceStateUpdate; + | GatewayVoiceStateUpdate + | GatewayRequestSoundboardSounds; export type GatewayReceivePayload = | GatewayDispatchPayload @@ -127,7 +129,12 @@ export type GatewayDispatchPayload = | GatewayUserUpdateDispatch | GatewayVoiceServerUpdateDispatch | GatewayVoiceStateUpdateDispatch - | GatewayWebhooksUpdateDispatch; + | GatewayWebhooksUpdateDispatch + | GatewayGuildSoundboardSoundCreateDispatch + | GatewayGuildSoundboardSoundDeleteDispatch + | GatewayGuildSoundboardSoundUpdateDispatch + | GatewayGuildSoundboardSoundsUpdateDispatch + | GatewaySoundboardSoundsDispatch; // #region Dispatch Payloads @@ -607,6 +614,14 @@ export interface GatewayGuildCreateDispatchData extends APIGuild { * https://discord.com/developers/docs/resources/guild-scheduled-event#guild-scheduled-event-object */ guild_scheduled_events: APIGuildScheduledEvent[]; + /** + * Soundboard sounds in the guild + * + * **This field is only sent within the [GUILD_CREATE](https://discord.com/developers/docs/topics/gateway-events#guild-create) event** + * + * https://discord.com/developers/docs/resources/soundboard + */ + soundboard_sounds: APISoundBoard[]; } /** @@ -968,6 +983,51 @@ export interface GatewayGuildScheduledEventUserRemoveDispatchData { guild_id: Snowflake; } +export type GatewayGuildSoundboardSoundCreateDispatchData = APISoundBoard; + +export type GatewayGuildSoundboardSoundCreateDispatch = DataPayload< + GatewayDispatchEvents.GuildSoundboardSoundCreate, + GatewayGuildSoundboardSoundCreateDispatchData +>; + +export type GatewayGuildSoundboardSoundUpdateDispatchData = APISoundBoard; + +export type GatewayGuildSoundboardSoundUpdateDispatch = DataPayload< + GatewayDispatchEvents.GuildSoundboardSoundUpdate, + GatewayGuildSoundboardSoundUpdateDispatchData +>; + +export interface GatewayGuildSoundboardSoundDeleteDispatchData { + /** ID of the sound that was deleted */ + sound_id: string; + /** ID of the guild the sound was in */ + guild_id: string; +} + +export type GatewayGuildSoundboardSoundDeleteDispatch = DataPayload< + GatewayDispatchEvents.GuildSoundboardSoundDelete, + GatewayGuildSoundboardSoundDeleteDispatchData +>; + +export type GatewayGuildSoundboardSoundsUpdateDispatchData = APISoundBoard[]; + +export type GatewayGuildSoundboardSoundsUpdateDispatch = DataPayload< + GatewayDispatchEvents.GuildSoundboardSoundsUpdate, + GatewayGuildSoundboardSoundsUpdateDispatchData +>; + +export interface GatewaySoundboardSoundsDispatchData { + /** The guild's soundboard sounds */ + soundboard_sounds: APISoundBoard[]; + /** ID of the guild */ + guild_id: string; +} + +export type GatewaySoundboardSoundsDispatch = DataPayload< + GatewayDispatchEvents.SoundboardSounds, + GatewaySoundboardSoundsDispatchData +>; + /** * https://discord.com/developers/docs/topics/gateway-events#integration-create */ @@ -1862,6 +1922,21 @@ export type GatewayRequestGuildMembersData = | GatewayRequestGuildMembersDataWithQuery | GatewayRequestGuildMembersDataWithUserIds; +/** + * https://discord.com/developers/docs/topics/gateway-events#request-soundboard-sounds + */ +export interface GatewayRequestSoundboardSounds { + op: GatewayOpcodes.RequestSoundboardSounds; + d: GatewayRequestSoundboardSoundsData; +} + +/** + * https://discord.com/developers/docs/topics/gateway-events#request-soundboard-sounds-request-soundboard-sounds-structure + */ +export interface GatewayRequestSoundboardSoundsData { + /** IDs of the guilds to get soundboard sounds for */ + guild_ids: string[]; +} /** * https://discord.com/developers/docs/topics/gateway-events#update-voice-state */ diff --git a/src/types/payloads/guild.ts b/src/types/payloads/guild.ts index 7c8350d..d9bc6d0 100644 --- a/src/types/payloads/guild.ts +++ b/src/types/payloads/guild.ts @@ -471,6 +471,10 @@ export enum GuildFeature { * Guild has enabled Membership Screening */ MemberVerificationGateEnabled = 'MEMBER_VERIFICATION_GATE_ENABLED', + /** + * Guild has increased custom soundboard sound slots + */ + MoreSoundboard = 'MORE_SOUNDBOARD', /** * Guild has enabled monetization * @@ -514,6 +518,10 @@ export enum GuildFeature { * Guild has enabled role subscriptions */ RoleSubscriptionsEnabled = 'ROLE_SUBSCRIPTIONS_ENABLED', + /** + * Guild has created soundboard sounds + */ + Soundboard = 'SOUNDBOARD', /** * Guild has enabled ticketed events */ diff --git a/src/types/payloads/index.ts b/src/types/payloads/index.ts index 49bc6bb..179e582 100644 --- a/src/types/payloads/index.ts +++ b/src/types/payloads/index.ts @@ -19,6 +19,7 @@ export * from './user'; export * from './voice'; export * from './webhook'; export * from './monetization'; +export * from './soundboard'; import type { LocaleString } from '../rest'; diff --git a/src/types/payloads/soundboard.ts b/src/types/payloads/soundboard.ts new file mode 100644 index 0000000..7c68439 --- /dev/null +++ b/src/types/payloads/soundboard.ts @@ -0,0 +1,25 @@ +/** + * Types extracted from https://discord.com/developers/docs/resources/soundboard + */ + +import type { APIUser } from './user'; + +/** https://discord.com/developers/docs/resources/soundboard#soundboard-sound-object-soundboard-sound-structure */ +export interface APISoundBoard { + /** the name of this sound */ + name: string; + /** the id of this sound */ + sound_id: string; + /** the volume of this sound, from 0 to 1 */ + volume: number; + /** the id of this sound's custom emoji */ + emoji_id: string | null; + /** the unicode character of this sound's standard emoji */ + emoji_name: string | null; + /** the id of the guild this sound is in */ + guild_id?: string; + /** whether this sound can be used, may be false due to loss of Server Boosts */ + available: boolean; + /** the user who created this sound */ + user?: APIUser; +} diff --git a/src/types/rest/index.ts b/src/types/rest/index.ts index 06565e1..853a778 100644 --- a/src/types/rest/index.ts +++ b/src/types/rest/index.ts @@ -19,6 +19,7 @@ export * from './user'; export * from './voice'; export * from './webhook'; export * from './monetization'; +export * from './soundboard'; export type DefaultUserAvatarAssets = 0 | 1 | 2 | 3 | 4 | 5; diff --git a/src/types/rest/soundboard.ts b/src/types/rest/soundboard.ts new file mode 100644 index 0000000..7be6595 --- /dev/null +++ b/src/types/rest/soundboard.ts @@ -0,0 +1,70 @@ +import type { APISoundBoard } from '../payloads/soundboard'; + +/** + * https://discord.com/developers/docs/resources/soundboard#send-soundboard-sound + * @fires VoiceChannelEffectSend + * @requires Permissions Speak and UseSoundboard + * @satisfies VoiceState without deaf, self_deaf, mute, or suppress enabled. + */ +export interface RESTPostAPISendSoundboardSound { + /** the id of the soundboard sound to play */ + sound_id: string; + /** the id of the guild the soundboard sound is from, required to play sounds from different servers */ + source_guild_id?: string; +} + +/** + * https://discord.com/developers/docs/resources/soundboard#list-default-soundboard-sounds + */ +export type RESTGetAPIDefaultsSoundboardSoundsResult = Omit[]; + +/** + * https://discord.com/developers/docs/resources/soundboard#list-guild-soundboard-sounds + */ +export type RESTGetAPIGuildSoundboardSoundsResult = { items: APISoundBoard[] }; + +/** + * https://discord.com/developers/docs/resources/soundboard#create-guild-soundboard-sound + * + * Soundboard sounds have a max file size of 512kb and a max duration of 5.2 seconds. + * This endpoint supports the X-Audit-Log-Reason header. + * @requires Permission CreateGuildExpressions + */ +export interface RESTPostAPIGuildSoundboardSound { + /** name of the soundboard sound (2-32 characters) */ + name: string; + /** the mp3 or ogg sound data, base64 encoded, similar to image data */ + sound: string; + /** the volume of the soundboard sound, from 0 to 1, defaults to 1 */ + volume?: number | null; + /** the id of the custom emoji for the soundboard sound */ + emoji_id?: string | null; + /** the unicode character of a standard emoji for the soundboard sound */ + emoji_name?: string | null; +} + +export type RESTPostAPIGuildSoundboardSoundResult = APISoundBoard; + +/** + * https://discord.com/developers/docs/resources/soundboard#modify-guild-soundboard-sound + * @fires GuildSoundboardSoundUpdate + */ +export interface RESTPatchAPIGuildSoundboardSound { + /** name of the soundboard sound (2-32 characters) */ + name?: string; + /** the volume of the soundboard sound, from 0 to 1, defaults to 1 */ + volume?: number | null; + /** the id of the custom emoji for the soundboard sound */ + emoji_id?: string | null; + /** the unicode character of a standard emoji for the soundboard sound */ + emoji_name?: string | null; +} + +export type RESTPatchAPIGuildSoundboardSoundResult = APISoundBoard; + +/** + * https://discord.com/developers/docs/resources/soundboard#delete-guild-soundboard-sound + * This endpoint supports the X-Audit-Log-Reason header. + * @fires GuildSoundboardSoundDelete + */ +export type RESTDeleteAPIGuildSoundboardSoundResult = never; diff --git a/src/types/utils/index.ts b/src/types/utils/index.ts index 174350e..07bd0f2 100644 --- a/src/types/utils/index.ts +++ b/src/types/utils/index.ts @@ -197,6 +197,10 @@ export enum GatewayOpcodes { * Sent in response to receiving a heartbeat to acknowledge that it has been received */ HeartbeatAck = 11, + /** + * Used to request soundboard sounds for a list of guilds. The server will send Soundboard Sounds events for each guild in response. + */ + RequestSoundboardSounds = 31, } /** @@ -292,9 +296,8 @@ export enum GatewayIntentBits { /** * @deprecated This is the old name for {@apilink GatewayIntentBits#GuildModeration} */ - GuildBans = GuildModeration, - GuildEmojisAndStickers = 1 << 3, + GuildExpressions = 1 << 3, GuildIntegrations = 1 << 4, GuildWebhooks = 1 << 5, GuildInvites = 1 << 6, @@ -380,6 +383,11 @@ export enum GatewayDispatchEvents { GuildScheduledEventDelete = 'GUILD_SCHEDULED_EVENT_DELETE', GuildScheduledEventUserAdd = 'GUILD_SCHEDULED_EVENT_USER_ADD', GuildScheduledEventUserRemove = 'GUILD_SCHEDULED_EVENT_USER_REMOVE', + GuildSoundboardSoundCreate = 'GUILD_SOUNDBOARD_SOUND_CREATE', + GuildSoundboardSoundUpdate = 'GUILD_SOUNDBOARD_SOUND_UPDATE', + GuildSoundboardSoundDelete = 'GUILD_SOUNDBOARD_SOUND_DELETE', + GuildSoundboardSoundsUpdate = 'GUILD_SOUNDBOARD_SOUNDS_UPDATE', + SoundboardSounds = 'SOUNDBOARD_SOUNDS', AutoModerationRuleCreate = 'AUTO_MODERATION_RULE_CREATE', AutoModerationRuleUpdate = 'AUTO_MODERATION_RULE_UPDATE', AutoModerationRuleDelete = 'AUTO_MODERATION_RULE_DELETE', diff --git a/src/websocket/SharedTypes.ts b/src/websocket/SharedTypes.ts index 77452ab..3e71444 100644 --- a/src/websocket/SharedTypes.ts +++ b/src/websocket/SharedTypes.ts @@ -29,6 +29,8 @@ import type { GatewayGuildRoleDeleteDispatchData, GatewayGuildRoleUpdateDispatchData, GatewayGuildScheduledEventUserRemoveDispatchData, + GatewayGuildSoundboardSoundDeleteDispatchData, + GatewayGuildSoundboardSoundsUpdateDispatchData, GatewayGuildStickersUpdateDispatchData, GatewayIntegrationCreateDispatchData, GatewayIntegrationDeleteDispatchData, @@ -49,6 +51,7 @@ import type { GatewayReadyDispatchData, GatewayRequestGuildMembersDataWithQuery, GatewayRequestGuildMembersDataWithUserIds, + GatewaySoundboardSoundsDispatchData, GatewayThreadCreateDispatchData, GatewayThreadDeleteDispatchData, GatewayThreadListSyncDispatchData, @@ -63,6 +66,7 @@ import type { PresenceUpdateStatus, } from '../types'; import { GatewayDispatchEvents } from '../types'; +import type { APISoundBoard } from '../types/payloads/soundboard'; /** https://discord.com/developers/docs/topics/gateway-events#update-presence */ export interface StatusUpdate { @@ -123,6 +127,9 @@ export interface Events { [GatewayDispatchEvents.GuildEmojisUpdate]: GatewayGuildEmojisUpdateDispatchData; [GatewayDispatchEvents.GuildStickersUpdate]: GatewayGuildStickersUpdateDispatchData; [GatewayDispatchEvents.GuildIntegrationsUpdate]: GatewayGuildIntegrationsUpdateDispatchData; + [GatewayDispatchEvents.GuildSoundboardSoundsUpdate]: GatewayGuildSoundboardSoundsUpdateDispatchData; + [GatewayDispatchEvents.GuildSoundboardSoundDelete]: GatewayGuildSoundboardSoundDeleteDispatchData; + [GatewayDispatchEvents.SoundboardSounds]: GatewaySoundboardSoundsDispatchData; [GatewayDispatchEvents.GuildMemberAdd]: GatewayGuildMemberAddDispatchData; [GatewayDispatchEvents.GuildMemberRemove]: GatewayGuildMemberRemoveDispatchData; [GatewayDispatchEvents.GuildMemberUpdate]: GatewayGuildMemberUpdateDispatchData; @@ -225,6 +232,10 @@ export type SubscriptionEvents = RestToKeys< ] >; +export type SoundboardSoundsEvents = RestToKeys< + [APISoundBoard, GatewayDispatchEvents.GuildSoundboardSoundCreate, GatewayDispatchEvents.GuildSoundboardSoundUpdate] +>; + export type NormalizeEvents = Events & AutoModetaractionRuleEvents & ChannelSameEvents & @@ -234,6 +245,9 @@ export type NormalizeEvents = Events & EntitlementEvents & PollVoteSameEvents & StageSameEvents & - SubscriptionEvents & { RAW: GatewayDispatchEvents }; + SubscriptionEvents & + SoundboardSoundsEvents & { + RAW: GatewayDispatchEvents; + }; export type GatewayEvents = { [x in keyof NormalizeEvents]: NormalizeEvents[x] };