[Heavy WIP] Initial commit

This commit is contained in:
Charlotte Som 2021-08-12 10:47:38 +01:00
commit 670b296628
9 changed files with 3214 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

3013
Cargo.lock generated Normal file

File diff suppressed because it is too large Load diff

16
Cargo.toml Normal file
View file

@ -0,0 +1,16 @@
[package]
name = "phoebe"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
bincode = "1.3.3"
discord_message_format = { git = "https://git.lavender.software/charlotte/discord-message-format.git" }
matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk.git" }
serde = { version = "1.0.127", features = ["derive"] }
serenity = "0.10.8"
sled = "0.34.6"
tokio = { version = "1.8.0", features = ["full"] }
tracing = "0.1.26"

3
README.md Normal file
View file

@ -0,0 +1,3 @@
# phoebe
bridgers

View file

@ -0,0 +1,43 @@
use super::{MessageContent, Styled};
use discord_message_format::DiscordComponent;
impl<'a> From<&DiscordComponent<'a>> for Styled {
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(Styled::from)
.collect::<MessageContent>()
}

32
src/ast/mod.rs Normal file
View file

@ -0,0 +1,32 @@
mod convert_discord;
pub type MessageContent = Vec<Styled>;
pub enum Styled {
Plain(String),
Link {
target: String,
text: MessageContent,
},
Italic(MessageContent),
Bold(MessageContent),
Strikethrough(MessageContent),
Underline(MessageContent),
Code(String),
CodeBlock {
lang: Option<String>,
source: String,
},
Spoiler {
reason: Option<String>,
content: MessageContent,
},
HardBreak,
BlockQuote(MessageContent),
}
pub use convert_discord::convert_discord;

32
src/discord.rs Normal file
View file

@ -0,0 +1,32 @@
use serenity::{async_trait, model::prelude::*, prelude::*};
use tracing::info;
use crate::{ast, MessageReference};
impl From<&Message> for MessageReference {
fn from(message: &Message) -> Self {
Self::Discord(message.channel_id.0, message.id.0)
}
}
// TODO: Some way to emit messages for matrix,
// and some way to receive messages from matrix.
struct DiscordSide {}
#[async_trait]
impl EventHandler for DiscordSide {
async fn ready(&self, _ctx: Context, _ready: Ready) {
info!("Discord side: Ready");
// TODO
}
async fn message(&self, ctx: Context, message: Message) {
let _message_ref = MessageReference::from(&message);
// TODO: Store this message ref & associations in the DB
let content = discord_message_format::parse(&message.content);
let content = ast::convert_discord(&content);
// TODO: Broadcast the message to other platforms
}
}

15
src/main.rs Normal file
View file

@ -0,0 +1,15 @@
use serde::{Deserialize, Serialize};
mod ast;
mod discord;
mod matrix;
#[derive(Serialize, Deserialize)]
pub enum MessageReference {
Discord(u64, u64),
Matrix(String, String),
}
fn main() {
println!("Hello, world!");
}

59
src/matrix.rs Normal file
View file

@ -0,0 +1,59 @@
use matrix_sdk::{
async_trait,
room::Room,
ruma::{
api::client::r0::room::get_room_event,
events::{
room::message::{MessageEventContent, MessageFormat, MessageType},
AnyMessageEvent, AnyRoomEvent, SyncMessageEvent,
},
},
EventHandler,
};
use crate::MessageReference;
impl From<(&Room, &SyncMessageEvent<MessageEventContent>)> for MessageReference {
fn from((room, event): (&Room, &SyncMessageEvent<MessageEventContent>)) -> Self {
let room_string = room.room_id().as_str().to_string();
let event_string = event.event_id.as_str().to_string();
Self::Matrix(room_string, event_string)
}
}
struct MatrixHandler;
#[async_trait]
impl EventHandler for MatrixHandler {
async fn on_room_message(&self, room: Room, event: &SyncMessageEvent<MessageEventContent>) {
let event_id = &event.event_id;
if let Room::Joined(room) = room {
let event = room
.event(get_room_event::Request::new(room.room_id(), event_id))
.await
.unwrap()
.event
.deserialize()
.unwrap();
if let AnyRoomEvent::Message(AnyMessageEvent::RoomMessage(message)) = event {
if let MessageEventContent {
msgtype: MessageType::Text(text_content),
..
} = &message.content
{
if let Some(html_body) = text_content
.formatted
.as_ref()
.filter(|f| f.format == MessageFormat::Html)
.map(|f| &f.body)
{
// TODO: Parse the html_body into the AST
}
}
}
}
}
}