Implement message deletion
This commit is contained in:
parent
4c37ec5f36
commit
cee7a551d1
7 changed files with 90 additions and 9 deletions
|
@ -1,6 +1,7 @@
|
|||
use crate::ChatMessage;
|
||||
use crate::{ChatMessage, ChatMessageReference};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ChatEvent {
|
||||
NewMessage(ChatMessage),
|
||||
NewMessage(Box<ChatMessage>),
|
||||
DeleteMessage(ChatMessageReference),
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue