diff --git a/src/structures/APIMessage.js b/src/structures/APIMessage.js index c9a0528b83a2..9ef29907874d 100644 --- a/src/structures/APIMessage.js +++ b/src/structures/APIMessage.js @@ -1,7 +1,6 @@ 'use strict'; const BaseMessageComponent = require('./BaseMessageComponent'); -const MessageAttachment = require('./MessageAttachment'); const MessageEmbed = require('./MessageEmbed'); const { RangeError } = require('../errors'); const DataResolver = require('../util/DataResolver'); @@ -308,82 +307,16 @@ class APIMessage { return { attachment, name, file: resource }; } - /** - * Partitions embeds and attachments. - * @param {Array} items Items to partition - * @returns {Array} - */ - static partitionMessageAdditions(items) { - const embeds = []; - const files = []; - for (const item of items) { - if (item instanceof MessageEmbed) { - embeds.push(item); - } else if (item instanceof MessageAttachment) { - files.push(item); - } - } - - return [embeds, files]; - } - - /** - * Transforms the user-level arguments into a final options object. Passing a transformed options object alone into - * this method will keep it the same, allowing for the reuse of the final options object. - * @param {string} [content] Content to send - * @param {MessageOptions|WebhookMessageOptions|MessageAdditions} [options={}] Options to use - * @param {MessageOptions|WebhookMessageOptions} [extra={}] Extra options to add onto transformed options - * @param {boolean} [isWebhook=false] Whether or not to use WebhookMessageOptions as the result - * @returns {MessageOptions|WebhookMessageOptions} - */ - static transformOptions(content, options, extra = {}, isWebhook = false) { - if (!options && typeof content === 'object' && !Array.isArray(content)) { - options = content; - content = undefined; - } - - if (!options) { - options = {}; - } else if (options instanceof MessageEmbed) { - return isWebhook ? { content, embeds: [options], ...extra } : { content, embed: options, ...extra }; - } else if (options instanceof MessageAttachment) { - return { content, files: [options], ...extra }; - } - - if (Array.isArray(options)) { - const [embeds, files] = this.partitionMessageAdditions(options); - return isWebhook ? { content, embeds, files, ...extra } : { content, embed: embeds[0], files, ...extra }; - } else if (Array.isArray(content)) { - const [embeds, files] = this.partitionMessageAdditions(content); - if (embeds.length || files.length) { - return isWebhook ? { embeds, files, ...extra } : { embed: embeds[0], files, ...extra }; - } - } - - return { content, ...options, ...extra }; - } - /** * Creates an `APIMessage` from user-level arguments. * @param {MessageTarget} target Target to send to - * @param {string} [content] Content to send - * @param {MessageOptions|WebhookMessageOptions|MessageAdditions} [options={}] Options to use - * @param {MessageOptions|WebhookMessageOptions} [extra={}] - Extra options to add onto transformed options + * @param {string|MessageOptions|WebhookMessageOptions} options Options or content to use + * @param {MessageOptions|WebhookMessageOptions} [extra={}] - Extra options to add onto specified options * @returns {MessageOptions|WebhookMessageOptions} */ - static create(target, content, options, extra = {}) { - const Interaction = require('./Interaction'); - const InteractionWebhook = require('./InteractionWebhook'); - const Webhook = require('./Webhook'); - const WebhookClient = require('../client/WebhookClient'); - - const isWebhook = - target instanceof Interaction || - target instanceof InteractionWebhook || - target instanceof Webhook || - target instanceof WebhookClient; - const transformed = this.transformOptions(content, options, extra, isWebhook); - return new this(target, transformed); + static create(target, options, extra = {}) { + if (typeof options === 'string') return new this(target, { content: options, ...extra }); + else return new this(target, { ...options, ...extra }); } } @@ -393,8 +326,3 @@ module.exports = APIMessage; * A target for a message. * @typedef {TextChannel|DMChannel|User|GuildMember|Webhook|WebhookClient|Interaction|InteractionWebhook} MessageTarget */ - -/** - * Additional items that can be sent with a message. - * @typedef {MessageEmbed|MessageAttachment|Array} MessageAdditions - */ diff --git a/src/structures/InteractionWebhook.js b/src/structures/InteractionWebhook.js index 2bb197202400..68efb3970b36 100644 --- a/src/structures/InteractionWebhook.js +++ b/src/structures/InteractionWebhook.js @@ -28,8 +28,7 @@ class InteractionWebhook { /* eslint-disable no-empty-function, valid-jsdoc */ /** * Sends a message with this webhook. - * @param {string|APIMessage|MessageAdditions} content The content for the reply - * @param {InteractionReplyOptions} [options] Additional options for the reply + * @param {string|APIMessage|InteractionReplyOptions} options The content for the reply * @returns {Promise} */ send() {} diff --git a/src/structures/Message.js b/src/structures/Message.js index 39ace4b9d296..56c788a35015 100644 --- a/src/structures/Message.js +++ b/src/structures/Message.js @@ -544,8 +544,7 @@ class Message extends Base { /** * Edits the content of the message. - * @param {?(string|APIMessage)} [content] The new content for the message - * @param {MessageEditOptions|MessageEmbed|MessageAttachment|MessageAttachment[]} [options] The options to provide + * @param {string|APIMessage|MessageEditOptions} options The options to provide * @returns {Promise} * @example * // Update the content of a message @@ -553,8 +552,7 @@ class Message extends Base { * .then(msg => console.log(`Updated the content of a message to ${msg.content}`)) * .catch(console.error); */ - edit(content, options) { - options = content instanceof APIMessage ? content : APIMessage.create(this, content, options); + edit(options) { return this.channel.messages.edit(this.id, options); } @@ -650,8 +648,7 @@ class Message extends Base { /** * Send an inline reply to this message. - * @param {string|APIMessage} [content=''] The content for the message - * @param {ReplyMessageOptions|MessageAdditions} [options] The additional options to provide + * @param {string|APIMessage|ReplyMessageOptions} options The options to provide * @returns {Promise} * @example * // Reply to a message @@ -659,17 +656,20 @@ class Message extends Base { * .then(() => console.log(`Replied to message "${message.content}"`)) * .catch(console.error); */ - reply(content, options) { - return this.channel.send( - content instanceof APIMessage - ? content - : APIMessage.transformOptions(content, options, { - reply: { - messageReference: this, - failIfNotExists: options?.failIfNotExists ?? content?.failIfNotExists ?? true, - }, - }), - ); + reply(options) { + let data; + + if (options instanceof APIMessage) { + data = options; + } else { + data = APIMessage.create(this, options, { + reply: { + messageReference: this, + failIfNotExists: options?.failIfNotExists ?? true, + }, + }); + } + return this.channel.send(data); } /** diff --git a/src/structures/Webhook.js b/src/structures/Webhook.js index 1bf929079fde..8bbf3b52c44d 100644 --- a/src/structures/Webhook.js +++ b/src/structures/Webhook.js @@ -107,8 +107,7 @@ class Webhook { /** * Sends a message with this webhook. - * @param {string|APIMessage} [content=''] The content to send - * @param {WebhookMessageOptions|MessageAdditions} [options={}] The options to provide + * @param {string|APIMessage|WebhookMessageOptions} options The options to provide * @returns {Promise} * @example * // Send a basic message @@ -134,7 +133,8 @@ class Webhook { * .catch(console.error); * @example * // Send an embed with a local image inside - * webhook.send('This is an embed', { + * webhook.send({ + * content: 'This is an embed', * embeds: [{ * thumbnail: { * url: 'attachment://file.jpg' @@ -148,13 +148,13 @@ class Webhook { * .then(console.log) * .catch(console.error); */ - async send(content, options) { + async send(options) { let apiMessage; - if (content instanceof APIMessage) { - apiMessage = content.resolveData(); + if (options instanceof APIMessage) { + apiMessage = options.resolveData(); } else { - apiMessage = APIMessage.create(this, content, options).resolveData(); + apiMessage = APIMessage.create(this, options).resolveData(); if (Array.isArray(apiMessage.data.content)) { return Promise.all(apiMessage.split().map(this.send.bind(this))); } @@ -244,15 +244,18 @@ class Webhook { /** * Edits a message that was sent by this webhook. * @param {MessageResolvable|'@original'} message The message to edit - * @param {?(string|APIMessage)} [content] The new content for the message - * @param {WebhookEditMessageOptions|MessageAdditions} [options] The options to provide + * @param {string|APIMessage|WebhookEditMessageOptions} options The options to provide * @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 editMessage(message, content, options) { - const { data, files } = await ( - content?.resolveData?.() ?? APIMessage.create(this, content, options).resolveData() - ).resolveFiles(); + async editMessage(message, options) { + let apiMessage; + + if (options instanceof APIMessage) apiMessage = options; + else apiMessage = APIMessage.create(this, options); + + const { data, files } = await apiMessage.resolveData().resolveFiles(); + const d = await this.client.api .webhooks(this.id, this.token) .messages(typeof message === 'string' ? message : message.id) diff --git a/src/structures/interfaces/InteractionResponses.js b/src/structures/interfaces/InteractionResponses.js index a6264c188e15..aaf5ec3180ad 100644 --- a/src/structures/interfaces/InteractionResponses.js +++ b/src/structures/interfaces/InteractionResponses.js @@ -53,8 +53,7 @@ class InteractionResponses { /** * Creates a reply to this interaction. - * @param {string|APIMessage|MessageAdditions} content The content for the reply - * @param {InteractionReplyOptions} [options] Additional options for the reply + * @param {string|APIMessage|InteractionReplyOptions} options The options for the reply * @returns {Promise} * @example * // Reply to the interaction with an embed @@ -65,13 +64,17 @@ class InteractionResponses { * .catch(console.error); * @example * // Create an ephemeral reply - * interaction.reply('Pong!', { ephemeral: true }) + * interaction.reply({ content: 'Pong!', ephemeral: true }) * .then(console.log) * .catch(console.error); */ - async reply(content, options) { + async reply(options) { if (this.deferred || this.replied) throw new Error('INTERACTION_ALREADY_REPLIED'); - const apiMessage = content instanceof APIMessage ? content : APIMessage.create(this, content, options); + + let apiMessage; + if (options instanceof APIMessage) apiMessage = options; + else apiMessage = APIMessage.create(this, options); + const { data, files } = await apiMessage.resolveData().resolveFiles(); await this.client.api.interactions(this.id, this.token).callback.post({ @@ -101,8 +104,7 @@ class InteractionResponses { /** * Edits the initial reply to this interaction. * @see Webhook#editMessage - * @param {string|APIMessage|MessageAdditions} content The new content for the message - * @param {WebhookEditMessageOptions} [options] The options to provide + * @param {string|APIMessage|WebhookEditMessageOptions} options The new options for the message * @returns {Promise} * @example * // Edit the reply to this interaction @@ -110,8 +112,8 @@ class InteractionResponses { * .then(console.log) * .catch(console.error); */ - editReply(content, options) { - return this.webhook.editMessage('@original', content, options); + editReply(options) { + return this.webhook.editMessage('@original', options); } /** @@ -130,12 +132,11 @@ class InteractionResponses { /** * Send a follow-up message to this interaction. - * @param {string|APIMessage|MessageAdditions} content The content for the reply - * @param {InteractionReplyOptions} [options] Additional options for the reply + * @param {string|APIMessage|InteractionReplyOptions} options The options for the reply * @returns {Promise} */ - followUp(content, options) { - return this.webhook.send(content, options); + followUp(options) { + return this.webhook.send(options); } /** @@ -159,8 +160,7 @@ class InteractionResponses { /** * Updates the original message whose button was pressed - * @param {string|APIMessage|MessageAdditions} content The content for the reply - * @param {WebhookEditMessageOptions} [options] Additional options for the reply + * @param {string|APIMessage|WebhookEditMessageOptions} options The options for the reply * @returns {Promise} * @example * // Remove the buttons from the message @@ -168,9 +168,13 @@ class InteractionResponses { * .then(console.log) * .catch(console.error); */ - async update(content, options) { + async update(options) { if (this.deferred || this.replied) throw new Error('INTERACTION_ALREADY_REPLIED'); - const apiMessage = content instanceof APIMessage ? content : APIMessage.create(this, content, options); + + let apiMessage; + if (options instanceof APIMessage) apiMessage = options; + else apiMessage = APIMessage.create(this, options); + const { data, files } = await apiMessage.resolveData().resolveFiles(); await this.client.api.interactions(this.id, this.token).callback.post({ diff --git a/src/structures/interfaces/TextBasedChannel.js b/src/structures/interfaces/TextBasedChannel.js index ee3dc8fa52cb..d6cbc77a96ec 100644 --- a/src/structures/interfaces/TextBasedChannel.js +++ b/src/structures/interfaces/TextBasedChannel.js @@ -117,8 +117,7 @@ class TextBasedChannel { /** * Sends a message to this channel. - * @param {string|APIMessage} [content=''] The content to send - * @param {MessageOptions|MessageAdditions} [options={}] The options to provide + * @param {string|APIMessage|MessageOptions} options The options to provide * @returns {Promise} * @example * // Send a basic message @@ -158,20 +157,20 @@ class TextBasedChannel { * .then(console.log) * .catch(console.error); */ - async send(content, options) { + async send(options) { const User = require('../User'); const GuildMember = require('../GuildMember'); if (this instanceof User || this instanceof GuildMember) { - return this.createDM().then(dm => dm.send(content, options)); + return this.createDM().then(dm => dm.send(options)); } let apiMessage; - if (content instanceof APIMessage) { - apiMessage = content.resolveData(); + if (options instanceof APIMessage) { + apiMessage = options.resolveData(); } else { - apiMessage = APIMessage.create(this, content, options).resolveData(); + apiMessage = APIMessage.create(this, options).resolveData(); if (Array.isArray(apiMessage.data.content)) { return Promise.all(apiMessage.split().map(this.send.bind(this))); } diff --git a/typings/index.d.ts b/typings/index.d.ts index c98e6f9548c6..aea36bf661fa 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -144,32 +144,10 @@ declare module 'discord.js' { public static create( target: MessageTarget, - content: string | null, - options?: undefined, + options: string | MessageOptions | WebhookMessageOptions, extra?: MessageOptions | WebhookMessageOptions, ): APIMessage; - public static create( - target: MessageTarget, - content: string | null, - options: MessageOptions | WebhookMessageOptions | MessageAdditions, - extra?: MessageOptions | WebhookMessageOptions, - ): APIMessage; - public static partitionMessageAdditions( - items: readonly (MessageEmbed | MessageAttachment)[], - ): [MessageEmbed[], MessageAttachment[]]; public static resolveFile(fileLike: BufferResolvable | Stream | FileOptions | MessageAttachment): Promise; - public static transformOptions( - content: string | null, - options?: undefined, - extra?: MessageOptions | WebhookMessageOptions, - isWebhook?: boolean, - ): MessageOptions | WebhookMessageOptions; - public static transformOptions( - content: string | null, - options: MessageOptions | WebhookMessageOptions | MessageAdditions, - extra?: MessageOptions | WebhookMessageOptions, - isWebhook?: boolean, - ): MessageOptions | WebhookMessageOptions; public makeContent(): string | string[] | undefined; public resolveData(): this; @@ -471,17 +449,10 @@ declare module 'discord.js' { public webhook: InteractionWebhook; public defer(options?: InteractionDeferOptions): Promise; public deleteReply(): Promise; - public editReply( - content: string | null | APIMessage | WebhookEditMessageOptions | MessageAdditions, - ): Promise; - public editReply(content: string | null, options?: WebhookEditMessageOptions): Promise; + public editReply(options: string | APIMessage | WebhookEditMessageOptions): Promise; public fetchReply(): Promise; - public followUp( - content: string | APIMessage | InteractionReplyOptions | MessageAdditions, - ): Promise; - public followUp(content: string | null, options?: InteractionReplyOptions): Promise; - public reply(content: string | null | APIMessage | InteractionReplyOptions | MessageAdditions): Promise; - public reply(content: string | null, options?: InteractionReplyOptions): Promise; + public followUp(options: string | APIMessage | InteractionReplyOptions): Promise; + public reply(options: string | APIMessage | InteractionReplyOptions): Promise; private transformOption(option: unknown, resolved: unknown): CommandInteractionOption; private _createOptionsCollection(options: unknown, resolved: unknown): Collection; } @@ -1151,24 +1122,11 @@ declare module 'discord.js' { constructor(client: Client, id: Snowflake, token: string); public token: string; public send( - content: string | (InteractionReplyOptions & { split?: false }) | MessageAdditions, - ): Promise; - public send(options: InteractionReplyOptions & { split: true | SplitOptions }): Promise<(Message | RawMessage)[]>; - public send( - options: InteractionReplyOptions | APIMessage, - ): Promise; - public send( - content: string | null, - options: (InteractionReplyOptions & { split?: false }) | MessageAdditions, + options: string | APIMessage | (InteractionReplyOptions & { split?: false }), ): Promise; public send( - content: string | null, - options: InteractionReplyOptions & { split: true | SplitOptions }, + options: APIMessage | (InteractionReplyOptions & { split: true | SplitOptions }), ): Promise<(Message | RawMessage)[]>; - public send( - content: string | null, - options: InteractionReplyOptions, - ): Promise; } export class Invite extends Base { @@ -1255,13 +1213,7 @@ declare module 'discord.js' { options?: MessageComponentInteractionCollectorOptions, ): MessageComponentInteractionCollector; public delete(): Promise; - public edit( - content: string | null | MessageEditOptions | MessageEmbed | APIMessage | MessageAttachment | MessageAttachment[], - ): Promise; - public edit( - content: string | null, - options: MessageEditOptions | MessageEmbed | MessageAttachment | MessageAttachment[], - ): Promise; + public edit(content: string | MessageEditOptions | APIMessage): Promise; public equals(message: Message, rawData: unknown): boolean; public fetchReference(): Promise; public fetchWebhook(): Promise; @@ -1270,20 +1222,8 @@ declare module 'discord.js' { public pin(): Promise; public react(emoji: EmojiIdentifierResolvable): Promise; public removeAttachments(): Promise; - public reply( - content: string | null | (ReplyMessageOptions & { split?: false }) | MessageAdditions, - ): Promise; - public reply(options: ReplyMessageOptions & { split: true | SplitOptions }): Promise; - public reply(options: ReplyMessageOptions | APIMessage): Promise; - public reply( - content: string | null, - options: (ReplyMessageOptions & { split?: false }) | MessageAdditions, - ): Promise; - public reply( - content: string | null, - options: ReplyMessageOptions & { split: true | SplitOptions }, - ): Promise; - public reply(content: string | null, options: ReplyMessageOptions): Promise; + public reply(options: string | APIMessage | (ReplyMessageOptions & { split?: false })): Promise; + public reply(options: APIMessage | (ReplyMessageOptions & { split: true | SplitOptions })): Promise; public suppressEmbeds(suppress?: boolean): Promise; public toJSON(): unknown; public toString(): string; @@ -1370,21 +1310,11 @@ declare module 'discord.js' { public defer(options?: InteractionDeferOptions): Promise; public deferUpdate(): Promise; public deleteReply(): Promise; - public editReply( - content: string | APIMessage | WebhookEditMessageOptions | MessageEmbed | MessageEmbed[], - ): Promise; - public editReply(content: string, options?: WebhookEditMessageOptions): Promise; + public editReply(options: string | APIMessage | WebhookEditMessageOptions): Promise; public fetchReply(): Promise; - public followUp( - content: string | APIMessage | InteractionReplyOptions | MessageAdditions, - ): Promise; - public followUp(content: string, options?: InteractionReplyOptions): Promise; - public reply(content: string | APIMessage | InteractionReplyOptions | MessageAdditions): Promise; - public reply(content: string, options?: InteractionReplyOptions): Promise; - public update( - content: string | APIMessage | WebhookEditMessageOptions | MessageEmbed | MessageEmbed[], - ): Promise; - public update(content: string, options?: WebhookEditMessageOptions): Promise; + public followUp(options: string | APIMessage | InteractionReplyOptions): Promise; + public reply(options: string | APIMessage | InteractionReplyOptions): Promise; + public update(content: string | APIMessage | WebhookEditMessageOptions): Promise; public static resolveType(type: MessageComponentTypeResolvable): MessageComponentType; } @@ -2143,23 +2073,13 @@ declare module 'discord.js' { public token: string; public editMessage( message: MessageResolvable, - content: string | null | APIMessage | MessageEmbed | MessageEmbed[], - options?: WebhookEditMessageOptions, + options: string | APIMessage | WebhookEditMessageOptions, ): Promise; - public editMessage(message: MessageResolvable, options: WebhookEditMessageOptions): Promise; public fetchMessage(message: Snowflake, cache?: boolean): Promise; - public send(content: string | (WebhookMessageOptions & { split?: false }) | MessageAdditions): Promise; - public send(options: WebhookMessageOptions & { split: true | SplitOptions }): Promise; - public send(options: WebhookMessageOptions | APIMessage): Promise; - public send( - content: string | null, - options: (WebhookMessageOptions & { split?: false }) | MessageAdditions, - ): Promise; + public send(options: string | APIMessage | (WebhookMessageOptions & { split?: false })): Promise; public send( - content: string | null, - options: WebhookMessageOptions & { split: true | SplitOptions }, + options: APIMessage | (WebhookMessageOptions & { split: true | SplitOptions }), ): Promise; - public send(content: string | null, options: WebhookMessageOptions): Promise; } export class WebSocketManager extends EventEmitter { @@ -2496,12 +2416,8 @@ declare module 'discord.js' { interface PartialTextBasedChannelFields { lastMessageID: Snowflake | null; readonly lastMessage: Message | null; - send(content: string | (MessageOptions & { split?: false }) | MessageAdditions): Promise; - send(options: MessageOptions & { split: true | SplitOptions }): Promise; - send(options: MessageOptions | APIMessage): Promise; - send(content: string | null, options: (MessageOptions & { split?: false }) | MessageAdditions): Promise; - send(content: string | null, options: MessageOptions & { split: true | SplitOptions }): Promise; - send(content: string | null, options: MessageOptions): Promise; + send(options: string | APIMessage | (MessageOptions & { split?: false })): Promise; + send(options: APIMessage | (MessageOptions & { split: true | SplitOptions })): Promise; } interface TextBasedChannelFields extends PartialTextBasedChannelFields { @@ -2542,31 +2458,13 @@ declare module 'discord.js' { deleteMessage(message: MessageResolvable | '@original'): Promise; editMessage( message: MessageResolvable | '@original', - content: string | null | APIMessage | MessageAdditions, - options?: WebhookEditMessageOptions, - ): Promise; - editMessage( - message: MessageResolvable | '@original', - options: WebhookEditMessageOptions, + options: string | APIMessage | WebhookEditMessageOptions, ): Promise; fetchMessage(message: Snowflake | '@original', cache?: boolean): Promise; send( - content: string | (WebhookMessageOptions & { split?: false }) | MessageAdditions, - ): Promise; - send(options: WebhookMessageOptions & { split: true | SplitOptions }): Promise<(Message | RawMessage)[]>; - send(options: WebhookMessageOptions | APIMessage): Promise; - send( - content: string | null, - options: (WebhookMessageOptions & { split?: false }) | MessageAdditions, - ): Promise; - send( - content: string | null, - options: WebhookMessageOptions & { split: true | SplitOptions }, + options: APIMessage | (WebhookMessageOptions & { split: true | SplitOptions }), ): Promise<(Message | RawMessage)[]>; - send( - content: string | null, - options: WebhookMessageOptions, - ): Promise; + send(options: string | APIMessage | (WebhookMessageOptions & { split?: false })): Promise; } interface WebhookFields extends PartialWebhookFields { @@ -3391,8 +3289,6 @@ declare module 'discord.js' { type MembershipStates = 'INVITED' | 'ACCEPTED'; - type MessageAdditions = MessageEmbed | MessageAttachment | (MessageEmbed | MessageAttachment)[]; - type MessageActionRowComponent = MessageButton; type MessageActionRowComponentOptions = MessageButtonOptions; diff --git a/typings/index.ts b/typings/index.ts index 0343e64f3cee..eb80fa3ea426 100644 --- a/typings/index.ts +++ b/typings/index.ts @@ -38,9 +38,9 @@ client.on('message', ({ channel }) => { const attachment = new MessageAttachment('file.png'); const embed = new MessageEmbed(); - assertIsMessage(channel.send(attachment)); + assertIsMessage(channel.send({ files: [attachment] })); assertIsMessage(channel.send(embed)); - assertIsMessage(channel.send([attachment, embed])); + assertIsMessage(channel.send({ embed, files: [attachment] })); assertIsMessageArray(channel.send({ split: true }));