2020-01-02 19:53:08 +00:00
|
|
|
package discord
|
2020-01-02 05:39:52 +00:00
|
|
|
|
2021-08-30 15:41:54 +00:00
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strconv"
|
|
|
|
)
|
2020-01-02 05:39:52 +00:00
|
|
|
|
2022-04-08 10:35:20 +00:00
|
|
|
// Color describes an RGB color (with NO alpha). If a value is -1, then it's
|
|
|
|
// marshaled to JSON as null.
|
2021-08-30 15:41:54 +00:00
|
|
|
type Color int32
|
2020-01-02 19:53:08 +00:00
|
|
|
|
2022-04-08 10:35:20 +00:00
|
|
|
// DefaultEmbedColor is the default color to use for an embed.
|
2020-01-21 04:25:47 +00:00
|
|
|
var DefaultEmbedColor Color = 0x303030
|
|
|
|
|
2022-04-08 10:35:20 +00:00
|
|
|
// NullColor is a Color that's marshaled to null.
|
2021-08-30 15:41:54 +00:00
|
|
|
const NullColor Color = -1
|
|
|
|
|
2022-03-31 18:42:22 +00:00
|
|
|
// Uint32 returns the color as a Uint32. If the color is null, then 0 is
|
|
|
|
// returned.
|
2020-01-21 04:25:47 +00:00
|
|
|
func (c Color) Uint32() uint32 {
|
2022-03-31 18:42:22 +00:00
|
|
|
if c == NullColor {
|
|
|
|
return 0
|
|
|
|
}
|
2020-01-21 04:25:47 +00:00
|
|
|
return uint32(c)
|
|
|
|
}
|
|
|
|
|
2022-03-31 18:42:22 +00:00
|
|
|
// Int converts Color to int.
|
2020-01-21 04:25:47 +00:00
|
|
|
func (c Color) Int() int {
|
|
|
|
return int(c)
|
|
|
|
}
|
2020-01-02 05:39:52 +00:00
|
|
|
|
2020-02-23 18:11:10 +00:00
|
|
|
// RGB splits Color into red, green, and blue. The maximum value is 255.
|
|
|
|
func (c Color) RGB() (uint8, uint8, uint8) {
|
|
|
|
var (
|
|
|
|
color = c.Uint32()
|
|
|
|
|
|
|
|
r = uint8((color >> 16) & 255)
|
|
|
|
g = uint8((color >> 8) & 255)
|
|
|
|
b = uint8(color & 255)
|
|
|
|
)
|
|
|
|
|
|
|
|
return r, g, b
|
|
|
|
}
|
|
|
|
|
2022-03-31 18:46:45 +00:00
|
|
|
// String returns the Color in hexadecimal (#FFFFFF) format.
|
|
|
|
func (c Color) String() string {
|
|
|
|
r, g, b := c.RGB()
|
|
|
|
return fmt.Sprintf("#%02X%02X%02X", r, g, b)
|
|
|
|
}
|
|
|
|
|
2021-08-30 15:41:54 +00:00
|
|
|
func (c Color) MarshalJSON() ([]byte, error) {
|
|
|
|
if c < 0 {
|
|
|
|
return []byte("null"), nil
|
|
|
|
}
|
|
|
|
return []byte(strconv.Itoa(c.Int())), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Color) UnmarshalJSON(json []byte) error {
|
|
|
|
s := string(json)
|
|
|
|
|
|
|
|
if s == "null" {
|
|
|
|
*c = NullColor
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
v, err := strconv.ParseInt(s, 10, 32)
|
|
|
|
*c = Color(v)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-04-08 10:35:20 +00:00
|
|
|
// Embed describes a box with a left colored border that sometimes appears in
|
|
|
|
// messages.
|
2020-01-02 05:39:52 +00:00
|
|
|
type Embed struct {
|
|
|
|
Title string `json:"title,omitempty"`
|
|
|
|
Type EmbedType `json:"type,omitempty"`
|
|
|
|
Description string `json:"description,omitempty"`
|
|
|
|
|
2020-01-02 19:53:08 +00:00
|
|
|
URL URL `json:"url,omitempty"`
|
2020-01-02 05:39:52 +00:00
|
|
|
|
2020-01-02 19:53:08 +00:00
|
|
|
Timestamp Timestamp `json:"timestamp,omitempty"`
|
|
|
|
Color Color `json:"color,omitempty"`
|
2020-01-02 05:39:52 +00:00
|
|
|
|
|
|
|
Footer *EmbedFooter `json:"footer,omitempty"`
|
|
|
|
Image *EmbedImage `json:"image,omitempty"`
|
|
|
|
Thumbnail *EmbedThumbnail `json:"thumbnail,omitempty"`
|
|
|
|
Video *EmbedVideo `json:"video,omitempty"`
|
|
|
|
Provider *EmbedProvider `json:"provider,omitempty"`
|
|
|
|
Author *EmbedAuthor `json:"author,omitempty"`
|
|
|
|
Fields []EmbedField `json:"fields,omitempty"`
|
|
|
|
}
|
|
|
|
|
2022-04-08 10:35:20 +00:00
|
|
|
// NewEmbed creates a normal embed with default values.
|
2020-01-02 05:39:52 +00:00
|
|
|
func NewEmbed() *Embed {
|
|
|
|
return &Embed{
|
|
|
|
Type: NormalEmbed,
|
2020-01-21 04:25:47 +00:00
|
|
|
Color: DefaultEmbedColor,
|
2020-01-02 19:53:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-08 10:35:20 +00:00
|
|
|
// Validate validates the embed.
|
2020-01-02 05:39:52 +00:00
|
|
|
func (e *Embed) Validate() error {
|
|
|
|
if e.Type == "" {
|
|
|
|
e.Type = NormalEmbed
|
|
|
|
}
|
|
|
|
|
|
|
|
if e.Color == 0 {
|
2020-01-21 04:25:47 +00:00
|
|
|
e.Color = DefaultEmbedColor
|
2020-01-02 05:39:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if len(e.Title) > 256 {
|
2021-06-06 19:40:24 +00:00
|
|
|
return &OverboundError{len(e.Title), 256, "title"}
|
2020-01-02 05:39:52 +00:00
|
|
|
}
|
|
|
|
|
2021-07-11 20:19:54 +00:00
|
|
|
if len(e.Description) > 4096 {
|
|
|
|
return &OverboundError{len(e.Description), 4096, "description"}
|
2020-01-02 05:39:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if len(e.Fields) > 25 {
|
2021-06-06 19:40:24 +00:00
|
|
|
return &OverboundError{len(e.Fields), 25, "fields"}
|
2020-01-02 05:39:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if e.Footer != nil {
|
|
|
|
if len(e.Footer.Text) > 2048 {
|
2021-06-06 19:40:24 +00:00
|
|
|
return &OverboundError{len(e.Footer.Text), 2048, "footer text"}
|
2020-01-02 05:39:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if e.Author != nil {
|
|
|
|
if len(e.Author.Name) > 256 {
|
2021-06-06 19:40:24 +00:00
|
|
|
return &OverboundError{len(e.Author.Name), 256, "author name"}
|
2020-01-02 05:39:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, field := range e.Fields {
|
|
|
|
if len(field.Name) > 256 {
|
2021-06-06 19:40:24 +00:00
|
|
|
return &OverboundError{len(field.Name), 256,
|
2020-01-02 05:39:52 +00:00
|
|
|
fmt.Sprintf("field %d name", i)}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(field.Value) > 1024 {
|
2021-06-06 19:40:24 +00:00
|
|
|
return &OverboundError{len(field.Value), 1024,
|
2020-01-16 04:51:22 +00:00
|
|
|
fmt.Sprintf("field %d value", i)}
|
2020-01-02 05:39:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-18 06:32:11 +00:00
|
|
|
if sum := e.Length(); sum > 6000 {
|
2021-06-06 19:40:24 +00:00
|
|
|
return &OverboundError{sum, 6000, "sum of all characters"}
|
2020-01-02 05:39:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-06-18 06:32:11 +00:00
|
|
|
// Length returns the sum of the lengths of all text in the embed.
|
|
|
|
func (e Embed) Length() int {
|
|
|
|
var sum = 0 +
|
|
|
|
len(e.Title) +
|
|
|
|
len(e.Description)
|
|
|
|
if e.Footer != nil {
|
|
|
|
sum += len(e.Footer.Text)
|
|
|
|
}
|
|
|
|
if e.Author != nil {
|
|
|
|
sum += len(e.Author.Name)
|
|
|
|
}
|
|
|
|
for _, field := range e.Fields {
|
|
|
|
sum += len(field.Name) + len(field.Value)
|
|
|
|
}
|
|
|
|
return sum
|
|
|
|
}
|
|
|
|
|
2022-04-08 10:35:20 +00:00
|
|
|
// EmbedTypes are "loosely defined" and, for the most part, are not used by our
|
|
|
|
// clients for rendering. Embed attributes power what is rendered.
|
|
|
|
//
|
|
|
|
// Deprecated: Embed types should be considered deprecated and might be removed
|
|
|
|
// in a future API version.
|
2020-01-02 05:39:52 +00:00
|
|
|
type EmbedType string
|
|
|
|
|
2022-04-08 10:35:20 +00:00
|
|
|
// Embed type constants.
|
2020-01-02 05:39:52 +00:00
|
|
|
const (
|
2020-02-22 07:56:25 +00:00
|
|
|
NormalEmbed EmbedType = "rich"
|
|
|
|
ImageEmbed EmbedType = "image"
|
|
|
|
VideoEmbed EmbedType = "video"
|
|
|
|
GIFVEmbed EmbedType = "gifv"
|
|
|
|
ArticleEmbed EmbedType = "article"
|
|
|
|
LinkEmbed EmbedType = "link"
|
2020-01-02 05:39:52 +00:00
|
|
|
)
|
|
|
|
|
2022-04-08 10:35:20 +00:00
|
|
|
// EmbedFooter is the footer of an embed.
|
2020-01-02 05:39:52 +00:00
|
|
|
type EmbedFooter struct {
|
2020-01-02 19:53:08 +00:00
|
|
|
Text string `json:"text"`
|
|
|
|
Icon URL `json:"icon_url,omitempty"`
|
|
|
|
ProxyIcon URL `json:"proxy_icon_url,omitempty"`
|
2020-01-02 05:39:52 +00:00
|
|
|
}
|
|
|
|
|
2022-04-08 10:35:20 +00:00
|
|
|
// EmbedImage is the large image of an embed.
|
2020-01-02 05:39:52 +00:00
|
|
|
type EmbedImage struct {
|
2020-02-23 00:38:19 +00:00
|
|
|
URL URL `json:"url"`
|
|
|
|
Proxy URL `json:"proxy_url"`
|
|
|
|
Height uint `json:"height,omitempty"`
|
|
|
|
Width uint `json:"width,omitempty"`
|
2020-01-02 05:39:52 +00:00
|
|
|
}
|
|
|
|
|
2022-04-08 10:35:20 +00:00
|
|
|
// EmbedThumbnail is the small image of an embed. It often appears on the right.
|
2020-01-02 05:39:52 +00:00
|
|
|
type EmbedThumbnail struct {
|
2020-01-02 19:53:08 +00:00
|
|
|
URL URL `json:"url,omitempty"`
|
|
|
|
Proxy URL `json:"proxy_url,omitempty"`
|
|
|
|
Height uint `json:"height,omitempty"`
|
|
|
|
Width uint `json:"width,omitempty"`
|
2020-01-02 05:39:52 +00:00
|
|
|
}
|
|
|
|
|
2022-04-08 10:35:20 +00:00
|
|
|
// EmbedVideo is the video of an embed.
|
2020-01-02 05:39:52 +00:00
|
|
|
type EmbedVideo struct {
|
2020-01-02 19:53:08 +00:00
|
|
|
URL URL `json:"url"`
|
2022-04-08 10:35:20 +00:00
|
|
|
Proxy URL `json:"proxy_url,omitempty"`
|
2020-01-02 19:53:08 +00:00
|
|
|
Height uint `json:"height"`
|
|
|
|
Width uint `json:"width"`
|
2020-01-02 05:39:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type EmbedProvider struct {
|
2020-01-02 19:53:08 +00:00
|
|
|
Name string `json:"name"`
|
|
|
|
URL URL `json:"url"`
|
2020-01-02 05:39:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type EmbedAuthor struct {
|
2020-01-02 19:53:08 +00:00
|
|
|
Name string `json:"name,omitempty"`
|
|
|
|
URL URL `json:"url,omitempty"`
|
|
|
|
Icon URL `json:"icon_url,omitempty"`
|
|
|
|
ProxyIcon URL `json:"proxy_icon_url,omitempty"`
|
2020-01-02 05:39:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type EmbedField struct {
|
|
|
|
Name string `json:"name"`
|
|
|
|
Value string `json:"value"`
|
|
|
|
Inline bool `json:"inline,omitempty"`
|
|
|
|
}
|