char/phoebe

git clone https://git.t4t.associates/char/phoebe

videogame hackerRoute messages from a source channel to a destinationb9daf95

main
2.9 KiB86 linesraw
1use discord_message_format::DiscordComponent;
2use phoebe::mid_chat::{ChatContentComponent, ChatContentComponent::*, ChatMessageContent};
3
4pub fn convert(discord_message: &[DiscordComponent<'_>]) -> ChatMessageContent {
5    discord_message
6        .iter()
7        .map(discord_to_mid)
8        .collect::<ChatMessageContent>()
9}
10
11pub fn format(message_content: &[ChatContentComponent]) -> String {
12    message_content.iter().map(mid_to_discord).collect()
13}
14
15fn discord_to_mid(discord: &DiscordComponent<'_>) -> ChatContentComponent {
16    match discord {
17        DiscordComponent::Plain(text) => Plain(text.to_string()),
18        DiscordComponent::Literal(char) => Plain(char.to_string()),
19        DiscordComponent::Link(link) => Link {
20            target: link.to_string(),
21            text: vec![Plain(link.to_string())],
22        },
23
24        DiscordComponent::Bold(content) => Bold(convert(content)),
25        DiscordComponent::Italic(content) => Italic(convert(content)),
26        DiscordComponent::Strikethrough(content) => Strikethrough(convert(content)),
27        DiscordComponent::Underline(content) => Underline(convert(content)),
28
29        DiscordComponent::Code(code) => Code(code.to_string()),
30        DiscordComponent::CodeBlock { lang, source } => CodeBlock {
31            lang: lang.map(|s| s.to_string()),
32            source: source.to_string(),
33        },
34
35        DiscordComponent::Spoiler(content) => Spoiler {
36            reason: None,
37            content: convert(content),
38        },
39
40        DiscordComponent::LineBreak => HardBreak,
41        DiscordComponent::Quote(content) => BlockQuote(convert(content)),
42    }
43}
44
45fn mid_to_discord(component: &ChatContentComponent) -> String {
46    match component {
47        Plain(text) => text.to_string(), // TODO: Escape
48
49        Link { target, text } => {
50            let formatted_text = format(text);
51
52            // TODO: Maybe tolerate a missing http(s) URL scheme?
53            if &formatted_text == target {
54                formatted_text
55            } else {
56                format!("{} ({})", formatted_text, target)
57            }
58        }
59
60        Italic(inner) => format!("*{}*", format(inner)),
61        Bold(inner) => format!("**{}**", format(inner)),
62        Strikethrough(inner) => format!("~~{}~~", format(inner)),
63        Underline(inner) => format!("__{}__", format(inner)),
64
65        Code(code) => format!("`{}`", code), // TODO: Double-grave delimiting when code contains '`'
66        CodeBlock { lang, source } => {
67            format!(
68                "```{}\n{}\n```",
69                lang.as_ref()
70                    .map(|s| s.to_string())
71                    .unwrap_or_else(|| "".to_string()),
72                source
73            )
74        }
75
76        Spoiler { content, .. } => {
77            format!("||{}||", format(content))
78        } // TODO: Spoiler reason
79
80        HardBreak => "\n".to_string(),
81        BlockQuote(inner) => format(inner)
82            .lines()
83            .map(|l| format!("> {}\n", l))
84            .collect(),
85    }
86}