Implement message deletion

This commit is contained in:
Charlotte Som 2022-04-17 13:03:21 +01:00
parent 4c37ec5f36
commit cee7a551d1
7 changed files with 90 additions and 9 deletions

View file

@ -1,6 +1,7 @@
use crate::ChatMessage;
use crate::{ChatMessage, ChatMessageReference};
#[derive(Debug, Clone)]
pub enum ChatEvent {
NewMessage(ChatMessage),
NewMessage(Box<ChatMessage>),
DeleteMessage(ChatMessageReference),
}

View file

@ -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::<Vec<_>>()
.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(())
}

View file

@ -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,

View file

@ -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<ChatMessageReference>;
async fn delete_message(&mut self, message: &ChatMessageReference) -> bool;
}

View file

@ -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<GuildId>,
) {
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");
}
}

View file

@ -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()
}
}

View file

@ -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::<ChannelId>()?;
let message_id: MessageId = message.message_id.parse::<u64>()?.into();
channel_id.delete_message(&discord.ctx, message_id).await?;
Ok(())
}