diff --git a/packages/discord.js/src/client/websocket/handlers/VOICE_CHANNEL_EFFECT_SEND.js b/packages/discord.js/src/client/websocket/handlers/VOICE_CHANNEL_EFFECT_SEND.js new file mode 100644 index 000000000000..350fdb90647f --- /dev/null +++ b/packages/discord.js/src/client/websocket/handlers/VOICE_CHANNEL_EFFECT_SEND.js @@ -0,0 +1,16 @@ +'use strict'; + +const VoiceChannelEffect = require('../../../structures/VoiceChannelEffect'); +const Events = require('../../../util/Events'); + +module.exports = (client, { d: data }) => { + const guild = client.guilds.cache.get(data.guild_id); + if (!guild) return; + + /** + * Emmited when someone sends an effect, such as an emoji reaction, in a voice channel the client is connected to. + * @event Client#voiceChannelEffectSend + * @param {VoiceChannelEffect} voiceChannelEffect The sent voice channel effect + */ + client.emit(Events.VoiceChannelEffectSend, new VoiceChannelEffect(data, guild)); +}; diff --git a/packages/discord.js/src/client/websocket/handlers/index.js b/packages/discord.js/src/client/websocket/handlers/index.js index e18b0196e1ec..c31962d981aa 100644 --- a/packages/discord.js/src/client/websocket/handlers/index.js +++ b/packages/discord.js/src/client/websocket/handlers/index.js @@ -61,6 +61,7 @@ const handlers = Object.fromEntries([ ['THREAD_UPDATE', require('./THREAD_UPDATE')], ['TYPING_START', require('./TYPING_START')], ['USER_UPDATE', require('./USER_UPDATE')], + ['VOICE_CHANNEL_EFFECT_SEND', require('./VOICE_CHANNEL_EFFECT_SEND')], ['VOICE_SERVER_UPDATE', require('./VOICE_SERVER_UPDATE')], ['VOICE_STATE_UPDATE', require('./VOICE_STATE_UPDATE')], ['WEBHOOKS_UPDATE', require('./WEBHOOKS_UPDATE')], diff --git a/packages/discord.js/src/index.js b/packages/discord.js/src/index.js index 5f3442cd7caa..0650afe3e558 100644 --- a/packages/discord.js/src/index.js +++ b/packages/discord.js/src/index.js @@ -213,6 +213,7 @@ exports.ThreadOnlyChannel = require('./structures/ThreadOnlyChannel'); exports.Typing = require('./structures/Typing'); exports.User = require('./structures/User'); exports.UserContextMenuCommandInteraction = require('./structures/UserContextMenuCommandInteraction'); +exports.VoiceChannelEffect = require('./structures/VoiceChannelEffect'); exports.VoiceChannel = require('./structures/VoiceChannel'); exports.VoiceRegion = require('./structures/VoiceRegion'); exports.VoiceState = require('./structures/VoiceState'); diff --git a/packages/discord.js/src/structures/VoiceChannelEffect.js b/packages/discord.js/src/structures/VoiceChannelEffect.js new file mode 100644 index 000000000000..0aee5459674c --- /dev/null +++ b/packages/discord.js/src/structures/VoiceChannelEffect.js @@ -0,0 +1,58 @@ +'use strict'; + +const { Emoji } = require('./Emoji'); + +/** + * Represents an effect used in a {@link VoiceChannel}. + */ +class VoiceChannelEffect { + constructor(data, guild) { + /** + * The guild where the effect was sent from. + * @type {Guild} + */ + this.guild = guild; + + /** + * The id of the channel the effect was sent in. + * @type {Snowflake} + */ + this.channelId = data.channel_id; + + /** + * The id of the user that sent the effect. + * @type {Snowflake} + */ + this.userId = data.user_id; + + /** + * The emoji of the effect. + * @type {?Emoji} + */ + this.emoji = data.emoji ? new Emoji(guild.client, data.emoji) : null; + + // TODO: Revise after discord-api-types. + /** + * The animation type of the effect. + * @type {?number} + */ + this.animationType = data.animation_type ?? null; + + /** + * The animation id of the effect. + * @type {?number} + */ + this.animationId = data.animation_id ?? null; + } + + /** + * The channel the effect was sent in. + * @type {?VoiceChannel} + * @readonly + */ + get channel() { + return this.guild.channels.resolve(this.channelId); + } +} + +module.exports = VoiceChannelEffect; diff --git a/packages/discord.js/src/util/Events.js b/packages/discord.js/src/util/Events.js index a8ee63f66a56..75436fdaae76 100644 --- a/packages/discord.js/src/util/Events.js +++ b/packages/discord.js/src/util/Events.js @@ -77,6 +77,7 @@ * @property {string} ThreadUpdate threadUpdate * @property {string} TypingStart typingStart * @property {string} UserUpdate userUpdate + * @property {string} VoiceChannelEffectSend voiceChannelEffectSend * @property {string} VoiceServerUpdate voiceServerUpdate * @property {string} VoiceStateUpdate voiceStateUpdate * @property {string} Warn warn @@ -165,6 +166,7 @@ module.exports = { ThreadUpdate: 'threadUpdate', TypingStart: 'typingStart', UserUpdate: 'userUpdate', + VoiceChannelEffectSend: 'voiceChannelEffectSend', VoiceServerUpdate: 'voiceServerUpdate', VoiceStateUpdate: 'voiceStateUpdate', Warn: 'warn', diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 8dd053843780..69a2da3c8d9d 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -3543,6 +3543,19 @@ export class VoiceChannel extends BaseGuildVoiceChannel { public type: ChannelType.GuildVoice; } +export class VoiceChannelEffect { + // TODO: Revise after discord-api-types. + private constructor(data: unknown, guild: Guild); + public guild: Guild; + public channelId: Snowflake; + public userId: Snowflake; + public emoji: Emoji | null; + // TODO: Revise after discord-api-types. + public animationType: 0 | 1 | null; + public animationId: number | null; + public get channel(): VoiceChannel | null; +} + export class VoiceRegion { private constructor(data: RawVoiceRegionData); public custom: boolean; @@ -5256,6 +5269,7 @@ export interface ClientEvents { threadUpdate: [oldThread: AnyThreadChannel, newThread: AnyThreadChannel]; typingStart: [typing: Typing]; userUpdate: [oldUser: User | PartialUser, newUser: User]; + voiceChannelEffectSend: [voiceChannelEffect: VoiceChannelEffect]; voiceStateUpdate: [oldState: VoiceState, newState: VoiceState]; /** @deprecated Use {@link ClientEvents.webhooksUpdate} instead. */ webhookUpdate: ClientEvents['webhooksUpdate']; @@ -5466,6 +5480,7 @@ export enum Events { ThreadMembersUpdate = 'threadMembersUpdate', UserUpdate = 'userUpdate', PresenceUpdate = 'presenceUpdate', + VoiceChannelEffectSend = 'voiceChannelEffectSend', VoiceServerUpdate = 'voiceServerUpdate', VoiceStateUpdate = 'voiceStateUpdate', TypingStart = 'typingStart',