From 8af6268e7ba080dd52b91a8d83699b0262552380 Mon Sep 17 00:00:00 2001 From: suneettipirneni Date: Sun, 17 Oct 2021 16:54:18 -0400 Subject: [PATCH 1/4] feat: add typeguards to webhooks --- src/structures/Webhook.js | 16 ++++++++++++++++ typings/index.d.ts | 8 +++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/structures/Webhook.js b/src/structures/Webhook.js index 0bffaa1101e1..e193e3980059 100644 --- a/src/structures/Webhook.js +++ b/src/structures/Webhook.js @@ -395,6 +395,22 @@ class Webhook { return this.client.rest.cdn.Avatar(this.id, this.avatar, format, size); } + /** + * Whether or not this webhook is a channel follower webhook. + * @returns {boolean} + */ + isChannelFollower() { + return this.type === WebhookTypes.Incoming; + } + + /** + * Whether or not this webhook is an incoming webhook. + * @returns {boolean} + */ + isIncoming() { + return this.type === WebhookTypes['Channel Follower']; + } + static applyToClass(structure, ignore = []) { for (const prop of [ 'send', diff --git a/typings/index.d.ts b/typings/index.d.ts index fb954f29314e..3f19762eebad 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -2200,10 +2200,12 @@ export class Webhook extends WebhookMixin() { public guildId: Snowflake; public name: string; public owner: User | APIUser | null; - public sourceGuild: Guild | APIPartialGuild | null; - public sourceChannel: NewsChannel | APIPartialChannel | null; - public token: string | null; public type: WebhookType; + public isIncoming(): this is this & { token: string }; + public isChannelFollower(): this is this & { + sourceGuild: Guild | APIPartialGuild; + sourceChannel: NewsChannel | APIPartialChannel; + }; } export class WebhookClient extends WebhookMixin(BaseClient) { From 9705f2414822650f952066c579135920a57c1db9 Mon Sep 17 00:00:00 2001 From: suneettipirneni Date: Sun, 17 Oct 2021 17:44:39 -0400 Subject: [PATCH 2/4] fix: typeguard logic --- src/structures/Webhook.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/structures/Webhook.js b/src/structures/Webhook.js index e193e3980059..3a6e4c9abf32 100644 --- a/src/structures/Webhook.js +++ b/src/structures/Webhook.js @@ -400,7 +400,7 @@ class Webhook { * @returns {boolean} */ isChannelFollower() { - return this.type === WebhookTypes.Incoming; + return this.type === WebhookTypes['Channel Follower']; } /** @@ -408,7 +408,7 @@ class Webhook { * @returns {boolean} */ isIncoming() { - return this.type === WebhookTypes['Channel Follower']; + return this.type === WebhookTypes.Incoming; } static applyToClass(structure, ignore = []) { From 473e0e590c23bf755544593283eb77aaef160f16 Mon Sep 17 00:00:00 2001 From: suneettipirneni Date: Sun, 17 Oct 2021 17:53:04 -0400 Subject: [PATCH 3/4] chore: revert field deletion --- typings/index.d.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/typings/index.d.ts b/typings/index.d.ts index 3f19762eebad..c1702bd7696f 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -2200,6 +2200,9 @@ export class Webhook extends WebhookMixin() { public guildId: Snowflake; public name: string; public owner: User | APIUser | null; + public sourceGuild: Guild | APIPartialGuild | null; + public sourceChannel: NewsChannel | APIPartialChannel | null; + public token: string | null; public type: WebhookType; public isIncoming(): this is this & { token: string }; public isChannelFollower(): this is this & { From bbddf7d1b5385ccd7006524da2d049cca910ff72 Mon Sep 17 00:00:00 2001 From: suneettipirneni Date: Sun, 17 Oct 2021 18:06:15 -0400 Subject: [PATCH 4/4] chore: add type tests --- typings/tests.ts | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/typings/tests.ts b/typings/tests.ts index 03aa9898be78..59e962374e5a 100644 --- a/typings/tests.ts +++ b/typings/tests.ts @@ -1,4 +1,10 @@ -import { APIGuildMember, APIInteractionGuildMember, APIMessage } from 'discord-api-types/v9'; +import { + APIGuildMember, + APIInteractionGuildMember, + APIMessage, + APIPartialChannel, + APIPartialGuild, +} from 'discord-api-types/v9'; import { ApplicationCommand, ApplicationCommandChannelOptionData, @@ -473,7 +479,7 @@ client.on('messageReactionRemoveAll', async message => { // This is to check that stuff is the right type declare const assertIsMessage: (m: Promise) => void; -client.on('messageCreate', message => { +client.on('messageCreate', async message => { const { channel } = message; assertIsMessage(channel.send('string')); assertIsMessage(channel.send({})); @@ -568,6 +574,22 @@ client.on('messageCreate', message => { }, }); + const webhook = await message.fetchWebhook(); + + if (webhook.isChannelFollower()) { + assertType(webhook.sourceGuild); + assertType(webhook.sourceChannel); + } else if (webhook.isIncoming()) { + assertType(webhook.token); + } + + // @ts-expect-error + assertType(webhook.sourceGuild); + // @ts-expect-error + assertType(webhook.sourceChannel); + // @ts-expect-error + assertType(webhook.token); + channel.awaitMessageComponent({ filter: i => { assertType(i);