diff --git a/packages/discord.js/src/client/WebhookClient.js b/packages/discord.js/src/client/WebhookClient.js deleted file mode 100644 index 17b0e0972..000000000 --- a/packages/discord.js/src/client/WebhookClient.js +++ /dev/null @@ -1,119 +0,0 @@ -'use strict'; - -const { DiscordjsError, ErrorCodes } = require('../errors/index.js'); -const { Webhook } = require('../structures/Webhook.js'); -const { parseWebhookURL } = require('../util/Util.js'); -const { BaseClient } = require('./BaseClient.js'); - -/** - * The webhook client. - * - * @implements {Webhook} - * @extends {BaseClient} - */ -class WebhookClient extends BaseClient { - /** - * Represents the credentials used for a webhook in the form of its id and token. - * - * @typedef {Object} WebhookClientDataIdWithToken - * @property {Snowflake} id The webhook's id - * @property {string} token The webhook's token - */ - - /** - * Represents the credentials used for a webhook in the form of a URL. - * - * @typedef {Object} WebhookClientDataURL - * @property {string} url The full URL for the webhook - */ - - /** - * Represents the credentials used for a webhook. - * - * @typedef {WebhookClientDataIdWithToken|WebhookClientDataURL} WebhookClientData - */ - - /** - * Options for a webhook client. - * - * @typedef {Object} WebhookClientOptions - * @property {MessageMentionOptions} [allowedMentions] Default value for {@link BaseMessageOptions#allowedMentions} - * @property {RESTOptions} [rest] Options for the REST manager - */ - - /** - * @param {WebhookClientData} data The data of the webhook - * @param {WebhookClientOptions} [options] Options for the webhook client - */ - constructor(data, options) { - super(options); - Object.defineProperty(this, 'client', { value: this }); - let { id, token } = data; - - if ('url' in data) { - const parsed = parseWebhookURL(data.url); - if (!parsed) { - throw new DiscordjsError(ErrorCodes.WebhookURLInvalid); - } - - ({ id, token } = parsed); - } - - this.id = id; - Object.defineProperty(this, 'token', { value: token, writable: true, configurable: true }); - } - - /** - * The options the webhook client was instantiated with. - * - * @type {WebhookClientOptions} - * @name WebhookClient#options - */ - - // These are here only for documentation purposes - they are implemented by Webhook - - /* eslint-disable jsdoc/check-param-names, getter-return */ - /** - * Sends a message with this webhook. - * - * @param {string|MessagePayload|WebhookMessageCreateOptions} options The content for the reply - * @returns {Promise} - */ - async send() {} - - /** - * Gets a message that was sent by this webhook. - * - * @param {Snowflake} message The id of the message to fetch - * @param {WebhookFetchMessageOptions} [options] The options to provide to fetch the message. - * @returns {Promise} Returns the message sent by this webhook - */ - async fetchMessage() {} - - /** - * Edits a message that was sent by this webhook. - * - * @param {MessageResolvable} message The message to edit - * @param {string|MessagePayload|WebhookMessageEditOptions} options The options to provide - * @returns {Promise} Returns the message edited by this webhook - */ - async editMessage() {} - - sendSlackMessage() {} - - edit() {} - - delete() {} - - deleteMessage() {} - - get createdTimestamp() {} - - get createdAt() {} - - get url() {} -} - -Webhook.applyToClass(WebhookClient); - -exports.WebhookClient = WebhookClient; diff --git a/packages/discord.js/src/errors/ErrorCodes.js b/packages/discord.js/src/errors/ErrorCodes.js index cbdbfab4b..6f2fc8db1 100644 --- a/packages/discord.js/src/errors/ErrorCodes.js +++ b/packages/discord.js/src/errors/ErrorCodes.js @@ -77,7 +77,6 @@ * * @property {'WebhookMessage'} WebhookMessage * @property {'WebhookTokenUnavailable'} WebhookTokenUnavailable - * @property {'WebhookURLInvalid'} WebhookURLInvalid * @property {'WebhookApplication'} WebhookApplication * * @property {'MessageReferenceMissing'} MessageReferenceMissing @@ -212,7 +211,6 @@ const keys = [ 'WebhookMessage', 'WebhookTokenUnavailable', - 'WebhookURLInvalid', 'WebhookApplication', 'MessageReferenceMissing', diff --git a/packages/discord.js/src/errors/Messages.js b/packages/discord.js/src/errors/Messages.js index 177d52d84..b9a54f998 100644 --- a/packages/discord.js/src/errors/Messages.js +++ b/packages/discord.js/src/errors/Messages.js @@ -82,7 +82,6 @@ const Messages = { [ErrorCodes.WebhookMessage]: 'The message was not sent by a webhook.', [ErrorCodes.WebhookTokenUnavailable]: 'This action requires a webhook token, but none is available.', - [ErrorCodes.WebhookURLInvalid]: 'The provided webhook URL is not valid.', [ErrorCodes.WebhookApplication]: 'This message webhook belongs to an application and cannot be fetched.', [ErrorCodes.MessageReferenceMissing]: 'The message does not reference another message', diff --git a/packages/discord.js/src/index.js b/packages/discord.js/src/index.js index 6f9ecc520..71bb83f79 100644 --- a/packages/discord.js/src/index.js +++ b/packages/discord.js/src/index.js @@ -8,7 +8,6 @@ exports.Client = require('./client/Client.js').Client; exports.Shard = require('./sharding/Shard.js').Shard; exports.ShardClientUtil = require('./sharding/ShardClientUtil.js').ShardClientUtil; exports.ShardingManager = require('./sharding/ShardingManager.js').ShardingManager; -exports.WebhookClient = require('./client/WebhookClient.js').WebhookClient; // Errors exports.DiscordjsError = require('./errors/DJSError.js').DiscordjsError; diff --git a/packages/discord.js/src/structures/MessagePayload.js b/packages/discord.js/src/structures/MessagePayload.js index 58d62c92f..8b5388c71 100644 --- a/packages/discord.js/src/structures/MessagePayload.js +++ b/packages/discord.js/src/structures/MessagePayload.js @@ -47,15 +47,14 @@ class MessagePayload { } /** - * Whether or not the target is a {@link Webhook} or a {@link WebhookClient} + * Whether or not the target is a {@link Webhook} * * @type {boolean} * @readonly */ get isWebhook() { const { Webhook } = require('./Webhook.js'); - const { WebhookClient } = require('../client/WebhookClient.js'); - return this.target instanceof Webhook || this.target instanceof WebhookClient; + return this.target instanceof Webhook; } /** @@ -302,7 +301,7 @@ exports.MessagePayload = MessagePayload; /** * A target for a message. * - * @typedef {TextBasedChannels|ChannelManager|Webhook|WebhookClient|BaseInteraction|InteractionWebhook| + * @typedef {TextBasedChannels|ChannelManager|Webhook|BaseInteraction|InteractionWebhook| * Message|MessageManager} MessageTarget */ diff --git a/packages/discord.js/src/structures/Webhook.js b/packages/discord.js/src/structures/Webhook.js index 046aa1e4d..cb3db87fa 100644 --- a/packages/discord.js/src/structures/Webhook.js +++ b/packages/discord.js/src/structures/Webhook.js @@ -95,9 +95,9 @@ class Webhook { /** * The owner of the webhook * - * @type {?(User|APIUser)} + * @type {?User} */ - this.owner = this.client.users?._add(data.user) ?? data.user; + this.owner = this.client.users._add(data.user); } else { this.owner ??= null; } @@ -119,7 +119,7 @@ class Webhook { * * @type {?(Guild|APIGuild)} */ - this.sourceGuild = this.client.guilds?.cache.get(data.source_guild.id) ?? data.source_guild; + this.sourceGuild = this.client.guilds.cache.get(data.source_guild.id) ?? data.source_guild; } else { this.sourceGuild ??= null; } @@ -130,7 +130,7 @@ class Webhook { * * @type {?(AnnouncementChannel|APIChannel)} */ - this.sourceChannel = this.client.channels?.cache.get(data.source_channel?.id) ?? data.source_channel; + this.sourceChannel = this.client.channels.cache.get(data.source_channel?.id) ?? data.source_channel; } else { this.sourceChannel ??= null; } @@ -248,7 +248,6 @@ class Webhook { auth: false, }); - if (!this.client.channels) return data; return ( this.client.channels.cache.get(data.channel_id)?.messages._add(data, false) ?? new (getMessage())(this.client, data) @@ -345,7 +344,6 @@ class Webhook { auth: false, }); - if (!this.client.channels) return data; return ( this.client.channels.cache.get(data.channel_id)?.messages._add(data, false) ?? new (getMessage())(this.client, data) @@ -384,10 +382,7 @@ class Webhook { }, ); - const channelManager = this.client.channels; - if (!channelManager) return data; - - const messageManager = channelManager.cache.get(data.channel_id)?.messages; + const messageManager = this.client.channels.cache.get(data.channel_id)?.messages; if (!messageManager) return new (getMessage())(this.client, data); const existing = messageManager.cache.get(data.id); diff --git a/packages/discord.js/src/util/Util.js b/packages/discord.js/src/util/Util.js index ba28771b7..ceccbd4ca 100644 --- a/packages/discord.js/src/util/Util.js +++ b/packages/discord.js/src/util/Util.js @@ -469,11 +469,19 @@ function cleanCodeBlockContent(text) { return text.replaceAll('```', '`\u200B``'); } +/** + * Represents the credentials used for a webhook in the form of its id and token. + * + * @typedef {Object} WebhookDataIdWithToken + * @property {Snowflake} id The webhook's id + * @property {string} token The webhook's token + */ + /** * Parses a webhook URL for the id and token. * * @param {string} url The URL to parse - * @returns {?WebhookClientDataIdWithToken} `null` if the URL is invalid, otherwise the id and the token + * @returns {?WebhookDataIdWithToken} `null` if the URL is invalid, otherwise the id and the token */ function parseWebhookURL(url) { const matches = diff --git a/packages/discord.js/test/webhooktest.js b/packages/discord.js/test/webhooktest.js index a34abdb9a..773ae73b9 100644 --- a/packages/discord.js/test/webhooktest.js +++ b/packages/discord.js/test/webhooktest.js @@ -7,8 +7,8 @@ const { setTimeout: sleep } = require('node:timers/promises'); const util = require('node:util'); const { GatewayIntentBits } = require('discord-api-types/v10'); const { fetch } = require('undici'); +const { Client, MessageAttachment, Embed } = require('../src/index.js'); const { owner, token, webhookChannel, webhookToken } = require('./auth.js'); -const { Client, MessageAttachment, Embed, WebhookClient } = require('../src/index.js'); const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages] }); @@ -84,30 +84,26 @@ client.on('messageCreate', async message => { if (message.author.id !== owner) return; const match = message.content.match(/^do (.+)$/); const hooks = [ - { type: 'WebhookClient', hook: new WebhookClient({ id: webhookChannel, token: webhookToken }) }, { type: 'TextChannel#fetchWebhooks', hook: await message.channel.fetchWebhooks().then(x => x.first()) }, { type: 'Guild#fetchWebhooks', hook: await message.guild.fetchWebhooks().then(x => x.first()) }, ]; if (match?.[1] === 'it') { - /* eslint-disable no-await-in-loop */ for (const { type, hook } of hooks) { for (const [i, test] of tests.entries()) { await message.channel.send(`**#${i}-Hook: ${type}**\n\`\`\`js\n${test.toString()}\`\`\``); - await test(message, hook).catch(e => message.channel.send(`Error!\n\`\`\`\n${e}\`\`\``)); + await test(message, hook).catch(error => message.channel.send(`Error!\n\`\`\`\n${error}\`\`\``)); await sleep(1_000); } } - /* eslint-enable no-await-in-loop */ } else if (match) { - const n = parseInt(match[1]) || 0; + const n = Number.parseInt(match[1]) || 0; const test = tests.slice(n)[0]; const i = tests.indexOf(test); - /* eslint-disable no-await-in-loop */ + for (const { type, hook } of hooks) { await message.channel.send(`**#${i}-Hook: ${type}**\n\`\`\`js\n${test.toString()}\`\`\``); - await test(message, hook).catch(e => message.channel.send(`Error!\n\`\`\`\n${e}\`\`\``)); + await test(message, hook).catch(error => message.channel.send(`Error!\n\`\`\`\n${error}\`\`\``)); } - /* eslint-enable no-await-in-loop */ } }); diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index ad57bdc3c..e3d1c1393 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -493,11 +493,11 @@ export abstract class Base { } export class BaseClient extends AsyncEventEmitter implements AsyncDisposable { - public constructor(options?: ClientOptions | WebhookClientOptions); + public constructor(options?: ClientOptions); private decrementMaxListeners(): void; private incrementMaxListeners(): void; - public options: ClientOptions | WebhookClientOptions; + public options: ClientOptions; public rest: REST; public destroy(): void; public toJSON(...props: Record[]): unknown; @@ -3742,7 +3742,7 @@ export function fetchRecommendedShardCount(token: string, options?: FetchRecomme export function flatten(obj: unknown, ...props: Record[]): unknown; export function parseEmoji(text: string): PartialEmoji | null; -export function parseWebhookURL(url: string): WebhookClientDataIdWithToken | null; +export function parseWebhookURL(url: string): WebhookDataIdWithToken | null; export function resolveColor(color: ColorResolvable): number; export function resolveSKUId(resolvable: SKUResolvable): Snowflake | null; export function verifyString(data: string, error?: typeof Error, errorMessage?: string, allowEmpty?: boolean): string; @@ -3828,7 +3828,7 @@ export class Webhook { public readonly client: Client; public guildId: Snowflake; public name: string; - public owner: Type extends WebhookType.Incoming ? APIUser | User | null : APIUser | User; + public owner: Type extends WebhookType.Incoming ? User | null : User; public sourceGuild: Type extends WebhookType.ChannelFollower ? APIPartialGuild | Guild : null; public sourceChannel: Type extends WebhookType.ChannelFollower ? AnnouncementChannel | APIPartialChannel : null; public token: Type extends WebhookType.Incoming @@ -3847,7 +3847,7 @@ export class Webhook { | VoiceChannel | null; public isUserCreated(): this is Webhook & { - owner: APIUser | User; + owner: User; }; public isApplicationCreated(): this is Webhook; public isIncoming(): this is Webhook; @@ -3861,20 +3861,6 @@ export class Webhook { public send(options: MessagePayload | WebhookMessageCreateOptions | string): Promise>; } -export interface WebhookClient extends WebhookFields, BaseClient<{}> {} -export class WebhookClient extends BaseClient<{}> { - public constructor(data: WebhookClientData, options?: WebhookClientOptions); - public readonly client: this; - public options: WebhookClientOptions; - public token: string; - public editMessage( - message: MessageResolvable, - options: MessagePayload | WebhookMessageEditOptions | string, - ): Promise; - public fetchMessage(message: Snowflake, options?: WebhookFetchMessageOptions): Promise; - public send(options: MessagePayload | WebhookMessageCreateOptions | string): Promise; -} - export class Widget extends Base { private constructor(client: Client, data: APIGuildWidget); private _patch(data: APIGuildWidget): void; @@ -4064,7 +4050,6 @@ export enum DiscordjsErrorCodes { WebhookMessage = 'WebhookMessage', WebhookTokenUnavailable = 'WebhookTokenUnavailable', - WebhookURLInvalid = 'WebhookURLInvalid', WebhookApplication = 'WebhookApplication', MessageReferenceMissing = 'MessageReferenceMissing', @@ -5576,7 +5561,8 @@ export interface ClientFetchInviteOptions { withCounts?: boolean; } -export interface ClientOptions extends WebhookClientOptions { +export interface ClientOptions { + allowedMentions?: MessageMentionOptions; closeTimeout?: number; enforceNonce?: boolean; failIfNotExists?: boolean; @@ -5585,6 +5571,7 @@ export interface ClientOptions extends WebhookClientOptions { makeCache?: CacheFactory; partials?: readonly Partials[]; presence?: PresenceData; + rest?: Partial; sweepers?: SweeperOptions; waitGuildTimeout?: number; ws?: Partial; @@ -6873,8 +6860,7 @@ export type MessageTarget = | Message | MessageManager | TextBasedChannel - | Webhook - | WebhookClient; + | Webhook; export interface MultipleShardRespawnOptions { respawnDelay?: number; @@ -7248,22 +7234,11 @@ export interface VoiceStateEditOptions { suppressed?: boolean; } -export type WebhookClientData = WebhookClientDataIdWithToken | WebhookClientDataURL; - -export interface WebhookClientDataIdWithToken { +export interface WebhookDataIdWithToken { id: Snowflake; token: string; } -export interface WebhookClientDataURL { - url: string; -} - -export interface WebhookClientOptions { - allowedMentions?: MessageMentionOptions; - rest?: Partial; -} - export interface WebhookDeleteOptions { reason?: string; token?: string; diff --git a/packages/discord.js/typings/index.test-d.ts b/packages/discord.js/typings/index.test-d.ts index 25e0fd1f9..7afce5f9a 100644 --- a/packages/discord.js/typings/index.test-d.ts +++ b/packages/discord.js/typings/index.test-d.ts @@ -10,7 +10,6 @@ import type { APIInteractionDataResolvedChannel, APIInteractionDataResolvedGuildMember, APIInteractionGuildMember, - APIMessage, APIPartialChannel, APIPartialGuild, APIRole, @@ -231,7 +230,6 @@ import { UserSelectMenuComponent, UserSelectMenuInteraction, Webhook, - WebhookClient, } from './index.js'; // Test type transformation: @@ -2683,7 +2681,6 @@ expectType(user.toString()); expectType(guildMember.toString()); declare const webhook: Webhook; -declare const webhookClient: WebhookClient; declare const interactionWebhook: InteractionWebhook; declare const snowflake: Snowflake; @@ -2692,10 +2689,6 @@ expectType>>(webhook.editMessage(snowflake, 'content')); expectType>>(webhook.fetchMessage(snowflake)); expectType>(webhook.edit({ name: 'name' })); -expectType>(webhookClient.send('content')); -expectType>(webhookClient.editMessage(snowflake, 'content')); -expectType>(webhookClient.fetchMessage(snowflake)); - expectType>(interactionWebhook.client); expectType>(interactionWebhook.send('content')); expectType>(interactionWebhook.editMessage(snowflake, 'content'));