diff --git a/src/bridgers.rs b/src/bridgers.rs index 7c7ae01..c9440cf 100644 --- a/src/bridgers.rs +++ b/src/bridgers.rs @@ -4,9 +4,11 @@ use sled::Db; use crate::{ channels::ChannelReference, - discord::{self, delete_on_discord, edit_on_discord, forward_to_discord}, + discord::{ + self, delete_on_discord, edit_on_discord, forward_image_to_discord, forward_to_discord, + }, matrix::{self, delete_on_matrix, edit_on_matrix, forward_to_matrix}, - messages::{DeletedMessage, EditedMessage, MessageReference, SentMediaMessage, SentMessage}, + messages::{DeletedMessage, EditedMessage, MessageReference, SentImageMessage, SentMessage}, }; pub struct Bridgers { @@ -278,21 +280,26 @@ impl Bridgers { } } - pub async fn send_media(&self, message: SentMediaMessage) { + pub async fn send_image(&self, message: SentImageMessage) { if self.get_related_messages(&message.source).is_some() { return; } - if let Some(_discord) = self.discord.lock().unwrap().borrow().as_ref() { - if let Some(_discord_channel) = self.get_linked_discord_channel(&message.source) { - // TODO: Send the media + let mut related_messages = vec![message.source.clone()]; + + if let Some(discord) = self.discord.lock().unwrap().borrow().as_ref() { + if let Some(discord_channel) = self.get_linked_discord_channel(&message.source) { + if let Some(m) = forward_image_to_discord(discord, discord_channel, &message).await + { + related_messages.push(m); + } } } if let Some(_matrix) = self.matrix.lock().unwrap().borrow().as_ref() { - if let Some(_room_id) = self.get_linked_matrix_room(&message.source) { - // TODO: Send the media - } + if let Some(_room_id) = self.get_linked_matrix_room(&message.source) {} } + + self.store_related_messages(&related_messages); } } diff --git a/src/discord.rs b/src/discord.rs index df5739d..b466665 100644 --- a/src/discord.rs +++ b/src/discord.rs @@ -1,12 +1,13 @@ use log::info; -use serenity::{async_trait, model::prelude::*, prelude::*}; +use serenity::{async_trait, http::AttachmentType, model::prelude::*, prelude::*}; use tokio::sync::mpsc; use crate::{ channels::ChannelReference, message_ast::{self, format_discord}, messages::{ - DeletedMessage, EditedMessage, MessageAuthor, MessageEvent, MessageReference, SentMessage, + DeletedMessage, EditedMessage, MessageAuthor, MessageEvent, MessageReference, + SentImageMessage, SentMessage, }, }; @@ -250,7 +251,12 @@ pub async fn forward_to_discord( channel .send_message(discord_ctx, |m| { - let content = format_discord(&message.content); + let content = format!( + "{} ({}): {}", + &message.author.display_name, + &message.author.service_name, + format_discord(&message.content) + ); if let Some((channel_id, message_id)) = reply { m.content(&content) @@ -311,6 +317,42 @@ pub async fn delete_on_discord( .is_ok() } +pub async fn forward_image_to_discord( + discord_ctx: &Context, + channel_id: ChannelId, + image: &SentImageMessage, +) -> Option { + if let Some(webhook) = get_or_create_webhook_for_channel(discord_ctx, &channel_id).await { + return webhook + .execute(discord_ctx, true, |w| { + w.add_file(AttachmentType::Image(&image.image_url)) + .username(format!( + "{} ({})", + &image.author.display_name, &image.author.service_name + )) + .avatar_url(&image.author.avatar_url) + }) + .await + .ok() + .flatten() + .as_ref() + .map(MessageReference::from); + } + + channel_id + .send_message(discord_ctx, |m| { + m.add_file(AttachmentType::Image(&image.image_url)) + .content(format!( + "{} ({}):", + &image.author.display_name, &image.author.service_name + )) + }) + .await + .as_ref() + .ok() + .map(MessageReference::from) +} + pub async fn create_discord_client( ctx_tx: mpsc::UnboundedSender, message_tx: mpsc::UnboundedSender, diff --git a/src/main.rs b/src/main.rs index cb1d30f..9a20d1f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -96,8 +96,8 @@ async fn main() { MessageEvent::Delete(deleted_message) => { bridgers.delete_message(*deleted_message).await; } - MessageEvent::SendMedia(sent_media) => { - bridgers.send_media(*sent_media).await; + MessageEvent::SendImage(sent_media) => { + bridgers.send_image(*sent_media).await; } MessageEvent::AdminLinkChannels(channels) => { diff --git a/src/matrix.rs b/src/matrix.rs index b88ba21..f2df149 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -38,7 +38,7 @@ use crate::{ }, messages::{ DeletedMessage, EditedMessage, MessageAuthor, MessageEvent, MessageReference, - SentMediaMessage, SentMessage, + SentImageMessage, SentMessage, }, }; @@ -211,21 +211,22 @@ async fn on_message_sent( if let Some((server_name, hash)) = uri.parts() { let server_name = server_name.as_str(); - let media_url = format!( + let image_url = format!( "https://{}/_matrix/media/r0/download/{}/{}", server_name, server_name, hash ); - Some(MessageEvent::SendMedia(Box::new(SentMediaMessage { + Some(MessageEvent::SendImage(Box::new(SentImageMessage { source: message_ref, author, - media_url, + image_url, }))) } else { None } } + // TODO: Handle encrypted image uploads (we will have to decrypt it and upload it somewhere) matrix_sdk::media::MediaType::Encrypted(_encrypted_file) => None, } } else { diff --git a/src/messages.rs b/src/messages.rs index d3e95e1..53ddb4f 100644 --- a/src/messages.rs +++ b/src/messages.rs @@ -28,10 +28,10 @@ pub struct EditedMessage { pub author: MessageAuthor, } -pub struct SentMediaMessage { +pub struct SentImageMessage { pub source: MessageReference, pub author: MessageAuthor, - pub media_url: String, + pub image_url: String, } pub struct DeletedMessage { @@ -42,6 +42,6 @@ pub enum MessageEvent { AdminLinkChannels(Vec), SendText(Box), EditText(Box), - SendMedia(Box), + SendImage(Box), Delete(Box), }