From 6cfbf76406360c1e126985ea1ccbcb2dc26c2d6b Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Fri, 2 Dec 2016 20:59:38 -0600 Subject: [PATCH] add more embed stuff (#939) * add fun embed stuff * add more docstrings * fix gawdl3y * Update RichEmbed.js --- src/index.js | 1 + src/structures/DMChannel.js | 1 + src/structures/GroupDMChannel.js | 1 + src/structures/RichEmbed.js | 179 +++++++++++++++++++ src/structures/TextChannel.js | 1 + src/structures/User.js | 1 + src/structures/interface/TextBasedChannel.js | 24 ++- 7 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 src/structures/RichEmbed.js diff --git a/src/index.js b/src/index.js index c1d262a7b..8df1d4ee6 100644 --- a/src/index.js +++ b/src/index.js @@ -33,6 +33,7 @@ module.exports = { PermissionOverwrites: require('./structures/PermissionOverwrites'), Presence: require('./structures/Presence').Presence, ReactionEmoji: require('./structures/ReactionEmoji'), + RichEmbed: require('./structures/RichEmbed'), Role: require('./structures/Role'), TextChannel: require('./structures/TextChannel'), User: require('./structures/User'), diff --git a/src/structures/DMChannel.js b/src/structures/DMChannel.js index 09213c977..abf197e4b 100644 --- a/src/structures/DMChannel.js +++ b/src/structures/DMChannel.js @@ -39,6 +39,7 @@ class DMChannel extends Channel { // These are here only for documentation purposes - they are implemented by TextBasedChannel sendMessage() { return; } sendTTSMessage() { return; } + sendEmbed() { return; } sendFile() { return; } sendCode() { return; } fetchMessage() { return; } diff --git a/src/structures/GroupDMChannel.js b/src/structures/GroupDMChannel.js index 1e81865ae..c79b6dcaa 100644 --- a/src/structures/GroupDMChannel.js +++ b/src/structures/GroupDMChannel.js @@ -126,6 +126,7 @@ class GroupDMChannel extends Channel { // These are here only for documentation purposes - they are implemented by TextBasedChannel sendMessage() { return; } sendTTSMessage() { return; } + sendEmbed() { return; } sendFile() { return; } sendCode() { return; } fetchMessage() { return; } diff --git a/src/structures/RichEmbed.js b/src/structures/RichEmbed.js new file mode 100644 index 000000000..fd56eb664 --- /dev/null +++ b/src/structures/RichEmbed.js @@ -0,0 +1,179 @@ +/** + * A rich embed to be sent with a message + * @param {Object} [data] Data to set in the rich embed + */ +class RichEmbed { + constructor(data = {}) { + /** + * Title for this Embed + * @type {string} + */ + this.title = data.title; + + /** + * Description for this Embed + * @type {string} + */ + this.description = data.description; + + /** + * URL for this Embed + * @type {string} + */ + this.url = data.url; + + /** + * Color for this Embed + * @type {number} + */ + this.color = data.color; + + /** + * Author for this Embed + * @type {Object} + */ + this.author = data.author; + + /** + * Timestamp for this Embed + * @type {Date} + */ + this.timestamp = data.timestamp; + + /** + * Fields for this Embed + * @type {Object[]} + */ + this.fields = data.fields || []; + + /** + * Thumbnail for this Embed + * @type {Object} + */ + this.thumbnail = data.thumbnail; + + /** + * Image for this Embed + * @type {Object} + */ + this.image = data.image; + + /** + * Footer for this Embed + * @type {Object} + */ + this.footer = data.footer; + } + + /** + * Sets the title of this embed + * @param {string} title The title + * @returns {RichEmbed} This embed + */ + setTitle(title) { + this.title = title; + return this; + } + + /** + * Sets the description of this embed + * @param {string} description The description + * @returns {RichEmbed} This embed + */ + setDescription(description) { + this.description = description; + return this; + } + + /** + * Sets the URL of this embed + * @param {string} url The URL + * @returns {RichEmbed} This embed + */ + setURL(url) { + this.url = url; + return this; + } + + /** + * Sets the color of this embed + * @param {string|number|number[]} color The color to set + * @returns {RichEmbed} This embed + */ + setColor(color) { + if (color instanceof Array) { + color = parseInt(((1 << 24) + (color[0] << 16) + (color[1] << 8) + color[2]).toString(16).slice(1), 16); + } else if (typeof color === 'string' && color.startsWith('#')) { + color = parseInt(color.replace('#', ''), 16); + } + this.color = color; + return this; + } + + /** + * Sets the author of this embed + * @param {string} name The name of the author + * @param {string} [icon] The icon of the author + * @returns {RichEmbed} This embed + */ + setAuthor(name, icon) { + this.author = { name, icon_url: icon }; + return this; + } + + /** + * Sets the timestamp of this embed + * @param {Date} [timestamp=current date] The timestamp + * @returns {RichEmbed} This embed + */ + addTimestamp(timestamp = new Date()) { + this.timestamp = timestamp; + return this; + } + + /** + * Adds a field to the embed (max 25) + * @param {string} name The name of the field + * @param {string} value The value of the field + * @param {boolean} [inline=false] Set the field to display inline + * @returns {RichEmbed} This embed + */ + addField(name, value, inline = false) { + if (this.fields.length >= 25) throw new RangeError('A RichEmbed may only have a maximum of 25 fields.'); + this.fields.push({ name, value, inline }); + return this; + } + + /** + * Set the thumbnail of this embed + * @param {string} url The URL of the thumbnail + * @returns {RichEmbed} This embed + */ + setThumbnail(url) { + this.thumbnail = { url }; + return this; + } + + /** + * Set the image of this embed + * @param {string} url The URL of the thumbnail + * @returns {RichEmbed} This embed + */ + setImage(url) { + this.image = { url }; + return this; + } + + /** + * Sets the footer of this embed + * @param {string} text The text of the footer + * @param {string} icon The icon of the footer + * @returns {RichEmbed} This embed + */ + setFooter(text, icon) { + this.footer = { text, icon_url: icon }; + return this; + } +} + +module.exports = RichEmbed; diff --git a/src/structures/TextChannel.js b/src/structures/TextChannel.js index 74c0ff2d0..449da6759 100644 --- a/src/structures/TextChannel.js +++ b/src/structures/TextChannel.js @@ -75,6 +75,7 @@ class TextChannel extends GuildChannel { // These are here only for documentation purposes - they are implemented by TextBasedChannel sendMessage() { return; } sendTTSMessage() { return; } + sendEmbed() { return; } sendFile() { return; } sendCode() { return; } fetchMessage() { return; } diff --git a/src/structures/User.js b/src/structures/User.js index d3218cf25..3bbc85f0f 100644 --- a/src/structures/User.js +++ b/src/structures/User.js @@ -232,6 +232,7 @@ class User { // These are here only for documentation purposes - they are implemented by TextBasedChannel sendMessage() { return; } sendTTSMessage() { return; } + sendEmbed() { return; } sendFile() { return; } sendCode() { return; } } diff --git a/src/structures/interface/TextBasedChannel.js b/src/structures/interface/TextBasedChannel.js index d622dcabe..f8ebdb4ae 100644 --- a/src/structures/interface/TextBasedChannel.js +++ b/src/structures/interface/TextBasedChannel.js @@ -2,6 +2,7 @@ const path = require('path'); const Message = require('../Message'); const MessageCollector = require('../MessageCollector'); const Collection = require('../../util/Collection'); +const RichEmbed = require('../RichEmbed'); const escapeMarkdown = require('../../util/EscapeMarkdown'); /** @@ -76,6 +77,27 @@ class TextBasedChannel { return this.client.rest.methods.sendMessage(this, content, options); } + /** + * Send an embed to this channel + * @param {RichEmbed|Object} embed The embed to send + * @param {string|MessageOptions} contentOrOptions Content to send or message options + * @param {MessageOptions} options If contentOrOptions is content, this will be options + * @returns {Promise} + */ + sendEmbed(embed, contentOrOptions, options = {}) { + if (!(embed instanceof RichEmbed)) embed = new RichEmbed(embed); + let content; + if (contentOrOptions) { + if (typeof contentOrOptions === 'string') { + content = contentOrOptions; + } else { + options = contentOrOptions; + } + } + options.embed = embed; + return this.sendMessage(content, options); + } + /** * Send a file to this channel * @param {BufferResolvable} attachment The file to send @@ -327,7 +349,7 @@ class TextBasedChannel { } exports.applyToClass = (structure, full = false) => { - const props = ['sendMessage', 'sendTTSMessage', 'sendFile', 'sendCode']; + const props = ['sendMessage', 'sendTTSMessage', 'sendEmbed', 'sendFile', 'sendCode']; if (full) { props.push('_cacheMessage'); props.push('fetchMessages');