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]) {
let discord_channels = self
.db
@ -111,7 +159,12 @@ impl Bridgers {
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(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);
}
}
@ -119,7 +172,12 @@ impl Bridgers {
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(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);
}
}
@ -136,11 +194,12 @@ impl Bridgers {
.filter(|r| r != &source)
.collect::<Vec<_>>();
tree.insert(
bincode::serialize(source).expect("Failed to serialize message reference"),
bincode::serialize(&relations).expect("Failed to serialize message relations"),
)
.expect("Failed to store message relations");
let key = bincode::serialize(source).expect("Failed to serialize message reference");
let value =
bincode::serialize(&relations).expect("Failed to serialize message relations");
tree.insert(key, value)
.expect("Failed to store message relations");
}
related_messages

View File

@ -62,6 +62,11 @@ impl EventHandler for DiscordHandler {
let content = discord_message_format::parse(&message.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 {
source: message_ref,
content,
@ -71,6 +76,7 @@ impl EventHandler for DiscordHandler {
.await
.unwrap_or(message.author.name),
},
replies_to,
}));
}
}
@ -79,10 +85,17 @@ pub async fn forward_to_discord(
discord_ctx: &Context,
channel: ChannelId,
message: &SentMessage,
reply: Option<(u64, u64)>,
) -> Option<MessageReference> {
channel
.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
.as_ref()

View File

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

View File

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