diff --git a/src/core/botinstance.rs b/src/core/botinstance.rs index f6e21b4..9bef035 100644 --- a/src/core/botinstance.rs +++ b/src/core/botinstance.rs @@ -14,9 +14,6 @@ use dotenv::dotenv; use casual_logger::Log; -// use rand::Rng; - -// use crate::core::ratelimiter; use crate::core::ratelimiter::RateLimiter; use crate::core::botmodules::bot_actions::actions_util::BotAR; @@ -33,105 +30,8 @@ pub enum ChType { pub use ChType::Channel; -// #[derive(Clone)] -// pub struct Chat { -// pub ratelimiters: Arc>>, // used to limit messages sent per channel -// pub client: TwitchIRCClient, StaticLoginCredentials>, -// } - -// impl Chat { -// pub fn init( -// ratelimiters: HashMap, -// client: TwitchIRCClient, StaticLoginCredentials>, -// ) -> Chat { -// Chat { -// ratelimiters: Arc::new(Mutex::new(ratelimiters)), -// // client: client, -// client, -// } -// } - -// pub async fn init_channel(&mut self, chnl: ChType) { -// let n = RateLimiter::new(); -// self.ratelimiters.lock().await.insert(chnl, n); -// } - -// // pub async fn say_in_reply_to(&mut self, msg:& PrivmsgMessage , mut outmsg:String) -> () { -// pub async fn say_in_reply_to(&self, msg: &PrivmsgMessage, mut outmsg: String) { -// /* -// formats message before sending to TwitchIRC - -// - [x] Custom String Formatting (e.g., adding random black spaces) -// - [x] Ratelimiter Handling -// - [ ] Checkf if BotActions is Enabled & Caller is Allowed to Run - -// */ -// let a = Arc::clone(&self.ratelimiters); -// let mut a = a.lock().await; - -// let contextratelimiter = a -// // .get_mut() -// .get_mut(&Channel(String::from(&msg.channel_login))) -// .expect("ERROR: Issue with Rate limiters"); - -// match contextratelimiter.check_limiter() { -// ratelimiter::LimiterResp::Allow => { -// let maxblanks = rand::thread_rng().gen_range(1..=20); - -// for _i in 1..maxblanks { -// let blankspace: &str = "󠀀"; -// outmsg.push_str(blankspace); -// } - -// self.client.say_in_reply_to(msg, outmsg).await.unwrap(); -// // println!("(#{}) > {}", msg.channel_login, "rate limit counter increase"); -// // Log::trace(&format!("(#{}) > {}", msg.channel_login, "rate limit counter increase")); -// botlog::trace( -// &format!( -// "(#{}) > {}", -// msg.channel_login, "rate limit counter increase" -// ), -// Some("Chat > say_in_reply_to".to_string()), -// Some(msg), -// ); -// contextratelimiter.increment_counter(); -// // println!("{:?}",self.ratelimiters); -// // Log::trace(&format!("{:?}",self.ratelimiters)); -// botlog::trace( -// &format!("{:?}", self.ratelimiters), -// Some("Chat > say_in_reply_to".to_string()), -// Some(msg), -// ); -// } -// ratelimiter::LimiterResp::Skip => { -// // (); // do nothing otherwise -// } -// } -// Log::flush(); -// } - -// async fn _say(&self, _: String, _: String) { -// // more info https://docs.rs/twitch-irc/latest/twitch_irc/client/struct.TwitchIRCClient.html#method.say - -// // self.client.say(msg,outmsg).await.unwrap(); -// } - -// async fn _me(&self, _: String, _: String) { -// // more info https://docs.rs/twitch-irc/latest/twitch_irc/client/struct.TwitchIRCClient.html#method.say - -// // self.client.me(msg,outmsg).await.unwrap(); -// } - -// async fn _me_in_reply_to(&self, _: String, _: String) { -// // more info https://docs.rs/twitch-irc/latest/twitch_irc/client/struct.TwitchIRCClient.html#method.say - -// // self.client.me(msg,outmsg).await.unwrap(); -// } -// } - #[derive(Clone)] pub struct BotManagers { - // pub botmodules : ModulesManager, pub identity: Arc>, pub chat: Chat, } @@ -160,8 +60,6 @@ impl ArcBox { } } -//#[derive(Clone)] -// #[derive(Copy)] // <-- Cannot be derived pub struct BotInstance { pub prefix: char, pub bot_channel: ChType, @@ -170,7 +68,7 @@ pub struct BotInstance { pub twitch_oauth: String, pub bot_channels: Vec, pub botmgrs: BotManagers, - //modesmgr : ModesManager, // Silent/Quiet , uwu , frisky/horny + //modesmgr : ModesManager, // [FUTURE] Silent/Quiet , uwu , frisky/horny } impl BotInstance { @@ -186,14 +84,9 @@ impl BotInstance { .next() .expect("ERROR : when defining prefix"); - /* - Vector of channels to join - */ - let mut botchannels = Vec::new(); for chnl in env::var("bot_channels").unwrap().split(',') { - // println!("(Env Var # {})",chnl); botchannels.push(Channel(String::from(chnl))); } @@ -205,32 +98,18 @@ impl BotInstance { let (incoming_messages, client) = TwitchIRCClient::::new(config); - // hashmap for channels and their associated ratelimiters let mut ratelimiters = HashMap::new(); for Channel(chnl) in &botchannels { - // For each channel in botchannels + // For each channel in botchannels , join & create ratelimiters client.join(chnl.to_owned()).unwrap(); - // ratelimiters are a hashmap of channel and a corresponding rate limiter let n = RateLimiter::new(); ratelimiters.insert(Channel(String::from(chnl)), n); - //self.chat.ratelimiters.insert(Channel(String::from(chnl)),n); } - // let b = BotInstance { - // prefix : prefix, - // bot_channel : Channel(login_name) , - // incoming_messages : Arc::new(RwLock::new(incoming_messages)), - // botmodules : ModulesManager::init().await, - // twitch_oauth : oauth_token, - // bot_channels : botchannels, - // botmgrs : BotManagers::init(ratelimiters,client), - // }; - BotInstance { - // prefix: prefix, prefix, bot_channel: Channel(login_name), incoming_messages: Arc::new(RwLock::new(incoming_messages)), @@ -239,57 +118,34 @@ impl BotInstance { bot_channels: botchannels, botmgrs: BotManagers::init(ratelimiters, client), } - - // b } pub async fn runner(self) { + // Main Game Loop + let bot = Arc::new(RwLock::new(self)); let join_handle = tokio::spawn(async move { - let a = bot.read().await; - let mut a = a.incoming_messages.write().await; - while let Some(message) = a.recv().await { + let botlock = bot.read().await; + let mut msglock = botlock.incoming_messages.write().await; + + while let Some(message) = msglock.recv().await { match message { ServerMessage::Notice(msg) => { - match &msg.channel_login { - Some(chnl) => { - // println!("NOTICE : (#{}) {}", chnl, msg.message_text) - // Log::notice(&format!("NOTICE : (#{}) {}", chnl, msg.message_text)); - botlog::notice( - &format!("NOTICE : (#{}) {}", chnl, msg.message_text), - Some("BotInstance > runner()".to_string()), - None, - ); - } - None => { - // println!("NOTICE : {}", msg.message_text); - // Log::notice(&format!("NOTICE : {}", msg.message_text)); - botlog::notice( - &format!("NOTICE : {}", msg.message_text), - Some("BotInstance > runner()".to_string()), - None, - ); - } - } + botlog::notice( + format!("NOTICE : (#{:?}) {}", msg.channel_login, msg.message_text) + .as_str(), + Some("BotInstance > runner()".to_string()), + None, + ); } ServerMessage::Privmsg(msg) => { - // println!("(#{}) {}: {}", msg.channel_login, msg.sender.name, msg.message_text); - // Log::trace(&format!("(#{}) {}: {}", msg.channel_login, msg.sender.name, msg.message_text)); botlog::debug( - &format!( - "Twitch Chat > {} @ #{}: {}", + format!( + "[Twitch Chat] > {} @ #{}: {}", msg.channel_login, msg.sender.name, msg.message_text - ), - Some("BotInstance > runner()".to_string()), - Some(&msg), - ); - - // println!("Privmsg section"); - // Log::debug(&format!("Privmsg section")); - botlog::trace( - // &format!("Privmsg section"), - "Privmsg section", + ) + .as_str(), Some("BotInstance > runner()".to_string()), Some(&msg), ); @@ -297,28 +153,22 @@ impl BotInstance { BotInstance::listener_main_prvmsg(Arc::clone(&bot), &msg).await; } ServerMessage::Whisper(msg) => { - // println!("(w) {}: {}", msg.sender.name, msg.message_text); - // Log::trace(&format!("(w) {}: {}", msg.sender.name, msg.message_text)); - botlog::trace( - &format!("(w) {}: {}", msg.sender.name, msg.message_text), + botlog::debug( + format!("[Whisper] {}: {}", msg.sender.name, msg.message_text).as_str(), Some("BotInstance > runner()".to_string()), None, ); } ServerMessage::Join(msg) => { - // println!("JOINED: {}", msg.channel_login); - // Log::notice(&format!("JOINED: {}", msg.channel_login)); botlog::notice( - &format!("JOINED: {}", msg.channel_login), + format!("JOINED: {}", msg.channel_login).as_str(), Some("BotInstance > runner()".to_string()), None, ); } ServerMessage::Part(msg) => { - // println!("PARTED: {}", msg.channel_login); - // Log::notice(&format!("PARTED: {}", msg.channel_login)); botlog::notice( - &format!("PARTED: {}", msg.channel_login), + format!("PARTED: {}", msg.channel_login).as_str(), Some("BotInstance > runner()".to_string()), None, ); @@ -332,84 +182,38 @@ impl BotInstance { join_handle.await.unwrap(); } - pub fn get_botmodules(self) -> Arc { - self.botmodules - } - - pub async fn get_botmgrs(self) -> BotManagers { - // let a = self.botmgrs; - // a - self.botmgrs - } - pub fn get_identity(&self) -> Arc> { Arc::clone(&self.botmgrs.identity) } pub fn get_prefix(&self) -> char { - // (*self).prefix self.prefix } // ----------------- // PRIVATE FUNCTIONS - pub async fn listener_main_prvmsg(bot: BotAR, msg: &PrivmsgMessage) { - // println!(">> Inner listenermain_prvmsg()"); - // Log::trace(">> Inner listenermain_prvmsg()"); + async fn listener_main_prvmsg(bot: BotAR, msg: &PrivmsgMessage) { botlog::trace( ">> Inner listenermain_prvmsg()", Some("BotInstance > listener_main_prvmsg()".to_string()), Some(msg), ); - // let a = a; - // println!("(#{}) {}: {}", msg.channel_login, msg.sender.name, msg.message_text); - - // // [ ] Need to run through all Listener Bodies for Enabled Modules for the context of the message (e.g., ModStatus is Enabled in the context for the channel) + // // [ ] #todo Need to run through all Listener Bodies for Enabled Modules for the context of the message (e.g., ModStatus is Enabled in the context for the channel) let botlock = bot.read().await; - let hacts = Arc::clone(&botlock.botmodules.botactions); - // let hacts = hacts.read().await; - let a = hacts.read().await; - // println!("hacts size : {}",(*a).len()); - // Log::debug(&format!("hacts size : {}",(*a).len())); - botlog::trace( - &format!("hacts size : {}", (*a).len()), + let actsdb = Arc::clone(&botlock.botmodules.botactions); + let actsdblock = actsdb.read().await; + + botlog::debug( + format!("# of BotModules: {}", (*actsdblock).len()).as_str(), Some("BotInstance > listener_main_prvmsg()".to_string()), Some(msg), ); - // println!(">> Inner listenermain_prvmsg() >> before for loop of bot actions"); - // Log::trace(">> Inner listenermain_prvmsg() >> before for loop of bot actions"); - botlog::trace( - ">> Inner listenermain_prvmsg() >> before for loop of bot actions", - Some("BotInstance > listener_main_prvmsg()".to_string()), - Some(msg), - ); - - // for (_m, acts) in &*hacts.read().await { - for acts in (*hacts.read().await).values() { - // println!(">> Inner listenermain_prvmsg() >> checking bot actions"); - // Log::trace(">> Inner listenermain_prvmsg() >> checking bot actions"); - botlog::trace( - ">> Inner listenermain_prvmsg() >> checking bot actions", - Some("BotInstance > listener_main_prvmsg()".to_string()), - Some(msg), - ); - - // let bot = bot; - + for acts in (*actsdblock).values() { for a in acts { - // println!(">> Inner listenermain_prvmsg() >> checking bot actions >> 2"); - // Log::trace(">> Inner listenermain_prvmsg() >> checking bot actions >> 2"); - botlog::trace( - ">> Inner listenermain_prvmsg() >> checking bot actions >> 2", - Some("BotInstance > listener_main_prvmsg()".to_string()), - Some(msg), - ); - - // let _act = match a { match a { crate::core::botmodules::BotAction::C(c) => { /* @@ -422,19 +226,12 @@ impl BotInstance { _cmdreqroles:Vec) */ - // for v in msg.message_text.split(" ") { - // println!("args : {v}"); - // } - - // println!("Reviewing internal commands"); - // Log::trace("Reviewing internal commands"); botlog::trace( "Reviewing internal commands", Some("BotInstance > listener_main_prvmsg()".to_string()), Some(msg), ); - // let inpt = msg.message_text.split("\n").next().expect("ERROR during BotCommand"); let inpt = msg .message_text .split(' ') @@ -460,114 +257,63 @@ impl BotInstance { } if confirmed_bot_command { - // println!("Confirmed bot command"); - // Log::debug("Confirmed bot command"); botlog::debug( - "Confirmed bot command", - Some("BotInstance > listener_main_prvmsg()".to_string()), - // Some(&msg), - Some(msg), - ); - - // println!("Going for botlock"); - // Log::trace("Going for botlock"); - botlog::trace( - "Going for botlock", + format!("Confirmed bot command ; Msg : {}", msg.message_text) + .as_str(), Some("BotInstance > listener_main_prvmsg()".to_string()), // Some(&msg), Some(msg), ); let botlock = bot.read().await; - // println!("Going for identity"); - // Log::trace("Going for identity"); - botlog::trace( - "Going for identity", - Some("BotInstance > listener_main_prvmsg()".to_string()), - // Some(&msg), - Some(msg), - ); - let id = botlock.get_identity(); let eval = { - let mut id = id.write().await; - // println!("Unlocking identity"); - // Log::trace("Unlocking identity"); - botlog::trace( - "Unpacking identity", - Some("BotInstance > listener_main_prvmsg()".to_string()), - // Some(&msg), - Some(msg), - ); + let mut idlock = id.write().await; + let (permissability, chngrslt) = idlock + .can_user_run_prvmsg(msg, c.required_roles.clone()) + .await; - // let (a, b) = - // id.can_user_run_prvmsg(&msg, c.required_roles.clone()).await; - let (a, b) = - id.can_user_run_prvmsg(msg, c.required_roles.clone()).await; - // // [-] #todo : need ot add functionality around here to do an o7 when a mod has been promoted => Preferring to do this outside the mutex - // if let ChangeResult::Success(b) = b { - // // let b = b.to_lowercase(); - // // let b = b.contains(&"Auto Promoted Mod".to_lowercase()); - // if b.to_lowercase().contains(&"Auto Promoted Mod".to_lowercase()) { - // let chat = - // } - // } - (a, b) + (permissability, chngrslt) }; - // println!("Checking if permissible"); - Log::trace("Checking if permissible"); + botlog::trace( "Checking if permissible", Some("BotInstance > listener_main_prvmsg()".to_string()), - // Some(&msg), Some(msg), ); let (eval, rolechange) = eval; - if let ChangeResult::Success(b) = rolechange { - if b.to_lowercase() + if let ChangeResult::Success(innerstr) = rolechange { + if innerstr + .to_lowercase() .contains(&"Auto Promoted Mod".to_lowercase()) { botlog::notice( "Assigning Mod UserRole to Mod", Some("botinstance > listener_main_prvmsg()".to_string()), - // Some(&msg), - Some(msg), - ); - - // println!("Read() lock Bot"); - // Log::trace("Read() lock Bot"); - botlog::trace( - "Read() lock Bot", - Some("BotInstance > listener_main_prvmsg()".to_string()), - // Some(&msg), Some(msg), ); let botlock = bot.read().await; let outstr = "o7 a Mod. I kneel to serve! pepeKneel ".to_string(); - // (*botlock).botmgrs.chat.say_in_reply_to(msg, outstr).await; botlock.botmgrs.chat.say_in_reply_to(msg, outstr).await; } } match eval { Permissible::Allow => { - // println!("Executed as permissible"); - // Log::debug("Executed as permissible"); botlog::debug( "Executed as permissible", Some("BotInstance > listener_main_prvmsg()".to_string()), - // Some(&msg), Some(msg), ); + let a = Arc::clone(&bot); c.execute(a, msg.clone()).await; - // println!("exit out of execution"); - // Log::trace("exit out of execution"); + botlog::trace( "exit out of execution", Some("BotInstance > listener_main_prvmsg()".to_string()), @@ -575,16 +321,14 @@ impl BotInstance { Some(msg), ); } + Permissible::Block => { - // println!("User Not allowed to run command"); - // Log::info("User Not allowed to run command"); botlog::info( "User Not allowed to run command", Some("BotInstance > listener_main_prvmsg()".to_string()), - // Some(&msg), Some(msg), ); - } // _ => (), + } }; } } @@ -599,20 +343,12 @@ impl BotInstance { } } - // // [ ] There should be a BotCommand Listener to check for prefixes ran - - // println!("End of Separate Listener Main prvmsg"); - // Log::trace("End of Separate Listener Main prvmsg"); botlog::trace( "End of Separate Listener Main prvmsg", Some("BotInstance > listener_main_prvmsg()".to_string()), - // Some(&msg), Some(msg), ); - // self - // bot - Log::flush(); } } diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index e30b567..b7b27fd 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -1,30 +1,3 @@ -use core::panic; -use std::error::Error; - -use std::collections::HashMap; - -use crate::core::identity; - -// use std::cell::RefCell; -use std::sync::Arc; -use tokio::sync::RwLock; - -// use std::future::Future; -// use futures::lock::Mutex; - -// Important to use tokios Mutex here since std Mutex doesn't work with async functions -// use tokio::sync::Mutex; - -use crate::core::botinstance::{self, BotInstance}; -use crate::core::botlog; - -// use std::rc::Rc; - -// use tokio::sync::RwLock; - -use async_trait::async_trait; -// use casual_logger::{Level, Log}; - /* ModulesManager is used to manage Modules and BotActions associated with those modules @@ -46,26 +19,32 @@ Example */ + +use core::panic; + +use std::error::Error; +use std::collections::HashMap; +use std::sync::Arc; + +use twitch_irc::message::PrivmsgMessage; + +use tokio::sync::RwLock; + +use async_trait::async_trait; + +use crate::core::botinstance::{BotInstance,ChType}; +use crate::core::botlog; +use crate::core::identity; +use self::bot_actions::actions_util::BotAR; + +pub use ChType::Channel; +pub use ModType::BotModule; + #[derive(Debug, PartialEq, Eq, Hash, Clone)] pub enum ModType { BotModule(String), } -pub use ModType::BotModule; - -// #[derive(Debug, PartialEq, Eq, Hash, Clone)] -// pub enum ChType { -// Channel(String), -// } - -use botinstance::ChType; - -use twitch_irc::message::PrivmsgMessage; -pub use ChType::Channel; - -// use self::bot_actions::actions_util; -use self::bot_actions::actions_util::BotAR; - #[derive(Debug)] pub enum StatusLvl { Instance, @@ -78,7 +57,6 @@ pub enum ModStatusType { Disabled(StatusLvl), } -// #[derive(Clone)] pub enum BotAction { C(BotCommand), L(Listener), @@ -101,12 +79,10 @@ pub trait BotActionTrait { async fn add_to_modmgr(self, modmgr: Arc); } -// #[derive(Clone)] pub struct BotCommand { pub module: ModType, pub command: String, // command call name pub alias: Vec, // String of alternative names - // bot_prefix : char, // although should be global? pub exec_body: bot_actions::actions_util::ExecBody, pub help: String, pub required_roles: Vec, @@ -114,7 +90,6 @@ pub struct BotCommand { impl BotCommand { pub async fn execute(&self, m: BotAR, n: PrivmsgMessage) { - // ((*self).exec_body)(m, n).await; (*self.exec_body)(m, n).await; } } @@ -125,7 +100,6 @@ impl BotActionTrait for BotCommand { self.add_to_modmgr(bot.botmodules).await; } - // async fn add_to_modmgr(self, modmgr:Arc>) { async fn add_to_modmgr(self, modmgr: Arc) { modmgr .add_botaction(self.module.clone(), BotAction::C(self)) diff --git a/src/core/chat.rs b/src/core/chat.rs index 0390647..4720af7 100644 --- a/src/core/chat.rs +++ b/src/core/chat.rs @@ -32,7 +32,6 @@ impl Chat { ) -> Chat { Chat { ratelimiters: Arc::new(Mutex::new(ratelimiters)), - // client: client, client, } } @@ -42,7 +41,6 @@ impl Chat { self.ratelimiters.lock().await.insert(chnl, n); } - // pub async fn say_in_reply_to(&mut self, msg:& PrivmsgMessage , mut outmsg:String) -> () { pub async fn say_in_reply_to(&self, msg: &PrivmsgMessage, mut outmsg: String) { /* formats message before sending to TwitchIRC @@ -53,10 +51,10 @@ impl Chat { */ - let a = Arc::clone(&self.ratelimiters); - let mut a = a.lock().await; + let rl = Arc::clone(&self.ratelimiters); + let mut rllock = rl.lock().await; - let contextratelimiter = a + let contextratelimiter = rllock // .get_mut() .get_mut(&Channel(String::from(&msg.channel_login))) .expect("ERROR: Issue with Rate limiters"); @@ -71,21 +69,16 @@ impl Chat { } self.client.say_in_reply_to(msg, outmsg).await.unwrap(); - // println!("(#{}) > {}", msg.channel_login, "rate limit counter increase"); - // Log::trace(&format!("(#{}) > {}", msg.channel_login, "rate limit counter increase")); - botlog::trace( - &format!( - "(#{}) > {}", - msg.channel_login, "rate limit counter increase" - ), - Some("Chat > say_in_reply_to".to_string()), - Some(msg), - ); + contextratelimiter.increment_counter(); - // println!("{:?}",self.ratelimiters); - // Log::trace(&format!("{:?}",self.ratelimiters)); + + let logstr = format!( + "(#{}) > {} ; Ratelimiers : {:?}", + msg.channel_login, "rate limit counter increase", self.ratelimiters + ); + botlog::trace( - &format!("{:?}", self.ratelimiters), + logstr.as_str(), Some("Chat > say_in_reply_to".to_string()), Some(msg), );