From ee906b544e46227e56fc0f72e98ce97d49e91514 Mon Sep 17 00:00:00 2001 From: Elysia <71698422+aiko-chan-ai@users.noreply.github.com> Date: Sun, 5 Mar 2023 17:05:40 +0700 Subject: [PATCH] feat: new class `Call` --- src/client/websocket/handlers/CALL_CREATE.js | 7 ++- src/client/websocket/handlers/CALL_DELETE.js | 5 +- src/client/websocket/handlers/CALL_UPDATE.js | 7 ++- src/structures/Call.js | 56 ++++++++++++++++++++ src/structures/ClientUser.js | 13 +++++ src/structures/User.js | 2 +- typings/index.d.ts | 19 +++++-- 7 files changed, 94 insertions(+), 15 deletions(-) create mode 100644 src/structures/Call.js diff --git a/src/client/websocket/handlers/CALL_CREATE.js b/src/client/websocket/handlers/CALL_CREATE.js index ee74260..4ff9c01 100644 --- a/src/client/websocket/handlers/CALL_CREATE.js +++ b/src/client/websocket/handlers/CALL_CREATE.js @@ -1,4 +1,5 @@ 'use strict'; +const Call = require('../../../structures/Call'); const { Events } = require('../../../util/Constants'); module.exports = (client, packet) => { for (const voice of packet.d.voice_states) { @@ -7,9 +8,7 @@ module.exports = (client, packet) => { /** * Emitted whenever received a call * @event Client#callCreate - * @param {Snowflake} channelId DM / Group DM channel ID - * @param {string} region Voice server region - * @param {?Snowflake[]} ringing List of user ID who is ringing + * @param {Call} call Call */ - client.emit(Events.CALL_CREATE, packet.d.channel_id, packet.d.region, packet.d.ringing); + client.emit(Events.CALL_CREATE, new Call(client, packet.d)); }; diff --git a/src/client/websocket/handlers/CALL_DELETE.js b/src/client/websocket/handlers/CALL_DELETE.js index e1599a3..996b97b 100644 --- a/src/client/websocket/handlers/CALL_DELETE.js +++ b/src/client/websocket/handlers/CALL_DELETE.js @@ -1,10 +1,11 @@ 'use strict'; +const Call = require('../../../structures/Call'); const { Events } = require('../../../util/Constants'); module.exports = (client, packet) => { /** * Emitted whenever delete a call * @event Client#callDelete - * @param {Snowflake} channelId DM / Group DM channel ID + * @param {Call} call Call */ - client.emit(Events.CALL_DELETE, packet.d.channel_id); + client.emit(Events.CALL_DELETE, new Call(client, packet.d)); }; diff --git a/src/client/websocket/handlers/CALL_UPDATE.js b/src/client/websocket/handlers/CALL_UPDATE.js index 6078587..377527e 100644 --- a/src/client/websocket/handlers/CALL_UPDATE.js +++ b/src/client/websocket/handlers/CALL_UPDATE.js @@ -1,12 +1,11 @@ 'use strict'; +const Call = require('../../../structures/Call'); const { Events } = require('../../../util/Constants'); module.exports = (client, packet) => { /** * Emitted whenever update a call * @event Client#callUpdate - * @param {Snowflake} channelId DM / Group DM channel ID - * @param {string} region Voice server region - * @param {?Snowflake[]} ringing List of user ID who is ringing + * @param {Call} call Call */ - client.emit(Events.CALL_UPDATE, packet.d.channel_id, packet.d.region, packet.d.ringing); + client.emit(Events.CALL_UPDATE, new Call(client, packet.d)); }; diff --git a/src/structures/Call.js b/src/structures/Call.js new file mode 100644 index 00000000..b7a389e --- /dev/null +++ b/src/structures/Call.js @@ -0,0 +1,56 @@ +'use strict'; + +const { Collection } = require('@discordjs/collection'); +const Base = require('./Base'); + +/** + * Represents a call + * @extends {Base} + */ +class Call extends Base { + constructor(client, data) { + super(client); + /** + * The channel ID of the call + * @type {Snowflake} + */ + this.channelId = data.channel_id; + + /** + * The list of user ID who is ringing + * @type {Collection} + */ + this.ringing = new Collection(); + } + _patch(data) { + if ('region' in data) { + /** + * The region of the call + * @type {string} + */ + this.region = data.region; + } + if ('ringing' in data) { + for (const userId of data.ringing) { + this.ringing.set(userId, this.client.users.cache.get(userId)); + } + } + } + /** + * The channel of the call + * @type {?DMChannel|PartialGroupDMChannel} + */ + get channel() { + return this.client.channels.cache.get(this.channelId); + } + /** + * Sets the voice region of the call + * @param {string} region Region of the call + * @returns {Promise} + */ + setVoiceRegion(region) { + return this.client.api.channels(this.channelId).call.patch({ data: { region } }); + } +} + +module.exports = Call; diff --git a/src/structures/ClientUser.js b/src/structures/ClientUser.js index 7e46326..e74589e 100644 --- a/src/structures/ClientUser.js +++ b/src/structures/ClientUser.js @@ -563,6 +563,19 @@ class ClientUser extends User { else this._packageName = null; return this; } + + /** + * Stop ringing + * @param {ChannelResolvable} channel DMChannel | GroupDMChannel + * @returns {Promise} + */ + stopRinging(channel) { + const id = this.client.channels.resolveId(channel); + if (!channel) return false; + return this.client.api.channels(id).call['stop-ringing'].post({ + data: {}, + }); + } } module.exports = ClientUser; diff --git a/src/structures/User.js b/src/structures/User.js index 1406134..a6fd582 100644 --- a/src/structures/User.js +++ b/src/structures/User.js @@ -471,7 +471,7 @@ class User extends Base { * @returns {Promise} */ ring() { - if (!this.dmChannel?.id) return Promise.reject(new Error('USER_NO_DM_CHANNEL')); + if (this.relationships !== 'FRIEND') return Promise.reject(new Error('USER_NOT_FRIEND')); if (!this.client.user.voice?.channelId || !this.client.callVoice) { return Promise.reject(new Error('CLIENT_NO_CALL')); } diff --git a/typings/index.d.ts b/typings/index.d.ts index 572aa6c..27a5f02 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -249,6 +249,15 @@ export class DiscordRPCServer extends EventEmitter { public on(event: 'activity', listener: (data: RPCActivityData) => void): this; } +export class Call extends Base { + constructor(client: Client, data: object); + public channelId: Snowflake; + public ringing: Collection; + public region?: string; + public readonly channel: PartialDMChannel | PartialGroupDMChannel; + public setVoiceRegion(region: string): Promise; +} + export interface RPCActivityData { activity?: RichPresence; pid: number; @@ -1064,6 +1073,7 @@ export class ClientUser extends User { public readonly phoneNumber: string; public readonly nsfwAllowed: boolean; public readonly emailAddress: string; + public stopRinging(channel: ChannelResolvable): Promise; } type NitroType = 'NONE' | 'NITRO_CLASSIC' | 'NITRO_BOOST' | 'NITRO_BASIC'; @@ -4708,9 +4718,9 @@ export interface ClientEvents extends BaseClientEvents { emojiDelete: [emoji: GuildEmoji]; emojiUpdate: [oldEmoji: GuildEmoji, newEmoji: GuildEmoji]; error: [error: Error]; - callCreate: [channelId: Snowflake, region: string, ringing?: Snowflake[]]; - callDelete: [channelId: Snowflake]; - callUpdate: [channelId: Snowflake, region: string, ringing?: Snowflake[]]; + callCreate: [call: Call]; + callDelete: [call: Call]; + callUpdate: [call: Call]; guildBanAdd: [ban: GuildBan]; guildBanRemove: [ban: GuildBan]; guildCreate: [guild: Guild]; @@ -7271,7 +7281,8 @@ export type AnyChannel = | TextChannel | ThreadChannel | VoiceChannel - | ForumChannel; + | ForumChannel + | PartialGroupDMChannel; export type TextBasedChannel = Exclude< Extract,