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)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ChatEvent {
|
pub enum ChatEvent {
|
||||||
NewMessage(Box<ChatMessage>),
|
NewMessage(Box<ChatMessage>),
|
||||||
DeleteMessage(ChatMessageReference),
|
DeleteMessage(ChatMessageReference),
|
||||||
|
EditMessage(ChatMessageReference, Box<ChatMessageEdit>),
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,4 +34,11 @@ pub struct ChatMessage {
|
||||||
pub replying: Option<ChatMessageReference>,
|
pub replying: Option<ChatMessageReference>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ChatMessageEdit {
|
||||||
|
pub origin: ChatMessageReference,
|
||||||
|
pub author: ChatAuthor,
|
||||||
|
pub new_content: ChatMessageContent,
|
||||||
|
}
|
||||||
|
|
||||||
pub mod event;
|
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]
|
#[async_trait::async_trait]
|
||||||
pub trait Service {
|
pub trait Service {
|
||||||
|
@ -10,4 +10,9 @@ pub trait Service {
|
||||||
destination_channel: ChatReference,
|
destination_channel: ChatReference,
|
||||||
) -> Vec<ChatMessageReference>;
|
) -> Vec<ChatMessageReference>;
|
||||||
async fn delete_message(&mut self, message: &ChatMessageReference) -> bool;
|
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))
|
.send(ChatEvent::DeleteMessage(origin))
|
||||||
.expect("Failed to dispatch incoming Discord chat message deletion");
|
.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::{
|
use phoebe::{
|
||||||
mid_chat::{self, ChatMessage, ChatMessageReference, ChatReference},
|
mid_chat::{self, ChatMessage, ChatMessageEdit, ChatMessageReference, ChatReference},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
DynServiceLookup,
|
DynServiceLookup,
|
||||||
};
|
};
|
||||||
|
@ -93,4 +93,14 @@ impl Service for DiscordService {
|
||||||
assert_eq!(message.channel.service, "discord");
|
assert_eq!(message.channel.service, "discord");
|
||||||
sender::delete_discord_message(self, message).await.is_ok()
|
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::{
|
use phoebe::{
|
||||||
attachments::attachment_to_url,
|
attachments::attachment_to_url,
|
||||||
mid_chat::{ChatMessage, ChatMessageReference, ChatReference},
|
mid_chat::{ChatMessage, ChatMessageEdit, ChatMessageReference, ChatReference},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -137,6 +137,7 @@ pub async fn send_discord_message(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let content = format!(
|
let content = format!(
|
||||||
"{} ({}): {}",
|
"{} ({}): {}",
|
||||||
source.author.display_name,
|
source.author.display_name,
|
||||||
|
@ -182,3 +183,37 @@ pub async fn delete_discord_message(
|
||||||
channel_id.delete_message(&discord.ctx, message_id).await?;
|
channel_id.delete_message(&discord.ctx, message_id).await?;
|
||||||
Ok(())
|
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