diff options
author | Ashelyn Rose <git@ashen.earth> | 2025-03-01 16:35:00 -0700 |
---|---|---|
committer | Ashelyn Rose <git@ashen.earth> | 2025-03-01 16:35:00 -0700 |
commit | 38be251b5f4ed4dabe21753451e23c233b62b6dd (patch) | |
tree | 565952fb5bd371b88c38af2e8ad7fe7bded6ed99 | |
parent | 04bbe74642f5b6257361014e0c122a33c9fa4d70 (diff) |
autoproxy: member mode
Also adds method for system to resolve mentions to system members
-rw-r--r-- | src/system/aggregator.rs | 14 | ||||
-rw-r--r-- | src/system/mod.rs | 9 | ||||
-rw-r--r-- | src/system/plugin/autoproxy.rs | 10 | ||||
-rw-r--r-- | src/system/types.rs | 21 |
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 + } +} |