From 6775175459338ab1c3299a3dc3f49797cf2b7049 Mon Sep 17 00:00:00 2001 From: Jiralite <33201955+Jiralite@users.noreply.github.com> Date: Thu, 14 Nov 2024 21:00:04 +0000 Subject: [PATCH] feat: Voice Channel Effect Send (#10318) * feat: Voice Channel Send Effects (#9288) * feat: add soundboard fields * chore: address TODO * docs: volume is a closed interval * types: use `GatewayVoiceChannelEffectSendDispatchData` * refactor: prefer getting from cache * fix: correctly access cache Co-authored-by: Danial Raza --------- Co-authored-by: Danial Raza --- .../handlers/VOICE_CHANNEL_EFFECT_SEND.js | 16 +++++ .../src/client/websocket/handlers/index.js | 1 + packages/discord.js/src/index.js | 1 + .../src/structures/VoiceChannelEffect.js | 69 +++++++++++++++++++ packages/discord.js/src/util/APITypes.js | 5 ++ packages/discord.js/src/util/Events.js | 2 + packages/discord.js/typings/index.d.ts | 17 +++++ 7 files changed, 111 insertions(+) create mode 100644 packages/discord.js/src/client/websocket/handlers/VOICE_CHANNEL_EFFECT_SEND.js create mode 100644 packages/discord.js/src/structures/VoiceChannelEffect.js 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 000000000..350fdb906 --- /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 4af0714a1..24c3f86a4 100644 --- a/packages/discord.js/src/client/websocket/handlers/index.js +++ b/packages/discord.js/src/client/websocket/handlers/index.js @@ -60,6 +60,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 cdedc8aa4..7c5c17cd6 100644 --- a/packages/discord.js/src/index.js +++ b/packages/discord.js/src/index.js @@ -206,6 +206,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 000000000..ee42ea6f7 --- /dev/null +++ b/packages/discord.js/src/structures/VoiceChannelEffect.js @@ -0,0 +1,69 @@ +'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; + + /** + * The animation type of the effect. + * @type {?VoiceChannelEffectSendAnimationType} + */ + this.animationType = data.animation_type ?? null; + + /** + * The animation id of the effect. + * @type {?number} + */ + this.animationId = data.animation_id ?? null; + + /** + * The id of the soundboard sound for soundboard effects. + * @type {?(Snowflake|number)} + */ + this.soundId = data.sound_id ?? null; + + /** + * The volume of the soundboard sound [0-1] for soundboard effects. + * @type {?number} + */ + this.soundVolume = data.sound_volume ?? null; + } + + /** + * The channel the effect was sent in. + * @type {?VoiceChannel} + * @readonly + */ + get channel() { + return this.guild.channels.cache.get(this.channelId) ?? null; + } +} + +module.exports = VoiceChannelEffect; diff --git a/packages/discord.js/src/util/APITypes.js b/packages/discord.js/src/util/APITypes.js index 8737623d6..0032dd436 100644 --- a/packages/discord.js/src/util/APITypes.js +++ b/packages/discord.js/src/util/APITypes.js @@ -589,6 +589,11 @@ * @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/VideoQualityMode} */ +/** + * @external VoiceChannelEffectSendAnimationType + * @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/VoiceChannelEffectSendAnimationType} + */ + /** * @external WebhookType * @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/WebhookType} diff --git a/packages/discord.js/src/util/Events.js b/packages/discord.js/src/util/Events.js index 1ab65a13d..a4b658e5c 100644 --- a/packages/discord.js/src/util/Events.js +++ b/packages/discord.js/src/util/Events.js @@ -72,6 +72,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 @@ -154,6 +155,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 afb73b20a..dc2aac43f 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -166,6 +166,8 @@ import { GuildScheduledEventRecurrenceRuleFrequency, GatewaySendPayload, GatewayDispatchPayload, + VoiceChannelEffectSendAnimationType, + GatewayVoiceChannelEffectSendDispatchData, } from 'discord-api-types/v10'; import { ChildProcess } from 'node:child_process'; import { EventEmitter } from 'node:events'; @@ -3557,6 +3559,19 @@ export class VoiceChannel extends BaseGuildVoiceChannel { public type: ChannelType.GuildVoice; } +export class VoiceChannelEffect { + private constructor(data: GatewayVoiceChannelEffectSendDispatchData, guild: Guild); + public guild: Guild; + public channelId: Snowflake; + public userId: Snowflake; + public emoji: Emoji | null; + public animationType: VoiceChannelEffectSendAnimationType | null; + public animationId: number | null; + public soundId: Snowflake | number | null; + public soundVolume: number | null; + public get channel(): VoiceChannel | null; +} + export class VoiceRegion { private constructor(data: RawVoiceRegionData); public custom: boolean; @@ -5163,6 +5178,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]; webhooksUpdate: [channel: TextChannel | AnnouncementChannel | VoiceChannel | ForumChannel | MediaChannel]; interactionCreate: [interaction: Interaction]; @@ -5357,6 +5373,7 @@ export enum Events { ThreadMembersUpdate = 'threadMembersUpdate', UserUpdate = 'userUpdate', PresenceUpdate = 'presenceUpdate', + VoiceChannelEffectSend = 'voiceChannelEffectSend', VoiceServerUpdate = 'voiceServerUpdate', VoiceStateUpdate = 'voiceStateUpdate', TypingStart = 'typingStart',