diff --git a/src/core/botinstance.rs b/src/core/botinstance.rs index eb9eadf..0fb7f88 100644 --- a/src/core/botinstance.rs +++ b/src/core/botinstance.rs @@ -145,7 +145,10 @@ impl Chat { -pub struct BotInstance { +pub struct BotInstance +where + F: std::future::Future + ?Sized, +{ prefix : char, bot_channel : ChType, //pub client : TwitchIRCClient,StaticLoginCredentials>, @@ -153,7 +156,7 @@ pub struct BotInstance { // pub ratelimiters : HashMap, // used to limit messages sent per channel pub chat : Chat, // botmodules : HashMap>, - pub botmodules : ModulesManager, + pub botmodules : ModulesManager, twitch_oauth : String, pub bot_channels : Vec, /*bot_commands : Vec[BotCommand], @@ -163,10 +166,18 @@ pub struct BotInstance { // identity : identitymodule, } -impl BotInstance { - pub fn init() -> BotInstance { +impl BotInstance +where + F: std::future::Future + 'static, +{ + + + pub fn init() -> BotInstance + where + F: std::future::Future + 'static, + { dotenv().ok(); let login_name = env::var("login_name").unwrap().to_owned(); @@ -237,6 +248,53 @@ impl BotInstance { b } + pub async fn runner(mut self) -> () { + + let join_handle = tokio::spawn(async move { + + while let Some(message) = self.incoming_messages.recv().await { + // Below can be used to debug if I want to capture all messages + // println!("Received message: {:?}", message); + + match message { + ServerMessage::Notice(msg) => { + if let Some(chnl) = msg.channel_login { + println!("NOTICE : (#{}) {}", chnl, msg.message_text); + } + } + ServerMessage::Privmsg(msg) => { + println!("(#{}) {}: {}", msg.channel_login, msg.sender.name, msg.message_text); + + println!("Privmsg section"); + + // b.listener_main_prvmsg(&msg); + self.listener_main_prvmsg(&msg).await; + // - BotCommand listener should likely need to be called within the above + + + }, + ServerMessage::Whisper(msg) => { + println!("(w) {}: {}", msg.sender.name, msg.message_text); + }, + ServerMessage::Join(msg) => { + println!("JOINED: {}", msg.channel_login); + }, + ServerMessage::Part(msg) => { + println!("PARTED: {}", msg.channel_login); + }, + _ => {} + } + } + }); + + + + + + join_handle.await.unwrap(); + } + + pub async fn run(mut self) -> () { @@ -341,3 +399,21 @@ impl BotInstance { + +// ====================================== +// ====================================== +// ====================================== +// ====================================== + +// UNIT TEST MODULES + + + + + +#[cfg(test)] +mod tests { + fn always() { + assert_eq!(1,1); + } +} diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 3aba55d..2dc8671 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -59,130 +59,154 @@ pub enum ModStatusType { // pub use EnType::Enabled; #[derive(Debug)] -pub enum BotAction { - C(BotCommand), - L(Listener), +pub enum BotAction +where + F: std::future::Future + ?Sized, +{ + //C(BotCommand), + L(Listener), R(Routine), } -pub trait BotActionTrait { +pub trait BotActionTrait +where + F: std::future::Future, +{ // async fn execute(&self,m:&mut BotInstance,n:&PrivmsgMessage); // fn add_to_bot(self, bot:BotInstance) -> Result>; - fn add_to_bot(self, bot:BotInstance); - fn add_to_modmgr(self, modmgr:&mut ModulesManager); + fn add_to_bot(self, bot:BotInstance); + fn add_to_modmgr(self, modmgr:&mut ModulesManager); } +// #[derive(Debug)] +// 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? +// exec_body : fn(&BotInstance,&PrivmsgMessage), +// pub help : String, +// } + +// impl BotCommand { +// // pub fn add_to_bot(self, bot:BotInstance) { +// // // let mut mgr = bot.botmodules; +// // // let nmod = self.module.clone(); +// // // mgr.add_botaction(nmod, BotAction::C(self)); +// // let mut mgr = bot.botmodules; +// // //let nmod = self.module.clone(); +// // // mgr.add_botaction(self.module.clone(), BotAction::C(self)); + +// // self.add_to_modmgr(&mut mgr); +// // } + + +// // pub fn add_to_modmgr(self, modmgr:&mut ModulesManager) { +// // // // let mut mgr = bot.botmodules; +// // // // let nmod = self.module.clone(); +// // // // mgr.add_botaction(nmod, BotAction::C(self)); +// // // let mut mgr = modmgr; +// // // //let nmod = self.module.clone(); +// // // mgr.add_botaction(self.module.clone(), BotAction::C(self)); +// // // let mut mgr = modmgr; +// // // //let nmod = self.module.clone(); +// // modmgr.add_botaction(self.module.clone(), BotAction::C(self)); +// // } + + +// } + +// impl BotActionTrait for BotCommand { +// // fn add_to_bot(&self) -> Result> { +// // println!("Calling Add to Bot"); +// // Ok(String::from("Hello")) +// // } + +// fn add_to_bot(self, bot:BotInstance) { +// // let mut mgr = bot.botmodules; +// // let nmod = self.module.clone(); +// // mgr.add_botaction(nmod, BotAction::C(self)); +// let mut mgr = bot.botmodules; +// //let nmod = self.module.clone(); +// // mgr.add_botaction(self.module.clone(), BotAction::C(self)); + +// self.add_to_modmgr(&mut mgr); +// } + +// fn add_to_modmgr(self, modmgr:&mut ModulesManager) { +// // // let mut mgr = bot.botmodules; +// // // let nmod = self.module.clone(); +// // // mgr.add_botaction(nmod, BotAction::C(self)); +// // let mut mgr = modmgr; +// // //let nmod = self.module.clone(); +// // mgr.add_botaction(self.module.clone(), BotAction::C(self)); +// // let mut mgr = modmgr; +// // //let nmod = self.module.clone(); +// modmgr.add_botaction(self.module.clone(), BotAction::C(self)); +// } + +// // => 12.23 - MF: NOTE : The exec body is defined ad module level , not this core level + +// // fn exec_body(&self,m:&BotInstance,n:&PrivmsgMessage){ +// // // => 12.23 - [ ] #todo requires field +// // // (&self.exec)(String::from("Hello from BotAction Trait")) +// // //self.exec_body(m,n) +// // } + +// // fn execute(&self,m:&mut BotInstance,n:&PrivmsgMessage){ +// // // => 12.23 - [ ] #todo requires field +// // // (&self.exec)(String::from("Hello from BotAction Trait")) +// // //self.exec_body(m,n) +// // (self.exec_body)(m,n) +// // } +// } + + +// #[derive(Debug)] +// pub struct Listener { +// pub module : ModType, +// pub name : String, +// pub exec_body : fn(&mut BotInstance,&PrivmsgMessage) , +// pub help : String +// } + #[derive(Debug)] -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? - exec_body : fn(&BotInstance,&PrivmsgMessage), - pub help : String, -} - -impl BotCommand { - // pub fn add_to_bot(self, bot:BotInstance) { - // // let mut mgr = bot.botmodules; - // // let nmod = self.module.clone(); - // // mgr.add_botaction(nmod, BotAction::C(self)); - // let mut mgr = bot.botmodules; - // //let nmod = self.module.clone(); - // // mgr.add_botaction(self.module.clone(), BotAction::C(self)); - - // self.add_to_modmgr(&mut mgr); - // } - - - // pub fn add_to_modmgr(self, modmgr:&mut ModulesManager) { - // // // let mut mgr = bot.botmodules; - // // // let nmod = self.module.clone(); - // // // mgr.add_botaction(nmod, BotAction::C(self)); - // // let mut mgr = modmgr; - // // //let nmod = self.module.clone(); - // // mgr.add_botaction(self.module.clone(), BotAction::C(self)); - // // let mut mgr = modmgr; - // // //let nmod = self.module.clone(); - // modmgr.add_botaction(self.module.clone(), BotAction::C(self)); - // } - - -} - -impl BotActionTrait for BotCommand { - // fn add_to_bot(&self) -> Result> { - // println!("Calling Add to Bot"); - // Ok(String::from("Hello")) - // } - - fn add_to_bot(self, bot:BotInstance) { - // let mut mgr = bot.botmodules; - // let nmod = self.module.clone(); - // mgr.add_botaction(nmod, BotAction::C(self)); - let mut mgr = bot.botmodules; - //let nmod = self.module.clone(); - // mgr.add_botaction(self.module.clone(), BotAction::C(self)); - - self.add_to_modmgr(&mut mgr); - } - - fn add_to_modmgr(self, modmgr:&mut ModulesManager) { - // // let mut mgr = bot.botmodules; - // // let nmod = self.module.clone(); - // // mgr.add_botaction(nmod, BotAction::C(self)); - // let mut mgr = modmgr; - // //let nmod = self.module.clone(); - // mgr.add_botaction(self.module.clone(), BotAction::C(self)); - // let mut mgr = modmgr; - // //let nmod = self.module.clone(); - modmgr.add_botaction(self.module.clone(), BotAction::C(self)); - } - - // => 12.23 - MF: NOTE : The exec body is defined ad module level , not this core level - - // fn exec_body(&self,m:&BotInstance,n:&PrivmsgMessage){ - // // => 12.23 - [ ] #todo requires field - // // (&self.exec)(String::from("Hello from BotAction Trait")) - // //self.exec_body(m,n) - // } - - // fn execute(&self,m:&mut BotInstance,n:&PrivmsgMessage){ - // // => 12.23 - [ ] #todo requires field - // // (&self.exec)(String::from("Hello from BotAction Trait")) - // //self.exec_body(m,n) - // (self.exec_body)(m,n) - // } -} - - -#[derive(Debug)] -pub struct Listener { +pub struct Listener +where + F: std::future::Future, +{ pub module : ModType, pub name : String, - pub exec_body : fn(&mut BotInstance,&PrivmsgMessage) , + //pub exec_body : fn(&mut BotInstance,&PrivmsgMessage) , + pub exec_body : fn(&mut Box>,&PrivmsgMessage) -> F , pub help : String } -impl Listener { +impl Listener +where + F: std::future::Future, +{ - async fn execute(&self,m:&mut BotInstance,n:&PrivmsgMessage){ + async fn execute(&self,m:&mut Box>,n:&PrivmsgMessage){ // => 12.23 - [ ] #todo requires field // (&self.exec)(String::from("Hello from BotAction Trait")) //self.exec_body(m,n) - (self.exec_body)(m,n) + (self.exec_body)(m,n).await; } } -impl BotActionTrait for Listener { +impl BotActionTrait for Listener +where + F: std::future::Future, +{ // fn add_to_bot(&self) -> Result> { // println!("Calling Add to Bot"); // Ok(String::from("Hello")) // } - fn add_to_bot(self, bot:BotInstance) { + fn add_to_bot(self, bot:BotInstance) { // let mut mgr = bot.botmodules; // let nmod = self.module.clone(); // mgr.add_botaction(nmod, BotAction::C(self)); @@ -193,7 +217,7 @@ impl BotActionTrait for Listener { self.add_to_modmgr(&mut mgr); } - fn add_to_modmgr(self, modmgr:&mut ModulesManager) { + fn add_to_modmgr(self, modmgr:&mut ModulesManager) { // // let mut mgr = bot.botmodules; // // let nmod = self.module.clone(); // // mgr.add_botaction(nmod, BotAction::C(self)); @@ -237,14 +261,20 @@ struct Routine {} #[derive(Debug)] -pub struct ModulesManager { +pub struct ModulesManager +where + F: std::future::Future, +{ statusdb: HashMap>, - botactions: HashMap>, + botactions: HashMap>>, } -impl ModulesManager { +impl ModulesManager +where + F: std::future::Future, +{ - pub fn init() -> ModulesManager { + pub fn init() -> ModulesManager { // initializes the modulers manager // Ideally, this should have added known modules based on @@ -341,7 +371,7 @@ impl ModulesManager { println!(">> Modules Manager : End of Init"); - println!(">> Modules Manager : {:?}",mgr); + //println!(">> Modules Manager : {:?}",mgr); mgr } @@ -371,7 +401,7 @@ impl ModulesManager { } - pub fn add_botaction(&mut self, in_module:ModType, in_action:BotAction ) -> () { + pub fn add_botaction(&mut self, in_module:ModType, in_action:BotAction ) -> () { /* adds a BotAction to the Modules Manager - This will require a BotModule passed as well This will including the logic of a valid add @@ -399,7 +429,10 @@ impl ModulesManager { // - If BotAction to Add is a BotCommand , In Module Manager DB (botactions), // Check All Other BotAction Command Names & Aliases to ensure they don't conflict - fn find_conflict_module(mgr:& ModulesManager, act:& BotAction) -> Option { + fn find_conflict_module(mgr:& ModulesManager, act:& BotAction) -> Option + where + F: std::future::Future, + { // Some(BotModule(String::from("GambaCore"))) @@ -412,70 +445,70 @@ impl ModulesManager { // BotAction::R(r) => None, // } - if let BotAction::C(incmd) = act { + // if let BotAction::C(incmd) = act { - // let n = & mgr.botactions; + // // let n = & mgr.botactions; - let d = &mgr.botactions; + // let d = &mgr.botactions; - for (module,moduleactions) in d { + // for (module,moduleactions) in d { - for modact in moduleactions.iter() { - if let BotAction::C(dbcmd) = &modact { - // At this point, there is an command incmd and looked up dbcmd + // for modact in moduleactions.iter() { + // if let BotAction::C(dbcmd) = &modact { + // // At this point, there is an command incmd and looked up dbcmd - // [x] check if given botcommand c.command:String conflicts with any in botactions + // // [x] check if given botcommand c.command:String conflicts with any in botactions - if incmd.command.to_lowercase() == dbcmd.command.to_lowercase() { - // Returning State - with the identified module - // return Some((module.clone(),BotAction::C(*dbcmd.clone()))); - // return Some(incmd); // for some reason I keep getting issues - //return Some(BotModule(String::from("GambaCore"))); // works - return Some(module.clone()); // works - // return Some(dbcmd.clone()); - } + // if incmd.command.to_lowercase() == dbcmd.command.to_lowercase() { + // // Returning State - with the identified module + // // return Some((module.clone(),BotAction::C(*dbcmd.clone()))); + // // return Some(incmd); // for some reason I keep getting issues + // //return Some(BotModule(String::from("GambaCore"))); // works + // return Some(module.clone()); // works + // // return Some(dbcmd.clone()); + // } - for a in &dbcmd.alias { - if incmd.command.to_lowercase() == a.to_lowercase() { - // Returning State - with the identified module - // return Some((module.clone(),BotAction::C(dbcmd))); - return Some(module.clone()); // works + // for a in &dbcmd.alias { + // if incmd.command.to_lowercase() == a.to_lowercase() { + // // Returning State - with the identified module + // // return Some((module.clone(),BotAction::C(dbcmd))); + // return Some(module.clone()); // works - } - } + // } + // } - // [x] Then do the same check except for each c.alias + // // [x] Then do the same check except for each c.alias - for inalias in &incmd.alias { + // for inalias in &incmd.alias { - if inalias.to_lowercase() == dbcmd.command.to_lowercase() { - // Returning State - with the identified module - // return Some((module.clone(),BotAction::C(dbcmd))); - return Some(module.clone()); // works + // if inalias.to_lowercase() == dbcmd.command.to_lowercase() { + // // Returning State - with the identified module + // // return Some((module.clone(),BotAction::C(dbcmd))); + // return Some(module.clone()); // works - } + // } - for a in &dbcmd.alias { - if inalias.to_lowercase() == a.to_lowercase() { - // Returning State - with the identified module - // return Some((module.clone(),BotAction::C(dbcmd))); - return Some(module.clone()); // works + // for a in &dbcmd.alias { + // if inalias.to_lowercase() == a.to_lowercase() { + // // Returning State - with the identified module + // // return Some((module.clone(),BotAction::C(dbcmd))); + // return Some(module.clone()); // works - } - } + // } + // } - } + // } - } - } + // } + // } - } + // } - // return Some(BotModule(String::from("GambaCore"))) - } + // // return Some(BotModule(String::from("GambaCore"))) + // } // for all other scenarios (e.g., Listener, Routine), find no conflicts @@ -488,7 +521,8 @@ impl ModulesManager { // panic!("ERROR: Could not add {:?} ; there was a conflict with existing module {:?}", in_action , probmod ); // } match find_conflict_module(&self, &in_action) { - Some(c) => panic!("ERROR: Could not add {:?} ; there was a conflict with existing module {:?}", in_action , c ), + // Some(c) => panic!("ERROR: Could not add {:?} ; there was a conflict with existing module {:?}", in_action , c ), + Some(c) => panic!("ERROR: Could not add module; there was a conflict with existing module {:?}", c ), None => (), } @@ -508,7 +542,7 @@ impl ModulesManager { modactions.push(in_action); println!(">> Modules Manager : Called Add bot Action"); - println!(">> Modules Manager : {:?}",&self); + //println!(">> Modules Manager : {:?}",&self); (); } diff --git a/src/main.rs b/src/main.rs index 90a3244..c31f2fc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,14 +17,17 @@ pub mod core; pub mod modules; +use std::process::Output; + use crate::core::botinstance::BotInstance; #[tokio::main] pub async fn main() { - let bot = BotInstance::init(); + let bot:BotInstance> = BotInstance::init(); + //let bot = BotInstance::init(); - bot.run().await; + bot.runner().await; } \ No newline at end of file diff --git a/src/modules.rs b/src/modules.rs index 74cd893..ddb87c1 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -19,7 +19,10 @@ mod experiments; // [ ] init() function that accepts bot instance - this is passed to init() on submodules -pub fn init(mgr:&mut ModulesManager) -> () { +pub fn init(mgr:&mut ModulesManager) -> () +where + F: std::future::Future, +{ // Modules initializer loads modules into the bot // this is achieved by calling submodules that also have fn init() defined diff --git a/src/modules/experiments.rs b/src/modules/experiments.rs index 94d9fdb..ae177ea 100644 --- a/src/modules/experiments.rs +++ b/src/modules/experiments.rs @@ -12,12 +12,15 @@ // mod crate::modules; //use crate::modules; -use crate::core::botmodules::{ModulesManager,BotCommand,Listener,BotModule,BotActionTrait}; +use crate::core::botmodules::{ModulesManager,Listener,BotModule,BotActionTrait}; use crate::core::botinstance::BotInstance; use twitch_irc::message::PrivmsgMessage; -pub fn init(mgr:&mut ModulesManager) -> () { +pub fn init(mgr:&mut ModulesManager) -> () +where + F: std::future::Future, +{ // BotCommand { @@ -55,7 +58,24 @@ pub fn init(mgr:&mut ModulesManager) -> () { // () // } - async fn good_girl(bot:&mut BotInstance,msg:&PrivmsgMessage) { +// async fn good_girl(bot:&mut BotInstance,msg:&PrivmsgMessage) +// where +// F: std::future::Future, +// { +// println!("In GoodGirl()"); +// println!("(#{}) {}: {}", msg.channel_login, msg.sender.name, msg.message_text); + +// if msg.sender.name == "ModulatingForce" && msg.message_text.contains("GoodGirl") { +// bot.chat.say_in_reply_to(msg,String::from("GoodGirl")).await; +// } + + +// } + +async fn good_girl(bot:&mut Box>,msg:&PrivmsgMessage) + where + F: std::future::Future, +{ println!("In GoodGirl()"); println!("(#{}) {}: {}", msg.channel_login, msg.sender.name, msg.message_text);