mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-18 12:33:30 +01:00
Backporting Attachments (#1817)
This commit is contained in:
@@ -234,6 +234,33 @@ class ClientDataResolver {
|
|||||||
return Promise.reject(new TypeError('The resource must be a string or Buffer.'));
|
return Promise.reject(new TypeError('The resource must be a string or Buffer.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @external Stream
|
||||||
|
* @see {@link https://nodejs.org/api/stream.html}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a Stream to a Buffer.
|
||||||
|
* @param {Stream} resource The stream to convert
|
||||||
|
* @returns {Promise<Buffer>}
|
||||||
|
*/
|
||||||
|
resolveFile(resource) {
|
||||||
|
return resource ? this.resolveBuffer(resource)
|
||||||
|
.catch(() => {
|
||||||
|
if (resource.pipe && typeof resource.pipe === 'function') {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const buffers = [];
|
||||||
|
resource.once('error', reject);
|
||||||
|
resource.on('data', data => buffers.push(data));
|
||||||
|
resource.once('end', () => resolve(Buffer.concat(buffers)));
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
throw new TypeError('The resource must be a string, Buffer or a valid file stream.');
|
||||||
|
}
|
||||||
|
}) :
|
||||||
|
Promise.reject(new TypeError('The resource must be a string, Buffer or a valid file stream.'));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data that can be resolved to give an emoji identifier. This can be:
|
* Data that can be resolved to give an emoji identifier. This can be:
|
||||||
* * The unicode representation of an emoji
|
* * The unicode representation of an emoji
|
||||||
|
|||||||
@@ -102,12 +102,12 @@ class RESTMethods {
|
|||||||
if (content instanceof Array) {
|
if (content instanceof Array) {
|
||||||
const messages = [];
|
const messages = [];
|
||||||
(function sendChunk(list, index) {
|
(function sendChunk(list, index) {
|
||||||
const options = index === list.length ? { tts, embed } : { tts };
|
const options = index === list.length - 1 ? { tts, embed, files } : { tts };
|
||||||
chan.send(list[index], options, index === list.length ? files : null).then(message => {
|
chan.send(list[index], options).then(message => {
|
||||||
messages.push(message);
|
messages.push(message);
|
||||||
if (index >= list.length - 1) return resolve(messages);
|
if (index >= list.length - 1) return resolve(messages);
|
||||||
return sendChunk(list, ++index);
|
return sendChunk(list, ++index);
|
||||||
});
|
}).catch(reject);
|
||||||
}(content, 0));
|
}(content, 0));
|
||||||
} else {
|
} else {
|
||||||
this.rest.makeRequest('post', Endpoints.Channel(chan).messages, true, {
|
this.rest.makeRequest('post', Endpoints.Channel(chan).messages, true, {
|
||||||
@@ -747,21 +747,30 @@ class RESTMethods {
|
|||||||
false, undefined, undefined, reason);
|
false, undefined, undefined, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
sendWebhookMessage(webhook, content, { avatarURL, tts, disableEveryone, embeds, username } = {}, file = null) {
|
sendWebhookMessage(webhook, content, { avatarURL, tts, embeds, username } = {}, files = null) {
|
||||||
username = username || webhook.name;
|
return new Promise((resolve, reject) => {
|
||||||
if (typeof content !== 'undefined') content = this.client.resolver.resolveString(content);
|
username = username || webhook.name;
|
||||||
if (content) {
|
|
||||||
if (disableEveryone || (typeof disableEveryone === 'undefined' && this.client.options.disableEveryone)) {
|
if (content instanceof Array) {
|
||||||
content = content.replace(/@(everyone|here)/g, '@\u200b$1');
|
const messages = [];
|
||||||
|
(function sendChunk(list, index) {
|
||||||
|
const options = index === list.length - 1 ? { tts, embeds, files } : { tts };
|
||||||
|
webhook.send(list[index], options).then(message => {
|
||||||
|
messages.push(message);
|
||||||
|
if (index >= list.length - 1) return resolve(messages);
|
||||||
|
return sendChunk(list, ++index);
|
||||||
|
}).catch(reject);
|
||||||
|
}(content, 0));
|
||||||
|
} else {
|
||||||
|
this.rest.makeRequest('post', `${Endpoints.Webhook(webhook.id, webhook.token)}?wait=true`, false, {
|
||||||
|
username,
|
||||||
|
avatar_url: avatarURL,
|
||||||
|
content,
|
||||||
|
tts,
|
||||||
|
embeds,
|
||||||
|
}, files).then(resolve, reject);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
return this.rest.makeRequest('post', `${Endpoints.Webhook(webhook.id, webhook.token)}?wait=true`, false, {
|
|
||||||
username,
|
|
||||||
avatar_url: avatarURL,
|
|
||||||
content,
|
|
||||||
tts,
|
|
||||||
embeds,
|
|
||||||
}, file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sendSlackWebhookMessage(webhook, body) {
|
sendSlackWebhookMessage(webhook, body) {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ module.exports = {
|
|||||||
splitMessage: Util.splitMessage,
|
splitMessage: Util.splitMessage,
|
||||||
|
|
||||||
// Structures
|
// Structures
|
||||||
|
Attachment: require('./structures/Attachment'),
|
||||||
Channel: require('./structures/Channel'),
|
Channel: require('./structures/Channel'),
|
||||||
ClientUser: require('./structures/ClientUser'),
|
ClientUser: require('./structures/ClientUser'),
|
||||||
ClientUserSettings: require('./structures/ClientUserSettings'),
|
ClientUserSettings: require('./structures/ClientUserSettings'),
|
||||||
|
|||||||
74
src/structures/Attachment.js
Normal file
74
src/structures/Attachment.js
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/**
|
||||||
|
* Represents an attachment in a message.
|
||||||
|
* @param {BufferResolvable|Stream} file The file
|
||||||
|
* @param {string} [name] The name of the file, if any
|
||||||
|
*/
|
||||||
|
class Attachment {
|
||||||
|
constructor(file, name) {
|
||||||
|
this.file = null;
|
||||||
|
if (name) this.setAttachment(file, name);
|
||||||
|
else this._attach(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the file
|
||||||
|
* @type {?string}
|
||||||
|
* @readonly
|
||||||
|
*/
|
||||||
|
get name() {
|
||||||
|
return this.file.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The file
|
||||||
|
* @type {?BufferResolvable|Stream}
|
||||||
|
* @readonly
|
||||||
|
*/
|
||||||
|
get attachment() {
|
||||||
|
return this.file.attachment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the file of this attachment.
|
||||||
|
* @param {BufferResolvable|Stream} file The file
|
||||||
|
* @param {string} name The name of the file
|
||||||
|
* @returns {Attachment} This attachment
|
||||||
|
*/
|
||||||
|
setAttachment(file, name) {
|
||||||
|
this.file = { attachment: file, name };
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the file of this attachment.
|
||||||
|
* @param {BufferResolvable|Stream} attachment The file
|
||||||
|
* @returns {Attachment} This attachment
|
||||||
|
*/
|
||||||
|
setFile(attachment) {
|
||||||
|
this.file = { attachment };
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the name of this attachment.
|
||||||
|
* @param {string} name The name of the image
|
||||||
|
* @returns {Attachment} This attachment
|
||||||
|
*/
|
||||||
|
setName(name) {
|
||||||
|
this.file.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the file of this attachment.
|
||||||
|
* @param {BufferResolvable|Stream} file The file
|
||||||
|
* @param {string} name The name of the file
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_attach(file, name) {
|
||||||
|
if (typeof file === 'string') this.file = file;
|
||||||
|
else this.setAttachment(file, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Attachment;
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
const ClientDataResolver = require('../client/ClientDataResolver');
|
const Attachment = require('./Attachment');
|
||||||
|
let ClientDataResolver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A rich embed to be sent with a message with a fluent interface for creation.
|
* A rich embed to be sent with a message with a fluent interface for creation.
|
||||||
@@ -113,6 +114,7 @@ class RichEmbed {
|
|||||||
* @returns {RichEmbed} This embed
|
* @returns {RichEmbed} This embed
|
||||||
*/
|
*/
|
||||||
setColor(color) {
|
setColor(color) {
|
||||||
|
if (!ClientDataResolver) ClientDataResolver = require('../client/ClientDataResolver');
|
||||||
this.color = ClientDataResolver.resolveColor(color);
|
this.color = ClientDataResolver.resolveColor(color);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -203,11 +205,13 @@ class RichEmbed {
|
|||||||
/**
|
/**
|
||||||
* Sets the file to upload alongside the embed. This file can be accessed via `attachment://fileName.extension` when
|
* Sets the file to upload alongside the embed. This file can be accessed via `attachment://fileName.extension` when
|
||||||
* setting an embed image or author/footer icons. Only one file may be attached.
|
* setting an embed image or author/footer icons. Only one file may be attached.
|
||||||
* @param {FileOptions|string} file Local path or URL to the file to attach, or valid FileOptions for a file to attach
|
* @param {FileOptions|string|Attachment} file Local path or URL to the file to attach,
|
||||||
|
* or valid FileOptions for a file to attach
|
||||||
* @returns {RichEmbed} This embed
|
* @returns {RichEmbed} This embed
|
||||||
*/
|
*/
|
||||||
attachFile(file) {
|
attachFile(file) {
|
||||||
if (this.file) throw new RangeError('You may not upload more than one file at once.');
|
if (this.file) throw new RangeError('You may not upload more than one file at once.');
|
||||||
|
if (file instanceof Attachment) file = file.file;
|
||||||
this.file = file;
|
this.file = file;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const Util = require('../util/Util');
|
||||||
|
const Attachment = require('./Attachment');
|
||||||
|
const RichEmbed = require('./RichEmbed');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a webhook.
|
* Represents a webhook.
|
||||||
@@ -76,11 +79,12 @@ class Webhook {
|
|||||||
* @property {string} [avatarURL] Avatar URL override for the message
|
* @property {string} [avatarURL] Avatar URL override for the message
|
||||||
* @property {boolean} [tts=false] Whether or not the message should be spoken aloud
|
* @property {boolean} [tts=false] Whether or not the message should be spoken aloud
|
||||||
* @property {string} [nonce=''] The nonce for the message
|
* @property {string} [nonce=''] The nonce for the message
|
||||||
* @property {Object[]} [embeds] An array of embeds for the message
|
* @property {Array<RichEmbed|Object>} [embeds] An array of embeds for the message
|
||||||
* (see [here](https://discordapp.com/developers/docs/resources/channel#embed-object) for more details)
|
* (see [here](https://discordapp.com/developers/docs/resources/channel#embed-object) for more details)
|
||||||
* @property {boolean} [disableEveryone=this.client.options.disableEveryone] Whether or not @everyone and @here
|
* @property {boolean} [disableEveryone=this.client.options.disableEveryone] Whether or not @everyone and @here
|
||||||
* should be replaced with plain-text
|
* should be replaced with plain-text
|
||||||
* @property {FileOptions|string} [file] A file to send with the message
|
* @property {FileOptions|BufferResolvable|Attachment} [file] A file to send with the message **(deprecated)**
|
||||||
|
* @property {FileOptions[]|BufferResolvable[]|Attachment[]} [files] Files to send with the message
|
||||||
* @property {string|boolean} [code] Language for optional codeblock formatting to apply
|
* @property {string|boolean} [code] Language for optional codeblock formatting to apply
|
||||||
* @property {boolean|SplitOptions} [split=false] Whether or not the message should be split into multiple messages if
|
* @property {boolean|SplitOptions} [split=false] Whether or not the message should be split into multiple messages if
|
||||||
* it exceeds the character limit. If an object is provided, these are the options for splitting the message.
|
* it exceeds the character limit. If an object is provided, these are the options for splitting the message.
|
||||||
@@ -89,7 +93,8 @@ class Webhook {
|
|||||||
/**
|
/**
|
||||||
* Send a message with this webhook.
|
* Send a message with this webhook.
|
||||||
* @param {StringResolvable} content The content to send
|
* @param {StringResolvable} content The content to send
|
||||||
* @param {WebhookMessageOptions} [options={}] The options to provide
|
* @param {WebhookMessageOptions|Attachment|RichEmbed} [options] The options to provide
|
||||||
|
* can also be just a RichEmbed or Attachment
|
||||||
* @returns {Promise<Message|Message[]>}
|
* @returns {Promise<Message|Message[]>}
|
||||||
* @example
|
* @example
|
||||||
* // Send a message
|
* // Send a message
|
||||||
@@ -97,39 +102,78 @@ class Webhook {
|
|||||||
* .then(message => console.log(`Sent message: ${message.content}`))
|
* .then(message => console.log(`Sent message: ${message.content}`))
|
||||||
* .catch(console.error);
|
* .catch(console.error);
|
||||||
*/
|
*/
|
||||||
send(content, options) {
|
send(content, options) { // eslint-disable-line complexity
|
||||||
if (!options && typeof content === 'object' && !(content instanceof Array)) {
|
if (!options && typeof content === 'object' && !(content instanceof Array)) {
|
||||||
options = content;
|
options = content;
|
||||||
content = '';
|
content = '';
|
||||||
} else if (!options) {
|
} else if (!options) {
|
||||||
options = {};
|
options = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options instanceof Attachment) options = { files: [options] };
|
||||||
|
if (options instanceof RichEmbed) options = { embeds: [options] };
|
||||||
|
|
||||||
|
if (content) {
|
||||||
|
content = this.client.resolver.resolveString(content);
|
||||||
|
let { split, code, disableEveryone } = options;
|
||||||
|
if (split && typeof split !== 'object') split = {};
|
||||||
|
if (typeof code !== 'undefined' && (typeof code !== 'boolean' || code === true)) {
|
||||||
|
content = Util.escapeMarkdown(content, true);
|
||||||
|
content = `\`\`\`${typeof code !== 'boolean' ? code || '' : ''}\n${content}\n\`\`\``;
|
||||||
|
if (split) {
|
||||||
|
split.prepend = `\`\`\`${typeof code !== 'boolean' ? code || '' : ''}\n`;
|
||||||
|
split.append = '\n```';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (disableEveryone || (typeof disableEveryone === 'undefined' && this.client.options.disableEveryone)) {
|
||||||
|
content = content.replace(/@(everyone|here)/g, '@\u200b$1');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (split) content = Util.splitMessage(content, split);
|
||||||
|
}
|
||||||
|
|
||||||
if (options.file) {
|
if (options.file) {
|
||||||
if (options.files) options.files.push(options.file);
|
if (options.files) options.files.push(options.file);
|
||||||
else options.files = [options.file];
|
else options.files = [options.file];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.embeds) {
|
||||||
|
const files = [];
|
||||||
|
for (const embed of options.embeds) {
|
||||||
|
if (embed.file) files.push(embed.file);
|
||||||
|
}
|
||||||
|
if (options.files) options.files.push(...files);
|
||||||
|
else options.files = files;
|
||||||
|
}
|
||||||
|
|
||||||
if (options.files) {
|
if (options.files) {
|
||||||
for (let i = 0; i < options.files.length; i++) {
|
for (let i = 0; i < options.files.length; i++) {
|
||||||
let file = options.files[i];
|
let file = options.files[i];
|
||||||
if (typeof file === 'string') file = { attachment: file };
|
if (typeof file === 'string' || Buffer.isBuffer(file)) file = { attachment: file };
|
||||||
if (!file.name) {
|
if (!file.name) {
|
||||||
if (typeof file.attachment === 'string') {
|
if (typeof file.attachment === 'string') {
|
||||||
file.name = path.basename(file.attachment);
|
file.name = path.basename(file.attachment);
|
||||||
} else if (file.attachment && file.attachment.path) {
|
} else if (file.attachment && file.attachment.path) {
|
||||||
file.name = path.basename(file.attachment.path);
|
file.name = path.basename(file.attachment.path);
|
||||||
|
} else if (file instanceof Attachment) {
|
||||||
|
file = { attachment: file.file, name: path.basename(file.file) || 'file.jpg' };
|
||||||
} else {
|
} else {
|
||||||
file.name = 'file.jpg';
|
file.name = 'file.jpg';
|
||||||
}
|
}
|
||||||
|
} else if (file instanceof Attachment) {
|
||||||
|
file = file.file;
|
||||||
}
|
}
|
||||||
|
options.files[i] = file;
|
||||||
}
|
}
|
||||||
return this.client.resolver.resolveBuffer(options.file.attachment).then(file =>
|
|
||||||
this.client.rest.methods.sendWebhookMessage(this, content, options, {
|
return Promise.all(options.files.map(file =>
|
||||||
file,
|
this.client.resolver.resolveFile(file.attachment).then(resource => {
|
||||||
name: options.file.name,
|
file.file = resource;
|
||||||
|
return file;
|
||||||
})
|
})
|
||||||
);
|
)).then(files => this.client.rest.methods.sendWebhookMessage(this, content, options, files));
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.client.rest.methods.sendWebhookMessage(this, content, options);
|
return this.client.rest.methods.sendWebhookMessage(this, content, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ const path = require('path');
|
|||||||
const Message = require('../Message');
|
const Message = require('../Message');
|
||||||
const MessageCollector = require('../MessageCollector');
|
const MessageCollector = require('../MessageCollector');
|
||||||
const Collection = require('../../util/Collection');
|
const Collection = require('../../util/Collection');
|
||||||
|
const Attachment = require('../../structures/Attachment');
|
||||||
|
const RichEmbed = require('../../structures/RichEmbed');
|
||||||
const util = require('util');
|
const util = require('util');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,8 +40,8 @@ class TextBasedChannel {
|
|||||||
* (see [here](https://discordapp.com/developers/docs/resources/channel#embed-object) for more details)
|
* (see [here](https://discordapp.com/developers/docs/resources/channel#embed-object) for more details)
|
||||||
* @property {boolean} [disableEveryone=this.client.options.disableEveryone] Whether or not @everyone and @here
|
* @property {boolean} [disableEveryone=this.client.options.disableEveryone] Whether or not @everyone and @here
|
||||||
* should be replaced with plain-text
|
* should be replaced with plain-text
|
||||||
* @property {FileOptions|string} [file] A file to send with the message **(deprecated)**
|
* @property {FileOptions|BufferResolvable|Attachment} [file] A file to send with the message **(deprecated)**
|
||||||
* @property {FileOptions[]|string[]} [files] Files to send with the message
|
* @property {FileOptions[]|BufferResolvable[]|Attachment[]} [files] Files to send with the message
|
||||||
* @property {string|boolean} [code] Language for optional codeblock formatting to apply
|
* @property {string|boolean} [code] Language for optional codeblock formatting to apply
|
||||||
* @property {boolean|SplitOptions} [split=false] Whether or not the message should be split into multiple messages if
|
* @property {boolean|SplitOptions} [split=false] Whether or not the message should be split into multiple messages if
|
||||||
* it exceeds the character limit. If an object is provided, these are the options for splitting the message
|
* it exceeds the character limit. If an object is provided, these are the options for splitting the message
|
||||||
@@ -64,7 +66,8 @@ class TextBasedChannel {
|
|||||||
/**
|
/**
|
||||||
* Send a message to this channel.
|
* Send a message to this channel.
|
||||||
* @param {StringResolvable} [content] Text for the message
|
* @param {StringResolvable} [content] Text for the message
|
||||||
* @param {MessageOptions} [options={}] Options for the message
|
* @param {MessageOptions|Attachment|RichEmbed} [options] Options for the message,
|
||||||
|
* can also be just a RichEmbed or Attachment
|
||||||
* @returns {Promise<Message|Message[]>}
|
* @returns {Promise<Message|Message[]>}
|
||||||
* @example
|
* @example
|
||||||
* // Send a message
|
* // Send a message
|
||||||
@@ -80,7 +83,13 @@ class TextBasedChannel {
|
|||||||
options = {};
|
options = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.embed && options.embed.file) options.file = options.embed.file;
|
if (options instanceof Attachment) options = { files: [options.file] };
|
||||||
|
if (options instanceof RichEmbed) options = { embed: options };
|
||||||
|
|
||||||
|
if (options.embed && options.embed.file) {
|
||||||
|
if (options.files) options.files.push(options.embed.file);
|
||||||
|
else options.files = [options.embed.file];
|
||||||
|
}
|
||||||
|
|
||||||
if (options.file) {
|
if (options.file) {
|
||||||
if (options.files) options.files.push(options.file);
|
if (options.files) options.files.push(options.file);
|
||||||
@@ -90,22 +99,26 @@ class TextBasedChannel {
|
|||||||
if (options.files) {
|
if (options.files) {
|
||||||
for (let i = 0; i < options.files.length; i++) {
|
for (let i = 0; i < options.files.length; i++) {
|
||||||
let file = options.files[i];
|
let file = options.files[i];
|
||||||
if (typeof file === 'string') file = { attachment: file };
|
if (typeof file === 'string' || Buffer.isBuffer(file)) file = { attachment: file };
|
||||||
if (!file.name) {
|
if (!file.name) {
|
||||||
if (typeof file.attachment === 'string') {
|
if (typeof file.attachment === 'string') {
|
||||||
file.name = path.basename(file.attachment);
|
file.name = path.basename(file.attachment);
|
||||||
} else if (file.attachment && file.attachment.path) {
|
} else if (file.attachment && file.attachment.path) {
|
||||||
file.name = path.basename(file.attachment.path);
|
file.name = path.basename(file.attachment.path);
|
||||||
|
} else if (file instanceof Attachment) {
|
||||||
|
file = { attachment: file.file, name: path.basename(file.file) || 'file.jpg' };
|
||||||
} else {
|
} else {
|
||||||
file.name = 'file.jpg';
|
file.name = 'file.jpg';
|
||||||
}
|
}
|
||||||
|
} else if (file instanceof Attachment) {
|
||||||
|
file = file.file;
|
||||||
}
|
}
|
||||||
options.files[i] = file;
|
options.files[i] = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.all(options.files.map(file =>
|
return Promise.all(options.files.map(file =>
|
||||||
this.client.resolver.resolveBuffer(file.attachment).then(buffer => {
|
this.client.resolver.resolveFile(file.attachment).then(resource => {
|
||||||
file.file = buffer;
|
file.file = resource;
|
||||||
return file;
|
return file;
|
||||||
})
|
})
|
||||||
)).then(files => this.client.rest.methods.sendMessage(this, content, options, files));
|
)).then(files => this.client.rest.methods.sendMessage(this, content, options, files));
|
||||||
|
|||||||
Reference in New Issue
Block a user