Add message editing support & impl for Discord
parent
2652f52a49
commit
4fc8c15b07
|
@ -1,7 +1,8 @@
|
|||
use crate::{ChatMessage, ChatMessageReference};
|
||||
use crate::{ChatMessage, ChatMessageEdit, ChatMessageReference};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ChatEvent {
|
||||
NewMessage(Box<ChatMessage>),
|
||||
DeleteMessage(ChatMessageReference),
|
||||
EditMessage(ChatMessageReference, Box<ChatMessageEdit>),
|
||||
}
|
||||
|
|
|
@ -34,4 +34,11 @@ pub struct ChatMessage {
|
|||
pub replying: Option<ChatMessageReference>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ChatMessageEdit {
|
||||
pub origin: ChatMessageReference,
|
||||
pub author: ChatAuthor,
|
||||
pub new_content: ChatMessageContent,
|
||||
}
|
||||
|
||||
pub mod event;
|
||||
|
|
|
@ -73,6 +73,31 @@ async fn handle_events(
|
|||
}
|
||||
}
|
||||
}
|
||||
ChatEvent::EditMessage(prev_origin, message_edit) => {
|
||||
let messages = if let Ok(message_stream) =
|
||||
get_linked_messages(&mut conn, dyn_service, &prev_origin).await
|
||||
{
|
||||
message_stream
|
||||
.filter(|r| future::ready(r.channel.service == service.tag()))
|
||||
.collect::<Vec<_>>()
|
||||
.await
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
let mut resulting_messages = vec![];
|
||||
for message in messages {
|
||||
resulting_messages.extend(service.edit_message(&message, &message_edit).await)
|
||||
}
|
||||
|
||||
if !resulting_messages.is_empty() {
|
||||
if let Err(e) =
|
||||
link_messages(&mut conn, &prev_origin, &resulting_messages).await
|
||||
{
|
||||
tracing::error!("Failed to link messages: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use mid_chat::{ChatMessage, ChatMessageReference, ChatReference};
|
||||
use mid_chat::*;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
pub trait Service {
|
||||
|
@ -10,4 +10,9 @@ pub trait Service {
|
|||
destination_channel: ChatReference,
|
||||
) -> Vec<ChatMessageReference>;
|
||||
async fn delete_message(&mut self, message: &ChatMessageReference) -> bool;
|
||||
async fn edit_message(
|
||||
&mut self,
|
||||
old_origin: &ChatMessageReference,
|
||||
edit: &ChatMessageEdit,
|
||||
) -> Vec<ChatMessageReference>;
|
||||
}
|
||||
|
|
|
@ -108,4 +108,40 @@ impl EventHandler for DiscordHandler {
|
|||
.send(ChatEvent::DeleteMessage(origin))
|
||||
.expect("Failed to dispatch incoming Discord chat message deletion");
|
||||
}
|
||||
|
||||
async fn message_update(
|
||||
&self,
|
||||
ctx: Context,
|
||||
_old_if_available: Option<Message>,
|
||||
new: Option<Message>,
|
||||
event: MessageUpdateEvent,
|
||||
) {
|
||||
if let Ok(new_message) = {
|
||||
if let Some(m) = new {
|
||||
Ok(m)
|
||||
} else {
|
||||
event.channel_id.message(&ctx, event.id).await
|
||||
}
|
||||
} {
|
||||
let origin = ChatMessageReference::new(
|
||||
discord_reference(new_message.channel_id),
|
||||
new_message.id,
|
||||
);
|
||||
let author = self.get_author(&ctx, &new_message).await;
|
||||
|
||||
let content = discord_message_format::parse(&new_message.content);
|
||||
let content = super::chat_conv::convert(&content);
|
||||
|
||||
let edit = ChatMessageEdit {
|
||||
origin: origin.clone(),
|
||||
author,
|
||||
new_content: content,
|
||||
};
|
||||
|
||||
let _ = self
|
||||
.chat_event_tx
|
||||
.send(ChatEvent::EditMessage(origin, Box::new(edit)))
|
||||
.expect("Failed to dispatch incoming Discord chat message update");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use phoebe::{
|
||||
mid_chat::{self, ChatMessage, ChatMessageReference, ChatReference},
|
||||
mid_chat::{self, ChatMessage, ChatMessageEdit, ChatMessageReference, ChatReference},
|
||||
prelude::*,
|
||||
DynServiceLookup,
|
||||
};
|
||||
|
@ -93,4 +93,14 @@ impl Service for DiscordService {
|
|||
assert_eq!(message.channel.service, "discord");
|
||||
sender::delete_discord_message(self, message).await.is_ok()
|
||||
}
|
||||
|
||||
async fn edit_message(
|
||||
&mut self,
|
||||
prev_origin: &ChatMessageReference,
|
||||
new_message: &ChatMessageEdit,
|
||||
) -> Vec<ChatMessageReference> {
|
||||
assert_eq!(prev_origin.channel.service, "discord");
|
||||
let _ = sender::edit_discord_message(self, prev_origin, new_message).await;
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use phoebe::{
|
||||
attachments::attachment_to_url,
|
||||
mid_chat::{ChatMessage, ChatMessageReference, ChatReference},
|
||||
mid_chat::{ChatMessage, ChatMessageEdit, ChatMessageReference, ChatReference},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
|
@ -137,6 +137,7 @@ pub async fn send_discord_message(
|
|||
));
|
||||
}
|
||||
}
|
||||
|
||||
let content = format!(
|
||||
"{} ({}): {}",
|
||||
source.author.display_name,
|
||||
|
@ -182,3 +183,37 @@ pub async fn delete_discord_message(
|
|||
channel_id.delete_message(&discord.ctx, message_id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn edit_discord_message(
|
||||
discord: &mut DiscordService,
|
||||
prev_origin: &ChatMessageReference,
|
||||
edit: &ChatMessageEdit,
|
||||
) -> Result<()> {
|
||||
let channel_id = prev_origin.channel.id.parse::<ChannelId>()?;
|
||||
let message_id: MessageId = prev_origin.message_id.parse::<u64>()?.into();
|
||||
|
||||
if let Some(webhook) = get_or_create_webhook_for_channel(&mut *discord, &channel_id).await {
|
||||
if webhook
|
||||
.edit_message(&discord.ctx, message_id, |w| {
|
||||
w.content(chat_conv::format(&edit.new_content))
|
||||
})
|
||||
.await
|
||||
.is_ok()
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
let content = format!(
|
||||
"{} ({}): {}",
|
||||
edit.author.display_name,
|
||||
edit.author.reference.service,
|
||||
chat_conv::format(&edit.new_content)
|
||||
);
|
||||
|
||||
channel_id
|
||||
.edit_message(&discord.ctx, message_id, |m| m.content(content))
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue