feat(GroupDM): Add setOwner, handle event update

Co-Authored-By: Nguyễn Hồng Đức <hongducyb123@gmail.com>
This commit is contained in:
March 7th 2022-08-19 18:16:11 +07:00
parent e4567e9caf
commit 15f95626c6
4 changed files with 90 additions and 59 deletions

View File

@ -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`, `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) { if (client.options.readyStatus && !running) {
client.customStatusAuto(client); 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) { for (const guild of data.guilds) {
guild.shardId = shard.id; guild.shardId = shard.id;
client.guilds._add(guild); client.guilds._add(guild);

View File

@ -3,9 +3,7 @@
const process = require('node:process'); const process = require('node:process');
const CachedManager = require('./CachedManager'); const CachedManager = require('./CachedManager');
const { Channel } = require('../structures/Channel'); const { Channel } = require('../structures/Channel');
// Not used: const PartialGroupDMChannel = require('../structures/PartialGroupDMChannel'); const { Events, ThreadChannelTypes, RelationshipTypes } = require('../util/Constants');
const User = require('../structures/User');
const { Events, ThreadChannelTypes } = require('../util/Constants');
let cacheWarningEmitted = false; let cacheWarningEmitted = false;
@ -119,19 +117,20 @@ class ChannelManager extends CachedManager {
this._remove(id); this._remove(id);
return this._add(data, null, { cache, allowUnknownGuild }); return this._add(data, null, { cache, allowUnknownGuild });
} }
// Create Group DM
/** /**
* Create Group DM * Create Group DM
* @param {Array<Discord.User>} recipients Array of recipients * @param {UserResolvable[]} recipients Array of recipients
* @returns {PartialGroupDMChannel} Channel * @returns {Promise<PartialGroupDMChannel>} Channel
*/ */
async createGroupDM(recipients) { async createGroupDM(recipients) {
// Check // Check
if (!recipients || !Array.isArray(recipients)) throw new Error('No recipients || Invalid Type (Array)'); if (!Array.isArray(recipients)) throw new Error(`Expected an array of recipients (got ${typeof recipients})`);
recipients = recipients.filter(r => r instanceof User && r.id && r.friend); 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)'); 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({ 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 }); return this._add(data, null, { cache: true, allowUnknownGuild: true });
} }

View File

@ -21,25 +21,19 @@ class PartialGroupDMChannel extends Channel {
* The name of this Group DM Channel * The name of this Group DM Channel
* @type {?string} * @type {?string}
*/ */
this.name = data.name; this.name = null;
/** /**
* The hash of the channel icon * The hash of the channel icon
* @type {?string} * @type {?string}
*/ */
this.icon = data.icon; this.icon = null;
/**
* Recipient data received in a {@link PartialGroupDMChannel}.
* @typedef {Object} PartialRecipient
* @property {string} username The username of the recipient
*/
/** /**
* The recipients of this Group DM Channel. * The recipients of this Group DM Channel.
* @type {PartialRecipient[]} * @type {Collection<Snowflake, User>}
*/ */
this.recipients = new Collection(); this.recipients = null;
/** /**
* Messages data * Messages data
@ -49,7 +43,7 @@ class PartialGroupDMChannel extends Channel {
/** /**
* Last Message ID * Last Message ID
* @type {?snowflake<Message.id>} * @type {?Snowflake}
*/ */
this.lastMessageId = null; this.lastMessageId = null;
@ -60,12 +54,10 @@ class PartialGroupDMChannel extends Channel {
this.lastPinTimestamp = null; this.lastPinTimestamp = null;
/** /**
* The owner of this Group DM Channel * Owner ID
* @type {?User} * @type {?Snowflake}
* @readonly
*/ */
this.owner = client.users.cache.get(data.owner_id); this.ownerId = null;
this.ownerId = data.owner_id;
/** /**
* Invites fetch * Invites fetch
@ -73,22 +65,28 @@ class PartialGroupDMChannel extends Channel {
*/ */
this.invites = new Collection(); 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 * @param {Object} data Channel Data
* @private * @private
*/ */
_setup(client, data) { _patch(data) {
super._patch(data);
if ('recipients' in data) { if ('recipients' in data) {
Promise.all( this.recipients = new Collection();
data.recipients.map(recipient => data.recipients.map(recipient => this.recipients.set(recipient.id, this.client.users._add(recipient)));
this.recipients.set(recipient.id, client.users.cache.get(data.owner_id) || recipient),
),
);
} }
if ('last_pin_timestamp' in data) { if ('last_pin_timestamp' in data) {
const date = new Date(data.last_pin_timestamp); const date = new Date(data.last_pin_timestamp);
@ -97,12 +95,21 @@ class PartialGroupDMChannel extends Channel {
if ('last_message_id' in data) { if ('last_message_id' in data) {
this.lastMessageId = data.last_message_id; 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;
}
} }
/** /**
* * Edit channel data
* @param {Object} data name, icon * @param {Object} data name, icon owner
* @returns {any} any data .-. * @returns {Promise<undefined>}
* @private * @private
*/ */
async edit(data) { async edit(data) {
@ -111,6 +118,9 @@ class PartialGroupDMChannel extends Channel {
if (typeof data.icon !== 'undefined') { if (typeof data.icon !== 'undefined') {
_data.icon = await DataResolver.resolveImage(data.icon); _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({ const newData = await this.client.api.channels(this.id).patch({
data: _data, data: _data,
}); });
@ -180,6 +190,25 @@ class PartialGroupDMChannel extends Channel {
return this.edit({ icon }); return this.edit({ icon });
} }
/**
* Changes the owner of this Group DM Channel.
* @param {UserResolvable} user User to transfer ownership to
* @returns {Promise<PartialGroupDMChannel>}
*/
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. * Gets the invite for this Group DM Channel.
* @returns {Promise<Invite>} * @returns {Promise<Invite>}
@ -227,6 +256,29 @@ class PartialGroupDMChannel extends Channel {
return this; return this;
} }
/**
* Leave this Group DM Channel.
* @param {?boolean} slient Leave without notifying other members
* @returns {Promise<Channel>}
* @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 // These are here only for documentation purposes - they are implemented by TextBasedChannel
/* eslint-disable no-empty-function */ /* eslint-disable no-empty-function */
get lastMessage() {} get lastMessage() {}

8
typings/index.d.ts vendored
View File

@ -2341,6 +2341,8 @@ export class PartialGroupDMChannel extends TextBasedChannelMixin(Channel, [
public getInvite(): Promise<Invite>; public getInvite(): Promise<Invite>;
public fetchInvite(force: boolean): Promise<Invite>; public fetchInvite(force: boolean): Promise<Invite>;
public removeInvite(invite: Invite): Promise<PartialGroupDMChannel>; public removeInvite(invite: Invite): Promise<PartialGroupDMChannel>;
public delete(slient?: boolean): Promise<this>;
public setOwner(user: UserResolvable): Promise<PartialGroupDMChannel>;
public readonly voiceAdapterCreator: InternalDiscordGatewayAdapterCreator; public readonly voiceAdapterCreator: InternalDiscordGatewayAdapterCreator;
public call(options?: object): Promise<VoiceConnection>; public call(options?: object): Promise<VoiceConnection>;
public sync(): undefined; public sync(): undefined;
@ -3553,7 +3555,7 @@ export class BaseGuildEmojiManager extends CachedManager<Snowflake, GuildEmoji,
export class ChannelManager extends CachedManager<Snowflake, AnyChannel, ChannelResolvable> { export class ChannelManager extends CachedManager<Snowflake, AnyChannel, ChannelResolvable> {
private constructor(client: Client, iterable: Iterable<RawChannelData>); private constructor(client: Client, iterable: Iterable<RawChannelData>);
public fetch(id: Snowflake, options?: FetchChannelOptions): Promise<AnyChannel | null>; public fetch(id: Snowflake, options?: FetchChannelOptions): Promise<AnyChannel | null>;
public createGroupDM(recipients: User[]): Promise<PartialGroupDMChannel>; public createGroupDM(recipients: UserResolvable[]): Promise<PartialGroupDMChannel>;
} }
export type FetchGuildApplicationCommandFetchOptions = Omit<FetchApplicationCommandOptions, 'guildId'>; export type FetchGuildApplicationCommandFetchOptions = Omit<FetchApplicationCommandOptions, 'guildId'>;
@ -6214,10 +6216,6 @@ export type RecursiveArray<T> = ReadonlyArray<T | RecursiveArray<T>>;
export type RecursiveReadonlyArray<T> = ReadonlyArray<T | RecursiveReadonlyArray<T>>; export type RecursiveReadonlyArray<T> = ReadonlyArray<T | RecursiveReadonlyArray<T>>;
export interface PartialRecipient {
username: string;
}
export type PremiumTier = keyof typeof PremiumTiers; export type PremiumTier = keyof typeof PremiumTiers;
export interface PresenceData { export interface PresenceData {