diff options
-rw-r--r-- | src/system/plugin/edit.rs | 11 | ||||
-rw-r--r-- | src/system/plugin/reproxy.rs | 12 | ||||
-rw-r--r-- | src/system/types.rs | 74 |
3 files changed, 77 insertions, 20 deletions
diff --git a/src/system/plugin/edit.rs b/src/system/plugin/edit.rs index 2edc504..1fd4e23 100644 --- a/src/system/plugin/edit.rs +++ b/src/system/plugin/edit.rs @@ -24,16 +24,7 @@ impl<'system> SeancePlugin<'system> for Edit { } async fn handle_command<'message>(&self, logger: &'system Logger, system: &'system System, message: &'message Message, command: PluginCommand, args: Vec<&'message str>) { - let most_recent_message = system.get_most_recent_message(message.channel_id).await; - - if let Some((edit_target, update_most_recent)) = match message.kind { - twilight_model::channel::message::MessageType::Regular => most_recent_message.map(|(message, _)| (message, true)), - twilight_model::channel::message::MessageType::Reply => async {Some(( - message.referenced_message.as_ref()?.as_ref().clone(), - message.referenced_message.as_ref()?.id == most_recent_message?.0.id - ))}.await, - _ => todo!(), - } { + if let Some((edit_target, update_most_recent)) = system.resolve_message_target(message).await { if let Some(authoring_member) = system.get_member_by_id(edit_target.author.id).await { if let Some(edit_contents) = match command { PluginCommand::Word("edit") => Some(args.join(" ")), diff --git a/src/system/plugin/reproxy.rs b/src/system/plugin/reproxy.rs index 145bed8..30b0c93 100644 --- a/src/system/plugin/reproxy.rs +++ b/src/system/plugin/reproxy.rs @@ -27,19 +27,11 @@ impl<'system> SeancePlugin<'system> for Reproxy { async fn handle_message<'message>(&self, logger: &'system Logger, system: &'system System, message: &'message Message, response: &'message mut Response) { if let Response::Proxy { member, content } = response { if content.as_str().trim() == "*" { - let most_recent_message = system.get_most_recent_message(message.channel_id).await; - if let Some((reproxy_target, update_most_recent)) = match message.kind { - twilight_model::channel::message::MessageType::Regular => most_recent_message.map(|(message, _)| (message, true)), - twilight_model::channel::message::MessageType::Reply => async {Some(( - message.referenced_message.as_ref()?.as_ref().clone(), - message.referenced_message.as_ref()?.id == most_recent_message?.0.id - ))}.await, - _ => todo!(), - } { + if let Some((reproxy_target, is_most_recent)) = system.resolve_message_target(message).await { if let Ok(new_message) = util::duplicate_message(&member.client, &reproxy_target, reproxy_target.content.as_str()).await { let _ = {member.client.lock().await.delete_message(reproxy_target.channel_id, reproxy_target.id).await}; - if update_most_recent { + if is_most_recent { system.cache_most_recent_message(new_message.channel_id, new_message, member.clone()).await; } diff --git a/src/system/types.rs b/src/system/types.rs index aaef165..2acf156 100644 --- a/src/system/types.rs +++ b/src/system/types.rs @@ -6,6 +6,7 @@ use twilight_model::channel::Message; use twilight_model::id::{marker::{ChannelMarker, UserMarker}, Id}; use std::{collections::HashMap, sync::Arc}; use tokio::sync::Mutex; +use futures::future::join_all; #[derive(Clone)] pub struct Member { @@ -68,4 +69,77 @@ impl System { pub async fn get_most_recent_message(&self, channel: Id<ChannelMarker>) -> Option<(Message, Member)> { self.message_cache.lock().await.get(&channel).map(|(member, message)| (message.clone(), member.clone())) } + + // Returns either the most recent message or replied message, with bool to indicate + // if it was the most recent message (and the cache should be updated if that's modified) + pub async fn resolve_message_target(&self, message: &Message) -> Option<(Message, bool)> { + let most_recent_message = self.get_most_recent_message(message.channel_id).await; + + if let Some(result) = async { + match message.kind { + twilight_model::channel::message::MessageType::Regular => Some((most_recent_message?.0, true)), + twilight_model::channel::message::MessageType::Reply => Some(( + message.referenced_message.as_ref()?.as_ref().clone(), + message.referenced_message.as_ref()?.id == most_recent_message?.0.id + )), + _ => return None, + } + }.await { + return Some(result) + } else { + let member_ids = join_all(self.members.iter().map(|member| async { + member.user_id.lock().await.clone() + })).await.iter().filter_map(|opt| *opt).collect::<Vec<_>>(); + + for member in &self.members { + let client = member.client.lock().await; + + let lookup: Result<Vec<Message>, LookupError> = async { + Ok(client + .channel_messages(message.channel_id) + .limit(10)? + .await? + .model() + .await? + ) + }.await; + + if let Ok(recent_messages) = lookup { + let recent_message = recent_messages.into_iter().find( + |message| member_ids.contains(&message.author.id) + ); + + if let Some(most_recent_message) = recent_message { + return Some((most_recent_message, true)) + } else { + // Successful lookup, but no recent messages, there's no point + // checking with the other members + return None + } + } + } + + None + } + } +} + +struct LookupError; + +impl From<twilight_validate::request::ValidationError> for LookupError { + fn from(_value: twilight_validate::request::ValidationError) -> Self { + Self + } +} + +impl From<twilight_http::Error> for LookupError { + fn from(_value: twilight_http::Error) -> Self { + Self + } +} + +impl From<twilight_http::response::DeserializeBodyError> for LookupError { + fn from(_value: twilight_http::response::DeserializeBodyError) -> Self { + Self + } } |