From 3bfa5b02478b1f892d223154b413ee2e142d4f0f Mon Sep 17 00:00:00 2001 From: MattIPv4 Date: Wed, 4 Mar 2020 12:49:16 +0000 Subject: [PATCH 01/10] fix(MessageEmbed): Add skipValidation flag to MessageEmbed --- src/structures/MessageEmbed.js | 34 ++++++++++++++++++++++++---------- typings/index.d.ts | 9 ++------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/structures/MessageEmbed.js b/src/structures/MessageEmbed.js index eb67b952c78b..580dab57ae6e 100644 --- a/src/structures/MessageEmbed.js +++ b/src/structures/MessageEmbed.js @@ -7,11 +7,19 @@ const Util = require('../util/Util'); * Represents an embed in a message (image/video preview, rich embed, etc.) */ class MessageEmbed { - constructor(data = {}) { - this.setup(data); + /** + * @param {Object} data The data to build the embed from + * @param {boolean} skipValidation A flag to skip field validations + */ + constructor(data = {}, skipValidation = false) { + this.setup(data, skipValidation); } - setup(data) { + /** + * @param {Object} data The data to build the embed from + * @param {boolean} skipValidation A flag to skip field validations + */ + setup(data, skipValidation) { /** * The type of this embed, either: * * `rich` - a rich embed @@ -65,7 +73,7 @@ class MessageEmbed { * The fields of this embed * @type {EmbedField[]} */ - this.fields = data.fields ? this.constructor.normalizeFields(data.fields) : []; + this.fields = data.fields ? this.normalizeFields(data.fields) : []; /** * @typedef {Object} MessageEmbedThumbnail @@ -193,6 +201,12 @@ class MessageEmbed { * @type {Array} */ this.files = data.files || []; + + /** + * If this embed should skip validation of its data + * @type {boolean} + */ + this.skipValidation = skipValidation; } /** @@ -246,7 +260,7 @@ class MessageEmbed { * @returns {MessageEmbed} */ addFields(...fields) { - this.fields.push(...this.constructor.normalizeFields(fields)); + this.fields.push(...this.normalizeFields(fields)); return this; } @@ -258,7 +272,7 @@ class MessageEmbed { * @returns {MessageEmbed} */ spliceFields(index, deleteCount, ...fields) { - this.fields.splice(index, deleteCount, ...this.constructor.normalizeFields(...fields)); + this.fields.splice(index, deleteCount, ...this.normalizeFields(...fields)); return this; } @@ -408,11 +422,11 @@ class MessageEmbed { * @param {boolean} [inline=false] Set the field to display inline * @returns {EmbedField} */ - static normalizeField(name, value, inline = false) { + normalizeField(name, value, inline = false) { name = Util.resolveString(name); - if (!name) throw new RangeError('EMBED_FIELD_NAME'); + if (!this.skipValidation && !name) throw new RangeError('EMBED_FIELD_NAME'); value = Util.resolveString(value); - if (!value) throw new RangeError('EMBED_FIELD_VALUE'); + if (!this.skipValidation && !value) throw new RangeError('EMBED_FIELD_VALUE'); return { name, value, inline }; } @@ -428,7 +442,7 @@ class MessageEmbed { * @param {...EmbedFieldData|EmbedFieldData[]} fields Fields to normalize * @returns {EmbedField[]} */ - static normalizeFields(...fields) { + normalizeFields(...fields) { return fields .flat(2) .map(field => diff --git a/typings/index.d.ts b/typings/index.d.ts index 8ceee251ba01..1252b3c816a3 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1152,13 +1152,8 @@ declare module 'discord.js' { public setURL(url: string): this; public spliceFields(index: number, deleteCount: number, ...fields: EmbedFieldData[] | EmbedFieldData[][]): this; public toJSON(): object; - - public static normalizeField( - name: StringResolvable, - value: StringResolvable, - inline?: boolean, - ): Required; - public static normalizeFields(...fields: EmbedFieldData[] | EmbedFieldData[][]): Required[]; + public normalizeField(name: StringResolvable, value: StringResolvable, inline?: boolean): Required; + public normalizeFields(...fields: EmbedFieldData[] | EmbedFieldData[][]): Required[]; } export class MessageFlags extends BitField { From c57cc9420c003f0cd394421662a1eac168e54248 Mon Sep 17 00:00:00 2001 From: MattIPv4 Date: Wed, 4 Mar 2020 12:52:06 +0000 Subject: [PATCH 02/10] fix(MessageEmbed): Use skipValidation flag in Message --- src/structures/Message.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/structures/Message.js b/src/structures/Message.js index 630d21e7e721..d76da05967ec 100644 --- a/src/structures/Message.js +++ b/src/structures/Message.js @@ -98,7 +98,7 @@ class Message extends Base { * A list of embeds in the message - e.g. YouTube Player * @type {MessageEmbed[]} */ - this.embeds = (data.embeds || []).map(e => new Embed(e)); + this.embeds = (data.embeds || []).map(e => new Embed(e, true)); /** * A collection of attachments in the message - e.g. Pictures - mapped by their ID @@ -225,7 +225,7 @@ class Message extends Base { if ('content' in data) this.content = data.content; if ('pinned' in data) this.pinned = data.pinned; if ('tts' in data) this.tts = data.tts; - if ('embeds' in data) this.embeds = data.embeds.map(e => new Embed(e)); + if ('embeds' in data) this.embeds = data.embeds.map(e => new Embed(e, true)); else this.embeds = this.embeds.slice(); if ('attachments' in data) { From d82f7944db9ef66213fa116342e9f0aaf10a543e Mon Sep 17 00:00:00 2001 From: MattIPv4 Date: Wed, 4 Mar 2020 13:43:34 +0000 Subject: [PATCH 03/10] fix(MessageEmbed): Restore static normalizeField(s) methods --- src/structures/MessageEmbed.js | 26 +++++++++++++++++++------- typings/index.d.ts | 14 ++++++++++++-- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/structures/MessageEmbed.js b/src/structures/MessageEmbed.js index 580dab57ae6e..e8d43f998ecc 100644 --- a/src/structures/MessageEmbed.js +++ b/src/structures/MessageEmbed.js @@ -73,7 +73,7 @@ class MessageEmbed { * The fields of this embed * @type {EmbedField[]} */ - this.fields = data.fields ? this.normalizeFields(data.fields) : []; + this.fields = data.fields ? this.constructor._normalizeFields(this.skipValidation, data.fields) : []; /** * @typedef {Object} MessageEmbedThumbnail @@ -260,7 +260,7 @@ class MessageEmbed { * @returns {MessageEmbed} */ addFields(...fields) { - this.fields.push(...this.normalizeFields(fields)); + this.fields.push(...this.constructor._normalizeFields(this.skipValidation, fields)); return this; } @@ -272,7 +272,7 @@ class MessageEmbed { * @returns {MessageEmbed} */ spliceFields(index, deleteCount, ...fields) { - this.fields.splice(index, deleteCount, ...this.normalizeFields(...fields)); + this.fields.splice(index, deleteCount, ...this.constructor._normalizeFields(this.skipValidation, ...fields)); return this; } @@ -420,13 +420,14 @@ class MessageEmbed { * @param {StringResolvable} name The name of the field * @param {StringResolvable} value The value of the field * @param {boolean} [inline=false] Set the field to display inline + * @param {boolean} [skipValidation=false] Skips the validation of the name and value * @returns {EmbedField} */ - normalizeField(name, value, inline = false) { + static normalizeField(name, value, inline = false, skipValidation = false) { name = Util.resolveString(name); - if (!this.skipValidation && !name) throw new RangeError('EMBED_FIELD_NAME'); + if (!skipValidation && !name) throw new RangeError('EMBED_FIELD_NAME'); value = Util.resolveString(value); - if (!this.skipValidation && !value) throw new RangeError('EMBED_FIELD_VALUE'); + if (!skipValidation && !value) throw new RangeError('EMBED_FIELD_VALUE'); return { name, value, inline }; } @@ -439,10 +440,11 @@ class MessageEmbed { /** * Normalizes field input and resolves strings. + * @param {boolean} skipValidation Skips the validation of the name and value in fields * @param {...EmbedFieldData|EmbedFieldData[]} fields Fields to normalize * @returns {EmbedField[]} */ - normalizeFields(...fields) { + static _normalizeFields(skipValidation, ...fields) { return fields .flat(2) .map(field => @@ -450,9 +452,19 @@ class MessageEmbed { field && field.name, field && field.value, field && typeof field.inline === 'boolean' ? field.inline : false, + skipValidation, ), ); } + + /** + * Normalizes field input and resolves strings. + * @param {...EmbedFieldData|EmbedFieldData[]} fields Fields to normalize + * @returns {EmbedField[]} + */ + static normalizeFields(...fields) { + return this._normalizeFields(false, ...fields); + } } module.exports = MessageEmbed; diff --git a/typings/index.d.ts b/typings/index.d.ts index 1252b3c816a3..20a3f105b7e5 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1152,8 +1152,18 @@ declare module 'discord.js' { public setURL(url: string): this; public spliceFields(index: number, deleteCount: number, ...fields: EmbedFieldData[] | EmbedFieldData[][]): this; public toJSON(): object; - public normalizeField(name: StringResolvable, value: StringResolvable, inline?: boolean): Required; - public normalizeFields(...fields: EmbedFieldData[] | EmbedFieldData[][]): Required[]; + + public static normalizeField( + name: StringResolvable, + value: StringResolvable, + inline?: boolean, + skipValidation?: boolean + ): Required; + public static _normalizeFields( + skipValidation: boolean, + ...fields: EmbedFieldData[] | EmbedFieldData[][] + ): Required[]; + public static normalizeFields(...fields: EmbedFieldData[] | EmbedFieldData[][]): Required[]; } export class MessageFlags extends BitField { From 9a3004795c8adc12c0109dbf2937957e2e9d9101 Mon Sep 17 00:00:00 2001 From: MattIPv4 Date: Wed, 4 Mar 2020 17:28:07 +0000 Subject: [PATCH 04/10] fix(MessageEmbed): Update typings for constructor --- src/structures/MessageEmbed.js | 4 ++-- typings/index.d.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/structures/MessageEmbed.js b/src/structures/MessageEmbed.js index e8d43f998ecc..b8cabab5c069 100644 --- a/src/structures/MessageEmbed.js +++ b/src/structures/MessageEmbed.js @@ -8,8 +8,8 @@ const Util = require('../util/Util'); */ class MessageEmbed { /** - * @param {Object} data The data to build the embed from - * @param {boolean} skipValidation A flag to skip field validations + * @param {Object} [data={}] The data to build the embed from + * @param {boolean} [skipValidation=false] A flag to skip field validations */ constructor(data = {}, skipValidation = false) { this.setup(data, skipValidation); diff --git a/typings/index.d.ts b/typings/index.d.ts index 20a3f105b7e5..6bc005e162fa 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1120,7 +1120,7 @@ declare module 'discord.js' { } export class MessageEmbed { - constructor(data?: MessageEmbed | MessageEmbedOptions); + constructor(data?: MessageEmbed | MessageEmbedOptions, skipValidation?: boolean); public author: MessageEmbedAuthor | null; public color?: number; public readonly createdAt: Date | null; From 867f095aa6c0ed7a49e2d39ab79ea19c719be826 Mon Sep 17 00:00:00 2001 From: MattIPv4 Date: Wed, 4 Mar 2020 17:58:27 +0000 Subject: [PATCH 05/10] fix(MessageEmbed): Remove private docstrings/typings --- src/structures/MessageEmbed.js | 8 -------- typings/index.d.ts | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/structures/MessageEmbed.js b/src/structures/MessageEmbed.js index b8cabab5c069..b6965220bde7 100644 --- a/src/structures/MessageEmbed.js +++ b/src/structures/MessageEmbed.js @@ -7,18 +7,10 @@ const Util = require('../util/Util'); * Represents an embed in a message (image/video preview, rich embed, etc.) */ class MessageEmbed { - /** - * @param {Object} [data={}] The data to build the embed from - * @param {boolean} [skipValidation=false] A flag to skip field validations - */ constructor(data = {}, skipValidation = false) { this.setup(data, skipValidation); } - /** - * @param {Object} data The data to build the embed from - * @param {boolean} skipValidation A flag to skip field validations - */ setup(data, skipValidation) { /** * The type of this embed, either: diff --git a/typings/index.d.ts b/typings/index.d.ts index 6bc005e162fa..20a3f105b7e5 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1120,7 +1120,7 @@ declare module 'discord.js' { } export class MessageEmbed { - constructor(data?: MessageEmbed | MessageEmbedOptions, skipValidation?: boolean); + constructor(data?: MessageEmbed | MessageEmbedOptions); public author: MessageEmbedAuthor | null; public color?: number; public readonly createdAt: Date | null; From 7f17f9cff590497b0581c2ae2a5ddf5b3118579f Mon Sep 17 00:00:00 2001 From: MattIPv4 Date: Thu, 5 Mar 2020 22:07:16 +0000 Subject: [PATCH 06/10] fix(MessageEmbed): Use skipValidation without storing in instance --- src/structures/MessageEmbed.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/structures/MessageEmbed.js b/src/structures/MessageEmbed.js index b6965220bde7..e7829d26bce3 100644 --- a/src/structures/MessageEmbed.js +++ b/src/structures/MessageEmbed.js @@ -65,7 +65,7 @@ class MessageEmbed { * The fields of this embed * @type {EmbedField[]} */ - this.fields = data.fields ? this.constructor._normalizeFields(this.skipValidation, data.fields) : []; + this.fields = data.fields ? this.constructor._normalizeFields(skipValidation, data.fields) : []; /** * @typedef {Object} MessageEmbedThumbnail @@ -193,12 +193,6 @@ class MessageEmbed { * @type {Array} */ this.files = data.files || []; - - /** - * If this embed should skip validation of its data - * @type {boolean} - */ - this.skipValidation = skipValidation; } /** From 21a22005979ec97df5524b9dfd8c1acf47f6861a Mon Sep 17 00:00:00 2001 From: MattIPv4 Date: Fri, 6 Mar 2020 11:40:18 +0000 Subject: [PATCH 07/10] fix(MessageEmbed): skipValidation without modifying normalizeFields --- src/structures/MessageEmbed.js | 42 +++++++++++++++++++--------------- typings/index.d.ts | 5 ---- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/structures/MessageEmbed.js b/src/structures/MessageEmbed.js index e7829d26bce3..d963063c1153 100644 --- a/src/structures/MessageEmbed.js +++ b/src/structures/MessageEmbed.js @@ -65,7 +65,10 @@ class MessageEmbed { * The fields of this embed * @type {EmbedField[]} */ - this.fields = data.fields ? this.constructor._normalizeFields(skipValidation, data.fields) : []; + this.fields = []; + if (data.fields) { + this.fields = skipValidation ? data.fields.map(Util.cloneObject) : this.constructor.normalizeFields(data.fields); + } /** * @typedef {Object} MessageEmbedThumbnail @@ -193,6 +196,13 @@ class MessageEmbed { * @type {Array} */ this.files = data.files || []; + + /** + * If this embed should skip validation of fields + * @type {boolean} + * @private + */ + this.skipValiation = skipValidation; } /** @@ -246,7 +256,10 @@ class MessageEmbed { * @returns {MessageEmbed} */ addFields(...fields) { - this.fields.push(...this.constructor._normalizeFields(this.skipValidation, fields)); + const preparedFields = this.skipValiation + ? fields.map(Util.cloneObject) + : this.constructor.normalizeFields(...fields); + this.fields.push(...preparedFields); return this; } @@ -258,7 +271,10 @@ class MessageEmbed { * @returns {MessageEmbed} */ spliceFields(index, deleteCount, ...fields) { - this.fields.splice(index, deleteCount, ...this.constructor._normalizeFields(this.skipValidation, ...fields)); + const preparedFields = this.skipValiation + ? fields.map(Util.cloneObject) + : this.constructor.normalizeFields(...fields); + this.fields.splice(index, deleteCount, ...preparedFields); return this; } @@ -406,14 +422,13 @@ class MessageEmbed { * @param {StringResolvable} name The name of the field * @param {StringResolvable} value The value of the field * @param {boolean} [inline=false] Set the field to display inline - * @param {boolean} [skipValidation=false] Skips the validation of the name and value * @returns {EmbedField} */ - static normalizeField(name, value, inline = false, skipValidation = false) { + static normalizeField(name, value, inline = false) { name = Util.resolveString(name); - if (!skipValidation && !name) throw new RangeError('EMBED_FIELD_NAME'); + if (!name) throw new RangeError('EMBED_FIELD_NAME'); value = Util.resolveString(value); - if (!skipValidation && !value) throw new RangeError('EMBED_FIELD_VALUE'); + if (!value) throw new RangeError('EMBED_FIELD_VALUE'); return { name, value, inline }; } @@ -426,11 +441,10 @@ class MessageEmbed { /** * Normalizes field input and resolves strings. - * @param {boolean} skipValidation Skips the validation of the name and value in fields * @param {...EmbedFieldData|EmbedFieldData[]} fields Fields to normalize * @returns {EmbedField[]} */ - static _normalizeFields(skipValidation, ...fields) { + static normalizeFields(...fields) { return fields .flat(2) .map(field => @@ -438,19 +452,9 @@ class MessageEmbed { field && field.name, field && field.value, field && typeof field.inline === 'boolean' ? field.inline : false, - skipValidation, ), ); } - - /** - * Normalizes field input and resolves strings. - * @param {...EmbedFieldData|EmbedFieldData[]} fields Fields to normalize - * @returns {EmbedField[]} - */ - static normalizeFields(...fields) { - return this._normalizeFields(false, ...fields); - } } module.exports = MessageEmbed; diff --git a/typings/index.d.ts b/typings/index.d.ts index 20a3f105b7e5..56b258b49f19 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1157,12 +1157,7 @@ declare module 'discord.js' { name: StringResolvable, value: StringResolvable, inline?: boolean, - skipValidation?: boolean ): Required; - public static _normalizeFields( - skipValidation: boolean, - ...fields: EmbedFieldData[] | EmbedFieldData[][] - ): Required[]; public static normalizeFields(...fields: EmbedFieldData[] | EmbedFieldData[][]): Required[]; } From f00662a96f95f3cdc441cd56e767c42eb7c0de50 Mon Sep 17 00:00:00 2001 From: MattIPv4 Date: Fri, 6 Mar 2020 11:42:35 +0000 Subject: [PATCH 08/10] fix(MessageEmbed): Revert indentation change in typings --- typings/index.d.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index 56b258b49f19..8ceee251ba01 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1154,9 +1154,9 @@ declare module 'discord.js' { public toJSON(): object; public static normalizeField( - name: StringResolvable, - value: StringResolvable, - inline?: boolean, + name: StringResolvable, + value: StringResolvable, + inline?: boolean, ): Required; public static normalizeFields(...fields: EmbedFieldData[] | EmbedFieldData[][]): Required[]; } From aff7f1f92140b05249a177a45fe4634d4f0b5c26 Mon Sep 17 00:00:00 2001 From: MattIPv4 Date: Fri, 6 Mar 2020 13:38:25 +0000 Subject: [PATCH 09/10] fix(MessageEmbed): Clone logic from normalizeFields (duplicated code ftw) --- src/structures/MessageEmbed.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/structures/MessageEmbed.js b/src/structures/MessageEmbed.js index d963063c1153..350a4f05c5b4 100644 --- a/src/structures/MessageEmbed.js +++ b/src/structures/MessageEmbed.js @@ -257,7 +257,7 @@ class MessageEmbed { */ addFields(...fields) { const preparedFields = this.skipValiation - ? fields.map(Util.cloneObject) + ? fields.flat(2).map(Util.cloneObject) : this.constructor.normalizeFields(...fields); this.fields.push(...preparedFields); return this; @@ -272,7 +272,7 @@ class MessageEmbed { */ spliceFields(index, deleteCount, ...fields) { const preparedFields = this.skipValiation - ? fields.map(Util.cloneObject) + ? fields.flat(2).map(Util.cloneObject) : this.constructor.normalizeFields(...fields); this.fields.splice(index, deleteCount, ...preparedFields); return this; From eb8151f2ac73796a147cd85e0955f5e631744887 Mon Sep 17 00:00:00 2001 From: SpaceEEC Date: Sun, 8 Mar 2020 17:20:34 +0100 Subject: [PATCH 10/10] revert(MessageEmbed): remove dead code / breaking change - dead code discord.js does not use those methods interally and won't in the future, as Discord does not emit any partial embed updates and doing so in the future seems unlikely. - a breaking change (an incompatible api change) Although it's not recommended to do, users can modify received embeds without cloning them, e.g.: const embed = message.embeds[0].addField('some title', ''); (replace '' with some function call; this is just an example) This would no longer throw a synchronous error (breaking change), but at a later point when actually sending it. (poorer to debug) --- src/structures/MessageEmbed.js | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/src/structures/MessageEmbed.js b/src/structures/MessageEmbed.js index 350a4f05c5b4..437fd9f7686c 100644 --- a/src/structures/MessageEmbed.js +++ b/src/structures/MessageEmbed.js @@ -196,13 +196,6 @@ class MessageEmbed { * @type {Array} */ this.files = data.files || []; - - /** - * If this embed should skip validation of fields - * @type {boolean} - * @private - */ - this.skipValiation = skipValidation; } /** @@ -256,10 +249,7 @@ class MessageEmbed { * @returns {MessageEmbed} */ addFields(...fields) { - const preparedFields = this.skipValiation - ? fields.flat(2).map(Util.cloneObject) - : this.constructor.normalizeFields(...fields); - this.fields.push(...preparedFields); + this.fields.push(...this.constructor.normalizeFields(fields)); return this; } @@ -271,10 +261,7 @@ class MessageEmbed { * @returns {MessageEmbed} */ spliceFields(index, deleteCount, ...fields) { - const preparedFields = this.skipValiation - ? fields.flat(2).map(Util.cloneObject) - : this.constructor.normalizeFields(...fields); - this.fields.splice(index, deleteCount, ...preparedFields); + this.fields.splice(index, deleteCount, ...this.constructor.normalizeFields(...fields)); return this; }