diff --git a/packages/discord.js/src/index.js b/packages/discord.js/src/index.js index c7c530ced537..737115d34fbc 100644 --- a/packages/discord.js/src/index.js +++ b/packages/discord.js/src/index.js @@ -55,6 +55,7 @@ exports.CachedManager = require('./managers/CachedManager'); exports.ChannelManager = require('./managers/ChannelManager'); exports.ClientVoiceManager = require('./client/voice/ClientVoiceManager'); exports.DataManager = require('./managers/DataManager'); +exports.DMMessageManager = require('./managers/DMMessageManager'); exports.GuildApplicationCommandManager = require('./managers/GuildApplicationCommandManager'); exports.GuildBanManager = require('./managers/GuildBanManager'); exports.GuildChannelManager = require('./managers/GuildChannelManager'); @@ -65,6 +66,7 @@ exports.GuildInviteManager = require('./managers/GuildInviteManager'); exports.GuildManager = require('./managers/GuildManager'); exports.GuildMemberManager = require('./managers/GuildMemberManager'); exports.GuildMemberRoleManager = require('./managers/GuildMemberRoleManager'); +exports.GuildMessageManager = require('./managers/GuildMessageManager'); exports.GuildScheduledEventManager = require('./managers/GuildScheduledEventManager'); exports.GuildStickerManager = require('./managers/GuildStickerManager'); exports.GuildTextThreadManager = require('./managers/GuildTextThreadManager'); diff --git a/packages/discord.js/src/managers/DMMessageManager.js b/packages/discord.js/src/managers/DMMessageManager.js new file mode 100644 index 000000000000..f0b3a338c92e --- /dev/null +++ b/packages/discord.js/src/managers/DMMessageManager.js @@ -0,0 +1,17 @@ +'use strict'; + +const MessageManager = require('./MessageManager'); + +/** + * Manages API methods for messages in direct message channels and holds their cache. + * @extends {MessageManager} + */ +class DMMessageManager extends MessageManager { + /** + * The channel that the messages belong to + * @name DMMessageManager#channel + * @type {DMChannel} + */ +} + +module.exports = DMMessageManager; diff --git a/packages/discord.js/src/managers/GuildMessageManager.js b/packages/discord.js/src/managers/GuildMessageManager.js new file mode 100644 index 000000000000..7a93c99f1ed2 --- /dev/null +++ b/packages/discord.js/src/managers/GuildMessageManager.js @@ -0,0 +1,17 @@ +'use strict'; + +const MessageManager = require('./MessageManager'); + +/** + * Manages API methods for messages in a guild and holds their cache. + * @extends {MessageManager} + */ +class GuildMessageManager extends MessageManager { + /** + * The channel that the messages belong to + * @name GuildMessageManager#channel + * @type {GuildTextBasedChannel} + */ +} + +module.exports = GuildMessageManager; diff --git a/packages/discord.js/src/managers/MessageManager.js b/packages/discord.js/src/managers/MessageManager.js index 28d622d2c79f..ea05b1d19418 100644 --- a/packages/discord.js/src/managers/MessageManager.js +++ b/packages/discord.js/src/managers/MessageManager.js @@ -12,6 +12,7 @@ const { resolvePartialEmoji } = require('../util/Util'); /** * Manages API methods for Messages and holds their cache. * @extends {CachedManager} + * @abstract */ class MessageManager extends CachedManager { constructor(channel, iterable) { diff --git a/packages/discord.js/src/structures/BaseGuildTextChannel.js b/packages/discord.js/src/structures/BaseGuildTextChannel.js index a8a608b3bdd0..f7d9d69889a6 100644 --- a/packages/discord.js/src/structures/BaseGuildTextChannel.js +++ b/packages/discord.js/src/structures/BaseGuildTextChannel.js @@ -2,8 +2,8 @@ const GuildChannel = require('./GuildChannel'); const TextBasedChannel = require('./interfaces/TextBasedChannel'); +const GuildMessageManager = require('../managers/GuildMessageManager'); const GuildTextThreadManager = require('../managers/GuildTextThreadManager'); -const MessageManager = require('../managers/MessageManager'); /** * Represents a text-based guild channel on Discord. @@ -16,9 +16,9 @@ class BaseGuildTextChannel extends GuildChannel { /** * A manager of the messages sent to this channel - * @type {MessageManager} + * @type {GuildMessageManager} */ - this.messages = new MessageManager(this); + this.messages = new GuildMessageManager(this); /** * A manager of the threads belonging to this channel diff --git a/packages/discord.js/src/structures/BaseGuildVoiceChannel.js b/packages/discord.js/src/structures/BaseGuildVoiceChannel.js index de80dfeaaed6..220ac6c8d83b 100644 --- a/packages/discord.js/src/structures/BaseGuildVoiceChannel.js +++ b/packages/discord.js/src/structures/BaseGuildVoiceChannel.js @@ -4,7 +4,7 @@ const { Collection } = require('@discordjs/collection'); const { PermissionFlagsBits } = require('discord-api-types/v10'); const GuildChannel = require('./GuildChannel'); const TextBasedChannel = require('./interfaces/TextBasedChannel'); -const MessageManager = require('../managers/MessageManager'); +const GuildMessageManager = require('../managers/GuildMessageManager'); /** * Represents a voice-based guild channel on Discord. @@ -16,9 +16,9 @@ class BaseGuildVoiceChannel extends GuildChannel { super(guild, data, client, false); /** * A manager of the messages sent to this channel - * @type {MessageManager} + * @type {GuildMessageManager} */ - this.messages = new MessageManager(this); + this.messages = new GuildMessageManager(this); /** * If the guild considers this channel NSFW diff --git a/packages/discord.js/src/structures/DMChannel.js b/packages/discord.js/src/structures/DMChannel.js index 8c13f7550058..0ade9aa0491f 100644 --- a/packages/discord.js/src/structures/DMChannel.js +++ b/packages/discord.js/src/structures/DMChannel.js @@ -4,7 +4,7 @@ const { userMention } = require('@discordjs/builders'); const { ChannelType } = require('discord-api-types/v10'); const { BaseChannel } = require('./BaseChannel'); const TextBasedChannel = require('./interfaces/TextBasedChannel'); -const MessageManager = require('../managers/MessageManager'); +const DMMessageManager = require('../managers/DMMessageManager'); const Partials = require('../util/Partials'); /** @@ -21,9 +21,9 @@ class DMChannel extends BaseChannel { /** * A manager of the messages belonging to this channel - * @type {MessageManager} + * @type {DMMessageManager} */ - this.messages = new MessageManager(this); + this.messages = new DMMessageManager(this); } _patch(data) { diff --git a/packages/discord.js/src/structures/ThreadChannel.js b/packages/discord.js/src/structures/ThreadChannel.js index d57fd9dd23f0..96b408701ade 100644 --- a/packages/discord.js/src/structures/ThreadChannel.js +++ b/packages/discord.js/src/structures/ThreadChannel.js @@ -4,7 +4,7 @@ const { ChannelType, PermissionFlagsBits, Routes, ChannelFlags } = require('disc const { BaseChannel } = require('./BaseChannel'); const TextBasedChannel = require('./interfaces/TextBasedChannel'); const { DiscordjsRangeError, ErrorCodes } = require('../errors'); -const MessageManager = require('../managers/MessageManager'); +const GuildMessageManager = require('../managers/GuildMessageManager'); const ThreadMemberManager = require('../managers/ThreadMemberManager'); const ChannelFlagsBitField = require('../util/ChannelFlagsBitField'); @@ -31,9 +31,9 @@ class ThreadChannel extends BaseChannel { /** * A manager of the messages sent to this thread - * @type {MessageManager} + * @type {GuildMessageManager} */ - this.messages = new MessageManager(this); + this.messages = new GuildMessageManager(this); /** * A manager of the members that are part of this thread diff --git a/packages/discord.js/src/structures/interfaces/TextBasedChannel.js b/packages/discord.js/src/structures/interfaces/TextBasedChannel.js index 97bc337313ae..cf455b9854b3 100644 --- a/packages/discord.js/src/structures/interfaces/TextBasedChannel.js +++ b/packages/discord.js/src/structures/interfaces/TextBasedChannel.js @@ -17,9 +17,9 @@ class TextBasedChannel { constructor() { /** * A manager of the messages sent to this channel - * @type {MessageManager} + * @type {GuildMessageManager} */ - this.messages = new MessageManager(this); + this.messages = new GuildMessageManager(this); /** * The channel's last message id, if one was sent @@ -410,4 +410,4 @@ module.exports = TextBasedChannel; // Fixes Circular // eslint-disable-next-line import/order -const MessageManager = require('../../managers/MessageManager'); +const GuildMessageManager = require('../../managers/GuildMessageManager'); diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 520274ae604c..930ee3f5f7b3 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -4005,14 +4005,13 @@ export class GuildMemberRoleManager extends DataManager; } -export class MessageManager extends CachedManager< +export abstract class MessageManager extends CachedManager< Snowflake, Message, MessageResolvable > { - private constructor(channel: TextBasedChannel, iterable?: Iterable); - public channel: If; - public crosspost(message: MessageResolvable): Promise>; + protected constructor(channel: TextBasedChannel, iterable?: Iterable); + public channel: TextBasedChannel; public delete(message: MessageResolvable): Promise; public edit( message: MessageResolvable, @@ -4026,6 +4025,15 @@ export class MessageManager extends CachedMan public unpin(message: MessageResolvable, reason?: string): Promise; } +export class DMMessageManager extends MessageManager { + public channel: DMChannel; +} + +export class GuildMessageManager extends MessageManager { + public channel: GuildTextBasedChannel; + public crosspost(message: MessageResolvable): Promise>; +} + export class PermissionOverwriteManager extends CachedManager< Snowflake, PermissionOverwrites, @@ -4192,7 +4200,7 @@ export interface TextBasedChannelFields get lastMessage(): Message | null; lastPinTimestamp: number | null; get lastPinAt(): Date | null; - messages: MessageManager; + messages: If; awaitMessageComponent( options?: AwaitMessageCollectorOptionsParams, ): Promise; diff --git a/packages/discord.js/typings/index.test-d.ts b/packages/discord.js/typings/index.test-d.ts index 552d39986b47..70f84d973e85 100644 --- a/packages/discord.js/typings/index.test-d.ts +++ b/packages/discord.js/typings/index.test-d.ts @@ -163,6 +163,8 @@ import { ThreadManager, FetchedThreads, FetchedThreadsMore, + DMMessageManager, + GuildMessageManager, ApplicationCommandChannelOptionData, ApplicationCommandChannelOption, ApplicationCommandChoicesOption, @@ -349,6 +351,19 @@ declare const assertIsMessage: (m: Promise) => void; client.on('messageCreate', async message => { const { client, channel } = message; + // https://github.com/discordjs/discord.js/issues/8545 + { + // These should not throw any errors when comparing messages from any source. + channel.messages.cache.filter(m => m); + (await channel.messages.fetch()).filter(m => m.author.id === message.author.id); + + if (channel.isDMBased()) { + expectType(channel.messages.channel.messages); + } else { + expectType(channel.messages.channel.messages); + } + } + if (!message.inGuild() && message.partial) { expectNotType(message); } @@ -1519,7 +1534,7 @@ declare const guildChannelManager: GuildChannelManager; if (channel.isTextBased()) { const { messages } = channel; const message = await messages.fetch('123'); - expectType>(messages); + expectType(messages); expectType>>(messages.crosspost('1234567890')); expectType>>(messages.edit('1234567890', 'text')); expectType>>(messages.fetch('1234567890')); @@ -1533,18 +1548,24 @@ declare const guildChannelManager: GuildChannelManager; { const { messages } = dmChannel; const message = await messages.fetch('123'); - expectType>(messages); - expectType>>(messages.crosspost('1234567890')); // This shouldn't even exist! - expectType>>(messages.edit('1234567890', 'text')); - expectType>>(messages.fetch('1234567890')); - expectType>>>(messages.fetchPinned()); - expectType(message.guild); - expectType(message.guildId); - expectType(message.channel.messages.channel); - - expectType>(message.mentions); - expectType(message.mentions.guild); - expectType(message.mentions.members); + expectType(messages); + expectType>(messages.edit('1234567890', 'text')); + expectType>(messages.fetch('1234567890')); + expectType>>(messages.fetchPinned()); + expectType(message.guild); + expectType(message.guildId); + expectType(message.channel.messages.channel); + expectType(message.mentions); + expectType(message.mentions.guild); + expectType | null>(message.mentions.members); + + if (messages.channel.isDMBased()) { + expectType(messages.channel); + expectType(messages.channel.messages.channel); + } + + // @ts-expect-error Crossposting is not possible in direct messages. + messages.crosspost('1234567890'); } declare const threadManager: ThreadManager;