From 15f95626c613663a4d8caa97301f5c01fbb5cc14 Mon Sep 17 00:00:00 2001 From: March 7th <71698422+aiko-chan-ai@users.noreply.github.com> Date: Fri, 19 Aug 2022 18:16:11 +0700 Subject: [PATCH] feat(GroupDM): Add `setOwner`, handle event update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Nguyễn Hồng Đức --- src/client/websocket/handlers/READY.js | 18 ---- src/managers/ChannelManager.js | 17 ++-- src/structures/PartialGroupDMChannel.js | 106 ++++++++++++++++++------ typings/index.d.ts | 8 +- 4 files changed, 90 insertions(+), 59 deletions(-) diff --git a/src/client/websocket/handlers/READY.js b/src/client/websocket/handlers/READY.js index 6e47a57..3c7726a 100644 --- a/src/client/websocket/handlers/READY.js +++ b/src/client/websocket/handlers/READY.js @@ -135,29 +135,11 @@ module.exports = (client, { d: data }, shard) => { `Gateway Rate Limit Warning: Sending ${data.private_channels.length} Requests / ${Date.now() - syncTime || 1} ms`, ); } - // Remove event because memory leak if (client.options.readyStatus && !running) { client.customStatusAuto(client); } - /** - * Read_state: Return Array: - * { - * mention_count: 14, // ok it's ping count - * last_pin_timestamp: '1970-01-01T00:00:00+00:00', // why discord ? - * last_message_id: 0, // :) - * id: '840218426969817119' // channel id - * }, - */ - - /* - for (const object of data.read_state) { - if (object.mention_count == 0) continue; - client.user.messageMentions.set(object.id, object); - } - */ - for (const guild of data.guilds) { guild.shardId = shard.id; client.guilds._add(guild); diff --git a/src/managers/ChannelManager.js b/src/managers/ChannelManager.js index d7484d8..50d87a9 100644 --- a/src/managers/ChannelManager.js +++ b/src/managers/ChannelManager.js @@ -3,9 +3,7 @@ const process = require('node:process'); const CachedManager = require('./CachedManager'); const { Channel } = require('../structures/Channel'); -// Not used: const PartialGroupDMChannel = require('../structures/PartialGroupDMChannel'); -const User = require('../structures/User'); -const { Events, ThreadChannelTypes } = require('../util/Constants'); +const { Events, ThreadChannelTypes, RelationshipTypes } = require('../util/Constants'); let cacheWarningEmitted = false; @@ -119,19 +117,20 @@ class ChannelManager extends CachedManager { this._remove(id); return this._add(data, null, { cache, allowUnknownGuild }); } - // Create Group DM /** * Create Group DM - * @param {Array} recipients Array of recipients - * @returns {PartialGroupDMChannel} Channel + * @param {UserResolvable[]} recipients Array of recipients + * @returns {Promise} Channel */ async createGroupDM(recipients) { // Check - if (!recipients || !Array.isArray(recipients)) throw new Error('No recipients || Invalid Type (Array)'); - recipients = recipients.filter(r => r instanceof User && r.id && r.friend); + if (!Array.isArray(recipients)) throw new Error(`Expected an array of recipients (got ${typeof recipients})`); + recipients = recipients + .map(r => this.client.users.resolveId(r)) + .filter(r => r && this.client.relationships.cache.get(r) == RelationshipTypes.FRIEND); if (recipients.length < 2 || recipients.length > 9) throw new Error('Invalid Users length (2 - 9)'); const data = await this.client.api.users['@me'].channels.post({ - data: { recipients: recipients.map(r => r.id) }, + data: { recipients }, }); return this._add(data, null, { cache: true, allowUnknownGuild: true }); } diff --git a/src/structures/PartialGroupDMChannel.js b/src/structures/PartialGroupDMChannel.js index 2eb1c96..59a63cf 100644 --- a/src/structures/PartialGroupDMChannel.js +++ b/src/structures/PartialGroupDMChannel.js @@ -21,25 +21,19 @@ class PartialGroupDMChannel extends Channel { * The name of this Group DM Channel * @type {?string} */ - this.name = data.name; + this.name = null; /** * The hash of the channel icon * @type {?string} */ - this.icon = data.icon; - - /** - * Recipient data received in a {@link PartialGroupDMChannel}. - * @typedef {Object} PartialRecipient - * @property {string} username The username of the recipient - */ + this.icon = null; /** * The recipients of this Group DM Channel. - * @type {PartialRecipient[]} + * @type {Collection} */ - this.recipients = new Collection(); + this.recipients = null; /** * Messages data @@ -49,7 +43,7 @@ class PartialGroupDMChannel extends Channel { /** * Last Message ID - * @type {?snowflake} + * @type {?Snowflake} */ this.lastMessageId = null; @@ -60,12 +54,10 @@ class PartialGroupDMChannel extends Channel { this.lastPinTimestamp = null; /** - * The owner of this Group DM Channel - * @type {?User} - * @readonly + * Owner ID + * @type {?Snowflake} */ - this.owner = client.users.cache.get(data.owner_id); - this.ownerId = data.owner_id; + this.ownerId = null; /** * Invites fetch @@ -73,22 +65,28 @@ class PartialGroupDMChannel extends Channel { */ this.invites = new Collection(); - this._setup(client, data); + this._patch(data); + } + + /** + * The owner of this Group DM Channel + * @type {?User} + * @readonly + */ + get owner() { + return this.client.users.cache.get(this.ownerId); } /** * - * @param {Discord.Client} client Discord Bot Client * @param {Object} data Channel Data * @private */ - _setup(client, data) { + _patch(data) { + super._patch(data); if ('recipients' in data) { - Promise.all( - data.recipients.map(recipient => - this.recipients.set(recipient.id, client.users.cache.get(data.owner_id) || recipient), - ), - ); + this.recipients = new Collection(); + data.recipients.map(recipient => this.recipients.set(recipient.id, this.client.users._add(recipient))); } if ('last_pin_timestamp' in data) { const date = new Date(data.last_pin_timestamp); @@ -97,12 +95,21 @@ class PartialGroupDMChannel extends Channel { if ('last_message_id' in data) { this.lastMessageId = data.last_message_id; } + if ('owner_id' in data) { + this.ownerId = data.owner_id; + } + if ('name' in data) { + this.name = data.name; + } + if ('icon' in data) { + this.icon = data.icon; + } } /** - * - * @param {Object} data name, icon - * @returns {any} any data .-. + * Edit channel data + * @param {Object} data name, icon owner + * @returns {Promise} * @private */ async edit(data) { @@ -111,6 +118,9 @@ class PartialGroupDMChannel extends Channel { if (typeof data.icon !== 'undefined') { _data.icon = await DataResolver.resolveImage(data.icon); } + if ('owner' in data) { + _data.owner = data.owner; + } const newData = await this.client.api.channels(this.id).patch({ data: _data, }); @@ -180,6 +190,25 @@ class PartialGroupDMChannel extends Channel { return this.edit({ icon }); } + /** + * Changes the owner of this Group DM Channel. + * @param {UserResolvable} user User to transfer ownership to + * @returns {Promise} + */ + setOwner(user) { + const id = this.client.users.resolveId(user); + if (!id) { + throw new TypeError('User is not a User or User ID'); + } + if (this.ownerId !== this.client.user.id) { + throw new Error('NOT_OWNER_GROUP_DM_CHANNEL'); + } + if (this.ownerId === id) { + return this; + } + return this.edit({ owner: id }); + } + /** * Gets the invite for this Group DM Channel. * @returns {Promise} @@ -227,6 +256,29 @@ class PartialGroupDMChannel extends Channel { return this; } + /** + * Leave this Group DM Channel. + * @param {?boolean} slient Leave without notifying other members + * @returns {Promise} + * @example + * // Delete the channel + * channel.delete() + * .then(console.log) + * .catch(console.error); + */ + async delete(slient = false) { + if (typeof slient === 'boolean' && slient) { + await this.client.api.channels(this.id).delete({ + query: { + silent: true, + }, + }); + } else { + await this.client.api.channels(this.id).delete(); + } + return this; + } + // These are here only for documentation purposes - they are implemented by TextBasedChannel /* eslint-disable no-empty-function */ get lastMessage() {} diff --git a/typings/index.d.ts b/typings/index.d.ts index 5cd781f..9883dfd 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -2341,6 +2341,8 @@ export class PartialGroupDMChannel extends TextBasedChannelMixin(Channel, [ public getInvite(): Promise; public fetchInvite(force: boolean): Promise; public removeInvite(invite: Invite): Promise; + public delete(slient?: boolean): Promise; + public setOwner(user: UserResolvable): Promise; public readonly voiceAdapterCreator: InternalDiscordGatewayAdapterCreator; public call(options?: object): Promise; public sync(): undefined; @@ -3553,7 +3555,7 @@ export class BaseGuildEmojiManager extends CachedManager { private constructor(client: Client, iterable: Iterable); public fetch(id: Snowflake, options?: FetchChannelOptions): Promise; - public createGroupDM(recipients: User[]): Promise; + public createGroupDM(recipients: UserResolvable[]): Promise; } export type FetchGuildApplicationCommandFetchOptions = Omit; @@ -6214,10 +6216,6 @@ export type RecursiveArray = ReadonlyArray>; export type RecursiveReadonlyArray = ReadonlyArray>; -export interface PartialRecipient { - username: string; -} - export type PremiumTier = keyof typeof PremiumTiers; export interface PresenceData {