diff --git a/packages/discord.js/src/managers/UserManager.js b/packages/discord.js/src/managers/UserManager.js index 167fe5796..ff865ba37 100644 --- a/packages/discord.js/src/managers/UserManager.js +++ b/packages/discord.js/src/managers/UserManager.js @@ -39,7 +39,7 @@ class UserManager extends CachedManager { * @private */ dmChannel(userId) { - return this.client.channels.cache.find(c => c.type === ChannelType.DM && c.recipient.id === userId) ?? null; + return this.client.channels.cache.find(c => c.type === ChannelType.DM && c.recipientId === userId) ?? null; } /** diff --git a/packages/discord.js/src/structures/DMChannel.js b/packages/discord.js/src/structures/DMChannel.js index 5117a0eae..f78f04cd1 100644 --- a/packages/discord.js/src/structures/DMChannel.js +++ b/packages/discord.js/src/structures/DMChannel.js @@ -1,9 +1,11 @@ 'use strict'; +const { userMention } = require('@discordjs/builders'); const { ChannelType } = require('discord-api-types/v9'); const { Channel } = require('./Channel'); const TextBasedChannel = require('./interfaces/TextBasedChannel'); const MessageManager = require('../managers/MessageManager'); +const Partials = require('../util/Partials'); /** * Represents a direct message channel between two users. @@ -28,11 +30,17 @@ class DMChannel extends Channel { super._patch(data); if (data.recipients) { + const recipient = data.recipients[0]; + /** - * The recipient on the other end of the DM - * @type {User} + * The recipient's id + * @type {Snowflake} */ - this.recipient = this.client.users._add(data.recipients[0]); + this.recipientId = recipient.id; + + if ('username' in recipient || this.client.options.partials.includes(Partials.Users)) { + this.client.users._add(recipient); + } } if ('last_message_id' in data) { @@ -63,13 +71,22 @@ class DMChannel extends Channel { return typeof this.lastMessageId === 'undefined'; } + /** + * The recipient on the other end of the DM + * @type {?User} + * @readonly + */ + get recipient() { + return this.client.users.resolve(this.recipientId); + } + /** * Fetch this DMChannel. * @param {boolean} [force=true] Whether to skip the cache check and request the API * @returns {Promise} */ fetch(force = true) { - return this.recipient.createDM(force); + return this.client.users.createDM(this.recipientId, force); } /** @@ -81,7 +98,7 @@ class DMChannel extends Channel { * console.log(`Hello from ${channel}!`); */ toString() { - return this.recipient.toString(); + return userMention(this.recipientId); } // These are here only for documentation purposes - they are implemented by TextBasedChannel diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 1eae27ba0..31cb0bb13 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -883,7 +883,8 @@ export class EnumResolvers extends null { export class DMChannel extends TextBasedChannelMixin(Channel, ['bulkDelete']) { private constructor(client: Client, data?: RawDMChannelData); public messages: MessageManager; - public recipient: User; + public recipientId: Snowflake; + public get recipient(): User | null; public type: ChannelType.DM; public fetch(force?: boolean): Promise; } @@ -2256,7 +2257,7 @@ export class ThreadMemberFlagsBitField extends BitField export class Typing extends Base { private constructor(channel: TextBasedChannel, user: PartialUser, data?: RawTypingData); public channel: TextBasedChannel; - public user: PartialUser; + public user: User | PartialUser; public startedTimestamp: number; public get startedAt(): Date; public get guild(): Guild | null; diff --git a/packages/discord.js/typings/index.test-d.ts b/packages/discord.js/typings/index.test-d.ts index cdd52597b..0e2cb3ac2 100644 --- a/packages/discord.js/typings/index.test-d.ts +++ b/packages/discord.js/typings/index.test-d.ts @@ -947,8 +947,9 @@ expectType>>(guildEmojiManager.fetch(u expectType>(guildEmojiManager.fetch('0')); declare const typing: Typing; -expectType(typing.user); +expectType(typing.user); if (typing.user.partial) expectType(typing.user.username); +if (!typing.user.partial) expectType(typing.user.tag); expectType(typing.channel); if (typing.channel.partial) expectType(typing.channel.lastMessageId);