summary refs log tree commit diff
diff options
context:
space:
mode:
authorAshelyn Rose <git@ashen.earth>2025-03-01 16:35:00 -0700
committerAshelyn Rose <git@ashen.earth>2025-03-01 16:35:00 -0700
commit38be251b5f4ed4dabe21753451e23c233b62b6dd (patch)
tree565952fb5bd371b88c38af2e8ad7fe7bded6ed99
parent04bbe74642f5b6257361014e0c122a33c9fa4d70 (diff)
autoproxy: member mode
Also adds method for system to resolve mentions to system members
-rw-r--r--src/system/aggregator.rs14
-rw-r--r--src/system/mod.rs9
-rw-r--r--src/system/plugin/autoproxy.rs10
-rw-r--r--src/system/types.rs21
4 files changed, 44 insertions, 10 deletions
diff --git a/src/system/aggregator.rs b/src/system/aggregator.rs
index 552ea8e..f73dec5 100644
--- a/src/system/aggregator.rs
+++ b/src/system/aggregator.rs
@@ -1,7 +1,7 @@
 use lru::LruCache;
 use std::num::NonZeroUsize;
 use tokio::sync::mpsc::{channel, Receiver};
-use twilight_model::{util::Timestamp, channel::Message, gateway::payload::incoming::MessageUpdate, id::{marker::MessageMarker, Id}};
+use twilight_model::{channel::Message, gateway::payload::incoming::MessageUpdate, id::{marker::{MessageMarker, UserMarker}, Id}, util::Timestamp};
 use crate::system::types::System;
 
 type DiscordToken = String;
