From b8517cfcf3143ce5b749b4504567dc5a10616d2e Mon Sep 17 00:00:00 2001 From: Jiralite <33201955+Jiralite@users.noreply.github.com> Date: Sun, 26 Sep 2021 00:56:17 +0100 Subject: [PATCH 01/10] feat: add support for webhook thread fetch/edit/delete --- src/structures/Webhook.js | 53 +++++++++++++++++++++++++++++++++------ src/util/Options.js | 2 ++ typings/index.d.ts | 17 ++++++++++--- 3 files changed, 61 insertions(+), 11 deletions(-) diff --git a/src/structures/Webhook.js b/src/structures/Webhook.js index fb7991f16226..23c46c673fdb 100644 --- a/src/structures/Webhook.js +++ b/src/structures/Webhook.js @@ -105,6 +105,8 @@ class Webhook { * @property {MessageAttachment[]} [attachments] Attachments to send with the message * @property {MessageActionRow[]|MessageActionRowOptions[]} [components] * Action rows containing interactive components for the message (buttons, select menus) + * @property {Snowflake} [threadId] The id of the thread this message belongs to + * For interaction webhooks, this property is ignored */ /** @@ -235,18 +237,44 @@ class Webhook { return this; } + /** + * Options that can be passed to fetch a message. + * @typedef {options} WebhookFetchMessageOptions + * @property {boolean} [cache=true] Whether to cache the message. + * @property {Snowflake} [threadId] The id of the thread this message belongs to. + * For interaction webhooks, this property is ignored + */ + /** * Gets a message that was sent by this webhook. * @param {Snowflake|'@original'} message The id of the message to fetch - * @param {boolean} [cache=true] Whether to cache the message + * @param {boolean|WebhookFetchMessageOptions} [cacheOrOptions=true|cacheOrOptions={}] If + * {@link ClientOptions#allowWebhookThreadFetching} is `true`, this will be {@link WebhookFetchMessageOptions} + * to enable fetching messages in threads. Otherwise, this will be the `cache` parameter. * @returns {Promise} Returns the raw message data if the webhook was instantiated as a * {@link WebhookClient} or if the channel is uncached, otherwise a {@link Message} will be returned */ - async fetchMessage(message, cache = true) { + async fetchMessage(message, cacheOrOptions) { + const options = { cache: true, threadId: undefined }; + + if (this.client.options.allowedWebhookThreadFetching) { + options.cache = cacheOrOptions.cache ?? true; + options.threadId = cacheOrOptions.threadId; + } else { + options.cache = cacheOrOptions ?? true; + } + if (!this.token) throw new Error('WEBHOOK_TOKEN_UNAVAILABLE'); - const data = await this.client.api.webhooks(this.id, this.token).messages(message).get(); - return this.client.channels?.cache.get(data.channel_id)?.messages._add(data, cache) ?? data; + const data = await this.client.api + .webhooks(this.id, this.token) + .messages(message) + .get({ + query: { + thread_id: options.threadId, + }, + }); + return this.client.channels?.cache.get(data.channel_id)?.messages._add(data, options.cache) ?? data; } /** @@ -269,7 +297,13 @@ class Webhook { const d = await this.client.api .webhooks(this.id, this.token) .messages(typeof message === 'string' ? message : message.id) - .patch({ data, files }); + .patch({ + data, + files, + query: { + thread_id: messagePayload.options.threadId, + }, + }); const messageManager = this.client.channels?.cache.get(d.channel_id)?.messages; if (!messageManager) return d; @@ -294,15 +328,20 @@ class Webhook { /** * Delete a message that was sent by this webhook. * @param {MessageResolvable|'@original'} message The message to delete + * @param {Snowflake} [threadId] The id of the thread this message belongs to * @returns {Promise} */ - async deleteMessage(message) { + async deleteMessage(message, threadId) { if (!this.token) throw new Error('WEBHOOK_TOKEN_UNAVAILABLE'); await this.client.api .webhooks(this.id, this.token) .messages(typeof message === 'string' ? message : message.id) - .delete(); + .delete({ + query: { + thread_id: threadId, + }, + }); } /** diff --git a/src/util/Options.js b/src/util/Options.js index 206bc59f5b15..fde42cffdd2a 100644 --- a/src/util/Options.js +++ b/src/util/Options.js @@ -71,6 +71,8 @@ * @property {IntentsResolvable} intents Intents to enable for this connection * @property {WebsocketOptions} [ws] Options for the WebSocket * @property {HTTPOptions} [http] HTTP options + * @property {boolean} [allowWebhookThreadFetching] This changes {@link Webhook#fetchMessage}'s second parameter to + * accept {@link WebhookFetchMessageOptions} which allows the fetching of messages in threads. */ /** diff --git a/typings/index.d.ts b/typings/index.d.ts index 61251c5fa5ba..bde60ac466a2 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -2825,12 +2825,15 @@ export function WebhookMixin(Base?: Constructable): Constructable; + deleteMessage(message: MessageResolvable | APIMessage | '@original', threadId?: Snowflake): Promise; editMessage( message: MessageResolvable | '@original', options: string | MessagePayload | WebhookEditMessageOptions, ): Promise; - fetchMessage(message: Snowflake | '@original', cache?: boolean): Promise; + fetchMessage( + message: Snowflake | '@original', + cacheOrOptions?: boolean | WebhookFetchMessageOptions, + ): Promise; send(options: string | MessagePayload | WebhookMessageOptions): Promise; } @@ -3378,6 +3381,7 @@ export interface ClientOptions { ws?: WebSocketOptions; http?: HTTPOptions; rejectOnRateLimit?: string[] | ((data: RateLimitData) => boolean | Promise); + allowWebhookThreadFetching?: boolean; } export type ClientPresenceStatus = 'online' | 'idle' | 'dnd'; @@ -4779,7 +4783,7 @@ export interface WebhookClientDataURL { export type WebhookClientOptions = Pick< ClientOptions, - 'allowedMentions' | 'restTimeOffset' | 'restRequestTimeout' | 'retryLimit' | 'http' + 'allowedMentions' | 'restTimeOffset' | 'restRequestTimeout' | 'retryLimit' | 'http' | 'allowWebhookThreadFetching' >; export interface WebhookEditData { @@ -4790,9 +4794,14 @@ export interface WebhookEditData { export type WebhookEditMessageOptions = Pick< WebhookMessageOptions, - 'content' | 'embeds' | 'files' | 'allowedMentions' | 'components' | 'attachments' + 'content' | 'embeds' | 'files' | 'allowedMentions' | 'components' | 'attachments' | 'threadId' >; +export interface WebhookFetchMessageOptions { + cache?: boolean; + threadId?: Snowflake; +} + export interface WebhookMessageOptions extends Omit { username?: string; avatarURL?: string; From 7eefd0e51dc748bf5670662f68f368acd62d55e3 Mon Sep 17 00:00:00 2001 From: Jiralite <33201955+Jiralite@users.noreply.github.com> Date: Sun, 26 Sep 2021 01:05:01 +0100 Subject: [PATCH 02/10] fix(Webhook): correct client option --- src/structures/Webhook.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/Webhook.js b/src/structures/Webhook.js index 23c46c673fdb..7bbe47591d87 100644 --- a/src/structures/Webhook.js +++ b/src/structures/Webhook.js @@ -257,7 +257,7 @@ class Webhook { async fetchMessage(message, cacheOrOptions) { const options = { cache: true, threadId: undefined }; - if (this.client.options.allowedWebhookThreadFetching) { + if (this.client.options.allowWebhookThreadFetching) { options.cache = cacheOrOptions.cache ?? true; options.threadId = cacheOrOptions.threadId; } else { From 7051e067ee442812e1c177e413bf51dccf786758 Mon Sep 17 00:00:00 2001 From: Jiralite <33201955+Jiralite@users.noreply.github.com> Date: Sun, 26 Sep 2021 01:14:08 +0100 Subject: [PATCH 03/10] types: update fetch --- typings/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index bde60ac466a2..709608856cba 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -2119,7 +2119,7 @@ export class WebhookClient extends WebhookMixin(BaseClient) { message: MessageResolvable, options: string | MessagePayload | WebhookEditMessageOptions, ): Promise; - public fetchMessage(message: Snowflake, cache?: boolean): Promise; + public fetchMessage(message: Snowflake, cacheOrOptions?: boolean | WebhookFetchMessageOptions): Promise; public send(options: string | MessagePayload | WebhookMessageOptions): Promise; } From 529f4d9fcdd872522294def11fe34621c3e248c9 Mon Sep 17 00:00:00 2001 From: Jiralite <33201955+Jiralite@users.noreply.github.com> Date: Sun, 26 Sep 2021 01:35:39 +0100 Subject: [PATCH 04/10] docs(Webhook): keep consistency with other typedefs --- src/structures/Webhook.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/Webhook.js b/src/structures/Webhook.js index 7bbe47591d87..12112b9051e7 100644 --- a/src/structures/Webhook.js +++ b/src/structures/Webhook.js @@ -238,7 +238,7 @@ class Webhook { } /** - * Options that can be passed to fetch a message. + * Options that can be passed into fetchMessage. * @typedef {options} WebhookFetchMessageOptions * @property {boolean} [cache=true] Whether to cache the message. * @property {Snowflake} [threadId] The id of the thread this message belongs to. From 749eb9d5488d155610b5d0d02b1609285bf60106 Mon Sep 17 00:00:00 2001 From: Jiralite <33201955+Jiralite@users.noreply.github.com> Date: Sun, 26 Sep 2021 01:41:13 +0100 Subject: [PATCH 05/10] fix(Options): default allowWebhookThreadFetching --- src/util/Options.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/Options.js b/src/util/Options.js index fde42cffdd2a..ab7b0bb6d954 100644 --- a/src/util/Options.js +++ b/src/util/Options.js @@ -144,6 +144,7 @@ class Options extends null { invite: 'https://discord.gg', template: 'https://discord.new', }, + allowWebhookThreadFetching: false, }; } From 7965f01d5db652a922c096b029ed673357a314df Mon Sep 17 00:00:00 2001 From: Jiralite <33201955+Jiralite@users.noreply.github.com> Date: Sun, 26 Sep 2021 01:55:01 +0100 Subject: [PATCH 06/10] docs(Options): specify default value --- src/util/Options.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util/Options.js b/src/util/Options.js index ab7b0bb6d954..496731ffea14 100644 --- a/src/util/Options.js +++ b/src/util/Options.js @@ -71,8 +71,8 @@ * @property {IntentsResolvable} intents Intents to enable for this connection * @property {WebsocketOptions} [ws] Options for the WebSocket * @property {HTTPOptions} [http] HTTP options - * @property {boolean} [allowWebhookThreadFetching] This changes {@link Webhook#fetchMessage}'s second parameter to - * accept {@link WebhookFetchMessageOptions} which allows the fetching of messages in threads. + * @property {boolean} [allowWebhookThreadFetching=false] This changes {@link Webhook#fetchMessage}'s second parameter + * to accept {@link WebhookFetchMessageOptions} which allows the fetching of messages in threads. */ /** From 5e63b15b896a3042c1f579bda15981be8c81176c Mon Sep 17 00:00:00 2001 From: Jiralite <33201955+Jiralite@users.noreply.github.com> Date: Sun, 26 Sep 2021 16:19:28 +0100 Subject: [PATCH 07/10] refactor: remove client option --- src/structures/Webhook.js | 20 ++++++++------------ src/util/Options.js | 3 --- typings/index.d.ts | 7 +++---- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/structures/Webhook.js b/src/structures/Webhook.js index 12112b9051e7..51be8f9a4484 100644 --- a/src/structures/Webhook.js +++ b/src/structures/Webhook.js @@ -248,20 +248,16 @@ class Webhook { /** * Gets a message that was sent by this webhook. * @param {Snowflake|'@original'} message The id of the message to fetch - * @param {boolean|WebhookFetchMessageOptions} [cacheOrOptions=true|cacheOrOptions={}] If - * {@link ClientOptions#allowWebhookThreadFetching} is `true`, this will be {@link WebhookFetchMessageOptions} - * to enable fetching messages in threads. Otherwise, this will be the `cache` parameter. + * @param {WebhookFetchMessageOptions|boolean} [cacheOrOptions={}] The options to provide to fetch the message. + * A boolean may be passed instead to specify whether to cache the message. * @returns {Promise} Returns the raw message data if the webhook was instantiated as a * {@link WebhookClient} or if the channel is uncached, otherwise a {@link Message} will be returned */ - async fetchMessage(message, cacheOrOptions) { - const options = { cache: true, threadId: undefined }; - - if (this.client.options.allowWebhookThreadFetching) { - options.cache = cacheOrOptions.cache ?? true; - options.threadId = cacheOrOptions.threadId; + async fetchMessage(message, cacheOrOptions = { cache: true }) { + if (typeof cacheOrOptions === 'object') { + cacheOrOptions.cache ??= true; } else { - options.cache = cacheOrOptions ?? true; + cacheOrOptions = { cache: cacheOrOptions }; } if (!this.token) throw new Error('WEBHOOK_TOKEN_UNAVAILABLE'); @@ -271,10 +267,10 @@ class Webhook { .messages(message) .get({ query: { - thread_id: options.threadId, + thread_id: cacheOrOptions.threadId, }, }); - return this.client.channels?.cache.get(data.channel_id)?.messages._add(data, options.cache) ?? data; + return this.client.channels?.cache.get(data.channel_id)?.messages._add(data, cacheOrOptions.cache) ?? data; } /** diff --git a/src/util/Options.js b/src/util/Options.js index 496731ffea14..206bc59f5b15 100644 --- a/src/util/Options.js +++ b/src/util/Options.js @@ -71,8 +71,6 @@ * @property {IntentsResolvable} intents Intents to enable for this connection * @property {WebsocketOptions} [ws] Options for the WebSocket * @property {HTTPOptions} [http] HTTP options - * @property {boolean} [allowWebhookThreadFetching=false] This changes {@link Webhook#fetchMessage}'s second parameter - * to accept {@link WebhookFetchMessageOptions} which allows the fetching of messages in threads. */ /** @@ -144,7 +142,6 @@ class Options extends null { invite: 'https://discord.gg', template: 'https://discord.new', }, - allowWebhookThreadFetching: false, }; } diff --git a/typings/index.d.ts b/typings/index.d.ts index 709608856cba..86a155367839 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -2119,7 +2119,7 @@ export class WebhookClient extends WebhookMixin(BaseClient) { message: MessageResolvable, options: string | MessagePayload | WebhookEditMessageOptions, ): Promise; - public fetchMessage(message: Snowflake, cacheOrOptions?: boolean | WebhookFetchMessageOptions): Promise; + public fetchMessage(message: Snowflake, cacheOrOptions?: WebhookFetchMessageOptions | boolean): Promise; public send(options: string | MessagePayload | WebhookMessageOptions): Promise; } @@ -2832,7 +2832,7 @@ export interface PartialWebhookFields { ): Promise; fetchMessage( message: Snowflake | '@original', - cacheOrOptions?: boolean | WebhookFetchMessageOptions, + cacheOrOptions?: WebhookFetchMessageOptions | boolean, ): Promise; send(options: string | MessagePayload | WebhookMessageOptions): Promise; } @@ -3381,7 +3381,6 @@ export interface ClientOptions { ws?: WebSocketOptions; http?: HTTPOptions; rejectOnRateLimit?: string[] | ((data: RateLimitData) => boolean | Promise); - allowWebhookThreadFetching?: boolean; } export type ClientPresenceStatus = 'online' | 'idle' | 'dnd'; @@ -4783,7 +4782,7 @@ export interface WebhookClientDataURL { export type WebhookClientOptions = Pick< ClientOptions, - 'allowedMentions' | 'restTimeOffset' | 'restRequestTimeout' | 'retryLimit' | 'http' | 'allowWebhookThreadFetching' + 'allowedMentions' | 'restTimeOffset' | 'restRequestTimeout' | 'retryLimit' | 'http' >; export interface WebhookEditData { From 7635bd38b2056bb043ea4f2e8faa1b6d0f5a28c6 Mon Sep 17 00:00:00 2001 From: Jiralite <33201955+Jiralite@users.noreply.github.com> Date: Sun, 26 Sep 2021 23:37:51 +0100 Subject: [PATCH 08/10] types: deprecate boolean --- typings/index.d.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index 86a155367839..3601e14f09ee 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -2119,7 +2119,11 @@ export class WebhookClient extends WebhookMixin(BaseClient) { message: MessageResolvable, options: string | MessagePayload | WebhookEditMessageOptions, ): Promise; - public fetchMessage(message: Snowflake, cacheOrOptions?: WebhookFetchMessageOptions | boolean): Promise; + public fetchMessage(message: Snowflake, options?: WebhookFetchMessageOptions): Promise; + /* tslint:disable:unified-signatures */ + /** @deprecated */ + public fetchMessage(message: Snowflake, cache?: boolean): Promise; + /* tslint:enable:unified-signatures */ public send(options: string | MessagePayload | WebhookMessageOptions): Promise; } @@ -2830,10 +2834,11 @@ export interface PartialWebhookFields { message: MessageResolvable | '@original', options: string | MessagePayload | WebhookEditMessageOptions, ): Promise; - fetchMessage( - message: Snowflake | '@original', - cacheOrOptions?: WebhookFetchMessageOptions | boolean, - ): Promise; + fetchMessage(message: Snowflake | '@original', options?: WebhookFetchMessageOptions): Promise; + /* tslint:disable:unified-signatures */ + /** @deprecated */ + fetchMessage(message: Snowflake | '@original', cache?: boolean): Promise; + /* tslint:enable:unified-signatures */ send(options: string | MessagePayload | WebhookMessageOptions): Promise; } From 11a57946ce12d2484b0460bf53a8f3a5e137becc Mon Sep 17 00:00:00 2001 From: Jiralite <33201955+Jiralite@users.noreply.github.com> Date: Sun, 26 Sep 2021 23:38:16 +0100 Subject: [PATCH 09/10] docs(Webhook): add deprecated text --- src/structures/Webhook.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/Webhook.js b/src/structures/Webhook.js index 51be8f9a4484..3afc3265d901 100644 --- a/src/structures/Webhook.js +++ b/src/structures/Webhook.js @@ -249,7 +249,7 @@ class Webhook { * Gets a message that was sent by this webhook. * @param {Snowflake|'@original'} message The id of the message to fetch * @param {WebhookFetchMessageOptions|boolean} [cacheOrOptions={}] The options to provide to fetch the message. - * A boolean may be passed instead to specify whether to cache the message. + * A **deprecated** boolean may be passed instead to specify whether to cache the message. * @returns {Promise} Returns the raw message data if the webhook was instantiated as a * {@link WebhookClient} or if the channel is uncached, otherwise a {@link Message} will be returned */ From f26437611cbc57d74fd45ef1538e78a472ed3270 Mon Sep 17 00:00:00 2001 From: Jiralite <33201955+Jiralite@users.noreply.github.com> Date: Tue, 28 Sep 2021 11:17:00 +0100 Subject: [PATCH 10/10] refactor: tidy fetchMessage handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Antonio Román --- src/structures/Webhook.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/structures/Webhook.js b/src/structures/Webhook.js index 3afc3265d901..31db5249a3f5 100644 --- a/src/structures/Webhook.js +++ b/src/structures/Webhook.js @@ -254,9 +254,7 @@ class Webhook { * {@link WebhookClient} or if the channel is uncached, otherwise a {@link Message} will be returned */ async fetchMessage(message, cacheOrOptions = { cache: true }) { - if (typeof cacheOrOptions === 'object') { - cacheOrOptions.cache ??= true; - } else { + if (typeof cacheOrOptions === 'boolean') { cacheOrOptions = { cache: cacheOrOptions }; }