use super::{MessageComponent, MessageContent}; use discord_message_format::DiscordComponent; impl<'a> From<&DiscordComponent<'a>> for MessageComponent { fn from(discord: &DiscordComponent<'a>) -> Self { match discord { DiscordComponent::Plain(text) => Self::Plain(text.to_string()), DiscordComponent::Literal(char) => Self::Plain(char.to_string()), DiscordComponent::Link(link) => Self::Link { target: link.to_string(), text: vec![Self::Plain(link.to_string())], }, DiscordComponent::Bold(content) => Self::Bold(convert_discord(content)), DiscordComponent::Italic(content) => Self::Italic(convert_discord(content)), DiscordComponent::Strikethrough(content) => { Self::Strikethrough(convert_discord(content)) } DiscordComponent::Underline(content) => Self::Underline(convert_discord(content)), DiscordComponent::Code(code) => Self::Code(code.to_string()), DiscordComponent::CodeBlock { lang, source } => Self::CodeBlock { lang: lang.map(|s| s.to_string()), source: source.to_string(), }, DiscordComponent::Spoiler(content) => Self::Spoiler { reason: None, content: convert_discord(content), }, DiscordComponent::LineBreak => Self::HardBreak, DiscordComponent::Quote(content) => Self::BlockQuote(convert_discord(content)), } } } pub fn convert_discord(discord_message: &[DiscordComponent<'_>]) -> MessageContent { discord_message .iter() .map(MessageComponent::from) .collect::() } pub fn format_discord(message_content: &[MessageComponent]) -> String { message_content .iter() .map(|component| match component { MessageComponent::Plain(text) => text.to_string(), // TODO: Escape MessageComponent::Link { target, text } => { let formatted_text = format_discord(text); // TODO: Maybe tolerate a missing http(s) URL scheme? if &formatted_text == target { formatted_text } else { format!("{} ({})", formatted_text, target) } } MessageComponent::Italic(inner) => format!("*{}*", format_discord(inner)), MessageComponent::Bold(inner) => format!("**{}**", format_discord(inner)), MessageComponent::Strikethrough(inner) => format!("~~{}~~", format_discord(inner)), MessageComponent::Underline(inner) => format!("__{}__", format_discord(inner)), MessageComponent::Code(code) => format!("`{}`", code), // TODO: Double-grave delimiting when code contains '`' MessageComponent::CodeBlock { lang, source } => { format!( "```{}\n{}\n```", lang.as_ref() .map(|s| s.to_string()) .unwrap_or_else(|| "".to_string()), source.to_string() ) } MessageComponent::Spoiler { content, .. } => format!("||{}||", format_discord(content)), // TODO: Spoiler reason MessageComponent::HardBreak => "\n".to_string(), MessageComponent::BlockQuote(inner) => format_discord(inner) .lines() .map(|l| format!("> {}\n", l)) .collect(), }) .collect() }