refactor: remove duplicate send checks (#2790)

* re-direct pr code to master

* fix Webhook send docs

* requested changes

* typings: Updated to latest commit

* requested change

* requested change
This commit is contained in:
bdistin
2018-09-21 03:59:58 -05:00
committed by SpaceEEC
parent 8a6d029c00
commit 6d184257b3
5 changed files with 92 additions and 50 deletions

View File

@@ -25,6 +25,18 @@ class APIMessage {
* @type {MessageOptions|WebhookMessageOptions} * @type {MessageOptions|WebhookMessageOptions}
*/ */
this.options = options; this.options = options;
/**
* Data sendable to the API
* @type {?Object}
*/
this.data = null;
/**
* Files sendable to the API
* @type {?Object[]}
*/
this.files = null;
} }
/** /**
@@ -100,9 +112,11 @@ class APIMessage {
/** /**
* Resolves data. * Resolves data.
* @returns {Object} * @returns {APIMessage}
*/ */
resolveData() { resolveData() {
if (this.data) return this;
const content = this.makeContent(); const content = this.makeContent();
const tts = Boolean(this.options.tts); const tts = Boolean(this.options.tts);
let nonce; let nonce;
@@ -128,7 +142,7 @@ class APIMessage {
if (this.options.avatarURL) avatarURL = this.options.avatarURL; if (this.options.avatarURL) avatarURL = this.options.avatarURL;
} }
return { this.data = {
content, content,
tts, tts,
nonce, nonce,
@@ -137,13 +151,16 @@ class APIMessage {
username, username,
avatar_url: avatarURL, avatar_url: avatarURL,
}; };
return this;
} }
/** /**
* Resolves files. * Resolves files.
* @returns {Promise<Object[]>} * @returns {Promise<APIMessage>}
*/ */
resolveFiles() { async resolveFiles() {
if (this.files) return this;
const embedLikes = []; const embedLikes = [];
if (this.isWebhook) { if (this.isWebhook) {
if (this.options.embeds) { if (this.options.embeds) {
@@ -163,7 +180,39 @@ class APIMessage {
} }
} }
return Promise.all(fileLikes.map(f => this.constructor.resolveFile(f))); this.files = await Promise.all(fileLikes.map(f => this.constructor.resolveFile(f)));
return this;
}
/**
* Converts this APIMessage into an array of APIMessages for each split content
* @returns {APIMessage[]}
*/
split() {
if (!this.data) this.resolveData();
if (!(this.data.content instanceof Array)) return [this];
const apiMessages = [];
for (let i = 0; i < this.data.content.length; i++) {
let data;
let opt;
if (i === this.data.content.length - 1) {
data = { ...this.data, content: this.data.content[i] };
opt = { ...this.options, content: this.data.content[i] };
} else {
data = { content: this.data.content[i], tts: this.data.tts };
opt = { content: this.data.content[i], tts: this.data.tts };
}
const apiMessage = new APIMessage(this.target, opt);
apiMessage.data = data;
apiMessages.push(apiMessage);
}
return apiMessages;
} }
/** /**

View File

@@ -359,7 +359,7 @@ class Message extends Base {
/** /**
* Edits the content of the message. * Edits the content of the message.
* @param {StringResolvable} [content=''] The new content for the message * @param {StringResolvable|APIMessage} [content=''] The new content for the message
* @param {MessageEditOptions|MessageEmbed} [options] The options to provide * @param {MessageEditOptions|MessageEmbed} [options] The options to provide
* @returns {Promise<Message>} * @returns {Promise<Message>}
* @example * @example
@@ -369,7 +369,9 @@ class Message extends Base {
* .catch(console.error); * .catch(console.error);
*/ */
edit(content, options) { edit(content, options) {
const data = APIMessage.create(this, content, options).resolveData(); const { data } = content instanceof APIMessage ?
content.resolveData() :
APIMessage.create(this, content, options).resolveData();
return this.client.api.channels[this.channel.id].messages[this.id] return this.client.api.channels[this.channel.id].messages[this.id]
.patch({ data }) .patch({ data })
.then(d => { .then(d => {
@@ -458,7 +460,7 @@ class Message extends Base {
/** /**
* Replies to the message. * Replies to the message.
* @param {StringResolvable} [content=''] The content for the message * @param {StringResolvable|APIMessage} [content=''] The content for the message
* @param {MessageOptions|MessageAdditions} [options={}] The options to provide * @param {MessageOptions|MessageAdditions} [options={}] The options to provide
* @returns {Promise<Message|Message[]>} * @returns {Promise<Message|Message[]>}
* @example * @example
@@ -468,7 +470,10 @@ class Message extends Base {
* .catch(console.error); * .catch(console.error);
*/ */
reply(content, options) { reply(content, options) {
return this.channel.send(APIMessage.transformOptions(content, options, { reply: this.member || this.author })); return this.channel.send(content instanceof APIMessage ?
content :
APIMessage.transformOptions(content, options, { reply: this.member || this.author })
);
} }
/** /**

View File

@@ -84,7 +84,7 @@ class Webhook {
/** /**
* Sends a message with this webhook. * Sends a message with this webhook.
* @param {StringResolvable} [content=''] The content to send * @param {StringResolvable|APIMessage} [content=''] The content to send
* @param {WebhookMessageOptions|MessageAdditions} [options={}] The options to provide * @param {WebhookMessageOptions|MessageAdditions} [options={}] The options to provide
* @returns {Promise<Message|Object>} * @returns {Promise<Message|Object>}
* @example * @example
@@ -126,27 +126,18 @@ class Webhook {
* .catch(console.error); * .catch(console.error);
*/ */
async send(content, options) { async send(content, options) {
const apiMessage = APIMessage.create(this, content, options); let apiMessage;
const data = apiMessage.resolveData();
if (data.content instanceof Array) {
const messages = [];
for (let i = 0; i < data.content.length; i++) {
let opt;
if (i === data.content.length - 1) {
opt = { embeds: data.embeds, files: apiMessage.options.files };
} else {
opt = {};
}
Object.assign(opt, { avatarURL: data.avatar_url, content: data.content[i], username: data.username }); if (content instanceof apiMessage) {
// eslint-disable-next-line no-await-in-loop apiMessage = content.resolveData();
const message = await this.send(data.content[i], opt); } else {
messages.push(message); apiMessage = APIMessage.create(this, content, options).resolveData();
if (apiMessage.data.content instanceof Array) {
return Promise.all(apiMessage.split().map(this.send.bind(this)));
} }
return messages;
} }
const files = await apiMessage.resolveFiles(); const { data, files } = await apiMessage.resolveFiles();
return this.client.api.webhooks(this.id, this.token).post({ return this.client.api.webhooks(this.id, this.token).post({
data, files, data, files,
query: { wait: true }, query: { wait: true },

View File

@@ -81,7 +81,7 @@ class TextBasedChannel {
/** /**
* Sends a message to this channel. * Sends a message to this channel.
* @param {StringResolvable} [content=''] The content to send * @param {StringResolvable|APIMessage} [content=''] The content to send
* @param {MessageOptions|MessageAdditions} [options={}] The options to provide * @param {MessageOptions|MessageAdditions} [options={}] The options to provide
* @returns {Promise<Message|Message[]>} * @returns {Promise<Message|Message[]>}
* @example * @example
@@ -125,30 +125,23 @@ class TextBasedChannel {
async send(content, options) { async send(content, options) {
const User = require('../User'); const User = require('../User');
const GuildMember = require('../GuildMember'); const GuildMember = require('../GuildMember');
if (this instanceof User || this instanceof GuildMember) { if (this instanceof User || this instanceof GuildMember) {
return this.createDM().then(dm => dm.send(content, options)); return this.createDM().then(dm => dm.send(content, options));
} }
const apiMessage = APIMessage.create(this, content, options); let apiMessage;
const data = apiMessage.resolveData();
if (data.content instanceof Array) {
const messages = [];
for (let i = 0; i < data.content.length; i++) {
let opt;
if (i === data.content.length - 1) {
opt = { tts: data.tts, embed: data.embed, files: apiMessage.options.files };
} else {
opt = { tts: data.tts };
}
// eslint-disable-next-line no-await-in-loop if (content instanceof APIMessage) {
const message = await this.send(data.content[i], opt); apiMessage = content.resolveData();
messages.push(message); } else {
apiMessage = APIMessage.create(this, content, options).resolveData();
if (apiMessage.data.content instanceof Array) {
return Promise.all(apiMessage.split().map(this.send.bind(this)));
} }
return messages;
} }
const files = await apiMessage.resolveFiles(); const { data, files } = await apiMessage.resolveFiles();
return this.client.api.channels[this.id].messages.post({ data, files }) return this.client.api.channels[this.id].messages.post({ data, files })
.then(d => this.client.actions.MessageCreate.handle(d).message); .then(d => this.client.actions.MessageCreate.handle(d).message);
} }

16
typings/index.d.ts vendored
View File

@@ -42,8 +42,10 @@ declare module 'discord.js' {
export class APIMessage { export class APIMessage {
constructor(target: MessageTarget, options: MessageOptions | WebhookMessageOptions); constructor(target: MessageTarget, options: MessageOptions | WebhookMessageOptions);
public data?: object;
public readonly isUser: boolean; public readonly isUser: boolean;
public readonly isWebhook: boolean; public readonly isWebhook: boolean;
public files?: object[];
public options: MessageOptions | WebhookMessageOptions; public options: MessageOptions | WebhookMessageOptions;
public target: MessageTarget; public target: MessageTarget;
@@ -63,8 +65,10 @@ declare module 'discord.js' {
): MessageOptions | WebhookMessageOptions; ): MessageOptions | WebhookMessageOptions;
public makeContent(): string | string[]; public makeContent(): string | string[];
public resolveData(): object; public resolve(): Promise<this>;
public resolveFiles(): Promise<object[]>; public resolveData(): this;
public resolveFiles(): Promise<this>;
public split(): APIMessage[];
} }
export class Base { export class Base {
@@ -663,13 +667,13 @@ declare module 'discord.js' {
public createReactionCollector(filter: CollectorFilter, options?: ReactionCollectorOptions): ReactionCollector; public createReactionCollector(filter: CollectorFilter, options?: ReactionCollectorOptions): ReactionCollector;
public delete(options?: { timeout?: number, reason?: string }): Promise<Message>; public delete(options?: { timeout?: number, reason?: string }): Promise<Message>;
public edit(content: StringResolvable, options?: MessageEditOptions | MessageEmbed): Promise<Message>; public edit(content: StringResolvable, options?: MessageEditOptions | MessageEmbed): Promise<Message>;
public edit(options: MessageEditOptions | MessageEmbed): Promise<Message>; public edit(options: MessageEditOptions | MessageEmbed | APIMessage): Promise<Message>;
public equals(message: Message, rawData: object): boolean; public equals(message: Message, rawData: object): boolean;
public fetchWebhook(): Promise<Webhook>; public fetchWebhook(): Promise<Webhook>;
public pin(): Promise<Message>; public pin(): Promise<Message>;
public react(emoji: EmojiIdentifierResolvable): Promise<MessageReaction>; public react(emoji: EmojiIdentifierResolvable): Promise<MessageReaction>;
public reply(content?: StringResolvable, options?: MessageOptions | MessageAdditions): Promise<Message | Message[]>; public reply(content?: StringResolvable, options?: MessageOptions | MessageAdditions): Promise<Message | Message[]>;
public reply(options?: MessageOptions | MessageAdditions): Promise<Message | Message[]>; public reply(options?: MessageOptions | MessageAdditions | APIMessage): Promise<Message | Message[]>;
public toJSON(): object; public toJSON(): object;
public toString(): string; public toString(): string;
public unpin(): Promise<Message>; public unpin(): Promise<Message>;
@@ -1382,7 +1386,7 @@ declare module 'discord.js' {
lastPinTimestamp: number; lastPinTimestamp: number;
readonly lastPinAt: Date; readonly lastPinAt: Date;
send(content?: StringResolvable, options?: MessageOptions | MessageAdditions): Promise<Message | Message[]>; send(content?: StringResolvable, options?: MessageOptions | MessageAdditions): Promise<Message | Message[]>;
send(options?: MessageOptions | MessageAdditions): Promise<Message | Message[]>; send(options?: MessageOptions | MessageAdditions | APIMessage): Promise<Message | Message[]>;
}; };
type TextBasedChannelFields = { type TextBasedChannelFields = {
@@ -1404,7 +1408,7 @@ declare module 'discord.js' {
delete(reason?: string): Promise<void>; delete(reason?: string): Promise<void>;
edit(options: WebhookEditData): Promise<Webhook>; edit(options: WebhookEditData): Promise<Webhook>;
send(content?: StringResolvable, options?: WebhookMessageOptions | MessageAdditions): Promise<Message | Message[]>; send(content?: StringResolvable, options?: WebhookMessageOptions | MessageAdditions): Promise<Message | Message[]>;
send(options?: WebhookMessageOptions | MessageAdditions): Promise<Message | Message[]>; send(options?: WebhookMessageOptions | MessageAdditions | APIMessage): Promise<Message | Message[]>;
sendSlackMessage(body: object): Promise<Message|object>; sendSlackMessage(body: object): Promise<Message|object>;
}; };