From b53047e7cfb8beaea093480d37155fb92f83772e Mon Sep 17 00:00:00 2001
From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com>
Date: Mon, 29 Jan 2024 04:09:53 -0500
Subject: [PATCH] Working BotCommand ExecBodies

---
 src/core/botinstance.rs    |  36 ++++++++++---
 src/core/botmodules.rs     | 103 ++++++++++---------------------------
 src/modules/experiments.rs |  18 ++++++-
 3 files changed, 72 insertions(+), 85 deletions(-)

diff --git a/src/core/botinstance.rs b/src/core/botinstance.rs
index 144c554..3d3f6b9 100644
--- a/src/core/botinstance.rs
+++ b/src/core/botinstance.rs
@@ -56,7 +56,7 @@ impl Chat {
 	pub async fn say_in_reply_to(&mut 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
@@ -269,16 +269,40 @@ impl BotInstance
 
     async fn listener_main_prvmsg(&mut self,msg:PrivmsgMessage) -> () {
 
-        println!("(#{}) {}: {}", msg.channel_login, msg.sender.name, msg.message_text);
+        // 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)
 
         for (_m,acts) in &self.botmodules.botactions {
             for a in acts {
-                // if let crate::core::botmodules::BotAction::L(lsnr) = a {
-                //     lsnr.execute(self.chat.clone(),msg.clone()).await;
-                // }
-                a.execute(self.chat.clone(), msg.clone()).await;
+
+                match a {
+
+                    crate::core::botmodules::BotAction::C(c) => {
+                        /* 
+                        BotCommand handling -
+                        - Checks if the input message is a prefix with command name or alias
+                        */
+
+                        let inpt = msg.message_text.split("\n").next().expect("ERROR during BotCommand");
+
+                        // [x] Check if a bot command based on ...
+                        //    [x] prefix + command
+                        if inpt == self.prefix.to_string() + c.command.as_str() {
+                            c.execute(self.chat.clone(), msg.clone()).await;
+                        } 
+
+                        //    [x] prefix + alias
+                        for alias in &c.alias {
+                            if inpt == self.prefix.to_string() + alias.as_str() {
+                                c.execute(self.chat.clone(), msg.clone()).await;
+                            } 
+                        }
+                    },
+
+                    crate::core::botmodules::BotAction::L(l) => l.execute(self.chat.clone(), msg.clone()).await,
+                    _ => (),
+                }
             }
         };
 
diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs
index 0705eae..aab2cf2 100644
--- a/src/core/botmodules.rs
+++ b/src/core/botmodules.rs
@@ -58,7 +58,7 @@ pub enum ModStatusType {
     
 pub enum BotAction
 {
-	//C(BotCommand),
+	C(BotCommand),
     L(Listener),
 	R(Routine),
 }
@@ -68,6 +68,7 @@ impl BotAction {
         
         match self {
             BotAction::L(a) => a.execute(m,n).await,
+            BotAction::C(a) => a.execute(m,n).await,
             _ => (),
         }
 
@@ -81,88 +82,36 @@ pub trait BotActionTrait
 }
 
 
-// #[derive(Debug)]
-// pub struct BotCommand {
-//     pub module : ModType,
-//     pub command : String, // command call name
-//     pub alias : Vec<String>, // String of alternative names
-//     // bot_prefix : char, // although should be global?
-//     exec_body : fn(&BotInstance<F>,&PrivmsgMessage),
-//     pub help : String,
-// }
+pub struct BotCommand {
+    pub module : ModType,
+    pub command : String, // command call name
+    pub alias : Vec<String>, // String of alternative names
+    // bot_prefix : char, // although should be global?
+    pub exec_body : bot_actions::actions_util::ExecBody,
+    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);
-//     // }
+impl BotCommand
+{
+    pub async fn execute(&self,m:botinstance::Chat,n:PrivmsgMessage){
+        (self.exec_body)(m,n).await;
+    }
+}
 
 
-//     // 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, mut bot:BotInstance) {    
+        let mgr = &mut bot.botmodules;
+        self.add_to_modmgr(mgr);
+    }
 
+    fn add_to_modmgr(self, modmgr:&mut ModulesManager) {
+        modmgr.add_botaction(self.module.clone(), BotAction::C(self))
+    }
 
-// }
+}
 
-// impl BotActionTrait for BotCommand {
-//     // fn add_to_bot(&self) -> Result<String,Box<dyn Error>> {
-//     //     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<F>(self, modmgr:&mut ModulesManager<F>) {
-//         // // 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)
-//     // }
-// }
 
 
 pub mod bot_actions {
diff --git a/src/modules/experiments.rs b/src/modules/experiments.rs
index a2d34a5..891db52 100644
--- a/src/modules/experiments.rs
+++ b/src/modules/experiments.rs
@@ -14,7 +14,7 @@
 
 use std::future::Future;
 
-use crate::core::botmodules::{ModulesManager,Listener,BotModule,BotActionTrait, self};
+use crate::core::botmodules::{ModulesManager,Listener,BotModule,BotActionTrait, BotCommand};
 use crate::core::botmodules::bot_actions::actions_util;
 
 use crate::core::botinstance::{self};
@@ -33,6 +33,14 @@ pub fn init(mgr:&mut ModulesManager)
     //     help : String::from("DUPCMD4 tester"),
     // }.add_to_modmgr(mgr);
 
+        BotCommand {
+            module : BotModule(String::from("experiments 004")),
+            command : String::from("test"), // command call name
+            alias : vec![String::from("tester"),String::from("testy")], // String of alternative names
+            exec_body : actions_util::asyncbox(testy) ,
+            help : String::from("DUPCMD4 tester"),
+        }.add_to_modmgr(mgr);
+
 
     let list1 = Listener {
             module : BotModule(String::from("experiments 004")),
@@ -50,7 +58,7 @@ pub fn init(mgr:&mut ModulesManager)
 async fn good_girl(mut chat:botinstance::Chat,msg:PrivmsgMessage)
 {
     println!("In GoodGirl()");
-    println!("(#{}) {}: {}", msg.channel_login, msg.sender.name, msg.message_text);
+    //println!("(#{}) {}: {}", msg.channel_login, msg.sender.name, msg.message_text);
 
     if msg.sender.name == "ModulatingForce" && msg.message_text.contains("GoodGirl") {
         chat.say_in_reply_to(&msg,String::from("GoodGirl")).await;
@@ -58,3 +66,9 @@ async fn good_girl(mut chat:botinstance::Chat,msg:PrivmsgMessage)
 
     
 }
+
+async fn testy(mut _chat:botinstance::Chat,_msg:PrivmsgMessage)
+{
+    println!("testy triggered!")
+
+}
\ No newline at end of file