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