From 1b2d8decb638faeae8184119c5cedfcdaf9485e3 Mon Sep 17 00:00:00 2001
From: Jiralite <33201955+Jiralite@users.noreply.github.com>
Date: Sun, 17 Apr 2022 09:55:17 +0100
Subject: [PATCH] fix(MessageManager): Allow caching option of an unspecified
limit (#7763)
* refactor: merge parameters
* refactor: remove default
---
.../discord.js/src/managers/MessageManager.js | 97 +++++++++++--------
packages/discord.js/typings/index.d.ts | 26 ++---
packages/discord.js/typings/index.test-d.ts | 17 ++++
3 files changed, 86 insertions(+), 54 deletions(-)
diff --git a/packages/discord.js/src/managers/MessageManager.js b/packages/discord.js/src/managers/MessageManager.js
index 6642efcac..cab6380a2 100644
--- a/packages/discord.js/src/managers/MessageManager.js
+++ b/packages/discord.js/src/managers/MessageManager.js
@@ -35,40 +35,79 @@ class MessageManager extends CachedManager {
}
/**
- * The parameters to pass in when requesting previous messages from a channel. `around`, `before` and
- * `after` are mutually exclusive. All the parameters are optional.
- * @typedef {Object} ChannelLogsQueryOptions
- * @property {number} [limit] Number of messages to acquire
- * @property {Snowflake} [before] The message's id to get the messages that were posted before it
- * @property {Snowflake} [after] The message's id to get the messages that were posted after it
- * @property {Snowflake} [around] The message's id to get the messages that were posted around it
+ * Data that can be resolved to a Message object. This can be:
+ * * A Message
+ * * A Snowflake
+ * @typedef {Message|Snowflake} MessageResolvable
*/
/**
- * Gets a message, or messages, from this channel.
+ * Options used to fetch a message.
+ * @typedef {BaseFetchOptions} FetchMessageOptions
+ * @property {MessageResolvable} [message] The message to fetch
+ */
+
+ /**
+ * Options used to fetch multiple messages.
+ * @typedef {Object} FetchMessagesOptions
+ * @property {number} [limit] The maximum number of messages to return
+ * @property {Snowflake} [before] Consider only messages before this id
+ * @property {Snowflake} [after] Consider only messages after this id
+ * @property {Snowflake} [around] Consider only messages around this id
+ * @property {boolean} [cache] Whether to cache the fetched messages
+ */
+
+ /**
+ * Fetches message(s) from a channel.
* The returned Collection does not contain reaction users of the messages if they were not cached.
* Those need to be fetched separately in such a case.
- * @param {Snowflake|ChannelLogsQueryOptions} [message] The id of the message to fetch, or query parameters.
- * @param {BaseFetchOptions} [options] Additional options for this fetch
+ * @param {MessageResolvable|FetchMessageOptions|FetchMessagesOptions} [options] Options for fetching message(s)
* @returns {Promise>}
* @example
- * // Get message
+ * // Fetch a message
* channel.messages.fetch('99539446449315840')
* .then(message => console.log(message.content))
* .catch(console.error);
* @example
- * // Get messages
- * channel.messages.fetch({ limit: 10 })
+ * // Fetch a maximum of 10 messages without caching
+ * channel.messages.fetch({ limit: 10, cache: false })
* .then(messages => console.log(`Received ${messages.size} messages`))
* .catch(console.error);
* @example
- * // Get messages and filter by user id
+ * // Fetch a maximum of 10 messages without caching around a message id
+ * channel.messages.fetch({ limit: 10, cache: false, around: '99539446449315840' })
+ * .then(messages => console.log(`Received ${messages.size} messages`))
+ * .catch(console.error);
+ * @example
+ * // Fetch messages and filter by a user id
* channel.messages.fetch()
* .then(messages => console.log(`${messages.filter(m => m.author.id === '84484653687267328').size} messages`))
* .catch(console.error);
*/
- fetch(message, { cache = true, force = false } = {}) {
- return typeof message === 'string' ? this._fetchId(message, cache, force) : this._fetchMany(message, cache);
+ fetch(options) {
+ if (!options) return this._fetchMany();
+ const { message, cache, force } = options;
+ const resolvedMessage = this.resolveId(message ?? options);
+ if (resolvedMessage) return this._fetchSingle({ message: resolvedMessage, cache, force });
+ return this._fetchMany(options);
+ }
+
+ async _fetchSingle({ message, cache, force = false }) {
+ if (!force) {
+ const existing = this.cache.get(message);
+ if (existing && !existing.partial) return existing;
+ }
+
+ const data = await this.client.rest.get(Routes.channelMessage(this.channel.id, message));
+ return this._add(data, cache);
+ }
+
+ async _fetchMany(options = {}) {
+ const data = await this.client.rest.get(Routes.channelMessages(this.channel.id), {
+ query: makeURLSearchParams(options),
+ });
+
+ return data.reduce((_data, message) => _data.set(message.id, this._add(message, options.cache)), new Collection());
}
/**
@@ -90,13 +129,6 @@ class MessageManager extends CachedManager {
return messages;
}
- /**
- * Data that can be resolved to a Message object. This can be:
- * * A Message
- * * A Snowflake
- * @typedef {Message|Snowflake} MessageResolvable
- */
-
/**
* Resolves a {@link MessageResolvable} to a {@link Message} object.
* @method resolve
@@ -212,25 +244,6 @@ class MessageManager extends CachedManager {
await this.client.rest.delete(Routes.channelMessage(this.channel.id, message));
}
-
- async _fetchId(messageId, cache, force) {
- if (!force) {
- const existing = this.cache.get(messageId);
- if (existing && !existing.partial) return existing;
- }
-
- const data = await this.client.rest.get(Routes.channelMessage(this.channel.id, messageId));
- return this._add(data, cache);
- }
-
- async _fetchMany(options = {}, cache) {
- const data = await this.client.rest.get(Routes.channelMessages(this.channel.id), {
- query: makeURLSearchParams(options),
- });
- const messages = new Collection();
- for (const message of data) messages.set(message.id, this._add(message, cache));
- return messages;
- }
}
module.exports = MessageManager;
diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts
index 977cad0b5..801244b0a 100644
--- a/packages/discord.js/typings/index.d.ts
+++ b/packages/discord.js/typings/index.d.ts
@@ -3207,11 +3207,8 @@ export class MessageManager extends CachedManager;
public delete(message: MessageResolvable): Promise;
public edit(message: MessageResolvable, options: string | MessagePayload | MessageEditOptions): Promise;
- public fetch(message: Snowflake, options?: BaseFetchOptions): Promise;
- public fetch(
- options?: ChannelLogsQueryOptions,
- cacheOptions?: BaseFetchOptions,
- ): Promise>;
+ public fetch(options: MessageResolvable | FetchMessageOptions): Promise;
+ public fetch(options?: FetchMessagesOptions): Promise>;
public fetchPinned(cache?: boolean): Promise>;
public react(message: MessageResolvable, emoji: EmojiIdentifierResolvable): Promise;
public pin(message: MessageResolvable, reason?: string): Promise;
@@ -3736,13 +3733,6 @@ export interface ChannelData {
videoQualityMode?: VideoQualityMode | null;
}
-export interface ChannelLogsQueryOptions {
- limit?: number;
- before?: Snowflake;
- after?: Snowflake;
- around?: Snowflake;
-}
-
export type ChannelMention = `<#${Snowflake}>`;
export interface ChannelPosition {
@@ -4324,6 +4314,18 @@ export interface FetchMembersOptions {
force?: boolean;
}
+export interface FetchMessageOptions extends BaseFetchOptions {
+ message: MessageResolvable;
+}
+
+export interface FetchMessagesOptions {
+ limit?: number;
+ before?: Snowflake;
+ after?: Snowflake;
+ around?: Snowflake;
+ cache?: boolean;
+}
+
export interface FetchReactionUsersOptions {
limit?: number;
after?: Snowflake;
diff --git a/packages/discord.js/typings/index.test-d.ts b/packages/discord.js/typings/index.test-d.ts
index 6a909be9e..b9c603f2e 100644
--- a/packages/discord.js/typings/index.test-d.ts
+++ b/packages/discord.js/typings/index.test-d.ts
@@ -119,6 +119,7 @@ import {
MessageActionRowComponentBuilder,
GuildBanManager,
GuildBan,
+ MessageManager,
} from '.';
import { expectAssignable, expectDeprecated, expectNotAssignable, expectNotType, expectType } from 'tsd';
import { UnsafeButtonBuilder, UnsafeEmbedBuilder, UnsafeSelectMenuBuilder } from '@discordjs/builders';
@@ -1019,6 +1020,22 @@ declare const guildChannelManager: GuildChannelManager;
expectType>(guildChannelManager.fetch('0'));
}
+declare const messageManager: MessageManager;
+{
+ expectType>(messageManager.fetch('1234567890'));
+ expectType>(messageManager.fetch({ message: '1234567890' }));
+ expectType>(messageManager.fetch({ message: '1234567890', cache: true, force: false }));
+ expectType>>(messageManager.fetch());
+ expectType>>(messageManager.fetch({}));
+ expectType>>(
+ messageManager.fetch({ limit: 100, before: '1234567890', cache: false }),
+ );
+ // @ts-expect-error
+ messageManager.fetch({ cache: true, force: false });
+ // @ts-expect-error
+ messageManager.fetch({ message: '1234567890', after: '1234567890', cache: true, force: false });
+}
+
declare const roleManager: RoleManager;
expectType>>(roleManager.fetch());
expectType>>(roleManager.fetch(undefined, {}));