@@ -15,7 +15,7 @@ enum IncomingMessage {
 
 pub enum MemberEvent {
     Message(Message, DiscordToken),
-    GatewayConnect(DiscordToken),
+    GatewayConnect(DiscordToken, Id<UserMarker>),
     GatewayDisconnect(DiscordToken),
     GatewayError(DiscordToken),
 }
@@ -46,7 +46,7 @@ impl MessageAggregator {
                             }
                         },
                         Ok(twilight_gateway::Event::Ready(ready)) => {
-                            let _ = outgoing_channel.send(MemberEvent::GatewayConnect(member.discord_token.clone())).await;
+                            let _ = outgoing_channel.send(MemberEvent::GatewayConnect(member.discord_token.clone(), ready.user.id)).await;
                         },
                         Ok(twilight_gateway::Event::MessageCreate(message)) => {
                             if message.author.id == followed_user {
@@ -84,23 +84,23 @@ impl MessageAggregator {
                     Some(IncomingMessage::Complete { message, timestamp, seen_by }) => {
                         if let None = message_cache.get(&message.id) {
                             message_cache.put(message.id.clone(), (message.clone(), timestamp, seen_by.clone()));
-                            sender.send(MemberEvent::Message(message, seen_by)).await;
+                            let _ = sender.send(MemberEvent::Message(message, seen_by)).await;
                         }
                         
                     },
                     Some(IncomingMessage::Partial { message, timestamp, seen_by }) => {
-                        if let Some((previous_message, previous_timestamp, previously_seen_by)) = message_cache.get(&message.id) {
+                        if let Some((previous_message, previous_timestamp, _)) = message_cache.get(&message.id) {
                             if previous_timestamp.as_micros() < timestamp.as_micros() {
                                 let mut updated_message = previous_message.clone();
                                 updated_message.content = message.content.unwrap_or(updated_message.content);
                                 message_cache.put(message.id.clone(), (updated_message.clone(), timestamp, seen_by.clone()));
-                                sender.send(MemberEvent::Message(updated_message, seen_by)).await;
+                                let _ = sender.send(MemberEvent::Message(updated_message, seen_by)).await;
                             }
                         } else {
                             let client = system.members.iter().find(|m| m.discord_token == seen_by).map(|m| m.client.clone()).expect("Could not find client");
                             if let Ok(updated_message) = client.lock().await.message(message.channel_id, message.id).await.unwrap().model().await.map(|r|r.clone()) {
                                 message_cache.put(message.id.clone(), (updated_message.clone(), timestamp, seen_by.clone()));
-                                sender.send(MemberEvent::Message(updated_message, seen_by)).await;
+                                let _ = sender.send(MemberEvent::Message(updated_message, seen_by)).await;
                             };
                         }
 
diff --git a/src/system/mod.rs b/src/system/mod.rs
index 0f5f23c..4eea408 100644
--- a/src/system/mod.rs
+++ b/src/system/mod.rs
@@ -25,7 +25,9 @@ impl Manager {
             followed_user: NonZeroU64::try_from(system_config.reference_user_id.parse::<u64>().unwrap()).unwrap().into(),
             command_prefix: "!".to_string(),
             members: system_config.members.iter().map(|member| Member {
+                name: member.name.clone(),
                 discord_token: member.discord_token.clone(),
+                user_id: Arc::new(Mutex::new(None)),
                 message_pattern: member.message_pattern.clone(),
                 shard: Arc::new(Mutex::new(Shard::new(
                     ShardId::ONE,
@@ -44,7 +46,12 @@ impl Manager {
         'member_event: loop {
             match message_receiver.recv().await {
                 None => (),
-                Some(MemberEvent::GatewayConnect(member_token)) => {
+                Some(MemberEvent::GatewayConnect(member_token, user_id)) => {
+                    for member in &system.members {
+                        if member.discord_token == member_token {
+                            {*member.user_id.lock().await = Some(user_id)};
+                        }
+                    }
                     logger.log_connect(member_token).await;
                 },
                 Some(MemberEvent::GatewayError(member_token)) => {
diff --git a/src/system/plugin/autoproxy.rs b/src/system/plugin/autoproxy.rs
index 0bbebf5..58f9668 100644
--- a/src/system/plugin/autoproxy.rs
+++ b/src/system/plugin/autoproxy.rs
@@ -42,7 +42,13 @@ impl<'system> SeancePlugin<'system> for Autoproxy {
             Some("off") => *self.current_state.lock().await = InnerState::Off,
             Some("latch") => *self.current_state.lock().await = InnerState::LatchInactive,
             Some("member") => {
-                logger.log_err(None, "Member mode not supported yet".to_string()).await;
+                let mention = args.next();
+                if let Some(member) = system.resolve_mention(mention).await {
+                    logger.log_line(Some(member.discord_token.clone()), "Setting member autoproxy".to_string()).await;
+                    {*self.current_state.lock().await = InnerState::Member { current_member: member.clone() }};
+                } else {
+                    logger.log_err(None, format!("Unknown user: {}", mention.unwrap_or("[empty string]"))).await;
+                }
             },
             Some(other) => {
                 logger.log_err(None, format!("Unknown autoproxy mode: {other}")).await;
@@ -104,7 +110,7 @@ impl<'system> SeancePlugin<'system> for Autoproxy {
                 let current_state = {self.current_state.lock().await.clone()};
                 match current_state {
                     InnerState::Off => return,
-                    InnerState::Member { current_member } => return,
+                    InnerState::Member { current_member: _ } => return,
                     InnerState::LatchInactive => {
                         logger.log_line(Some(member.discord_token.clone()), "Setting autoproxy latch".to_string()).await;
                         {*self.current_state.lock().await = InnerState::LatchActive {
diff --git a/src/system/types.rs b/src/system/types.rs
index bd1e40f..c4da066 100644
--- a/src/system/types.rs
+++ b/src/system/types.rs
@@ -1,13 +1,16 @@
 use regex::Regex;
 use twilight_http::Client;
 use twilight_gateway::Shard;
+use twilight_mention::ParseMention;
 use twilight_model::id::{marker::UserMarker, Id};
 use std::sync::Arc;
 use tokio::sync::Mutex;
 
 #[derive(Clone)]
 pub struct Member {
+    pub name: String,
     pub discord_token: String,
+    pub user_id: Arc<Mutex<Option<Id<UserMarker>>>>,
     pub message_pattern: Regex,
     pub shard: Arc<Mutex<Shard>>,
     pub client: Arc<Mutex<Client>>,
@@ -32,3 +35,21 @@ pub enum SystemThreadCommand {
     ShutdownSystem,
     ShutdownAll,
 }
+
+impl System {
+    pub async fn resolve_mention<'system>(&'system self, maybe_mention: Option<&str>) -> Option<&'system Member> {
+        if let Some(mention) = maybe_mention {
+            if let Ok(mention) = Id::<UserMarker>::parse(mention) {
+                for member in &self.members {
+                    let is_member = {member.user_id.lock().await.map(|id| id == mention).unwrap_or(false)};
+
+                    if is_member {
+                        return Some(&member)
+                    }
+                }
+            }
+        }
+
+        None
+    }
+}