Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: enforce single param on sending/editing methods #5758

Merged
merged 35 commits into from
Jun 9, 2021
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
58bcfee
refactor(InteractionResponses): only take one input param
castdrian Jun 6, 2021
4a7e5e6
fix(Typings): shouldn't be null
castdrian Jun 6, 2021
3bfa03a
refactor(TextBasedChannel): only take one input param
castdrian Jun 6, 2021
178f5be
fix(*): remove unecessary param
castdrian Jun 6, 2021
34dedac
refactor(Message): only take one param
castdrian Jun 6, 2021
572daae
refactor(Webhook): only take one param
castdrian Jun 6, 2021
8071d8a
fix(Typings): remove unnecessary overload
castdrian Jun 6, 2021
78d1c36
apply code suggestion
castdrian Jun 7, 2021
3b3a234
refactor(*): remove unnecessary statements
castdrian Jun 7, 2021
39a30e3
refactor(ApiMessage): only accept content or options
castdrian Jun 7, 2021
cc47061
fix(Message): fix reply
castdrian Jun 7, 2021
2503657
refactor(Typings): remove MessageAdditions and update method params
castdrian Jun 7, 2021
a7de98d
fix(Typings): fix index.ts
castdrian Jun 7, 2021
4b90dbd
fix(JsDoc): remove MessageAdditions
castdrian Jun 7, 2021
4be1f86
fix(InteractionResponses): proper arg order when creating apimessage
castdrian Jun 7, 2021
df49410
Update src/structures/Message.js
castdrian Jun 7, 2021
c790a52
Update src/structures/Webhook.js
castdrian Jun 7, 2021
f27654d
Update src/structures/interfaces/InteractionResponses.js
castdrian Jun 7, 2021
ad1c43b
Update src/structures/interfaces/InteractionResponses.js
castdrian Jun 7, 2021
3806379
Update src/structures/interfaces/InteractionResponses.js
castdrian Jun 7, 2021
812252e
Update typings/index.ts
castdrian Jun 7, 2021
932080c
fix(Message): fix JSDoc
castdrian Jun 7, 2021
ab52bf8
fix(Typings): remove unnecessary overloads
castdrian Jun 7, 2021
7cd765f
apply code suggestion
castdrian Jun 8, 2021
c8ebc24
apply code suggestion
castdrian Jun 8, 2021
77eb1a0
apply code suggestion
castdrian Jun 8, 2021
54378ee
apply code suggestion
castdrian Jun 8, 2021
ca02421
apply code suggestion
castdrian Jun 8, 2021
82abc5b
apply code suggestion
castdrian Jun 8, 2021
12fec18
apply code suggestion
castdrian Jun 8, 2021
abf2672
apply code suggestion
castdrian Jun 8, 2021
2c3b536
fix(Typings): fix syntax & remove unused overload
castdrian Jun 8, 2021
70f12e9
fix(Webhook): remove unnecessary call
castdrian Jun 8, 2021
a05cd88
Update typings/index.d.ts
castdrian Jun 9, 2021
0b472ce
Update typings/index.d.ts
castdrian Jun 9, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
82 changes: 5 additions & 77 deletions src/structures/APIMessage.js
Original file line number Diff line number Diff line change
@@ -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');
Expand Down Expand Up @@ -308,82 +307,16 @@ class APIMessage {
return { attachment, name, file: resource };
}

/**
* Partitions embeds and attachments.
* @param {Array<MessageEmbed|MessageAttachment>} items Items to partition
* @returns {Array<MessageEmbed[], MessageAttachment[]>}
*/
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 });
}
}

Expand All @@ -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<MessageEmbed|MessageAttachment>} MessageAdditions
*/
3 changes: 1 addition & 2 deletions src/structures/InteractionWebhook.js
Original file line number Diff line number Diff line change
Expand Up @@ -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<Message|Object>}
*/
send() {}
Expand Down
34 changes: 17 additions & 17 deletions src/structures/Message.js
Original file line number Diff line number Diff line change
Expand Up @@ -541,17 +541,15 @@ 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<Message>}
* @example
* // Update the content of a message
* message.edit('This is my new content!')
* .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);
}

Expand Down Expand Up @@ -647,26 +645,28 @@ 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
castdrian marked this conversation as resolved.
Show resolved Hide resolved
* @returns {Promise<Message|Message[]>}
* @example
* // Reply to a message
* message.reply('This is a reply!')
* .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);
}

/**
Expand Down
29 changes: 16 additions & 13 deletions src/structures/Webhook.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,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<Message|Object>}
* @example
* // Send a basic message
Expand All @@ -132,7 +131,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'
Expand All @@ -146,13 +146,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)));
}
Expand Down Expand Up @@ -242,15 +242,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<Message|Object>} 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)
Expand Down
38 changes: 21 additions & 17 deletions src/structures/interfaces/InteractionResponses.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,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<void>}
* @example
* // Reply to the interaction with an embed
Expand All @@ -64,13 +63,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({
Expand Down Expand Up @@ -100,17 +103,16 @@ 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<Message|Object>}
* @example
* // Edit the reply to this interaction
* interaction.editReply('New content')
* .then(console.log)
* .catch(console.error);
*/
editReply(content, options) {
return this.webhook.editMessage('@original', content, options);
editReply(options) {
return this.webhook.editMessage('@original', options);
}

/**
Expand All @@ -129,12 +131,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<Message|Object>}
*/
followUp(content, options) {
return this.webhook.send(content, options);
followUp(options) {
return this.webhook.send(options);
}

/**
Expand All @@ -158,18 +159,21 @@ 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<void>}
* @example
* // Remove the buttons from the message
* interaction.update("A button was clicked", { components: [] })
* .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({
Expand Down
13 changes: 6 additions & 7 deletions src/structures/interfaces/TextBasedChannel.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,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<Message|Message[]>}
* @example
* // Send a basic message
Expand Down Expand Up @@ -156,20 +155,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)));
}
Expand Down