From 29433e2f7dbd0e4a73d3c78ffe1005b922fb5982 Mon Sep 17 00:00:00 2001 From: Alee14 Date: Sun, 26 Mar 2017 15:18:10 -0400 Subject: Don't mind me i'm adding the discord.js files --- .../src/structures/interface/TextBasedChannel.js | 377 +++++++++++++++++++++ 1 file changed, 377 insertions(+) create mode 100644 node_modules/discord.js/src/structures/interface/TextBasedChannel.js (limited to 'node_modules/discord.js/src/structures/interface') diff --git a/node_modules/discord.js/src/structures/interface/TextBasedChannel.js b/node_modules/discord.js/src/structures/interface/TextBasedChannel.js new file mode 100644 index 0000000..353c0a9 --- /dev/null +++ b/node_modules/discord.js/src/structures/interface/TextBasedChannel.js @@ -0,0 +1,377 @@ +const path = require('path'); +const Message = require('../Message'); +const MessageCollector = require('../MessageCollector'); +const Collection = require('../../util/Collection'); + + +/** + * Interface for classes that have text-channel-like features + * @interface + */ +class TextBasedChannel { + constructor() { + /** + * A collection containing the messages sent to this channel. + * @type {Collection} + */ + this.messages = new Collection(); + + /** + * The ID of the last message in the channel, if one was sent. + * @type {?string} + */ + this.lastMessageID = null; + } + + /** + * Options that can be passed into send, sendMessage, sendFile, sendEmbed, sendCode, and Message#reply + * @typedef {Object} MessageOptions + * @property {boolean} [tts=false] Whether or not the message should be spoken aloud + * @property {string} [nonce=''] The nonce for the message + * @property {Object} [embed] An embed for the message + * (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 + * should be replaced with plain-text + * @property {FileOptions|string} [file] A file to send with the message + * @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 + * it exceeds the character limit. If an object is provided, these are the options for splitting the message. + */ + + /** + * @typedef {Object} FileOptions + * @property {BufferResolvable} attachment + * @property {string} [name='file.jpg'] + */ + + /** + * Options for splitting a message + * @typedef {Object} SplitOptions + * @property {number} [maxLength=1950] Maximum character length per message piece + * @property {string} [char='\n'] Character to split the message with + * @property {string} [prepend=''] Text to prepend to every piece except the first + * @property {string} [append=''] Text to append to every piece except the last + */ + + /** + * Send a message to this channel + * @param {StringResolvable} [content] Text for the message + * @param {MessageOptions} [options={}] Options for the message + * @returns {Promise} + * @example + * // send a message + * channel.send('hello!') + * .then(message => console.log(`Sent message: ${message.content}`)) + * .catch(console.error); + */ + send(content, options) { + if (!options && typeof content === 'object' && !(content instanceof Array)) { + options = content; + content = ''; + } else if (!options) { + options = {}; + } + if (options.file) { + if (typeof options.file === 'string') options.file = { attachment: options.file }; + if (!options.file.name) { + if (typeof options.file.attachment === 'string') { + options.file.name = path.basename(options.file.attachment); + } else if (options.file.attachment && options.file.attachment.path) { + options.file.name = path.basename(options.file.attachment.path); + } else { + options.file.name = 'file.jpg'; + } + } + return this.client.resolver.resolveBuffer(options.file.attachment).then(file => + this.client.rest.methods.sendMessage(this, content, options, { + file, + name: options.file.name, + }) + ); + } + return this.client.rest.methods.sendMessage(this, content, options); + } + + /** + * Send a message to this channel + * @param {StringResolvable} content Text for the message + * @param {MessageOptions} [options={}] Options for the message + * @returns {Promise} + * @example + * // send a message + * channel.sendMessage('hello!') + * .then(message => console.log(`Sent message: ${message.content}`)) + * .catch(console.error); + */ + sendMessage(content, options) { + return this.send(content, options); + } + + /** + * Send an embed to this channel + * @param {RichEmbed|Object} embed Embed for the message + * @param {string} [content] Text for the message + * @param {MessageOptions} [options] Options for the message + * @returns {Promise} + */ + sendEmbed(embed, content, options) { + if (!options && typeof content === 'object') { + options = content; + content = ''; + } else if (!options) { + options = {}; + } + return this.send(content, Object.assign(options, { embed })); + } + + /** + * Send a file to this channel + * @param {BufferResolvable} attachment File to send + * @param {string} [name='file.jpg'] Name and extension of the file + * @param {StringResolvable} [content] Text for the message + * @param {MessageOptions} [options] Options for the message + * @returns {Promise} + */ + sendFile(attachment, name, content, options = {}) { + return this.send(content, Object.assign(options, { file: { attachment, name } })); + } + + /** + * Send a code block to this channel + * @param {string} lang Language for the code block + * @param {StringResolvable} content Content of the code block + * @param {MessageOptions} [options] Options for the message + * @returns {Promise} + */ + sendCode(lang, content, options = {}) { + return this.send(content, Object.assign(options, { code: lang })); + } + + /** + * Gets a single message from this channel, regardless of it being cached or not. + * This is only available when using a bot account. + * @param {string} messageID ID of the message to get + * @returns {Promise} + * @example + * // get message + * channel.fetchMessage('99539446449315840') + * .then(message => console.log(message.content)) + * .catch(console.error); + */ + fetchMessage(messageID) { + return this.client.rest.methods.getChannelMessage(this, messageID).then(data => { + const msg = data instanceof Message ? data : new Message(this, data, this.client); + this._cacheMessage(msg); + return msg; + }); + } + + /** + * The parameters to pass in when requesting previous messages from a channel. `around`, `before` and + * `after` are mutually exclusive. All the parameters are optional. + * @typedef {Object} ChannelLogsQueryOptions + * @property {number} [limit=50] Number of messages to acquire + * @property {string} [before] ID of a message to get the messages that were posted before it + * @property {string} [after] ID of a message to get the messages that were posted after it + * @property {string} [around] ID of a message to get the messages that were posted around it + */ + + /** + * Gets the past messages sent in this channel. Resolves with a collection mapping message ID's to Message objects. + * @param {ChannelLogsQueryOptions} [options={}] Query parameters to pass in + * @returns {Promise>} + * @example + * // get messages + * channel.fetchMessages({limit: 10}) + * .then(messages => console.log(`Received ${messages.size} messages`)) + * .catch(console.error); + */ + fetchMessages(options = {}) { + return this.client.rest.methods.getChannelMessages(this, options).then(data => { + const messages = new Collection(); + for (const message of data) { + const msg = new Message(this, message, this.client); + messages.set(message.id, msg); + this._cacheMessage(msg); + } + return messages; + }); + } + + /** + * Fetches the pinned messages of this channel and returns a collection of them. + * @returns {Promise>} + */ + fetchPinnedMessages() { + return this.client.rest.methods.getChannelPinnedMessages(this).then(data => { + const messages = new Collection(); + for (const message of data) { + const msg = new Message(this, message, this.client); + messages.set(message.id, msg); + this._cacheMessage(msg); + } + return messages; + }); + } + + /** + * Starts a typing indicator in the channel. + * @param {number} [count] The number of times startTyping should be considered to have been called + * @example + * // start typing in a channel + * channel.startTyping(); + */ + startTyping(count) { + if (typeof count !== 'undefined' && count < 1) throw new RangeError('Count must be at least 1.'); + if (!this.client.user._typing.has(this.id)) { + this.client.user._typing.set(this.id, { + count: count || 1, + interval: this.client.setInterval(() => { + this.client.rest.methods.sendTyping(this.id); + }, 4000), + }); + this.client.rest.methods.sendTyping(this.id); + } else { + const entry = this.client.user._typing.get(this.id); + entry.count = count || entry.count + 1; + } + } + + /** + * Stops the typing indicator in the channel. + * The indicator will only stop if this is called as many times as startTyping(). + * It can take a few seconds for the client user to stop typing. + * @param {boolean} [force=false] Whether or not to reset the call count and force the indicator to stop + * @example + * // stop typing in a channel + * channel.stopTyping(); + * @example + * // force typing to fully stop in a channel + * channel.stopTyping(true); + */ + stopTyping(force = false) { + if (this.client.user._typing.has(this.id)) { + const entry = this.client.user._typing.get(this.id); + entry.count--; + if (entry.count <= 0 || force) { + this.client.clearInterval(entry.interval); + this.client.user._typing.delete(this.id); + } + } + } + + /** + * Whether or not the typing indicator is being shown in the channel. + * @type {boolean} + * @readonly + */ + get typing() { + return this.client.user._typing.has(this.id); + } + + /** + * Number of times `startTyping` has been called. + * @type {number} + * @readonly + */ + get typingCount() { + if (this.client.user._typing.has(this.id)) return this.client.user._typing.get(this.id).count; + return 0; + } + + /** + * Creates a Message Collector + * @param {CollectorFilterFunction} filter The filter to create the collector with + * @param {CollectorOptions} [options={}] The options to pass to the collector + * @returns {MessageCollector} + * @example + * // create a message collector + * const collector = channel.createCollector( + * m => m.content.includes('discord'), + * { time: 15000 } + * ); + * collector.on('message', m => console.log(`Collected ${m.content}`)); + * collector.on('end', collected => console.log(`Collected ${collected.size} items`)); + */ + createCollector(filter, options = {}) { + return new MessageCollector(this, filter, options); + } + + /** + * An object containing the same properties as CollectorOptions, but a few more: + * @typedef {CollectorOptions} AwaitMessagesOptions + * @property {string[]} [errors] Stop/end reasons that cause the promise to reject + */ + + /** + * Similar to createCollector but in promise form. Resolves with a collection of messages that pass the specified + * filter. + * @param {CollectorFilterFunction} filter The filter function to use + * @param {AwaitMessagesOptions} [options={}] Optional options to pass to the internal collector + * @returns {Promise>} + * @example + * // await !vote messages + * const filter = m => m.content.startsWith('!vote'); + * // errors: ['time'] treats ending because of the time limit as an error + * channel.awaitMessages(filter, { max: 4, time: 60000, errors: ['time'] }) + * .then(collected => console.log(collected.size)) + * .catch(collected => console.log(`After a minute, only ${collected.size} out of 4 voted.`)); + */ + awaitMessages(filter, options = {}) { + return new Promise((resolve, reject) => { + const collector = this.createCollector(filter, options); + collector.on('end', (collection, reason) => { + if (options.errors && options.errors.includes(reason)) { + reject(collection); + } else { + resolve(collection); + } + }); + }); + } + + /** + * Bulk delete given messages. + * This is only available when using a bot account. + * @param {Collection|Message[]|number} messages Messages to delete, or number of messages to delete + * @returns {Promise>} Deleted messages + */ + bulkDelete(messages) { + if (!isNaN(messages)) return this.fetchMessages({ limit: messages }).then(msgs => this.bulkDelete(msgs)); + if (messages instanceof Array || messages instanceof Collection) { + const messageIDs = messages instanceof Collection ? messages.keyArray() : messages.map(m => m.id); + return this.client.rest.methods.bulkDeleteMessages(this, messageIDs); + } + throw new TypeError('The messages must be an Array, Collection, or number.'); + } + + _cacheMessage(message) { + const maxSize = this.client.options.messageCacheMaxSize; + if (maxSize === 0) return null; + if (this.messages.size >= maxSize && maxSize > 0) this.messages.delete(this.messages.firstKey()); + this.messages.set(message.id, message); + return message; + } +} + +exports.applyToClass = (structure, full = false) => { + const props = ['send', 'sendMessage', 'sendEmbed', 'sendFile', 'sendCode']; + if (full) { + props.push( + '_cacheMessage', + 'fetchMessages', + 'fetchMessage', + 'bulkDelete', + 'startTyping', + 'stopTyping', + 'typing', + 'typingCount', + 'fetchPinnedMessages', + 'createCollector', + 'awaitMessages' + ); + } + for (const prop of props) { + Object.defineProperty(structure.prototype, prop, Object.getOwnPropertyDescriptor(TextBasedChannel.prototype, prop)); + } +}; -- cgit v1.2.3