summary refs log tree commit diff
diff options
context:
space:
mode:
authorAshelyn Rose <git@ashen.earth>2025-03-01 20:16:27 -0700
committerAshelyn Rose <git@ashen.earth>2025-03-01 20:16:27 -0700
commit0d54c17faa6b09f52fe9c1dcc23dc4edd02b3286 (patch)
treedd5d0d3c375f92b8fbe6d48fc3c93d7c827ed582
parent2cd846913aaba03dda8a6071ecc28c85c5a26fa4 (diff)
Better target message lookup plugin-architecture
-rw-r--r--src/system/plugin/edit.rs11
-rw-r--r--src/system/plugin/reproxy.rs12
-rw-r--r--src/system/types.rs74
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
+    }
 }