From cee7a551d14a035e6228013efa204ad768157811 Mon Sep 17 00:00:00 2001 From: videogame hacker Date: Sun, 17 Apr 2022 13:03:21 +0100 Subject: [PATCH] Implement message deletion --- mid-chat/src/event.rs | 5 ++-- phoebe-main/src/main.rs | 36 +++++++++++++++++++++++--- phoebe/src/lib.rs | 21 +++++++++++++++ phoebe/src/service.rs | 2 ++ services/phoebe-discord/src/handler.rs | 16 +++++++++++- services/phoebe-discord/src/lib.rs | 9 +++++-- services/phoebe-discord/src/sender.rs | 10 +++++++ 7 files changed, 90 insertions(+), 9 deletions(-) diff --git a/mid-chat/src/event.rs b/mid-chat/src/event.rs index 84f0f2b..ac87d4b 100644 --- a/mid-chat/src/event.rs +++ b/mid-chat/src/event.rs @@ -1,6 +1,7 @@ -use crate::ChatMessage; +use crate::{ChatMessage, ChatMessageReference}; #[derive(Debug, Clone)] pub enum ChatEvent { - NewMessage(ChatMessage), + NewMessage(Box), + DeleteMessage(ChatMessageReference), } diff --git a/phoebe-main/src/main.rs b/phoebe-main/src/main.rs index 7e15bef..fff7420 100644 --- a/phoebe-main/src/main.rs +++ b/phoebe-main/src/main.rs @@ -1,12 +1,13 @@ use color_eyre::Result; +use futures::{future, StreamExt}; use tracing::info; use tracing_subscriber::EnvFilter; use phoebe::{ - get_linked_channels, link_messages, + get_linked_channels, get_linked_messages, link_messages, prelude::{ChatEvent, SqlitePool}, service::Service, - DynServiceLookup, + unlink_message, DynServiceLookup, }; async fn handle_events( @@ -24,7 +25,7 @@ async fn handle_events( while let Ok(event) = rx.recv().await { match event { - phoebe::prelude::ChatEvent::NewMessage(message) => { + ChatEvent::NewMessage(message) => { let linked_channels = get_linked_channels(&mut conn, dyn_service, &message.origin.channel).await; @@ -45,6 +46,33 @@ async fn handle_events( } } } + + ChatEvent::DeleteMessage(origin) => { + let messages = if let Ok(message_stream) = + get_linked_messages(&mut conn, dyn_service, &origin).await + { + message_stream + .filter(|r| future::ready(r.channel.service == service.tag())) + .collect::>() + .await + } else { + vec![] + }; + + if !messages.is_empty() { + if let Err(e) = unlink_message(&mut conn, &origin).await { + tracing::error!("Failed to unlink origin message: {e}"); + } + + for message in messages { + if service.delete_message(&message).await { + if let Err(e) = unlink_message(&mut conn, &message).await { + tracing::error!("Failed to unlink related message: {e}"); + } + } + } + } + } } } } @@ -78,7 +106,7 @@ async fn main() -> Result<()> { .into_iter() .map(|srv| tokio::spawn(handle_events(dyn_service, db.clone(), srv, tx.subscribe()))); - let _ = futures::future::join_all(handles).await; + let _ = future::join_all(handles).await; Ok(()) } diff --git a/phoebe/src/lib.rs b/phoebe/src/lib.rs index f48db9a..4fa8da0 100644 --- a/phoebe/src/lib.rs +++ b/phoebe/src/lib.rs @@ -92,6 +92,27 @@ pub async fn link_messages( Ok(()) } +pub async fn unlink_message( + conn: &mut SqliteConnection, + message: &ChatMessageReference, +) -> sqlx::Result<()> { + let service = &message.channel.service; + let channel = &message.channel.id; + let message_id = &message.message_id; + let query = sqlx::query!( + "DELETE FROM messages WHERE service = ? AND channel = ? AND message = ?", + service, + channel, + message_id + ); + + if query.execute(&mut *conn).await?.rows_affected() == 0 { + return Err(sqlx::Error::RowNotFound); + } + + Ok(()) +} + pub async fn get_message_link_id( conn: &mut SqliteConnection, message: &ChatMessageReference, diff --git a/phoebe/src/service.rs b/phoebe/src/service.rs index 1a02dea..3c18025 100644 --- a/phoebe/src/service.rs +++ b/phoebe/src/service.rs @@ -3,9 +3,11 @@ use mid_chat::{ChatMessage, ChatMessageReference, ChatReference}; #[async_trait::async_trait] pub trait Service { fn tag(&self) -> &'static str; + async fn send_chat_message( &mut self, source: &ChatMessage, destination_channel: ChatReference, ) -> Vec; + async fn delete_message(&mut self, message: &ChatMessageReference) -> bool; } diff --git a/services/phoebe-discord/src/handler.rs b/services/phoebe-discord/src/handler.rs index 00f4563..c8cf85c 100644 --- a/services/phoebe-discord/src/handler.rs +++ b/services/phoebe-discord/src/handler.rs @@ -91,7 +91,21 @@ impl EventHandler for DiscordHandler { let _ = self .chat_event_tx - .send(ChatEvent::NewMessage(chat_message)) + .send(ChatEvent::NewMessage(Box::new(chat_message))) .expect("Failed to dispatch incoming Discord chat message"); } + + async fn message_delete( + &self, + _ctx: Context, + channel_id: ChannelId, + deleted_message_id: MessageId, + _guild_id: Option, + ) { + let origin = ChatMessageReference::new(discord_reference(channel_id), deleted_message_id); + let _ = self + .chat_event_tx + .send(ChatEvent::DeleteMessage(origin)) + .expect("Failed to dispatch incoming Discord chat message deletion"); + } } diff --git a/services/phoebe-discord/src/lib.rs b/services/phoebe-discord/src/lib.rs index c87cfce..ab2db5f 100644 --- a/services/phoebe-discord/src/lib.rs +++ b/services/phoebe-discord/src/lib.rs @@ -72,6 +72,10 @@ pub async fn setup( #[async_trait] impl Service for DiscordService { + fn tag(&self) -> &'static str { + "discord" + } + async fn send_chat_message( &mut self, source: &ChatMessage, @@ -85,7 +89,8 @@ impl Service for DiscordService { .collect() } - fn tag(&self) -> &'static str { - "discord" + async fn delete_message(&mut self, message: &ChatMessageReference) -> bool { + assert_eq!(message.channel.service, "discord"); + sender::delete_discord_message(self, message).await.is_ok() } } diff --git a/services/phoebe-discord/src/sender.rs b/services/phoebe-discord/src/sender.rs index 45130f8..7c478df 100644 --- a/services/phoebe-discord/src/sender.rs +++ b/services/phoebe-discord/src/sender.rs @@ -161,3 +161,13 @@ pub async fn send_discord_message( sent_message.id, )) } + +pub async fn delete_discord_message( + discord: &mut DiscordService, + message: &ChatMessageReference, +) -> Result<()> { + let channel_id = message.channel.id.parse::()?; + let message_id: MessageId = message.message_id.parse::()?.into(); + channel_id.delete_message(&discord.ctx, message_id).await?; + Ok(()) +}