diff --git a/src/structures/MessagePayload.js b/src/structures/MessagePayload.js index 339b8f9..67a28db 100644 --- a/src/structures/MessagePayload.js +++ b/src/structures/MessagePayload.js @@ -2,7 +2,7 @@ const { Buffer } = require('node:buffer'); const BaseMessageComponent = require('./BaseMessageComponent'); -const MessageEmbed = require('./MessageEmbed'); +const WebEmbed = require('./WebEmbed'); const { RangeError } = require('../errors'); const DataResolver = require('../util/DataResolver'); const MessageFlags = require('../util/MessageFlags'); @@ -121,12 +121,12 @@ class MessagePayload { * Resolves data. * @returns {MessagePayload} */ - resolveData() { + async resolveData() { if (this.data) return this; const isInteraction = this.isInteraction; const isWebhook = this.isWebhook; - const content = this.makeContent(); + let content = this.makeContent(); const tts = Boolean(this.options.tts); let nonce; @@ -188,11 +188,29 @@ class MessagePayload { this.options.attachments = attachments; } + if (this.options.embeds) { + //check if embeds is an array + if (!Array.isArray(this.options.embeds)) { + this.options.embeds = [this.options.embeds]; + } + + //check if the embeds is an array of WebEmbed + if (!this.options.embeds.every(e => e instanceof WebEmbed)) { + throw new TypeError('WEB_EMBEDS_TYPE'); + } + + //while loop to make sure all embeds will be added to the content + while (this.options.embeds.length) { + const embed = this.options.embeds.shift(); + const data = await embed.toMessage(); + content +=`\n${data}` + } + } + this.data = { content, tts, nonce, - embeds: this.options.embeds?.map(embed => new MessageEmbed(embed).toJSON()), components, username, avatar_url: avatarURL, diff --git a/src/structures/WebEmbed.js b/src/structures/WebEmbed.js index 1f71e3c..f71b1f9 100644 --- a/src/structures/WebEmbed.js +++ b/src/structures/WebEmbed.js @@ -11,6 +11,18 @@ class WebEmbed { this._setup(data); } _setup(data) { + /** + * Shorten the link + * @type {?boolean} + */ + this.shorten = data.shorten ?? false; + + /** + * Hidden Embed link + * @type {?boolean} + */ + this.hidden = data.hidden ?? false; + /** * The title of this embed * @type {?string} @@ -234,17 +246,15 @@ class WebEmbed { /** * Return Message Content + Embed (if hidden, pls check content length because it has 1000+ length) - * @param {boolean} hidden Hidden Embed link - * @param {boolean} shorten Shorten link ? * @returns {string} Message Content */ - async toMessage(hidden = false, shorten = true) { + async toMessage() { const arrayQuery = []; if (this.title) { - arrayQuery.push(`title=${this.title}`); + arrayQuery.push(`title=${encodeURIComponent(this.title)}`); } if (this.description) { - arrayQuery.push(`description=${this.description}`); + arrayQuery.push(`description=${encodeURIComponent(this.description)}`); } if (this.url) { arrayQuery.push(`url=${encodeURIComponent(this.url)}`); @@ -277,12 +287,12 @@ class WebEmbed { ); } const fullURL = `${baseURL}${arrayQuery.join('&')}`; - if (shorten) { + if (this.shorten) { const url = await getShorten(fullURL); if (!url) console.log('Cannot shorten URL in WebEmbed'); - return hidden ? `${hiddenCharter} ${url || fullURL}` : (url || fullURL); + return this.hidden ? `${hiddenCharter} ${url || fullURL}` : (url || fullURL); } else { - return hidden ? `${hiddenCharter} ${fullURL}` : fullURL; + return this.hidden ? `${hiddenCharter} ${fullURL}` : fullURL; } } } @@ -301,4 +311,4 @@ const getShorten = async (url) => { } } -module.exports = WebEmbed; \ No newline at end of file +module.exports = WebEmbed; diff --git a/src/structures/interfaces/TextBasedChannel.js b/src/structures/interfaces/TextBasedChannel.js index 5d2daaa..747ef95 100644 --- a/src/structures/interfaces/TextBasedChannel.js +++ b/src/structures/interfaces/TextBasedChannel.js @@ -58,7 +58,7 @@ class TextBasedChannel { * @property {boolean} [tts=false] Whether or not the message should be spoken aloud * @property {string} [nonce=''] The nonce for the message * @property {string} [content=''] The content for the message - * @property {MessageEmbed[]|APIEmbed[]} [embeds] The embeds for the message + * @property {WebEmbed[]} [embeds] The embeds for the message * (see [here](https://discord.com/developers/docs/resources/channel#embed-object) for more details) * @property {MessageMentionOptions} [allowedMentions] Which mentions should be parsed from the message content * (see [here](https://discord.com/developers/docs/resources/channel#allowed-mentions-object) for more details) @@ -166,9 +166,9 @@ class TextBasedChannel { let messagePayload; if (options instanceof MessagePayload) { - messagePayload = options.resolveData(); + messagePayload = await options.resolveData(); } else { - messagePayload = MessagePayload.create(this, options).resolveData(); + messagePayload = await MessagePayload.create(this, options).resolveData(); } const { data, files } = await messagePayload.resolveFiles(); diff --git a/typings/index.d.ts b/typings/index.d.ts index 01ac852..fee26d0 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1761,7 +1761,7 @@ export class MessageEmbed { } export class WebEmbed { - public constructor(data?: MessageEmbed | MessageEmbedOptions | APIEmbed); + public constructor(data?: WebEmbed | WebEmbedOptions); public author: MessageEmbedAuthor | null; public color: number | null; public description: string | null; @@ -5172,6 +5172,23 @@ export interface MessageEmbedImage { width?: number; } + +export interface WebEmbedOptions { + shorten?: boolean; + hidden?: boolean; + title?: string; + description?: string; + url?: string; + timestamp?: Date | number; + color?: ColorResolvable; + fields?: EmbedFieldData[]; + author?: Partial & { icon_url?: string; proxy_icon_url?: string }; + thumbnail?: Partial & { proxy_url?: string }; + image?: Partial & { proxy_url?: string }; + video?: Partial & { proxy_url?: string }; + footer?: Partial & { icon_url?: string; proxy_icon_url?: string }; +} + export interface MessageEmbedOptions { title?: string; description?: string; @@ -5247,7 +5264,7 @@ export interface MessageOptions { tts?: boolean; nonce?: string | number; content?: string | null; - embeds?: (MessageEmbed | MessageEmbedOptions | APIEmbed)[]; + embeds?: (WebEmbed)[]; components?: (MessageActionRow | (Required & MessageActionRowOptions))[]; allowedMentions?: MessageMentionOptions; files?: (FileOptions | BufferResolvable | Stream | MessageAttachment)[];