use crate::types::{EmbedAuthor, EmbedField, EmbedProvider, MessageEmbed}; const TITLE_MAX: usize = 256; const DESCRIPTION_MAX: usize = 4096; const DESCRIPTION_LINES: usize = 12; const FIELD_NAME_MAX: usize = 256; const FIELD_VALUE_MAX: usize = 1024; const MAX_FIELDS: usize = 25; const HTML_MAX: usize = 64 * 1024; pub fn normalize(embed: &mut MessageEmbed) { embed.title = embed .title .as_deref() .map(|value| truncate(value, TITLE_MAX)); embed.description = embed.description.as_deref().map(|value| { let value = &truncate(value, DESCRIPTION_MAX); let max_lines = DESCRIPTION_LINES; let mut output = String::with_capacity(value.len()); for (index, line) in value.lines().enumerate() { if index >= max_lines { break; } if index > 0 { output.push('\n'); } output.push_str(line); } output }); embed.author = embed.author.take().and_then(normalize_author); embed.provider = embed.provider.take().and_then(normalize_provider); for media in [ embed.thumbnail.as_mut(), embed.image.as_mut(), embed.video.as_mut(), embed.audio.as_mut(), ] .into_iter() .flatten() { { media.description = media .description .as_deref() .map(|value| truncate(value, DESCRIPTION_MAX)); } } embed.html = embed.html.as_deref().map(|value| truncate(value, HTML_MAX)); embed.fields = embed.fields.take().map(|fields| { fields .into_iter() .take(MAX_FIELDS) .filter_map(|mut field| { let name = truncate(&field.name, FIELD_NAME_MAX); if name.is_empty() { return None; } field.name = name; field.value = truncate(&field.value, FIELD_VALUE_MAX); Some(field) }) .collect::>() }); if let Some(children) = embed.children.take() { embed.children = Some( children .into_iter() .map(|mut child| { normalize(&mut child); child }) .collect(), ); } } fn normalize_author(mut author: EmbedAuthor) -> Option { author.name = truncate(&author.name, TITLE_MAX); (!author.name.is_empty()).then_some(author) } fn normalize_provider(mut provider: EmbedProvider) -> Option { provider.name = truncate(&provider.name, TITLE_MAX); (!provider.name.is_empty()).then_some(provider) } pub fn truncate(value: &str, max: usize) -> String { if value.chars().count() <= max { return value.to_owned(); } let mut output: String = value.chars().take(max).collect(); output.push('…'); output }