diff --git a/packages/discord.js/src/managers/MessageManager.js b/packages/discord.js/src/managers/MessageManager.js
index 284e15cf8545..30a4bb42dbe8 100644
--- a/packages/discord.js/src/managers/MessageManager.js
+++ b/packages/discord.js/src/managers/MessageManager.js
@@ -123,24 +123,63 @@ 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 fetchPinned(cache = 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));
- return messages;
+ 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,
+ };
}
/**
@@ -221,7 +260,7 @@ class MessageManager extends CachedManager {
const messageId = this.resolveId(message);
if (!messageId) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'message', 'MessageResolvable');
- await this.client.rest.put(Routes.channelPin(this.channel.id, messageId), { reason });
+ await this.client.rest.put(Routes.channelMessagesPin(this.channel.id, messageId), { reason });
}
/**
@@ -235,7 +274,7 @@ class MessageManager extends CachedManager {
const messageId = this.resolveId(message);
if (!messageId) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'message', 'MessageResolvable');
- await this.client.rest.delete(Routes.channelPin(this.channel.id, messageId), { reason });
+ await this.client.rest.delete(Routes.channelMessagesPin(this.channel.id, messageId), { reason });
}
/**
diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts
index c39dd4db68c2..53e83f95278d 100644
--- a/packages/discord.js/typings/index.d.ts
+++ b/packages/discord.js/typings/index.d.ts
@@ -4516,7 +4516,7 @@ export abstract class MessageManager extends
): Promise>;
public fetch(options: FetchMessageOptions | MessageResolvable): Promise>;
public fetch(options?: FetchMessagesOptions): Promise>>;
- 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;
@@ -5800,6 +5800,23 @@ export interface FetchMessagesOptions {
limit?: number;
}
+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 {
after?: Snowflake;
limit?: number;
diff --git a/packages/discord.js/typings/index.test-d.ts b/packages/discord.js/typings/index.test-d.ts
index 0ec7fe3bb9e6..7f2ea9e9d3ef 100644
--- a/packages/discord.js/typings/index.test-d.ts
+++ b/packages/discord.js/typings/index.test-d.ts
@@ -99,6 +99,7 @@ import type {
Entitlement,
FetchedThreads,
FetchedThreadsMore,
+ FetchPinnedMessagesResponse,
FileComponentData,
ForumChannel,
Guild,
@@ -1756,7 +1757,7 @@ declare const guildChannelManager: GuildChannelManager;
expectType>>(messages.crosspost('1234567890'));
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);
@@ -1769,7 +1770,7 @@ declare const guildChannelManager: GuildChannelManager;
expectType(messages);
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);