2021-04-04 09:29:56 +00:00
|
|
|
import type {
|
2020-10-22 15:50:47 +00:00
|
|
|
EmbedAuthor,
|
|
|
|
EmbedField,
|
|
|
|
EmbedFooter,
|
|
|
|
EmbedImage,
|
|
|
|
EmbedPayload,
|
|
|
|
EmbedProvider,
|
|
|
|
EmbedThumbnail,
|
|
|
|
EmbedTypes,
|
|
|
|
EmbedVideo
|
2020-10-31 12:33:34 +00:00
|
|
|
} from '../types/channel.ts'
|
2021-01-25 11:28:46 +00:00
|
|
|
import { Colors, ColorUtil } from '../utils/colorutil.ts'
|
2021-04-04 09:29:56 +00:00
|
|
|
import type { MessageAttachment } from './message.ts'
|
2020-10-22 15:50:47 +00:00
|
|
|
|
2021-01-25 11:28:46 +00:00
|
|
|
/** Message Embed Object */
|
2020-10-25 06:50:32 +00:00
|
|
|
export class Embed {
|
2020-10-22 15:50:47 +00:00
|
|
|
title?: string
|
|
|
|
type?: EmbedTypes
|
|
|
|
description?: string
|
|
|
|
url?: string
|
|
|
|
timestamp?: string
|
|
|
|
color?: number
|
|
|
|
footer?: EmbedFooter
|
|
|
|
image?: EmbedImage
|
|
|
|
thumbnail?: EmbedThumbnail
|
|
|
|
video?: EmbedVideo
|
|
|
|
provider?: EmbedProvider
|
|
|
|
author?: EmbedAuthor
|
|
|
|
fields?: EmbedField[]
|
2021-01-28 14:25:37 +00:00
|
|
|
files: MessageAttachment[] = []
|
2020-10-29 14:43:27 +00:00
|
|
|
|
2021-03-20 05:21:35 +00:00
|
|
|
static MAX_TITLE_LENGTH = 256
|
|
|
|
static MAX_DESCRIPTION_LENGTH = 2048
|
|
|
|
static MAX_FIELD_NAME_LENGTH = 256
|
|
|
|
static MAX_FIELD_VALUE_LENGTH = 1024
|
|
|
|
static MAX_FIELDS_LENGTH = 25
|
|
|
|
static MAX_FOOTER_TEXT_LENGTH = 2048
|
|
|
|
static MAX_AUTHOR_NAME_LENGTH = 256
|
|
|
|
static MAX_EMBED_LENGTH = 6000
|
|
|
|
|
2020-12-02 12:29:52 +00:00
|
|
|
constructor(data?: EmbedPayload) {
|
2020-10-29 14:43:27 +00:00
|
|
|
this.title = data?.title
|
|
|
|
this.type = data?.type
|
|
|
|
this.description = data?.description
|
|
|
|
this.url = data?.url
|
|
|
|
this.timestamp = data?.timestamp
|
|
|
|
this.color = data?.color
|
|
|
|
this.footer = data?.footer
|
|
|
|
this.image = data?.image
|
|
|
|
this.thumbnail = data?.thumbnail
|
|
|
|
this.video = data?.video
|
|
|
|
this.provider = data?.provider
|
|
|
|
this.author = data?.author
|
|
|
|
this.fields = data?.fields
|
|
|
|
}
|
|
|
|
|
2021-01-25 11:28:46 +00:00
|
|
|
/** Convert Embed Object to Embed Payload JSON */
|
2020-12-02 12:29:52 +00:00
|
|
|
toJSON(): EmbedPayload {
|
2021-04-04 09:29:56 +00:00
|
|
|
let total = 0
|
|
|
|
if (
|
|
|
|
this.title?.length !== undefined &&
|
|
|
|
this.title?.length > Embed.MAX_TITLE_LENGTH
|
|
|
|
) {
|
2021-03-20 05:29:53 +00:00
|
|
|
total += Number(this.title.length)
|
2021-04-04 09:29:56 +00:00
|
|
|
throw new Error(
|
|
|
|
`Embed title cannot exceed ${Embed.MAX_TITLE_LENGTH} characters.`
|
|
|
|
)
|
2021-03-20 05:21:35 +00:00
|
|
|
}
|
2021-04-04 09:29:56 +00:00
|
|
|
|
|
|
|
if (
|
|
|
|
this.description?.length !== undefined &&
|
|
|
|
this.description?.length > Embed.MAX_DESCRIPTION_LENGTH
|
|
|
|
) {
|
2021-03-20 05:29:53 +00:00
|
|
|
total += Number(this.description.length)
|
2021-04-04 09:29:56 +00:00
|
|
|
throw new Error(
|
|
|
|
`Embed description cannot exceed ${Embed.MAX_DESCRIPTION_LENGTH} characters.`
|
|
|
|
)
|
2021-03-20 05:21:35 +00:00
|
|
|
}
|
2021-04-04 09:29:56 +00:00
|
|
|
|
2021-03-20 05:21:35 +00:00
|
|
|
if (this.fields?.length !== undefined) {
|
|
|
|
this.fields.forEach((field) => {
|
|
|
|
if (field.name.length > Embed.MAX_FIELD_NAME_LENGTH) {
|
2021-03-20 05:29:53 +00:00
|
|
|
total += Number(field.name.length)
|
2021-04-04 09:29:56 +00:00
|
|
|
throw new Error(
|
|
|
|
`Embed field name cannot exceed ${Embed.MAX_FIELD_NAME_LENGTH} characters.`
|
|
|
|
)
|
2021-03-20 05:21:35 +00:00
|
|
|
}
|
2021-04-04 09:29:56 +00:00
|
|
|
|
2021-03-20 05:21:35 +00:00
|
|
|
if (field.value.length > Embed.MAX_FIELD_VALUE_LENGTH) {
|
2021-03-20 05:29:53 +00:00
|
|
|
total += Number(field.value.length)
|
2021-04-04 09:29:56 +00:00
|
|
|
throw new Error(
|
|
|
|
`Embed field value cannot exceed ${Embed.MAX_FIELD_VALUE_LENGTH} characters.`
|
|
|
|
)
|
2021-03-20 05:21:35 +00:00
|
|
|
}
|
|
|
|
})
|
2021-04-04 09:29:56 +00:00
|
|
|
if (this.fields.length > Embed.MAX_FIELDS_LENGTH)
|
|
|
|
throw new Error('Embed fields cannot exceed 25 field objects.')
|
2021-03-20 05:21:35 +00:00
|
|
|
}
|
2021-04-04 09:29:56 +00:00
|
|
|
|
|
|
|
if (
|
|
|
|
this.footer?.text?.length !== undefined &&
|
|
|
|
this.footer?.text?.length > Embed.MAX_FOOTER_TEXT_LENGTH
|
|
|
|
) {
|
2021-03-20 05:29:53 +00:00
|
|
|
total += Number(this.footer?.text?.length)
|
2021-04-04 09:29:56 +00:00
|
|
|
throw new Error(
|
|
|
|
`Embed footer text cannot exceed ${Embed.MAX_FOOTER_TEXT_LENGTH}.`
|
|
|
|
)
|
2021-03-20 05:21:35 +00:00
|
|
|
}
|
2021-04-04 09:29:56 +00:00
|
|
|
|
|
|
|
if (
|
|
|
|
this.author?.name?.length !== undefined &&
|
|
|
|
this.author?.name?.length > Embed.MAX_AUTHOR_NAME_LENGTH
|
|
|
|
) {
|
2021-03-20 05:29:53 +00:00
|
|
|
total += Number(this.author?.name?.length)
|
2021-04-04 09:29:56 +00:00
|
|
|
throw new Error(
|
|
|
|
`Embed author name cannot exceed ${Embed.MAX_AUTHOR_NAME_LENGTH}.`
|
|
|
|
)
|
2021-03-20 05:21:35 +00:00
|
|
|
}
|
2021-04-04 09:29:56 +00:00
|
|
|
|
|
|
|
if (total > Embed.MAX_EMBED_LENGTH)
|
|
|
|
throw new Error(
|
|
|
|
`Embed characters cannot exceed ${Embed.MAX_EMBED_LENGTH} characters in total.`
|
|
|
|
)
|
|
|
|
|
2020-10-29 14:43:27 +00:00
|
|
|
return {
|
|
|
|
title: this.title,
|
|
|
|
type: this.type,
|
|
|
|
description: this.description,
|
|
|
|
url: this.url,
|
|
|
|
timestamp: this.timestamp,
|
|
|
|
color: this.color,
|
|
|
|
footer: this.footer,
|
|
|
|
image: this.image,
|
|
|
|
thumbnail: this.thumbnail,
|
|
|
|
video: this.video,
|
|
|
|
provider: this.provider,
|
|
|
|
author: this.author,
|
|
|
|
fields: this.fields
|
2020-10-25 06:50:32 +00:00
|
|
|
}
|
2020-10-24 15:00:42 +00:00
|
|
|
}
|
2020-10-29 14:43:27 +00:00
|
|
|
|
2021-01-25 11:28:46 +00:00
|
|
|
/** Set Title of the Embed */
|
2020-12-02 12:29:52 +00:00
|
|
|
setTitle(title: string): Embed {
|
2020-10-29 14:43:27 +00:00
|
|
|
this.title = title
|
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
2021-01-25 11:28:46 +00:00
|
|
|
/** Set Embed description */
|
2020-12-02 12:29:52 +00:00
|
|
|
setDescription(description: string): Embed {
|
2020-10-29 14:43:27 +00:00
|
|
|
this.description = description
|
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
2021-01-28 14:25:37 +00:00
|
|
|
attach(...files: MessageAttachment[]): Embed {
|
|
|
|
for (const file of files) {
|
|
|
|
this.files.push(file)
|
|
|
|
}
|
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
2021-01-25 11:28:46 +00:00
|
|
|
/** Set Embed Type */
|
2020-12-02 12:29:52 +00:00
|
|
|
setType(type: EmbedTypes): Embed {
|
2020-10-29 14:43:27 +00:00
|
|
|
this.type = type
|
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
2021-01-25 11:28:46 +00:00
|
|
|
/** Set URL of the Embed */
|
|
|
|
setURL(url: string | URL): Embed {
|
|
|
|
this.url = typeof url === 'object' ? url.toString() : url
|
2020-10-29 14:43:27 +00:00
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
2021-01-25 11:28:46 +00:00
|
|
|
/** Set Timestamp of the Embed */
|
|
|
|
setTimestamp(timeString: string): Embed
|
|
|
|
setTimestamp(unixTimestamp: number): Embed
|
|
|
|
setTimestamp(dateObject: Date): Embed
|
|
|
|
setTimestamp(timestamp: string | Date | number): Embed {
|
|
|
|
this.timestamp = new Date(timestamp).toISOString()
|
2020-10-29 14:43:27 +00:00
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
2021-01-25 11:28:46 +00:00
|
|
|
/** Set Color of the Embed */
|
|
|
|
setColor(hexInt: number): Embed
|
|
|
|
setColor(r: number, g: number, b: number): Embed
|
|
|
|
setColor(random: 'random'): Embed
|
|
|
|
setColor(hexStr: string): Embed
|
|
|
|
setColor(namedColor: keyof Colors): Embed
|
|
|
|
setColor(
|
|
|
|
color: number | 'random' | string | keyof Colors,
|
|
|
|
g?: number,
|
|
|
|
b?: number
|
|
|
|
): Embed {
|
|
|
|
if (typeof color === 'number' && g === undefined && b === undefined) {
|
|
|
|
this.color = color
|
|
|
|
} else if (typeof color === 'string' && color.toLowerCase() === 'random') {
|
|
|
|
this.color = ColorUtil.resolveHex(ColorUtil.randomHex())
|
|
|
|
} else if (typeof color === 'string' && color.startsWith('#')) {
|
|
|
|
this.color = ColorUtil.resolveHex(color)
|
|
|
|
} else if (
|
|
|
|
typeof color === 'number' &&
|
|
|
|
g !== undefined &&
|
|
|
|
b !== undefined
|
|
|
|
) {
|
|
|
|
this.color = ColorUtil.resolveRGB([color, g, b])
|
|
|
|
} else if (typeof color === 'string') {
|
|
|
|
this.color = ColorUtil.resolveColor(color as keyof Colors)
|
|
|
|
} else
|
|
|
|
throw new Error(
|
|
|
|
'Invalid Embed Color. Must be RGB, Hex (string or number), valid color name or a valid CSS color.'
|
|
|
|
)
|
2020-10-29 14:43:27 +00:00
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
2021-01-25 11:28:46 +00:00
|
|
|
/** Set Footer of the Embed */
|
|
|
|
setFooter(text: string, icon?: string): Embed
|
|
|
|
setFooter(footer: EmbedFooter): Embed
|
|
|
|
setFooter(footer: EmbedFooter | string, icon?: string): Embed {
|
|
|
|
this.footer =
|
|
|
|
typeof footer === 'string' ? { text: footer, icon_url: icon } : footer
|
2020-10-29 14:43:27 +00:00
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
2021-01-25 11:28:46 +00:00
|
|
|
/** Set Image of the Embed */
|
|
|
|
setImage(image: EmbedImage | string): Embed {
|
|
|
|
this.image = typeof image === 'string' ? { url: image } : image
|
2020-10-29 14:43:27 +00:00
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
2021-01-25 11:28:46 +00:00
|
|
|
/** Set Thumbnail Image of the Embed */
|
|
|
|
setThumbnail(thumbnail: EmbedThumbnail | string): Embed {
|
|
|
|
this.thumbnail =
|
|
|
|
typeof thumbnail === 'string' ? { url: thumbnail } : thumbnail
|
2020-10-29 14:43:27 +00:00
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
2021-01-25 11:28:46 +00:00
|
|
|
/** Set Embed Video */
|
|
|
|
setVideo(video: EmbedVideo | string): Embed {
|
|
|
|
this.video = typeof video === 'string' ? { url: video } : video
|
2020-10-29 14:43:27 +00:00
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
2021-01-25 11:28:46 +00:00
|
|
|
/** Set Provider of the Embed */
|
|
|
|
setProvider(name: string, url?: string): Embed
|
|
|
|
setProvider(provider: EmbedProvider): Embed
|
|
|
|
setProvider(provider: EmbedProvider | string, url?: string): Embed {
|
|
|
|
this.provider =
|
|
|
|
typeof provider === 'string' ? { name: provider, url } : provider
|
2020-10-29 14:43:27 +00:00
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
2021-01-25 11:28:46 +00:00
|
|
|
/** Set Author of the Embed */
|
|
|
|
setAuthor(author: EmbedAuthor): Embed
|
|
|
|
setAuthor(name: string, image?: string): Embed
|
|
|
|
setAuthor(author: EmbedAuthor | string, image?: string): Embed {
|
|
|
|
this.author =
|
|
|
|
typeof author === 'string' ? { name: author, icon_url: image } : author
|
2020-10-29 14:43:27 +00:00
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
2020-12-02 12:29:52 +00:00
|
|
|
setFields(fields: EmbedField[]): Embed {
|
2020-10-29 14:43:27 +00:00
|
|
|
this.fields = fields
|
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
2021-01-25 11:28:46 +00:00
|
|
|
/** Adds a Field to the Embed */
|
|
|
|
addField(field: EmbedField): Embed
|
|
|
|
addField(name: string, value: string, inline?: boolean): Embed
|
|
|
|
addField(name: string | EmbedField, value?: string, inline?: boolean): Embed {
|
|
|
|
if (typeof name !== 'object' && value === undefined)
|
|
|
|
throw new Error('field value is required')
|
|
|
|
const field: EmbedField =
|
|
|
|
typeof name === 'object' ? name : { name, value: value as string, inline }
|
|
|
|
|
2020-10-29 14:43:27 +00:00
|
|
|
if (this.fields === undefined) {
|
2021-01-25 11:28:46 +00:00
|
|
|
this.fields = [field]
|
2020-10-29 14:43:27 +00:00
|
|
|
} else {
|
2021-01-25 11:28:46 +00:00
|
|
|
this.fields.push(field)
|
2020-10-29 14:43:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return this
|
|
|
|
}
|
2021-01-25 11:28:46 +00:00
|
|
|
|
|
|
|
/** Adds multiple fields to the Embed */
|
|
|
|
addFields(...fields: EmbedField[]): Embed {
|
|
|
|
for (const field of fields) {
|
|
|
|
this.addField(field)
|
|
|
|
}
|
|
|
|
return this
|
|
|
|
}
|
2020-10-22 15:50:47 +00:00
|
|
|
}
|