diff --git a/src/core/bot_actions.rs b/src/core/bot_actions.rs index d2d8d25..4b17758 100644 --- a/src/core/bot_actions.rs +++ b/src/core/bot_actions.rs @@ -6,7 +6,7 @@ use tokio::sync::RwLock; use crate::core::botinstance::BotInstance; -use super::botmodules::{BotAction, BotModule}; +use super::{botmodules::{BotAction, BotModule}, identity::ChatBadge}; pub type BotAR = Arc>; @@ -41,6 +41,26 @@ impl ExecBodyParams { parent_module } + pub fn get_sender(&self) -> String { + self.msg.sender.name.clone() + } + + pub fn get_sender_chatbadge(&self) -> Option { + + let mut requestor_badge_mut: Option = None; + + for b in &self.msg.badges { + if b.name == "moderator" { + requestor_badge_mut = Some(ChatBadge::Mod); + } else if b.name == "broadcaster" { + requestor_badge_mut = Some(ChatBadge::Broadcaster); + } + } + + let requestor_badge = requestor_badge_mut; + + requestor_badge + } } diff --git a/src/core/botinstance.rs b/src/core/botinstance.rs index dc5e70b..b202e5b 100644 --- a/src/core/botinstance.rs +++ b/src/core/botinstance.rs @@ -390,6 +390,12 @@ impl BotInstance { Some(msg), ); + botlog::trace( + "ACQUIRING WRITE LOCK : ID", + Some("BotInstance > listener_main_prvmsg()".to_string()), + Some(msg), + ); + const OF_CMD_CHANNEL:Channel = Channel(String::new()); @@ -431,6 +437,11 @@ impl BotInstance { return; }; + botlog::trace( + "ACQUIRING WRITE LOCK : ID", + Some("BotInstance > listener_main_prvmsg()".to_string()), + Some(msg), + ); let eval = { diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index b173e7b..5ae8ceb 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -846,6 +846,12 @@ impl ModulesManager { return ChangeResult::Failed("Module doesn't exist".to_string()); } + botlog::trace( + "ACQUIRING WRITE LOCK : ID", + Some("ModulesManager > Exec_enable".to_string()), + None, + ); + let mut idlock = id.write().await; @@ -1028,6 +1034,13 @@ impl ModulesManager { return ChangeResult::Failed("Module doesn't exist".to_string()); } + botlog::trace( + "ACQUIRING WRITE LOCK : ID", + Some("ModulesManager > Exec_disable".to_string()), + None, + ); + + let mut idlock = id.write().await; diff --git a/src/core/chat.rs b/src/core/chat.rs index a2d5b2b..2a6fc26 100644 --- a/src/core/chat.rs +++ b/src/core/chat.rs @@ -12,6 +12,7 @@ use casual_logger::Log; use rand::Rng; +use crate::core::identity::Permissible; use crate::core::ratelimiter; use crate::core::ratelimiter::RateLimiter; @@ -23,6 +24,7 @@ use tokio::time::{sleep, Duration}; use super::bot_actions::ExecBodyParams; use super::botmodules::BotModule; +use super::identity; use async_recursion::async_recursion; @@ -34,7 +36,7 @@ pub struct Chat { } -#[derive(Clone)] +#[derive(Clone,Debug)] enum BotMsgType<'a> { SayInReplyTo(&'a PrivmsgMessage,String), Say(String,String), @@ -62,6 +64,9 @@ impl Chat { // async fn send_botmsg(&self, msginput: BotMsgType<'_>) { async fn send_botmsg(&self, msginput: BotMsgType<'_>, params : ExecBodyParams) { + + + /* formats message before sending to TwitchIRC @@ -71,6 +76,13 @@ impl Chat { */ + + botlog::trace( + format!("send_bot_msg params : {:?}",msginput).as_str(), + Some("chat.rs > send_botmsg ".to_string()), + Some(¶ms.msg), + ); + let (channel_login,mut outmsg) = match msginput.clone() { BotMsgType::SayInReplyTo(msg, outmsg) => { (msg.channel_login.clone(),outmsg) @@ -80,19 +92,75 @@ impl Chat { }, }; - if self.client.get_channel_status(channel_login.clone()).await == (false,false) { - // in the case where the provided channel isn't something we're known to be connected to + + + botlog::trace( + "BEFORE parent_module call", + Some("chat.rs > send_botmsg ".to_string()), + Some(¶ms.msg), + ); + + let parent_module = params.get_parent_module().await; + // let parent_module = parent_module.clone(); + + let params_clone = params.clone(); + let botclone = Arc::clone(¶ms_clone.bot); + let botlock = botclone.read().await; + let modmgr = Arc::clone(&botlock.botmodules); + let modstatus = (*modmgr).modstatus( + parent_module.clone().expect("ERROR - Expected a module"), + Channel(channel_login.clone()) + ).await; + + + // botlog::trace( + // "BEFORE GET_CHANNEL_STATUS", + // Some("chat.rs > send_botmsg ".to_string()), + // Some(¶ms.msg), + // ); + + // let rslt = self.client.get_channel_status(channel_login.clone()).await == (false,false); + + // botlog::trace( + // format!("GET_CHANNEL_STATUS result = {:?}",rslt).as_str(), + // Some("chat.rs > send_botmsg ".to_string()), + // Some(¶ms.msg), + // ); + + // Log::flush(); + + + + // if rslt { + // // in the case where the provided channel isn't something we're known to be connected to + + // botlog::warn( + // &format!("A message attempted to send for a Non-Joined Channel : {}",channel_login.clone()), + // Some("Chat > send_botmsg".to_string()), + // None, + // ); + // return ; + // } + + if !params.bot.read().await.bot_channels.contains(&Channel(channel_login.clone())) { botlog::warn( &format!("A message attempted to send for a Non-Joined Channel : {}",channel_login.clone()), Some("Chat > send_botmsg".to_string()), None, ); + + self.say_in_reply_to( + ¶ms.msg, + "uuh Bot can't send to a channel it isn't joined".to_string(), + params.clone() + ).await; + return ; } /* - [ ] !! => 03.24 - Somewhere around here, we should be validating module for target channel + [x] !! => 03.24 - Somewhere around here, we should be validating module for target channel */ @@ -103,27 +171,46 @@ impl Chat { */ - let parent_module = params.get_parent_module().await; - // let parent_module = parent_module.clone(); - let botlock = params.bot.read().await; - let modmgr = Arc::clone(&botlock.botmodules); - let modstatus = (*modmgr).modstatus( - parent_module.clone().expect("ERROR - Expected a module"), - Channel(channel_login.clone()) - ).await; + // match modstatus { + // super::botmodules::StatusType::Enabled(_) => (), + // super::botmodules::StatusType::Disabled(_) => (), + // } - match modstatus { - super::botmodules::StatusType::Enabled(_) => (), - super::botmodules::StatusType::Disabled(_) => (), - } + + botlog::trace( + format!("BEFORE modstatus check : modstatus = {:?}",modstatus).as_str(), + Some("chat.rs > send_botmsg ".to_string()), + Some(¶ms.msg), + ); + + if let super::botmodules::StatusType::Disabled(lvl) = modstatus { // Note : At this point, chat was called in a channel where the parent module IS enabled // - this type of validation is done outside of Chat() // This though takes into account scenarios where we are targetting a different channel + + botlog::trace( + "BEFORE msginput check", + Some("chat.rs > send_botmsg ".to_string()), + Some(¶ms.msg), + ); + + Log::flush(); + + if let BotMsgType::SayInReplyTo(a, _) = msginput { + + botlog::trace( + "BEFORE potential Async recursion", + Some("chat.rs > send_botmsg ".to_string()), + Some(¶ms.clone().msg), + ); + + Log::flush(); + self.say_in_reply_to( a, @@ -135,13 +222,243 @@ impl Chat { params.clone() ).await; + // let chat_clone = self.clone(); + + // // tokio::spawn( async move { + // // // for _ in 0..5 { + // // // println!(">> Innterroutine triggered!"); + // // // sleep(Duration::from_secs_f64(5.0)).await; + // // // } + + // // chat_clone.say_in_reply_to( + // // a, + // // format!("uuh {:?} is disabled on {} : {:?}", + // // parent_module.clone().unwrap(), + // // channel_login.clone(), + // // lvl + // // ), + // // params.clone() + // // ).await; + // // } + // // ); + + + botlog::trace( + "AFTER potential Async recursion", + Some("chat.rs > send_botmsg ".to_string()), + Some(¶ms.msg), + ); + + + Log::flush(); + + } return } + + /* + + [ ] !! => 03.24 - Would be nice if around here , validate the user has at least some special roles in target channel + - NOTE : If these need to be refined, they can be by the custom module developer at the parent calling function of say() + - This just prevents Chat from being triggered in a channel where the sending chatter does not have any special roles + + */ + + + /* + + Use + pub async fn getspecialuserroles( + &self, + chattername: String, + channel: Option, + ) -> Vec { + + */ + + // let params_clone = params.clone(); + + let botclone = Arc::clone(¶ms.bot); + let botlock = botclone.read().await; + let id = botlock.get_identity(); + let id = Arc::clone(&id); + let idlock = id.read().await; // <-- [ ] 03.24 - seems to work + let user_roles = idlock.getspecialuserroles( + params.get_sender(), + Some(Channel(channel_login.clone())) + ).await; + + // [ ] If user has any of the following target roles, they will be allowed - otherwise, they will not be allowed to send + // - Otherwise if not (checked here) , this will not run + // - NOTE : For now, I've removed BotAdmin just for curiosity - BotAdmins can always elevate themselves if they want + + if !(user_roles.contains(&identity::UserRole::Mod(Channel(channel_login.clone()))) + || user_roles.contains(&identity::UserRole::SupMod(Channel(channel_login.clone()))) + || user_roles.contains(&identity::UserRole::Broadcaster)) + { + + + self.say_in_reply_to( + ¶ms.msg, + format!("uuh You do not have the right roles to send to {}", + channel_login.clone(), + ), + params.clone() + ).await; + + return; + + } + + /* + + Use the following + + pub async fn can_user_run( + &mut self, + usr: String, + channelname: Channel, + chat_badge: Option, + cmdreqroles: Vec, // ) -> Result> { + ) -> (Permissible, ChangeResult) { + + */ + + /* + + botlog::trace( + "BEFORE Permissibility checks", + Some("chat.rs > send_botmsg ".to_string()), + Some(¶ms.msg), + ); + + Log::flush(); + + + const OF_CMD_CHANNEL:Channel = Channel(String::new()); + + let permissability = Permissible::Allow; + + { + + + // let id = botlock.get_identity(); + // let mut idlock = id.write().await; // <-- [ ] 03.24 - This is definitely locking it + let channel_login_clone = channel_login.clone(); + + + let spawnhandle = tokio::spawn( + async move { + let botclone = Arc::clone(¶ms_clone.bot); + let botlock = botclone.read().await; + let id = botlock.get_identity(); + + + // botlog::trace( + // "ACQUIRING WRITE LOCK : ID", + // Some("Chat > send_botmsg".to_string()), + // Some(¶ms.msg), + // ); + + + // { + // let mut idlock = id.write().await; // <-- [ ] 03.24 - This is definitely locking it + // } + + // botlog::trace( + // "ACQUIRED WRITE LOCK : ID", + // Some("Chat > send_botmsg".to_string()), + // Some(¶ms.msg), + // ); + + // let (permissability, _) = idlock + // .can_user_run( + // params.get_sender(), + // Channel(channel_login_clone), + // params.get_sender_chatbadge(), + // vec![ + // //identity::UserRole::BotAdmin, + // identity::UserRole::Mod(OF_CMD_CHANNEL), + // identity::UserRole::SupMod(OF_CMD_CHANNEL), + // identity::UserRole::Broadcaster, + // ] + // ).await; + // permissability + } + ); + + if let Ok(permissibility) = spawnhandle.await { + botlog::trace( + format!("permisibility check : {:?}",permissability).as_str(), + Some("chat.rs > send_botmsg ".to_string()), + None + ); + + } + + + } + + + + + // let permissability = { + // let id = botlock.get_identity(); + // let mut idlock = id.write().await; // <-- [ ] 03.24 - This is definitely locking it + // let (permissability, _) = idlock + // .can_user_run( + // params.get_sender(), + // Channel(channel_login.clone()), + // params.get_sender_chatbadge(), + // vec![ + // //identity::UserRole::BotAdmin, + // identity::UserRole::Mod(OF_CMD_CHANNEL), + // identity::UserRole::SupMod(OF_CMD_CHANNEL), + // identity::UserRole::Broadcaster, + // ] + // ).await; + // permissability + // }; + + // match permissability { + // Permissible::Allow => (), + // Permissible::Block => (), + // } + + + botlog::trace( + format!("permisibility check : {:?}",permissability).as_str(), + Some("chat.rs > send_botmsg ".to_string()), + None, + ); + + Log::flush(); + + if let Permissible::Block = permissability { + + + if let BotMsgType::SayInReplyTo(a, _) = msginput { + + // self.say_in_reply_to( + // a, + // format!("uuh you don't have special privileges in {}", + // channel_login.clone() + // ), + // params.clone() + // ).await; + + } + return + + } + + + */ let rl = Arc::clone(&self.ratelimiters); let mut rllock = rl.lock().await; @@ -222,6 +539,57 @@ impl Chat { #[async_recursion] pub async fn say_in_reply_to(&self, msg: &PrivmsgMessage, outmsg: String , params : ExecBodyParams) { + // let params_clone = params.clone(); + + // let botclone = Arc::clone(¶ms_clone.bot); + // let botlock = botclone.read().await; + // let id = botlock.get_identity(); + // let id = Arc::clone(&id); + + // // botlog::trace( + // // "ACQUIRING WRITE LOCK : ID", + // // Some("Chat > send_botmsg".to_string()), + // // Some(¶ms.msg), + // // ); + // // Log::flush(); + + // botlog::trace( + // "ACQUIRING READ LOCK : ID", + // Some("Chat > send_botmsg".to_string()), + // Some(¶ms.msg), + // ); + // Log::flush(); + + + // // let idlock = id.write().await; // <-- [ ] 03.24 - This is definitely locking it + // let idlock = id.read().await; // <-- [ ] 03.24 - seems to work + // let a = idlock.getspecialuserroles(params.get_sender(), Some(Channel(msg.channel_login.clone()))).await; + // botlog::trace( + // format!("GETSPECIALUSERROLES RESULT : {:?}",a).as_str(), + // Some("Chat > send_botmsg".to_string()), + // Some(¶ms.msg), + // ); + // Log::flush(); + + + + // // botlog::trace( + // // "ACQUIRED WRITE LOCK : ID", + // // Some("Chat > send_botmsg".to_string()), + // // Some(¶ms.msg), + // // ); + // // Log::flush(); + + + + // botlog::trace( + // "ACQUIRED READ LOCK : ID", + // Some("Chat > send_botmsg".to_string()), + // Some(¶ms.msg), + // ); + // Log::flush(); + + self.send_botmsg(BotMsgType::SayInReplyTo(msg, outmsg) , params).await; } diff --git a/src/custom/experimental/experiment002.rs b/src/custom/experimental/experiment002.rs index be53ffa..d657c19 100644 --- a/src/custom/experimental/experiment002.rs +++ b/src/custom/experimental/experiment002.rs @@ -57,8 +57,11 @@ pub async fn init(mgr: Arc) { // 2. Add the BotAction to ModulesManager botc1.add_to_modmgr(Arc::clone(&mgr)).await; + // If enabling by defauling at instance level mgr.set_instance_enabled(BotModule(String::from("experiments002"))).await; + // [ ] #TODO - FOR SOME REASON, IF DISABLED BY DEFAULT, IT OVERFLOWS at RUNGTIME + } @@ -79,15 +82,6 @@ async fn sayout(params : ExecBodyParams) { [x] Get the parent module */ - // let params_clone = Arc::clone(¶ms.parent_act); - // let actlock = params_clone.read().await; - // let act = &(*actlock); - // let parent_module = match act { - // BotAction::C(c) => Some(&(*c).module), - // BotAction::L(l) => Some(&(*l).module), - // _ => None, - // }; - let parent_module = params.get_parent_module().await;