diff --git a/packages/discord.js/src/managers/MessageManager.js b/packages/discord.js/src/managers/MessageManager.js
index dcddf2857383..bd38a1a77673 100644
--- a/packages/discord.js/src/managers/MessageManager.js
+++ b/packages/discord.js/src/managers/MessageManager.js
@@ -1,5 +1,6 @@
'use strict';
+const process = require('node:process');
const { Collection } = require('@discordjs/collection');
const { makeURLSearchParams } = require('@discordjs/rest');
const { Routes } = require('discord-api-types/v10');
@@ -10,6 +11,8 @@ const MessagePayload = require('../structures/MessagePayload');
const { MakeCacheOverrideSymbol } = require('../util/Symbols');
const { resolvePartialEmoji } = require('../util/Util');
+let deprecationEmittedForFetchPinned = false;
+
/**
* Manages API methods for Messages and holds their cache.
* @extends {CachedManager}
@@ -116,19 +119,83 @@ class MessageManager extends CachedManager {
return data.reduce((_data, message) => _data.set(message.id, this._add(message, options.cache)), new Collection());
}
+ /**
+ * Options used to fetch pinned messages.
+ *
+ * @typedef {Object} FetchPinnedMessagesOptions
+ * @property {DateResolvable} [before] Consider only pinned messages before this time
+ * @property {number} [limit] The maximum number of pinned messages to return
+ * @property {boolean} [cache] Whether to cache the pinned messages
+ */
+
+ /**
+ * Data returned from fetching pinned messages.
+ *
+ * @typedef {Object} FetchPinnedMessagesResponse
+ * @property {MessagePin[]} items The pinned messages
+ * @property {boolean} hasMore Whether there are additional pinned messages that require a subsequent call
+ */
+
+ /**
+ * Pinned message data returned from fetching pinned messages.
+ *
+ * @typedef {Object} MessagePin
+ * @property {Date} pinnedAt The time the message was pinned at
+ * @property {number} pinnedTimestamp The timestamp the message was pinned at
+ * @property {Message} message The pinned message
+ */
+
/**
* Fetches the pinned messages of this channel and returns a collection of them.
* The returned Collection does not contain any reaction data of the messages.
* Those need to be fetched separately.
- * @param {boolean} [cache=true] Whether to cache the message(s)
- * @returns {Promise>}
+ *
+ * @param {FetchPinnedMessagesOptions} [options={}] Options for fetching pinned messages
+ * @returns {Promise}
* @example
* // Get pinned messages
- * channel.messages.fetchPinned()
- * .then(messages => console.log(`Received ${messages.size} messages`))
+ * channel.messages.fetchPins()
+ * .then(messages => console.log(`Received ${messages.items.length} messages`))
* .catch(console.error);
*/
+ async fetchPins(options = {}) {
+ const data = await this.client.rest.get(Routes.channelMessagesPins(this.channel.id), {
+ query: makeURLSearchParams({
+ ...options,
+ before: options.before && new Date(options.before).toISOString(),
+ }),
+ });
+
+ return {
+ items: data.items.map(item => ({
+ pinnedTimestamp: Date.parse(item.pinned_at),
+ get pinnedAt() {
+ return new Date(this.pinnedTimestamp);
+ },
+ message: this._add(item.message, options.cache),
+ })),
+ hasMore: data.has_more,
+ };
+ }
+
+ /**
+ * Fetches the pinned messages of this channel and returns a collection of them.
+ * The returned Collection does not contain any reaction data of the messages.
+ * Those need to be fetched separately.
+ * @param {boolean} [cache=true] Whether to cache the message(s)
+ * @deprecated Use {@link MessageManager#fetchPins} instead.
+ * @returns {Promise>}
+ */
async fetchPinned(cache = true) {
+ if (!deprecationEmittedForFetchPinned) {
+ process.emitWarning(
+ 'The MessageManager#fetchPinned() method is deprecated. Use MessageManager#fetchPins() instead.',
+ 'DeprecationWarning',
+ );
+
+ deprecationEmittedForFetchPinned = true;
+ }
+
const data = await this.client.rest.get(Routes.channelPins(this.channel.id));
const messages = new Collection();
for (const message of data) messages.set(message.id, this._add(message, cache));
@@ -219,7 +286,7 @@ class MessageManager extends CachedManager {
message = this.resolveId(message);
if (!message) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'message', 'MessageResolvable');
- await this.client.rest.put(Routes.channelPin(this.channel.id, message), { reason });
+ await this.client.rest.put(Routes.channelMessagesPin(this.channel.id, message), { reason });
}
/**
@@ -232,7 +299,7 @@ class MessageManager extends CachedManager {
message = this.resolveId(message);
if (!message) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'message', 'MessageResolvable');
- await this.client.rest.delete(Routes.channelPin(this.channel.id, message), { reason });
+ await this.client.rest.delete(Routes.channelMessagesPin(this.channel.id, message), { reason });
}
/**
diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts
index b895604c1901..27015a8c6cf5 100644
--- a/packages/discord.js/typings/index.d.ts
+++ b/packages/discord.js/typings/index.d.ts
@@ -5025,7 +5025,9 @@ export abstract class MessageManager extends
): Promise>;
public fetch(options: MessageResolvable | FetchMessageOptions): Promise>;
public fetch(options?: FetchMessagesOptions): Promise>>;
+ /** @deprecated Use {@link MessageManager.fetchPins} instead. */
public fetchPinned(cache?: boolean): Promise>>;
+ public fetchPins(options?: FetchPinnedMessagesOptions): Promise>;
public react(message: MessageResolvable, emoji: EmojiIdentifierResolvable): Promise;
public pin(message: MessageResolvable, reason?: string): Promise;
public unpin(message: MessageResolvable, reason?: string): Promise;
@@ -6349,6 +6351,23 @@ export interface FetchMessagesOptions {
cache?: boolean;
}
+export interface FetchPinnedMessagesOptions {
+ before?: DateResolvable;
+ cache?: boolean;
+ limit?: number;
+}
+
+export interface FetchPinnedMessagesResponse {
+ hasMore: boolean;
+ items: readonly MessagePin[];
+}
+
+export interface MessagePin {
+ message: Message;
+ get pinnedAt(): Date;
+ pinnedTimestamp: number;
+}
+
export interface FetchReactionUsersOptions {
type?: ReactionType;
limit?: number;
diff --git a/packages/discord.js/typings/index.test-d.ts b/packages/discord.js/typings/index.test-d.ts
index 2316cb088f80..4507770a6c14 100644
--- a/packages/discord.js/typings/index.test-d.ts
+++ b/packages/discord.js/typings/index.test-d.ts
@@ -231,6 +231,7 @@ import {
FileComponentData,
ContainerComponentData,
InteractionResponse,
+ FetchPinnedMessagesResponse,
} from '.';
import {
expectAssignable,
@@ -1690,6 +1691,7 @@ declare const guildChannelManager: GuildChannelManager;
expectType>>(messages.edit('1234567890', 'text'));
expectType>>(messages.fetch('1234567890'));
expectType>>>(messages.fetchPinned());
+ expectType>>(messages.fetchPins());
expectType(message.guild);
expectType(message.guildId);
expectType(message.channel.messages.channel);
@@ -1703,6 +1705,7 @@ declare const guildChannelManager: GuildChannelManager;
expectType>(messages.edit('1234567890', 'text'));
expectType>(messages.fetch('1234567890'));
expectType>>(messages.fetchPinned());
+ expectType>(messages.fetchPins());
expectType(message.guild);
expectType(message.guildId);
expectType(message.channel.messages.channel);