From 5e66f85f55724a583921252b035eb2097345fec8 Mon Sep 17 00:00:00 2001 From: Naiyar <137700126+imnaiyar@users.noreply.github.com> Date: Tue, 14 Jan 2025 15:22:14 +0600 Subject: [PATCH] feat(PartialGroupDMChannel): add missing properties (#10502) * fix(PartialGroupDMChannel): add missing ownerId property * refactor: make ownerID nullable * feat: add last_message_id & last_pin_timestamp prop * feat: add component collector methods * fix: handle null case Co-authored-by: Vlad Frangu --------- Co-authored-by: Vlad Frangu Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- packages/discord.js/src/errors/Messages.js | 3 +- .../src/structures/PartialGroupDMChannel.js | 64 +++++++++++++++++++ packages/discord.js/typings/index.d.ts | 22 +++++-- 3 files changed, 84 insertions(+), 5 deletions(-) diff --git a/packages/discord.js/src/errors/Messages.js b/packages/discord.js/src/errors/Messages.js index 234718c50..c61ce7d3f 100644 --- a/packages/discord.js/src/errors/Messages.js +++ b/packages/discord.js/src/errors/Messages.js @@ -95,7 +95,8 @@ const Messages = { [DjsErrorCodes.ChannelNotCached]: 'Could not find the channel where this message came from in the cache!', [DjsErrorCodes.StageChannelResolve]: 'Could not resolve channel to a stage channel.', [DjsErrorCodes.GuildScheduledEventResolve]: 'Could not resolve the guild scheduled event.', - [DjsErrorCodes.FetchOwnerId]: type => `Couldn't resolve the ${type} ownerId to fetch the ${type} member.`, + [DjsErrorCodes.FetchOwnerId]: type => + `Couldn't resolve the ${type} ownerId to fetch the ${type} ${type === 'group DM' ? 'owner' : 'member'}.`, [DjsErrorCodes.InvalidType]: (name, expected, an = false) => `Supplied ${name} is not a${an ? 'n' : ''} ${expected}.`, [DjsErrorCodes.InvalidElement]: (type, name, elem) => `Supplied ${type} ${name} includes an invalid element: ${elem}`, diff --git a/packages/discord.js/src/structures/PartialGroupDMChannel.js b/packages/discord.js/src/structures/PartialGroupDMChannel.js index 704c86557..144c2091b 100644 --- a/packages/discord.js/src/structures/PartialGroupDMChannel.js +++ b/packages/discord.js/src/structures/PartialGroupDMChannel.js @@ -1,12 +1,14 @@ 'use strict'; const { BaseChannel } = require('./BaseChannel'); +const TextBasedChannel = require('./interfaces/TextBasedChannel'); const { DiscordjsError, ErrorCodes } = require('../errors'); const PartialGroupDMMessageManager = require('../managers/PartialGroupDMMessageManager'); /** * Represents a Partial Group DM Channel on Discord. * @extends {BaseChannel} + * @implements {TextBasedChannel} */ class PartialGroupDMChannel extends BaseChannel { constructor(client, data) { @@ -44,6 +46,36 @@ class PartialGroupDMChannel extends BaseChannel { * @type {PartialGroupDMMessageManager} */ this.messages = new PartialGroupDMMessageManager(this); + + if ('owner_id' in data) { + /** + * The user id of the owner of this Group DM Channel + * @type {?Snowflake} + */ + this.ownerId = data.owner_id; + } else { + this.ownerId ??= null; + } + + if ('last_message_id' in data) { + /** + * The channel's last message id, if one was sent + * @type {?Snowflake} + */ + this.lastMessageId = data.last_message_id; + } else { + this.lastMessageId ??= null; + } + + if ('last_pin_timestamp' in data) { + /** + * The timestamp when the last pinned message was pinned, if there was one + * @type {?number} + */ + this.lastPinTimestamp = data.last_pin_timestamp ? Date.parse(data.last_pin_timestamp) : null; + } else { + this.lastPinTimestamp ??= null; + } } /** @@ -55,6 +87,19 @@ class PartialGroupDMChannel extends BaseChannel { return this.icon && this.client.rest.cdn.channelIcon(this.id, this.icon, options); } + /** + * Fetches the owner of this Group DM Channel. + * @param {BaseFetchOptions} [options] The options for fetching the user + * @returns {Promise} + */ + async fetchOwner(options) { + if (!this.ownerId) { + throw new DiscordjsError(ErrorCodes.FetchOwnerId, 'group DM'); + } + + return this.client.users.fetch(this.ownerId, options); + } + delete() { return Promise.reject(new DiscordjsError(ErrorCodes.DeleteGroupDMChannel)); } @@ -62,6 +107,25 @@ class PartialGroupDMChannel extends BaseChannel { fetch() { return Promise.reject(new DiscordjsError(ErrorCodes.FetchGroupDMChannel)); } + + // These are here only for documentation purposes - they are implemented by TextBasedChannel + /* eslint-disable no-empty-function */ + get lastMessage() {} + get lastPinAt() {} + createMessageComponentCollector() {} + awaitMessageComponent() {} } +TextBasedChannel.applyToClass(PartialGroupDMChannel, true, [ + 'bulkDelete', + 'send', + 'sendTyping', + 'createMessageCollector', + 'awaitMessages', + 'fetchWebhooks', + 'createWebhook', + 'setRateLimitPerUser', + 'setNSFW', +]); + module.exports = PartialGroupDMChannel; diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 29d571df6..890629cda 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -1373,7 +1373,7 @@ export class ContextMenuCommandInteraction // tslint:disable-next-line no-empty-interface export interface DMChannel extends Omit< - TextBasedChannelFields, + TextBasedChannelFields, 'bulkDelete' | 'fetchWebhooks' | 'createWebhook' | 'setRateLimitPerUser' | 'setNSFW' > {} export class DMChannel extends BaseChannel { @@ -2694,6 +2694,19 @@ export class OAuth2Guild extends BaseGuild { public permissions: Readonly; } +export interface PartialGroupDMChannel + extends Omit< + TextBasedChannelFields, + | 'bulkDelete' + | 'send' + | 'sendTyping' + | 'createMessageCollector' + | 'awaitMessages' + | 'fetchWebhooks' + | 'createWebhook' + | 'setRateLimitPerUser' + | 'setNSFW' + > {} export class PartialGroupDMChannel extends BaseChannel { private constructor(client: Client, data: RawPartialGroupDMChannelData); public type: ChannelType.GroupDM; @@ -2701,8 +2714,9 @@ export class PartialGroupDMChannel extends BaseChannel { public name: string | null; public icon: string | null; public recipients: PartialRecipient[]; - public messages: PartialGroupDMMessageManager; + public ownerId: Snowflake | null; public iconURL(options?: ImageURLOptions): string | null; + public fetchOwner(options?: BaseFetchOptions): Promise; public toString(): ChannelMention; } @@ -4858,13 +4872,13 @@ export interface PartialTextBasedChannelFields>; } -export interface TextBasedChannelFields +export interface TextBasedChannelFields extends PartialTextBasedChannelFields { lastMessageId: Snowflake | null; get lastMessage(): Message | null; lastPinTimestamp: number | null; get lastPinAt(): Date | null; - messages: If; + messages: If>; awaitMessageComponent( options?: AwaitMessageCollectorOptionsParams, ): Promise;