Implement bridged message replies
parent
079efa5095
commit
535afb4796
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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()?;
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue