serenity/model/channel/
embed.rs

1use crate::model::{Colour, Timestamp};
2
3/// Represents a rich embed which allows using richer markdown, multiple fields and more. This was
4/// heavily inspired by [slack's attachments].
5///
6/// You can include an attachment in your own message by a user or a bot, or in a webhook.
7///
8/// **Note**: Maximum amount of characters you can put is 256 in a field name,
9/// 1024 in a field value, and 2048 in a description.
10///
11/// [Discord docs](https://discord.com/developers/docs/resources/channel#embed-object).
12///
13/// [slack's attachments]: https://api.slack.com/docs/message-attachments
14#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
15#[derive(Clone, Default, Debug, Deserialize, Serialize, PartialEq)]
16#[non_exhaustive]
17pub struct Embed {
18    /// The title of the embed.
19    #[serde(skip_serializing_if = "Option::is_none")]
20    pub title: Option<String>,
21    /// The type of the embed. For embeds not generated by Discord's backend, this will always be
22    /// "rich".
23    #[serde(rename = "type")]
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub kind: Option<String>,
26    /// The description of the embed.
27    ///
28    /// The maximum value for this field is 2048 unicode codepoints.
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub description: Option<String>,
31    /// The URL of the embed.
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub url: Option<String>,
34    /// Timestamp information.
35    #[serde(skip_serializing_if = "Option::is_none")]
36    pub timestamp: Option<Timestamp>,
37    /// The colour code of the embed.
38    #[serde(rename = "color")]
39    #[serde(skip_serializing_if = "Option::is_none")]
40    pub colour: Option<Colour>,
41    /// Footer information for the embed.
42    #[serde(skip_serializing_if = "Option::is_none")]
43    pub footer: Option<EmbedFooter>,
44    /// Image information of the embed.
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub image: Option<EmbedImage>,
47    /// Thumbnail information of the embed.
48    #[serde(skip_serializing_if = "Option::is_none")]
49    pub thumbnail: Option<EmbedThumbnail>,
50    /// The embed's video information.
51    ///
52    /// This is present if the [`Self::kind`] is `"video"`.
53    #[serde(skip_serializing_if = "Option::is_none")]
54    pub video: Option<EmbedVideo>,
55    /// Provider information for the embed.
56    ///
57    /// For example, if the embed [`Self::kind`] is `"video"`, the provider might contain
58    /// information about YouTube.
59    #[serde(skip_serializing_if = "Option::is_none")]
60    pub provider: Option<EmbedProvider>,
61    /// Information about the author of the embed.
62    #[serde(skip_serializing_if = "Option::is_none")]
63    pub author: Option<EmbedAuthor>,
64    /// The array of fields.
65    ///
66    /// The maximum number of fields is 25.
67    #[serde(default)]
68    #[serde(skip_serializing_if = "Vec::is_empty")]
69    pub fields: Vec<EmbedField>,
70}
71
72/// An author object in an embed.
73///
74/// [Discord docs](https://discord.com/developers/docs/resources/channel#embed-object-embed-author-structure).
75#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
76#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
77#[non_exhaustive]
78pub struct EmbedAuthor {
79    /// The name of the author.
80    pub name: String,
81    /// The URL of the author.
82    #[serde(skip_serializing_if = "Option::is_none")]
83    pub url: Option<String>,
84    /// The URL of the author icon.
85    ///
86    /// This only supports HTTP(S) and attachments.
87    #[serde(skip_serializing_if = "Option::is_none")]
88    pub icon_url: Option<String>,
89    /// A proxied URL of the author icon.
90    #[serde(skip_serializing_if = "Option::is_none")]
91    pub proxy_icon_url: Option<String>,
92}
93
94/// A field object in an embed.
95///
96/// [Discord docs](https://discord.com/developers/docs/resources/channel#embed-object-embed-field-structure).
97#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
98#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
99#[non_exhaustive]
100pub struct EmbedField {
101    /// The name of the field.
102    ///
103    /// The maximum length of this field is 512 unicode codepoints.
104    pub name: String,
105    /// The value of the field.
106    ///
107    /// The maximum length of this field is 1024 unicode codepoints.
108    pub value: String,
109    /// Indicator of whether the field should display as inline.
110    #[serde(default)]
111    pub inline: bool,
112}
113
114impl EmbedField {
115    /// Creates a new embed field.
116    ///
117    /// **Note**: Refer to the [`Self::name`] and [`Self::value`] documentation for maximum
118    /// lengths.
119    pub fn new<T, U>(name: T, value: U, inline: bool) -> Self
120    where
121        T: Into<String>,
122        U: Into<String>,
123    {
124        Self::new_(name.into(), value.into(), inline)
125    }
126
127    pub(crate) const fn new_(name: String, value: String, inline: bool) -> Self {
128        Self {
129            name,
130            value,
131            inline,
132        }
133    }
134}
135
136/// Footer information for an embed.
137///
138/// [Discord docs](https://discord.com/developers/docs/resources/channel#embed-object-embed-footer-structure).
139#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
140#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
141#[non_exhaustive]
142pub struct EmbedFooter {
143    /// The associated text with the footer.
144    pub text: String,
145    /// The URL of the footer icon.
146    ///
147    /// This only supports HTTP(S) and attachments.
148    #[serde(skip_serializing_if = "Option::is_none")]
149    pub icon_url: Option<String>,
150    /// A proxied URL of the footer icon.
151    #[serde(skip_serializing_if = "Option::is_none")]
152    pub proxy_icon_url: Option<String>,
153}
154
155/// An image object in an embed.
156///
157/// [Discord docs](https://discord.com/developers/docs/resources/channel#embed-object-embed-image-structure).
158#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
159#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
160#[non_exhaustive]
161pub struct EmbedImage {
162    /// Source URL of the image.
163    ///
164    /// This only supports HTTP(S) and attachments.
165    pub url: String,
166    /// A proxied URL of the image.
167    pub proxy_url: Option<String>,
168    /// The height of the image.
169    pub height: Option<u32>,
170    /// The width of the image.
171    pub width: Option<u32>,
172}
173
174/// The provider of an embed.
175///
176/// [Discord docs](https://discord.com/developers/docs/resources/channel#embed-object-embed-provider-structure).
177#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
178#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
179#[non_exhaustive]
180pub struct EmbedProvider {
181    /// The name of the provider.
182    pub name: Option<String>,
183    /// The URL of the provider.
184    pub url: Option<String>,
185}
186
187/// The dimensions and URL of an embed thumbnail.
188///
189/// [Discord docs](https://discord.com/developers/docs/resources/channel#embed-object-embed-thumbnail-structure).
190#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
191#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
192#[non_exhaustive]
193pub struct EmbedThumbnail {
194    /// The source URL of the thumbnail.
195    ///
196    /// This only supports HTTP(S) and attachments.
197    pub url: String,
198    /// A proxied URL of the thumbnail.
199    pub proxy_url: Option<String>,
200    /// The height of the thumbnail in pixels.
201    pub height: Option<u32>,
202    /// The width of the thumbnail in pixels.
203    pub width: Option<u32>,
204}
205
206/// Video information for an embed.
207///
208/// [Discord docs](https://discord.com/developers/docs/resources/channel#embed-object-embed-video-structure).
209#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
210#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
211#[non_exhaustive]
212pub struct EmbedVideo {
213    /// The source URL of the video.
214    pub url: String,
215    /// A proxied URL of the thumbnail.
216    pub proxy_url: Option<String>,
217    /// The height of the video in pixels.
218    pub height: Option<u32>,
219    /// The width of the video in pixels.
220    pub width: Option<u32>,
221}