use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(tag = "type", rename = "rich")]
pub struct Embed {
pub title: Option<String>,
pub description: Option<String>,
pub url: Option<String>,
pub timestamp: Option<String>,
pub color: Option<u32>,
pub footer: Option<EmbedFooter>,
pub image: Option<EmbedImage>,
pub thumbnail: Option<EmbedThumbnail>,
pub video: Option<EmbedVideo>,
pub provider: Option<EmbedProvider>,
pub author: Option<EmbedAuthor>,
pub fields: Option<Vec<EmbedField>>,
}
impl Default for Embed {
fn default() -> Self {
Self::new()
}
}
impl Embed {
pub fn new() -> Self {
Self {
title: None,
description: None,
url: None,
timestamp: None,
color: None,
footer: None,
image: None,
thumbnail: None,
video: None,
provider: None,
author: None,
fields: None,
}
}
pub fn with_title(mut self, title: &str) -> Self {
self.title = Some(title.into());
self
}
pub fn with_description(mut self, description: &str) -> Self {
self.description = Some(description.into());
self
}
pub fn with_url(mut self, url: &str) -> Self {
self.url = Some(url.into());
self
}
pub fn with_timestamp(mut self, timestamp: &str) -> Self {
self.timestamp = Some(timestamp.into());
self
}
pub fn with_color(mut self, color: u32) -> Self {
self.color = Some(color);
self
}
pub fn with_footer(mut self, footer: EmbedFooter) -> Self {
self.footer = Some(footer);
self
}
pub fn with_image(mut self, image: EmbedImage) -> Self {
self.image = Some(image);
self
}
pub fn with_thumbnail(mut self, thumbnail: EmbedThumbnail) -> Self {
self.thumbnail = Some(thumbnail);
self
}
pub fn with_video(mut self, video: EmbedVideo) -> Self {
self.video = Some(video);
self
}
pub fn with_provider(mut self, provider: EmbedProvider) -> Self {
self.provider = Some(provider);
self
}
pub fn with_author(mut self, author: EmbedAuthor) -> Self {
self.author = Some(author);
self
}
pub fn with_field(mut self, field: EmbedField) -> Self {
if let Some(fields) = &mut self.fields {
fields.push(field);
} else {
self.fields = Some(vec![field]);
}
self
}
pub fn with_fields(mut self, fields: Vec<EmbedField>) -> Self {
if let Some(existing_fields) = &mut self.fields {
existing_fields.extend(fields);
} else {
self.fields = Some(fields);
}
self
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct EmbedFooter {
pub text: String,
pub icon_url: Option<String>,
pub proxy_icon_url: Option<String>,
}
impl EmbedFooter {
pub fn new(text: String, icon_url: Option<String>, proxy_icon_url: Option<String>) -> Self {
Self {
text,
icon_url,
proxy_icon_url,
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct EmbedImage {
pub url: String,
pub proxy_url: Option<String>,
pub height: Option<i32>,
pub width: Option<i32>,
}
impl EmbedImage {
pub fn new(
url: String,
proxy_url: Option<String>,
height: Option<i32>,
width: Option<i32>,
) -> Self {
Self {
url,
proxy_url,
height,
width,
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct EmbedThumbnail {
pub url: String,
pub proxy_url: Option<String>,
pub height: Option<i32>,
pub width: Option<i32>,
}
impl EmbedThumbnail {
pub fn new(
url: String,
proxy_url: Option<String>,
height: Option<i32>,
width: Option<i32>,
) -> Self {
Self {
url,
proxy_url,
height,
width,
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct EmbedVideo {
pub url: Option<String>,
pub proxy_url: Option<String>,
pub height: Option<i32>,
pub width: Option<i32>,
}
impl EmbedVideo {
pub fn new(
url: Option<String>,
proxy_url: Option<String>,
height: Option<i32>,
width: Option<i32>,
) -> Self {
Self {
url,
proxy_url,
height,
width,
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct EmbedProvider {
pub name: Option<String>,
pub url: Option<String>,
}
impl EmbedProvider {
pub fn new(name: Option<String>, url: Option<String>) -> Self {
Self { name, url }
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct EmbedAuthor {
pub name: String,
pub url: Option<String>,
pub icon_url: Option<String>,
pub proxy_icon_url: Option<String>,
}
impl EmbedAuthor {
pub fn new(
name: String,
url: Option<String>,
icon_url: Option<String>,
proxy_icon_url: Option<String>,
) -> Self {
Self {
name,
url,
icon_url,
proxy_icon_url,
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct EmbedField {
pub name: String,
pub value: String,
pub inline: Option<bool>,
}
impl EmbedField {
pub fn new(name: String, value: String, inline: Option<bool>) -> Self {
Self {
name,
value,
inline,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
pub fn embed_serialize_test() {
let embed = Embed::new().with_title("title").with_color(0xFFFFFF);
let json = serde_json::to_string_pretty(&embed).unwrap();
println!("{}", json);
}
#[test]
pub fn embed_deserialize_test() {
let json = r#"{
"type": "rich",
"title": "title",
"description": null,
"url": null,
"timestamp": null,
"color": null,
"footer": null,
"image": null,
"thumbnail": null,
"video": null,
"provider": null,
"author": null,
"fields": null
}"#;
let embed = serde_json::from_str::<Embed>(json).unwrap();
println!("{:#?}", embed);
}
}