diff --git a/src/rest/DiscordAPIError.js b/src/rest/DiscordAPIError.js index aebe513d0e19..af060da30c4b 100644 --- a/src/rest/DiscordAPIError.js +++ b/src/rest/DiscordAPIError.js @@ -5,7 +5,7 @@ * @extends Error */ class DiscordAPIError extends Error { - constructor(path, error, method, status) { + constructor(error, status, request) { super(); const flattened = this.constructor.flattenErrors(error.errors || error).join('\n'); this.name = 'DiscordAPIError'; @@ -15,13 +15,13 @@ class DiscordAPIError extends Error { * The HTTP method used for the request * @type {string} */ - this.method = method; + this.method = request.method; /** * The path of the request relative to the HTTP endpoint * @type {string} */ - this.path = path; + this.path = request.path; /** * HTTP error code returned by Discord @@ -34,6 +34,15 @@ class DiscordAPIError extends Error { * @type {number} */ this.httpStatus = status; + + /** + * The data associated with the request that caused this error + * @type {HTTPErrorData} + */ + this.requestData = { + json: request.options.data, + files: request.options.files ?? [], + }; } /** diff --git a/src/rest/HTTPError.js b/src/rest/HTTPError.js index 2911467fcdfd..8613cd947529 100644 --- a/src/rest/HTTPError.js +++ b/src/rest/HTTPError.js @@ -5,7 +5,7 @@ * @extends Error */ class HTTPError extends Error { - constructor(message, name, code, method, path) { + constructor(message, name, code, request) { super(message); /** @@ -24,13 +24,36 @@ class HTTPError extends Error { * The HTTP method used for the request * @type {string} */ - this.method = method; + this.method = request.method; /** * The path of the request relative to the HTTP endpoint * @type {string} */ - this.path = path; + this.path = request.path; + + /** + * The HTTP data that was sent to Discord + * @typedef {Object} HTTPErrorData + * @property {*} json The JSON data that was sent + * @property {HTTPAttachmentData[]} files The files that were sent with this request, if any + */ + + /** + * The attachment data that is sent to Discord + * @typedef {Object} HTTPAttachmentData + * @property {string} name The file name + * @property {Buffer} file The file buffer + */ + + /** + * The data associated with the request that caused this error + * @type {HTTPErrorData} + */ + this.requestData = { + json: request.options.data, + files: request.options.files ?? [], + }; } } diff --git a/src/rest/RequestHandler.js b/src/rest/RequestHandler.js index 2b76ecf2c416..1c27a172a28f 100644 --- a/src/rest/RequestHandler.js +++ b/src/rest/RequestHandler.js @@ -143,7 +143,7 @@ class RequestHandler { } catch (error) { // Retry the specified number of times for request abortions if (request.retries === this.manager.client.options.retryLimit) { - throw new HTTPError(error.message, error.constructor.name, error.status, request.method, request.path); + throw new HTTPError(error.message, error.constructor.name, error.status, request); } request.retries++; @@ -237,17 +237,17 @@ class RequestHandler { try { data = await parseResponse(res); } catch (err) { - throw new HTTPError(err.message, err.constructor.name, err.status, request.method, request.path); + throw new HTTPError(err.message, err.constructor.name, err.status, request); } - throw new DiscordAPIError(request.path, data, request.method, res.status); + throw new DiscordAPIError(data, res.status, request); } // Handle 5xx responses if (res.status >= 500 && res.status < 600) { // Retry the specified number of times for possible serverside issues if (request.retries === this.manager.client.options.retryLimit) { - throw new HTTPError(res.statusText, res.constructor.name, res.status, request.method, request.path); + throw new HTTPError(res.statusText, res.constructor.name, res.status, request); } request.retries++; diff --git a/src/structures/APIMessage.js b/src/structures/APIMessage.js index c3bcfab32d8c..56840bd6205f 100644 --- a/src/structures/APIMessage.js +++ b/src/structures/APIMessage.js @@ -125,6 +125,9 @@ class APIMessage { */ resolveData() { if (this.data) return this; + const isInteraction = this.isInteraction; + const isWebhook = this.isWebhook; + const isWebhookLike = isInteraction || isWebhook; const content = this.makeContent(); const tts = Boolean(this.options.tts); @@ -139,7 +142,7 @@ class APIMessage { } const embedLikes = []; - if (this.isInteraction || this.isWebhook) { + if (isWebhookLike) { if (this.options.embeds) { embedLikes.push(...this.options.embeds); } @@ -150,7 +153,7 @@ class APIMessage { let username; let avatarURL; - if (this.isWebhook) { + if (isWebhook) { username = this.options.username || this.target.name; if (this.options.avatarURL) avatarURL = this.options.avatarURL; } @@ -159,7 +162,7 @@ class APIMessage { if (this.isMessage) { // eslint-disable-next-line eqeqeq flags = this.options.flags != null ? new MessageFlags(this.options.flags).bitfield : this.target.flags.bitfield; - } else if (this.isInteraction && this.options.ephemeral) { + } else if (isInteraction && this.options.ephemeral) { flags = MessageFlags.FLAGS.EPHEMERAL; } @@ -191,8 +194,8 @@ class APIMessage { content, tts, nonce, - embed: this.options.embed === null ? null : embeds[0], - embeds, + embed: !isWebhookLike ? (this.options.embed === null ? null : embeds[0]) : undefined, + embeds: isWebhookLike ? embeds : undefined, username, avatar_url: avatarURL, allowed_mentions: