diff --git a/forcebot_core/src/bin/fun_bot.rs b/forcebot_core/src/bin/fun_bot.rs index 872aff9..483177c 100644 --- a/forcebot_core/src/bin/fun_bot.rs +++ b/forcebot_core/src/bin/fun_bot.rs @@ -1,9 +1,10 @@ //! WIP Fun forcebot with catered customizations #todo //! //! Custom modules that can be managed in chat through `disable` and `enable` commands -//! - `besty` +//! - `besty` - uses a custom prefix tp trigger //! - `guests` //! - `pyramid` +//! - `quiet` //! //! //! Be sure the followig is defined in `.env` @@ -18,7 +19,7 @@ //! - More Info - <https://dev.twitch.tv/docs/authentication> // use forcebot_rs_v2::{custom_mods::{guest_badge, pyramid}, Bot}; -use forcebot_core::{custom_mods::{debug, guest_badge, pyramid}, Bot}; +use forcebot_core::{custom_mods::{debug, guest_badge, pyramid, quiet}, Bot}; @@ -35,6 +36,7 @@ pub async fn main() { bot.load_module(guest_badge::create_module()).await; bot.load_module(pyramid::create_module()).await; bot.load_module(debug::create_module()).await; + bot.load_module(quiet::create_module()).await; /* 3. Run the bot */ bot.run().await; @@ -45,7 +47,7 @@ pub async fn main() { pub mod funbot_objs { use std::sync::Arc; - use forcebot_core::{execution_async, modules::Status, Badge, Bot, Command, Module}; + use forcebot_core::{execution_async, Badge, Bot, Command, Module}; use twitch_irc::message::ServerMessage; /// Create a Module with a loaded Command object @@ -55,7 +57,7 @@ pub mod funbot_objs { "Now Aware of besty xdd666 ".to_string()); custom_mod.load_command(create_cmd_test()); - custom_mod.set_status_by_default(Status::Disabled); + // custom_mod.set_status_by_default(Status::Disabled); custom_mod } diff --git a/forcebot_core/src/botcore/bot.rs b/forcebot_core/src/botcore/bot.rs index 9e3070f..e8a4d04 100644 --- a/forcebot_core/src/botcore/bot.rs +++ b/forcebot_core/src/botcore/bot.rs @@ -41,7 +41,9 @@ pub struct Bot chatter_guest_badges: Mutex<Vec<(String,String,Badge,Instant,Duration)>>, /// Message cache message_cache: Mutex<Vec<PrivmsgMessage>>, - // message_cache: Vec<PrivmsgMessage> + /// channel_quiet + channel_quiet_yn: RwLock<Vec<(String,RwLock<bool>)>>, + } @@ -118,6 +120,7 @@ impl Bot channel_module_status: RwLock::new(vec![]), chatter_guest_badges: Mutex::new(vec![]), message_cache : Mutex::new(vec![]), + channel_quiet_yn : RwLock::new(vec![]), }; for cmd in built_in_objects::create_commands() { @@ -183,14 +186,13 @@ impl Bot // dbg!("try cms read"); let cms_lock = bot.channel_module_status.read().unwrap(); - // dbg!("cms read lock"); - // dbg!(module.get_names()); + for channel_flags in cms_lock.iter() { if channel_flags.0 == channel { if module.get_names().contains(&channel_flags.1) && channel_flags.2 == Status::Disabled { continue 'module_loop; - // disabled_mods.push(module); + } } } @@ -202,7 +204,6 @@ impl Bot } - for module in get_enabled_channel_modules(bot.clone(), msg.clone().channel_login) { @@ -224,12 +225,8 @@ impl Bot } } - - - } else {} ; - } drop(in_msgs_lock); }); @@ -360,13 +357,11 @@ impl Bot if !found_disabled { - // self.channel_module_status. - // dbg!("try cms write"); /*,self.channel_module_status */ + let mut cms_lock = self.channel_module_status.write().unwrap(); - // cms_lock. - // dbg!("cms write lock"); + cms_lock.push((channel,module.clone(),Status::Disabled)); - // dbg!(module.clone()); + drop(cms_lock); @@ -434,6 +429,39 @@ impl Bot rslt } + /// Get the quiet status of a channel + pub fn get_channel_quiet(&self,channel:String) -> bool { + for a in self.channel_quiet_yn.read().unwrap().iter() { + if a.0 == channel { + return a.1.read().unwrap().clone(); + } + } + return false; + } + + /// Get the quiet status of a channel + pub fn set_channel_quiet(&self,channel:String,quiet_on:bool) { + let mut found = false; + + let chnlquiet = self.channel_quiet_yn.read().unwrap(); + for rec in chnlquiet.iter() { + if rec.0 == channel { + found = true; + let mut status = rec.1.write().unwrap(); + *status = quiet_on; + drop(status); + } + } + drop(chnlquiet); + + if !found { + // dbg!("set chn quiet > !found channel quiet status"); + let mut chnlquiet = self.channel_quiet_yn.write().unwrap(); + chnlquiet.push((channel,RwLock::new(quiet_on))); + drop(chnlquiet); + } + + } } diff --git a/forcebot_core/src/botcore/bot_objects/command.rs b/forcebot_core/src/botcore/bot_objects/command.rs index 54c4b85..7095ca5 100644 --- a/forcebot_core/src/botcore/bot_objects/command.rs +++ b/forcebot_core/src/botcore/bot_objects/command.rs @@ -188,18 +188,17 @@ impl Command (cmd.custom_cond_fn)(bot.clone(),message.clone()) && (cmd.custom_cond_async)(bot,message).await } - // dbg!(msg.clone()); + fn quiet_off_ok(cmd:&Command,bot:Arc<Bot>,message:PrivmsgMessage) -> bool { + !bot.get_channel_quiet(message.channel_login.clone()) + || bot.get_channel_quiet(message.channel_login.clone()) && cmd.commands.contains(&("quiet off".to_string())) + } - // dbg!(caller_badge_ok(self, bot.clone(), msg.clone())); - // dbg!(cmd_called(self, bot.clone(), msg.clone()) && - // caller_badge_ok(self, bot.clone(), msg.clone()) && - // admin_only_ok(self, bot.clone(), msg.clone()) && - // custom_cond_ok(self, bot.clone(), msg.clone())); cmd_called(self, bot.clone(), msg.clone()) && caller_badge_ok(self, bot.clone(), msg.clone()).await && admin_only_ok(self, bot.clone(), msg.clone()) && - custom_cond_ok(self, bot, msg).await + custom_cond_ok(self, bot.clone(), msg.clone()).await && + quiet_off_ok(self, bot, msg) } diff --git a/forcebot_core/src/botcore/bot_objects/listener.rs b/forcebot_core/src/botcore/bot_objects/listener.rs index 84bd468..2895acb 100644 --- a/forcebot_core/src/botcore/bot_objects/listener.rs +++ b/forcebot_core/src/botcore/bot_objects/listener.rs @@ -1,7 +1,10 @@ use std::sync::Arc; +// use tokio::sync::Mutex; use twitch_irc::message::ServerMessage; +use crate::Module; + use super::{execution_async,Bot,listener_condition_async}; use super::{ExecBody, ListenerTrigger}; @@ -27,6 +30,7 @@ pub struct Listener trigger_cond_async : Arc<ListenerTrigger> , /// execution body exec_fn : Arc<ExecBody>, + parent_module : Arc<Option<Module>>, } impl Listener @@ -50,6 +54,7 @@ impl Listener trigger_cond_fn : |_:Arc<Bot>,_:ServerMessage| true, trigger_cond_async : Arc::new(listener_condition_async(condition01)), exec_fn : Arc::new(execution_async(execbody)), + parent_module : Arc::new(None), } } @@ -103,14 +108,41 @@ impl Listener /// checks if the trigger condition is met pub async fn cond_triggered(&self,bot:Arc<Bot>,msg:ServerMessage) -> bool { - let list = Arc::new(self); - (list.trigger_cond_fn)(bot.clone(),msg.clone()) && (list.trigger_cond_async)(bot,msg).await + + let list = Arc::new(self.clone()); + + async fn defined_conditions_ok(list:Arc<Listener>,bot:Arc<Bot>,msg:ServerMessage) -> bool { + // let list = Arc::new(self); + (list.trigger_cond_fn)(bot.clone(),msg.clone()) && (list.trigger_cond_async)(bot,msg).await + } + + fn quiet_off_ok(list:Arc<Listener>,bot:Arc<Bot>,message:ServerMessage) -> bool { + if let ServerMessage::Privmsg(msg) = message { + + if let Some(parent_mod) = &*list.parent_module { + return !bot.get_channel_quiet(msg.channel_login) || parent_mod.get_names().contains(&"debug".to_string()); + } + + return !bot.get_channel_quiet(msg.channel_login) ; + } + return true; /* quiet is off for non chat msgs */ + } + + defined_conditions_ok(list.clone(), bot.clone(), msg.clone()).await && + quiet_off_ok(list, bot, msg) } /// executes the listeners executon body pub async fn execute_fn(&self,bot:Arc<Bot>,msg:ServerMessage) -> Result<String, String> { - // (self.exec_fn)(bot,msg) + (self.exec_fn)(bot,msg).await } + + /// sets parent module + pub fn set_parent_module(&mut self,module:Module) { + self.parent_module = Arc::new(Some(module)); + } + + } diff --git a/forcebot_core/src/botcore/modules.rs b/forcebot_core/src/botcore/modules.rs index 889cf9e..d3802b5 100644 --- a/forcebot_core/src/botcore/modules.rs +++ b/forcebot_core/src/botcore/modules.rs @@ -1,4 +1,6 @@ +// use std::sync::{Arc, Mutex}; + use super::bot_objects::command::Command; use super::bot_objects::listener::Listener; @@ -40,13 +42,14 @@ impl Module } /// Loads a `Listener` into the module - pub fn load_listener(&mut self,l : Listener) { + pub fn load_listener(&mut self,mut l : Listener) { + l.set_parent_module(self.clone()); self.listeners.push(l); } /// Loads a `Command` into the module pub fn load_command(&mut self,c : Command) { - self.commands.push(c); + self.commands.push(c); } pub fn get_listeners(&self) -> Vec<Listener> { diff --git a/forcebot_core/src/custom_mods.rs b/forcebot_core/src/custom_mods.rs index f295b1e..49848a1 100644 --- a/forcebot_core/src/custom_mods.rs +++ b/forcebot_core/src/custom_mods.rs @@ -1,3 +1,4 @@ pub mod guest_badge; pub mod pyramid; -pub mod debug; \ No newline at end of file +pub mod debug; +pub mod quiet; \ No newline at end of file diff --git a/forcebot_core/src/custom_mods/debug.rs b/forcebot_core/src/custom_mods/debug.rs index df5b321..4bbfc73 100644 --- a/forcebot_core/src/custom_mods/debug.rs +++ b/forcebot_core/src/custom_mods/debug.rs @@ -1,15 +1,9 @@ -use std::sync::{Arc}; +use std::sync::Arc; use crate::{execution_async, modules::Status, Bot, Command, Listener, Module}; use twitch_irc::message::ServerMessage; -// use lazy_static::lazy_static; - -// lazy_static!{ -// /// Listener per channel (channel:String,Listener) -// pub static ref LISTENER_PER_CHNL: Mutex<Vec<(String,Mutex<Listener>)>> = Mutex::new(vec![]); -// } /// debug module /// diff --git a/forcebot_core/src/custom_mods/quiet.rs b/forcebot_core/src/custom_mods/quiet.rs new file mode 100644 index 0000000..a9827f6 --- /dev/null +++ b/forcebot_core/src/custom_mods/quiet.rs @@ -0,0 +1,84 @@ +use std::sync::Arc; + +use twitch_irc::message::ServerMessage; + +use crate::{execution_async, Badge, Bot, Command, Module}; + + +/// quiet the bot in a channel +/// +/// use +/// `quiet on` +/// `quiet off` +/// +/// +/// + +/// Use this function when loading modules into the bot +/// +/// For example +/// ```rust +/// bot.load_module(quiet::create_module()); +/// ``` +/// +pub fn create_module() -> Module { + /* 1. Create a new module */ + let mut custom_mod = Module::new( + vec!["quiet".to_string()], + "".to_string()); + + /* 2. Load the cmd into a new module */ + custom_mod.load_command(cmd_quiet_on()); + custom_mod.load_command(cmd_quiet_off()); + custom_mod + +} + +/// Command definition for quiet command +fn cmd_quiet_on() -> Command { + /* 1. Create a new cmd */ + let mut cmd = Command::new(vec!["quiet on".to_string()],"".to_string()); + + /* 2. Define exec callback */ + async fn execbody(bot:Arc<Bot>,message:ServerMessage) -> Result<String,String> { + if let ServerMessage::Privmsg(msg) = message { + + // dbg!("quiet on called"); + bot.set_channel_quiet(msg.channel_login.clone(), true); + println!("channel {} set quiet true",msg.channel_login); + } + Result::Err("Not Valid message type".to_string()) + } + + /* 3. Set Command flags */ + cmd.set_exec_fn(execution_async(execbody)); + cmd.set_admin_only(false); + cmd.set_min_badge(Badge::Moderator); + cmd.set_admin_override(true); + + cmd +} + +/// Command definition for quiet command +fn cmd_quiet_off() -> Command { + /* 1. Create a new cmd */ + let mut cmd = Command::new(vec!["quiet off".to_string()],"".to_string()); + + /* 2. Define exec callback */ + async fn execbody(bot:Arc<Bot>,message:ServerMessage) -> Result<String,String> { + if let ServerMessage::Privmsg(msg) = message { + + bot.set_channel_quiet(msg.channel_login.clone(), false); + println!("channel {} set quiet false",msg.channel_login); + } + Result::Err("Not Valid message type".to_string()) + } + + /* 3. Set Command flags */ + cmd.set_exec_fn(execution_async(execbody)); + cmd.set_admin_only(false); + cmd.set_min_badge(Badge::Moderator); + cmd.set_admin_override(true); + + cmd +} diff --git a/simple_command_bot/src/main.rs b/simple_command_bot/src/main.rs index 3806e7f..f231f0c 100644 --- a/simple_command_bot/src/main.rs +++ b/simple_command_bot/src/main.rs @@ -26,7 +26,7 @@ use twitch_irc::message::ServerMessage; pub async fn main() { /* Create the bot using env */ - let mut bot = Bot::new().await; + let bot = Bot::new().await; /* 1. Create a new blank cmd */ let mut cmd = Command::new(vec!["test".to_string()],"".to_string()); @@ -50,7 +50,7 @@ pub async fn main() { cmd.set_min_badge(Badge::Moderator); /* 6. Load the cmd into the bot */ - bot.load_command(cmd); + bot.load_command(cmd).await; /* Run the bot */ bot.run().await;