Add long message splitting

This commit is contained in:
Schuyler Cebulskie
2016-09-11 01:01:36 -04:00
parent 68879777d8
commit 7da00cf0fe
5 changed files with 86 additions and 27 deletions

View File

@@ -5,12 +5,22 @@ class MessageCreateAction extends Action {
handle(data) {
const client = this.client;
const channel = client.channels.get(data.channel_id);
const channel = client.channels.get((data instanceof Array ? data[0] : data).channel_id);
if (channel) {
const message = channel._cacheMessage(new Message(channel, data, client));
return {
message,
};
if (data instanceof Array) {
const messages = new Array(data.length);
for (let i = 0; i < data.length; i++) {
messages[i] = channel._cacheMessage(new Message(channel, data[i], client));
}
return {
messages,
};
} else {
const message = channel._cacheMessage(new Message(channel, data, client));
return {
message,
};
}
}
return {

View File

@@ -1,5 +1,6 @@
const Constants = require('../../util/Constants');
const Collection = require('../../util/Collection');
const splitMessage = require('../../util/SplitMessage');
const requireStructure = name => require(`../../structures/${name}`);
const User = requireStructure('User');
@@ -46,36 +47,58 @@ class RESTMethods {
});
}
sendMessage(channel, content, tts, nonce, disableEveryone, file) {
sendMessage(channel, content, { tts, nonce, disable_everyone, split } = {}, file = null) {
return new Promise((resolve, reject) => {
const $this = this;
if (typeof content !== 'undefined') content = this.rest.client.resolver.resolveString(content);
if (disableEveryone || (typeof disableEveryone === 'undefined' && this.rest.client.options.disable_everyone)) {
if (disable_everyone || (typeof disable_everyone === 'undefined' && this.rest.client.options.disable_everyone)) {
content = content.replace('@everyone', '@\u200beveryone').replace('@here', '@\u200bhere');
}
function req() {
$this.rest.makeRequest('post', Constants.Endpoints.channelMessages(channel.id), true, {
content, tts, nonce,
}, file)
.then(data => resolve($this.rest.client.actions.MessageCreate.handle(data).message))
.catch(reject);
}
if (split) content = splitMessage(content, typeof split === 'object' ? split : {});
if (channel instanceof User || channel instanceof GuildMember) {
this.createDM(channel).then(chan => {
channel = chan;
req();
this._sendMessageRequest(channel, content, file, tts, nonce, resolve, reject);
})
.catch(reject);
} else {
req();
this._sendMessageRequest(channel, content, file, tts, nonce, resolve, reject);
}
});
}
_sendMessageRequest(channel, content, file, tts, nonce, resolve, reject) {
if (content instanceof Array) {
const datas = [];
const promise = this.rest.makeRequest('post', Constants.Endpoints.channelMessages(channel.id), true, {
content: content[0], tts, nonce,
}, file);
for (let i = 1; i <= content.length; i++) {
if (i < content.length) {
promise.then(data => {
datas.push(data);
return this.rest.makeRequest('post', Constants.Endpoints.channelMessages(channel.id), true, {
content: content[i], tts, nonce,
}, file);
});
} else {
promise.then(data => {
datas.push(data);
resolve(this.rest.client.actions.MessageCreate.handle(datas).messages).catch(reject);
});
}
}
} else {
this.rest.makeRequest('post', Constants.Endpoints.channelMessages(channel.id), true, {
content, tts, nonce,
}, file)
.then(data => resolve(this.rest.client.actions.MessageCreate.handle(data).message))
.catch(reject);
}
}
deleteMessage(message) {
return new Promise((resolve, reject) => {
this.rest.makeRequest('del', Constants.Endpoints.channelMessage(message.channel.id, message.id), true)

View File

@@ -290,7 +290,7 @@ class Message {
* Reply to a message
* @param {StringResolvable} content The content for the message
* @param {MessageOptions} [options = {}] The options to provide
* @returns {Promise<Message>}
* @returns {Promise<Message|Message[]>}
* @example
* // reply to a message
* message.reply('Hey, I'm a reply!')
@@ -299,8 +299,15 @@ class Message {
*/
reply(content, options = {}) {
content = this.client.resolver.resolveString(content);
const newContent = this.guild ? `${this.author}, ${content}` : content;
return this.client.rest.methods.sendMessage(this.channel, newContent, options.tts);
const prepend = this.guild ? `${this.author}, ` : '';
content = `${prepend}${content}`;
if (options.split) {
if (typeof options.split !== 'object') options.split = {};
if (!options.split.prepend) options.split.prepend = prepend;
}
return this.client.rest.methods.sendMessage(this.channel, content, options);
}
/**

View File

@@ -29,6 +29,7 @@ class TextBasedChannel {
* tts: false,
* nonce: '',
* disable_everyone: false,
* split: false,
* };
* ```
* @typedef {Object} MessageOptions
@@ -38,7 +39,7 @@ class TextBasedChannel {
* Send a message to this channel
* @param {StringResolvable} content The content to send
* @param {MessageOptions} [options={}] The options to provide
* @returns {Promise<Message>}
* @returns {Promise<Message|Message[]>}
* @example
* // send a message
* channel.sendMessage('hello!')
@@ -46,14 +47,14 @@ class TextBasedChannel {
* .catch(console.log);
*/
sendMessage(content, options = {}) {
return this.client.rest.methods.sendMessage(this, content, options.tts, options.nonce, options.disable_everyone);
return this.client.rest.methods.sendMessage(this, content, options);
}
/**
* Send a text-to-speech message to this channel
* @param {StringResolvable} content The content to send
* @param {MessageOptions} [options={}] The options to provide
* @returns {Promise<Message>}
* @returns {Promise<Message|Message[]>}
* @example
* // send a TTS message
* channel.sendTTSMessage('hello!')
@@ -61,7 +62,8 @@ class TextBasedChannel {
* .catch(console.log);
*/
sendTTSMessage(content, options = {}) {
return this.client.rest.methods.sendMessage(this, content, true, options.nonce, options.disable_everyone);
Object.assign(options, { tts: true });
return this.client.rest.methods.sendMessage(this, content, options);
}
/**
@@ -69,9 +71,10 @@ class TextBasedChannel {
* @param {FileResolvable} attachment The file to send
* @param {string} [fileName="file.jpg"] The name and extension of the file
* @param {StringResolvable} [content] Text message to send with the attachment
* @param {MessageOptions} [options] The options to provide
* @returns {Promise<Message>}
*/
sendFile(attachment, fileName, content) {
sendFile(attachment, fileName, content, options = {}) {
if (!fileName) {
if (typeof attachment === 'string') {
fileName = path.basename(attachment);
@@ -83,7 +86,7 @@ class TextBasedChannel {
}
return new Promise((resolve, reject) => {
this.client.resolver.resolveFile(attachment).then(file => {
this.client.rest.methods.sendMessage(this, content, false, undefined, false, {
this.client.rest.methods.sendMessage(this, content, options, {
file,
name: fileName,
}).then(resolve).catch(reject);

16
src/util/SplitMessage.js Normal file
View File

@@ -0,0 +1,16 @@
module.exports = function splitMessage(text, { maxLength = 1950, char = '\n', prepend = '', append = '' } = {}) {
if (text.length <= maxLength) return text;
const splitText = text.split(char);
if (splitText.length === 1) throw new Error('Message exceeds the max length and contains no split characters.');
const messages = [''];
let msg = 0;
for (let i = 0; i < splitText.length; i++) {
if (messages[msg].length + splitText[i].length + 1 > maxLength) {
messages[msg] += append;
messages.push(prepend);
msg++;
}
messages[msg] += (messages[msg].length > 0 && messages[msg] !== prepend ? char : '') + splitText[i];
}
return messages;
};