Implement bridged message replies

legacy
Charlotte Som 2021-09-13 20:41:55 +01:00
parent 079efa5095
commit 535afb4796
4 changed files with 136 additions and 17 deletions

View File

@ -70,6 +70,54 @@ impl Bridgers {
} }
} }
fn get_related_messages(&self, source: &MessageReference) -> Option<Vec<MessageReference>> {
let message_relations = self
.db
.open_tree("message_relations")
.expect("Failed to open relations tree");
let key = bincode::serialize(source).expect("Failed to serialize message reference");
message_relations
.get(key)
.expect("Failed to retrieve message references")
.map(|r| {
bincode::deserialize::<Vec<MessageReference>>(&r)
.expect("Failed to deserialize message references")
})
}
fn get_related_discord_message(&self, source: &MessageReference) -> Option<(u64, u64)> {
if let MessageReference::Discord(channel_id, message_id) = source {
return Some((*channel_id, *message_id));
}
if let Some(relations) = self.get_related_messages(source) {
for relation in relations {
if let MessageReference::Discord(channel_id, message_id) = relation {
return Some((channel_id, message_id));
}
}
}
None
}
fn get_related_matrix_message(&self, source: &MessageReference) -> Option<(String, String)> {
if let MessageReference::Matrix(room_id, event_id) = source {
return Some((room_id.to_string(), event_id.to_string()));
}
if let Some(relations) = self.get_related_messages(source) {
for relation in relations {
if let MessageReference::Matrix(room_id, event_id) = relation {
return Some((room_id, event_id));
}
}
}
None
}
pub fn link_channels(&self, channels: &[ChannelReference]) { pub fn link_channels(&self, channels: &[ChannelReference]) {
let discord_channels = self let discord_channels = self
.db .db
@ -111,7 +159,12 @@ impl Bridgers {
if let Some(discord) = self.discord.lock().unwrap().borrow().as_ref() { if let Some(discord) = self.discord.lock().unwrap().borrow().as_ref() {
if let Some(channel) = self.get_linked_discord_channel(&message.source) { if let Some(channel) = self.get_linked_discord_channel(&message.source) {
if let Some(m) = forward_to_discord(discord, channel, &message).await { let reply = message
.replies_to
.as_ref()
.and_then(|r| self.get_related_discord_message(r));
if let Some(m) = forward_to_discord(discord, channel, &message, reply).await {
related_messages.push(m); related_messages.push(m);
} }
} }
@ -119,7 +172,12 @@ impl Bridgers {
if let Some(matrix) = self.matrix.lock().unwrap().borrow().as_ref() { if let Some(matrix) = self.matrix.lock().unwrap().borrow().as_ref() {
if let Some(room_id) = self.get_linked_matrix_room(&message.source) { if let Some(room_id) = self.get_linked_matrix_room(&message.source) {
if let Some(m) = forward_to_matrix(matrix, room_id, &message).await { let reply = message
.replies_to
.as_ref()
.and_then(|r| self.get_related_matrix_message(r));
if let Some(m) = forward_to_matrix(matrix, room_id, &message, reply).await {
related_messages.push(m); related_messages.push(m);
} }
} }
@ -136,11 +194,12 @@ impl Bridgers {
.filter(|r| r != &source) .filter(|r| r != &source)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
tree.insert( let key = bincode::serialize(source).expect("Failed to serialize message reference");
bincode::serialize(source).expect("Failed to serialize message reference"), let value =
bincode::serialize(&relations).expect("Failed to serialize message relations"), bincode::serialize(&relations).expect("Failed to serialize message relations");
)
.expect("Failed to store message relations"); tree.insert(key, value)
.expect("Failed to store message relations");
} }
related_messages related_messages

View File

@ -62,6 +62,11 @@ impl EventHandler for DiscordHandler {
let content = discord_message_format::parse(&message.content); let content = discord_message_format::parse(&message.content);
let content = message_ast::convert_discord(&content); let content = message_ast::convert_discord(&content);
let replies_to = message
.referenced_message
.as_ref()
.map(|m| MessageReference::from(m.as_ref()));
let _ = self.event_tx.send(MessageEvent::Send(SentMessage { let _ = self.event_tx.send(MessageEvent::Send(SentMessage {
source: message_ref, source: message_ref,
content, content,
@ -71,6 +76,7 @@ impl EventHandler for DiscordHandler {
.await .await
.unwrap_or(message.author.name), .unwrap_or(message.author.name),
}, },
replies_to,
})); }));
} }
} }
@ -79,10 +85,17 @@ pub async fn forward_to_discord(
discord_ctx: &Context, discord_ctx: &Context,
channel: ChannelId, channel: ChannelId,
message: &SentMessage, message: &SentMessage,
reply: Option<(u64, u64)>,
) -> Option<MessageReference> { ) -> Option<MessageReference> {
channel channel
.send_message(&discord_ctx.http, |m| { .send_message(&discord_ctx.http, |m| {
m.content(format_discord(&message.content)) let b = m.content(format_discord(&message.content));
if let Some((channel_id, message_id)) = reply {
b.reference_message((ChannelId(channel_id), MessageId(message_id)))
} else {
b
}
}) })
.await .await
.as_ref() .as_ref()

View File

@ -1,4 +1,4 @@
use std::sync::Arc; use std::{str::FromStr, sync::Arc};
use matrix_sdk::{ use matrix_sdk::{
room::{Joined, Room}, room::{Joined, Room},
@ -10,7 +10,8 @@ use matrix_sdk::{
}, },
redaction::RedactionEventContent, redaction::RedactionEventContent,
}, },
AnyMessageEventContent, AnySyncRoomEvent, SyncMessageEvent, AnyMessageEvent, AnyMessageEventContent, AnyRoomEvent, AnySyncRoomEvent,
SyncMessageEvent,
}, },
EventId, UserId, EventId, UserId,
}, },
@ -125,10 +126,21 @@ async fn on_room_message_event(
let content = ctx.get_content(&text.body, &text.formatted); let content = ctx.get_content(&text.body, &text.formatted);
if let Some(author) = ctx.get_message_author(&room, &event.sender).await { if let Some(author) = ctx.get_message_author(&room, &event.sender).await {
let replies_to =
if let Some(Relation::Reply { in_reply_to }) = &event.content.relates_to {
Some(MessageReference::from((
room.room_id(),
&in_reply_to.event_id,
)))
} else {
None
};
let _ = ctx.message_tx.send(MessageEvent::Send(SentMessage { let _ = ctx.message_tx.send(MessageEvent::Send(SentMessage {
source: message_ref, source: message_ref,
content, content,
author, author,
replies_to,
})); }));
} }
} }
@ -142,6 +154,7 @@ async fn on_room_message_event(
source: message_ref, source: message_ref,
content, content,
author, author,
replies_to: None,
})); }));
} }
} }
@ -158,16 +171,49 @@ pub async fn forward_to_matrix(
client: &Client, client: &Client,
room_id: RoomId, room_id: RoomId,
message: &SentMessage, message: &SentMessage,
reply: Option<(String, String)>,
) -> Option<MessageReference> { ) -> Option<MessageReference> {
if let Some(room) = client.get_joined_room(&room_id) { if let Some(room) = client.get_joined_room(&room_id) {
let event = room let replied_message_event = if let Some((room_id, event_id)) = reply {
.send( let event = room
AnyMessageEventContent::RoomMessage(MessageEventContent::text_html( .event(
format_discord(&message.content), matrix_sdk::ruma::api::client::r0::room::get_room_event::Request::new(
format_matrix(&message.content), &RoomId::from_str(&room_id).unwrap(),
)), &EventId::from_str(&event_id).unwrap(),
None, ),
)
.await
.unwrap()
.event
.deserialize()
.unwrap();
if let AnyRoomEvent::Message(AnyMessageEvent::RoomMessage(original_message_event)) =
event
{
Some(original_message_event)
} else {
None
}
} else {
None
};
let content = if let Some(replied_message_event) = &replied_message_event {
MessageEventContent::text_reply_html(
format_discord(&message.content),
format_matrix(&message.content),
replied_message_event,
) )
} else {
MessageEventContent::text_html(
format_discord(&message.content),
format_matrix(&message.content),
)
};
let event = room
.send(AnyMessageEventContent::RoomMessage(content), None)
.await .await
.ok()?; .ok()?;

View File

@ -16,6 +16,7 @@ pub struct SentMessage {
pub source: MessageReference, pub source: MessageReference,
pub content: MessageContent, pub content: MessageContent,
pub author: MessageAuthor, pub author: MessageAuthor,
pub replies_to: Option<MessageReference>,
} }
pub struct EditedMessage { pub struct EditedMessage {