diff options
author | Ashelyn Rose <git@ashen.earth> | 2025-02-28 21:52:16 -0700 |
---|---|---|
committer | Ashelyn Rose <git@ashen.earth> | 2025-02-28 21:52:16 -0700 |
commit | e9253bd959bf5bf6e8bcc6de4db247895b015a16 (patch) | |
tree | 1817aed80c8255d1292007a81e7f0a16138d25cc /src/system/plugin | |
parent | 5cb49a76c2cedb500b82f405af3cf1dcc0507f98 (diff) |
Partial refactor
Handles message prefixes and autoproxy
Diffstat (limited to 'src/system/plugin')
-rw-r--r-- | src/system/plugin/autoproxy.rs | 143 | ||||
-rw-r--r-- | src/system/plugin/prefixes.rs | 40 |
2 files changed, 183 insertions, 0 deletions
diff --git a/src/system/plugin/autoproxy.rs b/src/system/plugin/autoproxy.rs new file mode 100644 index 0000000..cd24e0b --- /dev/null +++ b/src/system/plugin/autoproxy.rs @@ -0,0 +1,143 @@ +use async_trait::async_trait; +use std::sync::Arc; +use tokio::sync::Mutex; +use twilight_model::{channel::{Channel, Message}, id::{marker::ChannelMarker, Id}, util::Timestamp}; +use crate::system::types::{System, Member, Response}; +use super::{CommandOutcome, SeancePlugin}; +use tokio::time::sleep; +use std::time::Duration; + +pub struct Autoproxy { + current_state: Arc<Mutex<InnerState>>, +} + +#[derive(Clone)] +enum InnerState { + Off, + LatchActive { current_member: Member, last_message: Timestamp }, + LatchInactive, + Member { current_member: Member }, +} + +impl Autoproxy { + pub fn new() -> Self { + Self { + current_state: Arc::new(Mutex::new(InnerState::Off)) + } + } +} + +#[async_trait] +impl SeancePlugin for Autoproxy { + async fn handle_command(&self, system: &System, message: &Message) -> CommandOutcome { + if message.content.starts_with(format!("{}auto ", system.command_prefix).as_str()) { + let args = message.content.replace(format!("{}auto ", system.command_prefix).as_str(), ""); + let mut remainder = args.split_whitespace(); + let first_word = remainder.next(); + + match first_word { + Some("off") => *self.current_state.lock().await = InnerState::Off, + Some("latch") => *self.current_state.lock().await = InnerState::LatchInactive, + Some("member") => { + return CommandOutcome::Errored { message: "Member mode not supported yet".to_string() } + }, + Some(other) => return CommandOutcome::Errored { message: format!("Unknown autoproxy mode: {other}") }, + None => return CommandOutcome::Errored { message: "Must specify autoproxy mode".to_string() }, + } + + CommandOutcome::Handled + } else { + CommandOutcome::Skipped + } + } + + async fn handle_message(&self, system: &System, message: &Message, response: &mut Response) { + if message.content.starts_with("\\") { + if message.content.starts_with("\\\\") { + if let InnerState::LatchActive {current_member: _, last_message: _} = {self.current_state.lock().await.clone()} { + {*self.current_state.lock().await = InnerState::LatchInactive}; + } + } + + *response = Response::Noop { delete_source: message.content == "\\\\" }; + return + } + + if let Response::Noop { delete_source: _ } = response { + let current_state = {self.current_state.lock().await.clone()}; + match current_state { + InnerState::Off => return, + InnerState::LatchInactive => return, + InnerState::Member { current_member } => { + *response = Response::Proxy { + member: current_member.clone(), + content: message.content.clone(), + } + }, + InnerState::LatchActive { current_member, last_message: _ } => { + *response = Response::Proxy { + member: current_member.clone(), + content: message.content.clone(), + } + }, + } + + } + } + + async fn post_response(&self, system: &System, message: &Message, channel: Id<ChannelMarker>, response: &Response) { + match response { + Response::Noop { delete_source } => return, + Response::Proxy { member, content } => { + let current_state = {self.current_state.lock().await.clone()}; + match current_state { + InnerState::Off => return, + InnerState::Member { current_member } => return, + InnerState::LatchInactive => { + {*self.current_state.lock().await = InnerState::LatchActive { + current_member: member.clone(), + last_message: message.timestamp, + }}; + + let state_arc = self.current_state.clone(); + let sent_member = member.clone(); + let sent_timestamp = message.timestamp.clone(); + + tokio::spawn(async move { + sleep(Duration::from_secs(15 * 60)).await; + let current_state = {state_arc.lock().await.clone()}; + + if let InnerState::LatchActive { current_member, last_message } = current_state { + if sent_member.discord_token == current_member.discord_token && sent_timestamp.as_micros() == last_message.as_micros() { + {*state_arc.lock().await = InnerState::LatchInactive}; + } + } + }); + }, + InnerState::LatchActive { current_member: _, last_message: _ } => { + {*self.current_state.lock().await = InnerState::LatchActive { + current_member: member.clone(), + last_message: message.timestamp, + }}; + + let state_arc = self.current_state.clone(); + let sent_member = member.clone(); + let sent_timestamp = message.timestamp.clone(); + + tokio::spawn(async move { + sleep(Duration::from_secs(15 * 60)).await; + let current_state = {state_arc.lock().await.clone()}; + + if let InnerState::LatchActive { current_member, last_message } = current_state { + if sent_member.discord_token == current_member.discord_token && sent_timestamp.as_micros() == last_message.as_micros() { + {*state_arc.lock().await = InnerState::LatchInactive}; + } + } + }); + }, + } + }, + } + + } +} diff --git a/src/system/plugin/prefixes.rs b/src/system/plugin/prefixes.rs new file mode 100644 index 0000000..a513573 --- /dev/null +++ b/src/system/plugin/prefixes.rs @@ -0,0 +1,40 @@ +use async_trait::async_trait; +use twilight_model::id::{marker::ChannelMarker, Id}; +use crate::system::types::Response; + +use super::{CommandOutcome, SeancePlugin}; + +pub struct ProxyPrefixes; + +#[async_trait] +impl SeancePlugin for ProxyPrefixes { + async fn handle_command(&self, _system: &crate::system::types::System, _message: &twilight_model::channel::Message) -> CommandOutcome { + CommandOutcome::Skipped + } + + async fn handle_message(&self, system: &crate::system::types::System, message: &twilight_model::channel::Message, response: &mut crate::system::types::Response) { + if let Response::Noop { delete_source: _ } = response { + for member in &system.members { + println!("Checking member prefix: {:?}", member.message_pattern); + match member.message_pattern.captures(message.content.as_str()) { + None => { + println!("Nope"); + continue; + }, + Some(captures) => match captures.name("content") { + None => continue, + Some(matched_content) => { + println!("Matched member prefix: {:?}", member.message_pattern); + *response = Response::Proxy { member: member.clone(), content: matched_content.as_str().to_string() }; + return + }, + } + } + } + } + } + + async fn post_response(&self, _system: &crate::system::types::System, _message: &twilight_model::channel::Message, _channel: Id<ChannelMarker>, _response: &crate::system::types::Response) { + return + } +} |