From 1e5e855ca07a9fe1684d9b95bca18d9051a47504 Mon Sep 17 00:00:00 2001
From: March 7th <71698422+aiko-chan-ai@users.noreply.github.com>
Date: Wed, 18 Jan 2023 14:24:06 +0700
Subject: [PATCH] feat: thread channel
fix: ThreadManager#fetchArchived()
feat: ThreadChannel#firstMessage
todo: #486
---
src/managers/ThreadManager.js | 56 +++++++++++++++++++--------------
src/structures/ThreadChannel.js | 9 ++++++
typings/index.d.ts | 15 +++++++--
3 files changed, 54 insertions(+), 26 deletions(-)
diff --git a/src/managers/ThreadManager.js b/src/managers/ThreadManager.js
index 5341e51..81c6be1 100644
--- a/src/managers/ThreadManager.js
+++ b/src/managers/ThreadManager.js
@@ -67,7 +67,7 @@ class ThreadManager extends CachedManager {
/**
* Obtains a thread from Discord, or the channel cache if it's already available.
- * @param {ThreadChannelResolvable|FetchThreadsOptions} [options] The options to fetch threads. If it is a
+ * @param {ThreadChannelResolvable|FetchChannelThreadsOptions} [options] The options to fetch threads. If it is a
* ThreadChannelResolvable then the specified thread will be fetched. Fetches all active threads if `undefined`
* @param {BaseFetchOptions} [cacheOptions] Additional options for this fetch. The `force` field gets ignored
* if `options` is not a {@link ThreadChannelResolvable}
@@ -116,38 +116,44 @@ class ThreadManager extends CachedManager {
/**
* Obtains a set of archived threads from Discord, requires `READ_MESSAGE_HISTORY` in the parent channel.
- * @param {FetchArchivedThreadOptions} [options] The options to fetch archived threads
+ * @param {FetchChannelThreadsOptions} [options] The options to fetch archived threads
* @param {boolean} [cache=true] Whether to cache the new thread objects if they aren't already
* @returns {Promise}
*/
- async fetchArchived({ type = 'public', fetchAll = false, before, limit } = {}, cache = true) {
- let path = this.client.api.channels(this.channel.id);
- if (type === 'private' && !fetchAll) {
- path = path.users('@me');
- }
- let timestamp;
- let id;
- if (typeof before !== 'undefined') {
- if (before instanceof ThreadChannel || /^\d{16,19}$/.test(String(before))) {
- id = this.resolveId(before);
- timestamp = this.resolve(before)?.archivedAt?.toISOString();
- } else {
- try {
- timestamp = new Date(before).toISOString();
- } catch {
- throw new TypeError('INVALID_TYPE', 'before', 'DateResolvable or ThreadChannelResolvable');
+ async fetchArchived(options = {}, cache = true) {
+ if (this.client.user.bot) {
+ let { type = 'public', fetchAll = false, before, limit } = options;
+ let path = this.client.api.channels(this.channel.id);
+ if (type === 'private' && !fetchAll) {
+ path = path.users('@me');
+ }
+ let timestamp;
+ let id;
+ if (typeof before !== 'undefined') {
+ if (before instanceof ThreadChannel || /^\d{16,19}$/.test(String(before))) {
+ id = this.resolveId(before);
+ timestamp = this.resolve(before)?.archivedAt?.toISOString();
+ } else {
+ try {
+ timestamp = new Date(before).toISOString();
+ } catch {
+ throw new TypeError('INVALID_TYPE', 'before', 'DateResolvable or ThreadChannelResolvable');
+ }
}
}
+ const raw = await path.threads
+ .archived(type)
+ .get({ query: { before: type === 'private' && !fetchAll ? id : timestamp, limit } });
+ return this.constructor._mapThreads(raw, this.client, { parent: this.channel, cache });
+ } else {
+ return this.fetchActive(cache, { archived: true, ...options });
}
- const raw = await path.threads
- .archived(type)
- .get({ query: { before: type === 'private' && !fetchAll ? id : timestamp, limit } });
- return this.constructor._mapThreads(raw, this.client, { parent: this.channel, cache });
}
/**
* Discord.js self-bot specific options field for fetching active threads.
* @typedef {Object} FetchChannelThreadsOptions
+ * @property {boolean} [archived] Whether to fetch archived threads (default is false)
* @property {string} [sortBy] The order in which the threads should be fetched in (default is last_message_time)
* @property {string} [sortOrder] How the threads should be ordered (default is desc)
* @property {number} [limit] The maximum number of threads to return (default is 25)
@@ -169,7 +175,7 @@ class ThreadManager extends CachedManager {
? await this.client.api.guilds(this.channel.guild.id).threads.active.get()
: await this.client.api.channels(this.channel.id).threads.search.get({
query: {
- archived: false,
+ archived: options?.archived ?? false,
limit: options?.limit ?? 25,
offset: options?.offset ?? 0,
sort_by: options?.sortBy ?? 'last_message_time',
@@ -188,6 +194,10 @@ class ThreadManager extends CachedManager {
}, new Collection());
// Discord sends the thread id as id in this object
for (const rawMember of rawThreads.members) client.channels.cache.get(rawMember.id)?.members._add(rawMember);
+ // Patch firstMessage
+ for (const rawMessage of rawThreads.first_messages) {
+ client.channels.cache.get(rawMessage.id)?.messages._add(rawMessage);
+ }
return {
threads,
hasMore: rawThreads.has_more ?? false,
diff --git a/src/structures/ThreadChannel.js b/src/structures/ThreadChannel.js
index 2c67652..3245119 100644
--- a/src/structures/ThreadChannel.js
+++ b/src/structures/ThreadChannel.js
@@ -51,6 +51,15 @@ class ThreadChannel extends Channel {
if (data) this._patch(data, fromInteraction);
}
+ /**
+ * First message in the thread
+ * @type {?Message}
+ * @readonly
+ */
+ get firstMessage() {
+ return this.messages.cache.get(this.id);
+ }
+
_patch(data, partial = false) {
super._patch(data);
diff --git a/typings/index.d.ts b/typings/index.d.ts
index 4899d86..16d2410 100644
--- a/typings/index.d.ts
+++ b/typings/index.d.ts
@@ -2976,6 +2976,7 @@ export class TextInputComponent extends BaseMessageComponent {
export class ThreadChannel extends TextBasedChannelMixin(Channel, ['fetchWebhooks', 'createWebhook', 'setNSFW']) {
private constructor(guild: Guild, data?: RawThreadChannelData, client?: Client, fromInteraction?: boolean);
public archived: boolean | null;
+ public readonly firstMessage: Message | null;
public readonly archivedAt: Date | null;
public archiveTimestamp: number | null;
public readonly createdAt: Date | null;
@@ -4178,9 +4179,9 @@ export class ThreadManager extends CachedManager);
public channel: TextChannel | NewsChannel;
public fetch(options: ThreadChannelResolvable, cacheOptions?: BaseFetchOptions): Promise;
- public fetch(options?: FetchThreadsOptions, cacheOptions?: { cache?: boolean }): Promise;
- public fetchArchived(options?: FetchArchivedThreadOptions, cache?: boolean): Promise;
- public fetchActive(cache?: boolean): Promise;
+ public fetch(options?: FetchChannelThreadsOptions, cacheOptions?: { cache?: boolean }): Promise;
+ public fetchArchived(options?: FetchChannelThreadsOptions, cache?: boolean): Promise;
+ public fetchActive(cache?: boolean, options?: FetchChannelThreadsOptions): Promise;
}
export class ThreadMemberManager extends CachedManager {
@@ -5708,6 +5709,14 @@ export interface FetchArchivedThreadOptions {
limit?: number;
}
+export interface FetchChannelThreadsOptions {
+ archived?: boolean;
+ limit?: number;
+ offset?: number;
+ sort_by?: string;
+ sort_order?: string;
+}
+
export interface FetchBanOptions extends BaseFetchOptions {
user: UserResolvable;
}