├── .replit
├── index.js
├── src
├── Tools.js
├── CreateMessage.js
├── CreateChannel.js
├── User.js
└── MessageEmbed.js
├── package.json
├── util
├── Constants.js
└── Util.js
└── README.md
/.replit:
--------------------------------------------------------------------------------
1 | language = "nodejs"
2 | run = "npm start"
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | MessageEmbed: require("./src/MessageEmbed"),
3 | CreateMessage: require('./src/CreateMessage'),
4 | CreateChannel: require('./src/CreateChannel'),
5 | Tools: require('./src/Tools.js'),
6 | User: require('./src/User.js'),
7 | }
--------------------------------------------------------------------------------
/src/Tools.js:
--------------------------------------------------------------------------------
1 | const { FLAGS } = require("../util/Constants")
2 |
3 | class Tools {
4 | static getUserBadges(flag) {
5 | return Object.entries(FLAGS).reduce((badges, [key, bit]) => (flag & bit) > 0 ? [...badges, key] : badges, [])
6 | }
7 | }
8 |
9 | module.exports = Tools;
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "autocode-discordjs",
3 | "version": "1.1.0",
4 | "description": "Allows you to use discord.js syntax in autocode.",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/CTK-WARRIOR/autocode-discordjs"
12 | },
13 | "keywords": [
14 | "autocode",
15 | "discordjs",
16 | "autocode"
17 | ],
18 | "bugs": {
19 | "url": "https://github.com/CTK-WARRIOR/autocode-discordjs/issues"
20 | },
21 | "homepage": "https://github.com/CTK-WARRIOR/autocode-discordjs#readme",
22 | "author": "ctk",
23 | "license": "ISC",
24 | "dependencies": {
25 | "lib": "^4.3.3"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/CreateMessage.js:
--------------------------------------------------------------------------------
1 | const lib = require('lib')({token: process.env.STDLIB_SECRET_TOKEN});
2 | const CreateChannel = require('./CreateChannel')
3 |
4 | class createMessage {
5 | /**
6 | * @name MessageEmbed
7 | * @kind constructor
8 | */
9 |
10 | constructor(data = {}) {
11 | /**
12 | * Duplicate all the data key and values
13 | */
14 | Object.keys(data).forEach(key => {
15 | this[key] = data[key] || null
16 | })
17 |
18 | /**
19 | * CreateChannel Class
20 | */
21 | this.channel = new CreateChannel(data)
22 | }
23 |
24 | /**
25 | * Reply to the author of the command
26 | * @param {String} [content]
27 | * @param {Options} [channel_id, embed, tts, components, allowed_mentions]
28 | */
29 | async reply(content, { channel_id, embed, tts, components, allowed_mentions }={}) {
30 | return await lib.discord.channels['@0.1.1'].messages.create({
31 | content: content,
32 | channel_id: this.channel_id,
33 | embed,
34 | tts,
35 | components,
36 | allowed_mentions,
37 | message_reference : {
38 | message_id: this.id
39 | }
40 | });
41 | }
42 |
43 | }
44 |
45 | module.exports = createMessage;
--------------------------------------------------------------------------------
/util/Constants.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | Colors: {
3 | DEFAULT: 0x000000,
4 | WHITE: 0xffffff,
5 | AQUA: 0x1abc9c,
6 | GREEN: 0x2ecc71,
7 | BLUE: 0x3498db,
8 | YELLOW: 0xffff00,
9 | PURPLE: 0x9b59b6,
10 | LUMINOUS_VIVID_PINK: 0xe91e63,
11 | GOLD: 0xf1c40f,
12 | ORANGE: 0xe67e22,
13 | RED: 0xe74c3c,
14 | GREY: 0x95a5a6,
15 | NAVY: 0x34495e,
16 | DARK_AQUA: 0x11806a,
17 | DARK_GREEN: 0x1f8b4c,
18 | DARK_BLUE: 0x206694,
19 | DARK_PURPLE: 0x71368a,
20 | DARK_VIVID_PINK: 0xad1457,
21 | DARK_GOLD: 0xc27c0e,
22 | DARK_ORANGE: 0xa84300,
23 | DARK_RED: 0x992d22,
24 | DARK_GREY: 0x979c9f,
25 | DARKER_GREY: 0x7f8c8d,
26 | LIGHT_GREY: 0xbcc0c0,
27 | DARK_NAVY: 0x2c3e50,
28 | BLURPLE: 0x7289da,
29 | GREYPLE: 0x99aab5,
30 | DARK_BUT_NOT_BLACK: 0x2c2f33,
31 | NOT_QUITE_BLACK: 0x23272a,
32 | },
33 |
34 | FLAGS: {
35 | DISCORD_EMPLOYEE: 1 << 0,
36 | PARTNERED_SERVER_OWNER: 1 << 1,
37 | DISCORD_PARTNER: 1 << 1,
38 | HYPESQUAD_EVENTS: 1 << 2,
39 | BUGHUNTER_LEVEL_1: 1 << 3,
40 | HOUSE_BRAVERY: 1 << 6,
41 | HOUSE_BRILLIANCE: 1 << 7,
42 | HOUSE_BALANCE: 1 << 8,
43 | EARLY_SUPPORTER: 1 << 9,
44 | TEAM_USER: 1 << 10,
45 | SYSTEM: 1 << 12,
46 | BUGHUNTER_LEVEL_2: 1 << 14,
47 | VERIFIED_BOT: 1 << 16,
48 | EARLY_VERIFIED_DEVELOPER: 1 << 17,
49 | VERIFIED_DEVELOPER: 1 << 17,
50 | }
51 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # @notedwin/autocode-discordjs
2 |
3 | ## Example Usage For Autocode
4 |
5 | ### **Tools:** get user's publicly displayed badges like hypesquad badge, discord moderator badge, etc.
6 | ```js
7 | let { User, Tools } = require('@notedwin/autocode-discordjs');
8 |
9 | let user = new User();
10 |
11 | Tools.getUserBadges(user.public_flags);
12 | ```
13 |
14 | ### **CreateChannel:** ability to use this class similar like Discord.js to create new channels, set parent (category), set position (position of the channel in a category), and send message to a specific channel.
15 | ```js
16 | let { CreateChannel } = require('@notedwin/autocode-discordjs');
17 |
18 | let event = context.params.event;
19 |
20 | /** CreateChannel.create(name, { guild_id, type, topic, bitrate, user_limit, rate_limit_per_user, position, permission_overwrites, parent_id, nsfw });
21 | * bitrate and user_limit is only applicable for voice channels and stage channels.
22 | * check out more about bitrates here by reading the * section: https://discord.com/developers/docs/resources/channel#modify-channel-json-params-guild-channel
23 | * Check out more about channel type here: https://discord.com/developers/docs/resources/channel#channel-object-channel-types
24 | */
25 |
26 | let channel = new CreateChannel(event);
27 |
28 | let createdChannel = await channel.create('test-channel', {
29 | type: 0, //for now, you will have to use the integer type from Discord Dev Portal. An alternative way is coming soon.
30 | topic: `channel topic here`, //optional
31 | })
32 |
33 | /** replace the data with the created channel's data if you wanna update the created channel's info.
34 | * use the original context.params.event if you wanna update the current channel's info instead.
35 | */
36 | channel = new CreateChannel(createdChannel)
37 | await channel.setName('new-channel-name')
38 | await channel.setParent('891309033884094525')
39 | ```
40 |
--------------------------------------------------------------------------------
/src/CreateChannel.js:
--------------------------------------------------------------------------------
1 | const lib = require('lib')({ token: process.env.STDLIB_SECRET_TOKEN });
2 |
3 | class channel {
4 | constructor(data = {}) {
5 |
6 | if ('position' in data) {
7 | /**
8 | * The raw position of the channel from Discord
9 | * @type {number}
10 | */
11 | this.rawPosition = data.position;
12 | }
13 |
14 | if ('guild_id' in data) {
15 | this.guildId = data.guild_id;
16 | }
17 |
18 | if ('parent_id' in data) {
19 | /**
20 | * The id of the category parent of this channel
21 | * @type {?Snowflake}
22 | */
23 | this.parentId = data.parent_id;
24 | }
25 |
26 | this.id = data.id;
27 | }
28 |
29 | async send(content, { channel_id, embed, tts, components, allowed_mentions, message_reference, attachments } = {}) {
30 | return await lib.discord.channels['@0.3.2'].messages.create({
31 | content: content,
32 | channel_id: channel_id || this.id,
33 | attachments,
34 | embed,
35 | tts,
36 | components,
37 | allowed_mentions,
38 | message_reference
39 | });
40 | }
41 |
42 | async create(name, { guild_id, type, topic, bitrate, user_limit, rate_limit_per_user, position, permission_overwrites, parent_id, nsfw } = {}) {
43 | return await lib.discord.guilds['@0.2.4'].channels.create({
44 | guild_id: guild_id ? guild_id : this.guildId,
45 | name,
46 | type,
47 | topic,
48 | bitrate,
49 | user_limit,
50 | rate_limit_per_user,
51 | position,
52 | permission_overwrites,
53 | parent_id,
54 | nsfw,
55 | });
56 | }
57 |
58 | async setName(name) {
59 | return await lib.discord.channels['@0.3.2'].update({
60 | channel_id: `${this.id}`,
61 | name,
62 | });
63 | }
64 |
65 | async setParent(parent_id = '', options = {}){
66 | return await lib.discord.guilds['@0.2.4'].channels.update({
67 | guild_id: `${this.guildId}`,
68 | id: `${this.id}`,
69 | parent_id,
70 | });
71 | }
72 |
73 | async setPosition(position, options = {}) {
74 | return await lib.discord.guilds['@0.2.4'].channels.update({
75 | guild_id: `${this.guildId}`,
76 | id: `${this.id}`,
77 | position,
78 | });
79 | }
80 | }
81 |
82 | module.exports = channel;
83 |
--------------------------------------------------------------------------------
/util/Util.js:
--------------------------------------------------------------------------------
1 | const { Colors } = require('./Constants')
2 |
3 | class Util {
4 |
5 | /**
6 | * Data that can be resolved to give a string. This can be:
7 | * * A string
8 | * * An array (joined with a new line delimiter to give a string)
9 | * * Any value
10 | * @typedef {string|Array|*} StringResolvable
11 | */
12 |
13 | /**
14 | * Resolves a StringResolvable to a string.
15 | * @param {StringResolvable} data The string resolvable to resolve
16 | * @returns {string}
17 | */
18 | static resolveString(data) {
19 | if (typeof data === 'string') return data;
20 | if (Array.isArray(data)) return data.join('\n');
21 | return String(data);
22 | }
23 |
24 |
25 |
26 | /**
27 | * Can be a number, hex string, an RGB array like:
28 | * ```js
29 | * [255, 0, 255] // purple
30 | * ```
31 | * or one of the following strings:
32 | * - `DEFAULT`
33 | * - `WHITE`
34 | * - `AQUA`
35 | * - `GREEN`
36 | * - `BLUE`
37 | * - `YELLOW`
38 | * - `PURPLE`
39 | * - `LUMINOUS_VIVID_PINK`
40 | * - `GOLD`
41 | * - `ORANGE`
42 | * - `RED`
43 | * - `GREY`
44 | * - `DARKER_GREY`
45 | * - `NAVY`
46 | * - `DARK_AQUA`
47 | * - `DARK_GREEN`
48 | * - `DARK_BLUE`
49 | * - `DARK_PURPLE`
50 | * - `DARK_VIVID_PINK`
51 | * - `DARK_GOLD`
52 | * - `DARK_ORANGE`
53 | * - `DARK_RED`
54 | * - `DARK_GREY`
55 | * - `LIGHT_GREY`
56 | * - `DARK_NAVY`
57 | * - `BLURPLE`
58 | * - `GREYPLE`
59 | * - `DARK_BUT_NOT_BLACK`
60 | * - `NOT_QUITE_BLACK`
61 | * - `RANDOM`
62 | * @typedef {string|number|number[]} ColorResolvable
63 | */
64 |
65 | /**
66 | * Resolves a ColorResolvable into a color number.
67 | * @param {ColorResolvable} color Color to resolve
68 | * @returns {number} A color
69 | */
70 | static resolveColor(color) {
71 | if (typeof color === 'string') {
72 | if (color === 'RANDOM') return Math.floor(Math.random() * (0xffffff + 1));
73 | if (color === 'DEFAULT') return 0;
74 | color = Colors[color] || parseInt(color.replace('#', ''), 16);
75 | } else if (Array.isArray(color)) {
76 | color = (color[0] << 16) + (color[1] << 8) + color[2];
77 | }
78 |
79 | if (color < 0 || color > 0xffffff) throw new Error('COLOR_RANGE');
80 | else if (color && isNaN(color)) throw new Error('COLOR_CONVERT');
81 |
82 | return color;
83 | }
84 |
85 | }
86 |
87 | module.exports = Util;
--------------------------------------------------------------------------------
/src/User.js:
--------------------------------------------------------------------------------
1 | const lib = require('lib')({ token: process.env.STDLIB_SECRET_TOKEN });
2 |
3 | const Tools = require('./Tools');
4 |
5 | class User {
6 | constructor(data) {
7 | /**
8 | * The user's id
9 | * @type {Snowflake}
10 | */
11 | this.id = data.id;
12 |
13 | this.bot = null;
14 |
15 | this.system = null;
16 |
17 | this.flags = null;
18 |
19 | if ('username' in data) {
20 | /**
21 | * The username of the user
22 | * @type {?string}
23 | */
24 | this.username = data.username;
25 | } else {
26 | this.username ?? null;
27 | }
28 |
29 | if ('bot' in data) {
30 | /**
31 | * Whether or not the user is a bot
32 | * @type {?boolean}
33 | */
34 | this.bot = Boolean(data.bot);
35 | } else if (!this.partial && typeof this.bot !== 'boolean') {
36 | this.bot = false;
37 | }
38 |
39 | if ('discriminator' in data) {
40 | /**
41 | * A discriminator based on username for the user
42 | * @type {?string}
43 | */
44 | this.discriminator = data.discriminator;
45 | } else {
46 | this.discriminator ?? null;
47 | }
48 |
49 | if ('avatar' in data) {
50 | /**
51 | * The user avatar's hash
52 | * @type {?string}
53 | */
54 | this.avatar = data.avatar;
55 | } else {
56 | this.avatar ?? null;
57 | }
58 |
59 | if ('banner' in data) {
60 | /**
61 | * The user banner's hash
62 | * The user must be force fetched for this property to be present or be updated
63 | * @type {?string}
64 | */
65 | this.banner = data.banner;
66 | } else if (this.banner !== null) {
67 | this.banner ?? undefined;
68 | }
69 |
70 | if ('accent_color' in data) {
71 | /**
72 | * The base 10 accent color of the user's banner
73 | * The user must be force fetched for this property to be present or be updated
74 | * @type {?number}
75 | */
76 | this.accentColor = data.accent_color;
77 | } else if (this.accentColor !== null) {
78 | this.accentColor ?? undefined;
79 | }
80 |
81 | if ('system' in data) {
82 | /**
83 | * Whether the user is an Official Discord System user (part of the urgent message system)
84 | * @type {?boolean}
85 | */
86 | this.system = Boolean(data.system);
87 | } else if (!this.partial && typeof this.system !== 'boolean') {
88 | this.system = false;
89 | }
90 |
91 | if ('public_flags' in data) {
92 | /**
93 | * The flags for this user
94 | * @type {?UserFlagsBitField}
95 | */
96 | this.flags = new Tools.getUserBadges(data.public_flags);
97 | }
98 | }
99 | /**
100 | * Whether this User is a partial
101 | * @type {boolean}
102 | * @readonly
103 | */
104 | get partial() {
105 | return typeof this.username !== 'string';
106 | }
107 |
108 | /**
109 | * The timestamp the user was created at
110 | * @type {number}
111 | * @readonly
112 | */
113 | get createdTimestamp() {
114 | const DISCORD_EPOCH = 1420070400000;
115 |
116 | function convertSnowflakeToDate(snowflake) {
117 | return new Date(snowflake / 4194304 + DISCORD_EPOCH);
118 | }
119 |
120 | return convertSnowflakeToDate(this.id)
121 | }
122 |
123 | /**
124 | * The time the user was created at
125 | * @type {Date}
126 | * @readonly
127 | */
128 | get createdAt() {
129 | return new Date(this.createdTimestamp);
130 | }
131 |
132 | /**
133 | * The hexadecimal version of the user accent color, with a leading hash
134 | * @type {?string}
135 | * @readonly
136 | */
137 | get hexAccentColor() {
138 | if (typeof this.accentColor !== 'number') return this.accentColor;
139 | return `#${this.accentColor.toString(16).padStart(6, '0')}`;
140 | }
141 |
142 | /**
143 | * The Discord "tag" (e.g. `CTK WARRIOR#7923`) for this user
144 | * @type {?string}
145 | * @readonly
146 | */
147 | get tag() {
148 | return typeof this.username === 'string' ? `${this.username}#${this.discriminator}` : null;
149 | }
150 |
151 | async fetch(user_id) {
152 | const id = user_id ? user_id : this.id;
153 |
154 | return await lib.discord.users['@0.2.1'].retrieve({
155 | user_id: id,
156 | });
157 | }
158 | }
--------------------------------------------------------------------------------
/src/MessageEmbed.js:
--------------------------------------------------------------------------------
1 | const Util = require('../util/Util.js');
2 |
3 | class MessageEmbed {
4 | /**
5 | * @name MessageEmbed
6 | * @kind constructor
7 | * @memberof MessageEmbed
8 | * @param {MessageEmbed|Object} [data={}] MessageEmbed to clone or raw embed data
9 | */
10 |
11 | constructor(data = {}) {
12 | /**
13 | * The type of this embed, either:
14 | * * `rich` - a rich embed
15 | * * `image` - an image embed
16 | * * `video` - a video embed
17 | * * `gifv` - a gifv embed
18 | * * `article` - an article embed
19 | * * `link` - a link embed
20 | * @type {string}
21 | */
22 | this.type = data.type || 'rich';
23 |
24 | /**
25 | * The title of this embed
26 | * @type {?string}
27 | */
28 | this.title = 'title' in data ? data.title : null;
29 |
30 | /**
31 | * The description of this embed
32 | * @type {?string}
33 | */
34 | this.description = 'description' in data ? data.description : null;
35 |
36 | /**
37 | * The URL of this embed
38 | * @type {?string}
39 | */
40 | this.url = 'url' in data ? data.url : null;
41 |
42 | /**
43 | * The color of this embed
44 | * @type {?number}
45 | */
46 | this.color = 'color' in data ? Util.resolveColor(data.color) : null;
47 |
48 | /**
49 | * The timestamp of this embed
50 | * @type {?number}
51 | */
52 | this.timestamp = 'timestamp' in data ? new Date(data.timestamp).getTime() : null;
53 |
54 | /**
55 | * Represents a field of a MessageEmbed
56 | * @typedef {Object} EmbedField
57 | * @property {string} name The name of this field
58 | * @property {string} value The value of this field
59 | * @property {boolean} inline If this field will be displayed inline
60 | */
61 |
62 | /**
63 | * The fields of this embed
64 | * @type {EmbedField[]}
65 | */
66 | this.fields = [];
67 | if (data.fields) {
68 | this.fields = skipValidation ? data.fields.map(Util.cloneObject) : this.constructor.normalizeFields(data.fields);
69 | }
70 |
71 | /**
72 | * Represents the thumbnail of a MessageEmbed
73 | * @typedef {Object} MessageEmbedThumbnail
74 | * @property {string} url URL for this thumbnail
75 | * @property {string} proxyURL ProxyURL for this thumbnail
76 | * @property {number} height Height of this thumbnail
77 | * @property {number} width Width of this thumbnail
78 | */
79 |
80 | /**
81 | * The thumbnail of this embed (if there is one)
82 | * @type {?MessageEmbedThumbnail}
83 | */
84 | this.thumbnail = data.thumbnail
85 | ? {
86 | url: data.thumbnail.url,
87 | proxyURL: data.thumbnail.proxyURL || data.thumbnail.proxy_url,
88 | height: data.thumbnail.height,
89 | width: data.thumbnail.width,
90 | }
91 | : null;
92 |
93 | /**
94 | * Represents the image of a MessageEmbed
95 | * @typedef {Object} MessageEmbedImage
96 | * @property {string} url URL for this image
97 | * @property {string} proxyURL ProxyURL for this image
98 | * @property {number} height Height of this image
99 | * @property {number} width Width of this image
100 | */
101 |
102 | /**
103 | * The image of this embed, if there is one
104 | * @type {?MessageEmbedImage}
105 | */
106 | this.image = data.image
107 | ? {
108 | url: data.image.url,
109 | proxyURL: data.image.proxyURL || data.image.proxy_url,
110 | height: data.image.height,
111 | width: data.image.width,
112 | }
113 | : null;
114 |
115 | /**
116 | * Represents the author field of a MessageEmbed
117 | * @typedef {Object} MessageEmbedAuthor
118 | * @property {string} name The name of this author
119 | * @property {string} url URL of this author
120 | * @property {string} iconURL URL of the icon for this author
121 | * @property {string} proxyIconURL Proxied URL of the icon for this author
122 | */
123 |
124 | /**
125 | * The author of this embed (if there is one)
126 | * @type {?MessageEmbedAuthor}
127 | */
128 | this.author = data.author
129 | ? {
130 | name: data.author.name,
131 | url: data.author.url,
132 | iconURL: data.author.iconURL || data.author.icon_url,
133 | proxyIconURL: data.author.proxyIconURL || data.author.proxy_icon_url,
134 | }
135 | : null;
136 |
137 | /**
138 | * Represents the footer field of a MessageEmbed
139 | * @typedef {Object} MessageEmbedFooter
140 | * @property {string} text The text of this footer
141 | * @property {string} iconURL URL of the icon for this footer
142 | * @property {string} proxyIconURL Proxied URL of the icon for this footer
143 | */
144 |
145 | /**
146 | * The footer of this embed
147 | * @type {?MessageEmbedFooter}
148 | */
149 | this.footer = data.footer
150 | ? {
151 | text: data.footer.text,
152 | iconURL: data.footer.iconURL || data.footer.icon_url,
153 | proxyIconURL: data.footer.proxyIconURL || data.footer.proxy_icon_url,
154 | }
155 | : null;
156 |
157 | /**
158 | * The files of this embed
159 | * @type {Array}
160 | */
161 | this.files = data.files || [];
162 | }
163 |
164 | /**
165 | * The date displayed on this embed
166 | * @type {?Date}
167 | * @readonly
168 | */
169 | get createdAt() {
170 | return this.timestamp ? new Date(this.timestamp) : null;
171 | }
172 |
173 | /**
174 | * The hexadecimal version of the embed color, with a leading hash
175 | * @type {?string}
176 | * @readonly
177 | */
178 | get hexColor() {
179 | return this.color ? `#${this.color.toString(16).padStart(6, '0')}` : null;
180 | }
181 |
182 | /**
183 | * The accumulated length for the embed title, description, fields and footer text
184 | * @type {number}
185 | * @readonly
186 | */
187 | get length() {
188 | return (
189 | (this.title ? this.title.length : 0) +
190 | (this.description ? this.description.length : 0) +
191 | (this.fields.length >= 1
192 | ? this.fields.reduce((prev, curr) => prev + curr.name.length + curr.value.length, 0)
193 | : 0) +
194 | (this.footer ? this.footer.text.length : 0)
195 | );
196 | }
197 |
198 | /**
199 | * Adds a field to the embed (max 25).
200 | * @param {StringResolvable} name The name of this field
201 | * @param {StringResolvable} value The value of this field
202 | * @param {boolean} [inline=false] If this field will be displayed inline
203 | * @returns {MessageEmbed}
204 | */
205 | addField(name, value, inline) {
206 | return this.addFields({ name, value, inline });
207 | }
208 |
209 | /**
210 | * Adds fields to the embed (max 25).
211 | * @param {...EmbedFieldData|EmbedFieldData[]} fields The fields to add
212 | * @returns {MessageEmbed}
213 | */
214 | addFields(...fields) {
215 | this.fields.push(...this.constructor.normalizeFields(fields));
216 | return this;
217 | }
218 |
219 | /**
220 | * Removes, replaces, and inserts fields in the embed (max 25).
221 | * @param {number} index The index to start at
222 | * @param {number} deleteCount The number of fields to remove
223 | * @param {...EmbedFieldData|EmbedFieldData[]} [fields] The replacing field objects
224 | * @returns {MessageEmbed}
225 | */
226 | spliceFields(index, deleteCount, ...fields) {
227 | this.fields.splice(index, deleteCount, ...this.constructor.normalizeFields(...fields));
228 | return this;
229 | }
230 |
231 | /**
232 | * Sets the file to upload alongside the embed. This file can be accessed via `attachment://fileName.extension` when
233 | * setting an embed image or author/footer icons. Multiple files can be attached.
234 | * @param {Array} files Files to attach
235 | * @returns {MessageEmbed}
236 | */
237 | attachFiles(files) {
238 | this.files = this.files.concat(files);
239 | return this;
240 | }
241 |
242 | /**
243 | * Sets the author of this embed.
244 | * @param {StringResolvable} name The name of the author
245 | * @param {string} [iconURL] The icon URL of the author
246 | * @param {string} [url] The URL of the author
247 | * @returns {MessageEmbed}
248 | */
249 | setAuthor(name, iconURL, url) {
250 | this.author = { name: Util.resolveString(name), iconURL, url };
251 | return this;
252 | }
253 |
254 | /**
255 | * Sets the color of this embed.
256 | * @param {ColorResolvable} color The color of the embed
257 | * @returns {MessageEmbed}
258 | */
259 | setColor(color) {
260 | this.color = Util.resolveColor(color);
261 | return this;
262 | }
263 |
264 | /**
265 | * Sets the description of this embed.
266 | * @param {StringResolvable} description The description
267 | * @returns {MessageEmbed}
268 | */
269 | setDescription(description) {
270 | description = Util.resolveString(description);
271 | this.description = description;
272 | return this;
273 | }
274 |
275 | /**
276 | * Sets the footer of this embed.
277 | * @param {StringResolvable} text The text of the footer
278 | * @param {string} [iconURL] The icon URL of the footer
279 | * @returns {MessageEmbed}
280 | */
281 | setFooter(text, iconURL) {
282 | text = Util.resolveString(text);
283 | this.footer = { text, iconURL };
284 | return this;
285 | }
286 |
287 | /**
288 | * Sets the image of this embed.
289 | * @param {string} url The URL of the image
290 | * @returns {MessageEmbed}
291 | */
292 | setImage(url) {
293 | this.image = { url };
294 | return this;
295 | }
296 |
297 | /**
298 | * Sets the thumbnail of this embed.
299 | * @param {string} url The URL of the thumbnail
300 | * @returns {MessageEmbed}
301 | */
302 | setThumbnail(url) {
303 | this.thumbnail = { url };
304 | return this;
305 | }
306 |
307 | /**
308 | * Sets the timestamp of this embed.
309 | * @param {Date|number} [timestamp=Date.now()] The timestamp or date
310 | * @returns {MessageEmbed}
311 | */
312 | setTimestamp(timestamp = Date.now()) {
313 | if (timestamp instanceof Date) timestamp = timestamp.getTime();
314 | this.timestamp = timestamp;
315 | return this;
316 | }
317 |
318 | /**
319 | * Sets the title of this embed.
320 | * @param {StringResolvable} title The title
321 | * @returns {MessageEmbed}
322 | */
323 | setTitle(title) {
324 | title = Util.resolveString(title);
325 | this.title = title;
326 | return this;
327 | }
328 |
329 | /**
330 | * Sets the URL of this embed.
331 | * @param {string} url The URL
332 | * @returns {MessageEmbed}
333 | */
334 | setURL(url) {
335 | this.url = url;
336 | return this;
337 | }
338 |
339 | /**
340 | * Transforms the embed to a plain object.
341 | * @returns {Object} The raw data of this embed
342 | */
343 | toJSON() {
344 | return {
345 | title: this.title,
346 | type: 'rich',
347 | description: this.description,
348 | url: this.url,
349 | timestamp: this.timestamp ? new Date(this.timestamp) : null,
350 | color: this.color,
351 | fields: this.fields,
352 | thumbnail: this.thumbnail,
353 | image: this.image,
354 | author: this.author
355 | ? {
356 | name: this.author.name,
357 | url: this.author.url,
358 | icon_url: this.author.iconURL,
359 | }
360 | : null,
361 | footer: this.footer
362 | ? {
363 | text: this.footer.text,
364 | icon_url: this.footer.iconURL,
365 | }
366 | : null,
367 | };
368 | }
369 |
370 | /**
371 | * Normalizes field input and resolves strings.
372 | * @param {StringResolvable} name The name of the field
373 | * @param {StringResolvable} value The value of the field
374 | * @param {boolean} [inline=false] Set the field to display inline
375 | * @returns {EmbedField}
376 | */
377 | static normalizeField(name, value, inline = false) {
378 | name = Util.resolveString(name);
379 | if (!name) throw new Error('EMBED_FIELD_NAME');
380 | value = Util.resolveString(value);
381 | if (!value) throw new Error('EMBED_FIELD_VALUE');
382 | return { name, value, inline };
383 | }
384 |
385 | /**
386 | * @typedef {Object} EmbedFieldData
387 | * @property {StringResolvable} name The name of this field
388 | * @property {StringResolvable} value The value of this field
389 | * @property {boolean} [inline] If this field will be displayed inline
390 | */
391 |
392 | /**
393 | * Normalizes field input and resolves strings.
394 | * @param {...EmbedFieldData|EmbedFieldData[]} fields Fields to normalize
395 | * @returns {EmbedField[]}
396 | */
397 | static normalizeFields(...fields) {
398 | return fields
399 | .flat(2)
400 | .map(field =>
401 | this.normalizeField(
402 | field && field.name,
403 | field && field.value,
404 | field && typeof field.inline === 'boolean' ? field.inline : false,
405 | ),
406 | );
407 | }
408 | }
409 |
410 | module.exports = MessageEmbed;
--------------------------------------------------------------------------------