From fb1617d6d9c07e14e70a024c02b255b78b0079e2 Mon Sep 17 00:00:00 2001
From: haruyuumei <luzivotto.erick@gmail.com>
Date: Sun, 17 Mar 2024 18:40:12 -0300
Subject: [PATCH 01/31] minor spelling mistake

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index c736061..8637fdc 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ test ModulatingForceBot
 
 ```
 login_name = <botname>
-access_token = <oath token>
+access_token = <oauth token>
 bot_channels = <chnl1>,<chnl2>
 prefix = <prefix>
 ```
\ No newline at end of file

From 5fb373c522abbf350596e7c0ed98d7b4ec015513 Mon Sep 17 00:00:00 2001
From: haruyuumei <luzivotto.erick@gmail.com>
Date: Sun, 17 Mar 2024 19:12:33 -0300
Subject: [PATCH 02/31] bot admins change

---
 src/core/identity.rs | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/src/core/identity.rs b/src/core/identity.rs
index 877fb6c..6392eb3 100644
--- a/src/core/identity.rs
+++ b/src/core/identity.rs
@@ -11,10 +11,19 @@ use crate::core::bot_actions::actions_util::{self, BotAR};
 use crate::core::botinstance::ChType;
 use crate::core::botlog;
 use crate::core::botmodules::{BotActionTrait, BotCommand, BotModule, ModulesManager};
+use dotenv::dotenv;
+use std::env;
 
 fn adminvector() -> Vec<String> {
-    vec![String::from("ModulatingForce")]
-    //vec![]
+    // vec![String::from("ModulatingForce")]
+    // //vec![]
+    dotenv().ok();
+    let mut admins = Vec::new();
+
+    for admin in env::var("bot_admins").unwrap().split(',') {
+        admins.push(String::from(admin))
+    }
+    admins
 }
 
 pub async fn init(mgr: Arc<ModulesManager>) {

From f7881fa07d5ff5a6d1295eaf80c88214437df746 Mon Sep 17 00:00:00 2001
From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com>
Date: Sun, 17 Mar 2024 19:29:22 -0400
Subject: [PATCH 03/31] adj adminvector()

---
 README.md            |  1 +
 src/core/identity.rs | 17 +++++++++++++++--
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 8637fdc..33fdb59 100644
--- a/README.md
+++ b/README.md
@@ -12,4 +12,5 @@ login_name = <botname>
 access_token = <oauth token>
 bot_channels = <chnl1>,<chnl2>
 prefix = <prefix>
+bot_admins = <admins>
 ```
\ No newline at end of file
diff --git a/src/core/identity.rs b/src/core/identity.rs
index 6392eb3..42bc4c7 100644
--- a/src/core/identity.rs
+++ b/src/core/identity.rs
@@ -20,9 +20,22 @@ fn adminvector() -> Vec<String> {
     dotenv().ok();
     let mut admins = Vec::new();
 
-    for admin in env::var("bot_admins").unwrap().split(',') {
-        admins.push(String::from(admin))
+    // for admin in env::var("bot_admins").unwrap().split(',') {
+    //     admins.push(String::from(admin))
+    // }
+
+    // 03.17 - Forcen - Suggesting below instead : 
+    /*
+        - this will push only if env::var() returns Ok() ; 
+            otherwise (like in Err(_)) do nothing
+     */
+
+    if let Ok(value) = env::var("bot_admins") {
+        for admin in value.split(',') {
+            admins.push(String::from(admin))        
+        }
     }
+
     admins
 }
 

From 95a9962721c53c4a199434333f22b279cec87766 Mon Sep 17 00:00:00 2001
From: haruyuumei <luzivotto.erick@gmail.com>
Date: Thu, 28 Mar 2024 15:38:49 -0300
Subject: [PATCH 04/31] new module test

trying to add a new module
---
 src/custom/experimental/experiment001.rs |  4 --
 src/lib.rs                               |  1 +
 src/modules.rs                           | 10 ++++
 src/modules/test.rs                      | 17 ++++++
 src/modules/thisguy.rs                   | 68 ++++++++++++++++++++++++
 5 files changed, 96 insertions(+), 4 deletions(-)
 create mode 100644 src/modules.rs
 create mode 100644 src/modules/test.rs
 create mode 100644 src/modules/thisguy.rs

diff --git a/src/custom/experimental/experiment001.rs b/src/custom/experimental/experiment001.rs
index dd3cba4..28d499b 100644
--- a/src/custom/experimental/experiment001.rs
+++ b/src/custom/experimental/experiment001.rs
@@ -122,8 +122,6 @@ async fn good_girl(params : ExecBodyParams) {
             );
 
             let bot = Arc::clone(&params.bot);
-
-
             let botlock = bot.read().await;
 
             // uses chat.say_in_reply_to() for the bot controls for messages
@@ -135,8 +133,6 @@ async fn good_girl(params : ExecBodyParams) {
                 String::from("GoodGirl xdd "),
                 params.clone()
             ).await;
-
-
         }
     }
 }
diff --git a/src/lib.rs b/src/lib.rs
index c5ba775..f01fd10 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,2 +1,3 @@
 pub mod core;
 pub mod custom;
+pub mod modules;
\ No newline at end of file
diff --git a/src/modules.rs b/src/modules.rs
new file mode 100644
index 0000000..d0b1c6e
--- /dev/null
+++ b/src/modules.rs
@@ -0,0 +1,10 @@
+use std::sync::Arc;
+pub use crate::core::botinstance::BotInstance;
+pub use crate::core::botmodules::ModulesManager;
+
+
+mod thisguy;
+
+pub async fn init(mgr:&Arc<ModulesManager>){
+    thisguy::init(mgr).await;
+}
\ No newline at end of file
diff --git a/src/modules/test.rs b/src/modules/test.rs
new file mode 100644
index 0000000..ba7d68d
--- /dev/null
+++ b/src/modules/test.rs
@@ -0,0 +1,17 @@
+use std::sync::Arc;
+
+// pub use crate::core::botinstance::BotInstance;
+pub use crate::core::botmodules::ModulesManager;
+
+// [ ] Load submodules
+
+mod thisguy;
+
+// [ ] init() function that accepts bot instance - this is passed to init() on submodules
+
+pub async fn init(mgr: Arc<ModulesManager>) {
+    // Modules initializer loads modules into the bot
+    // this is achieved by calling submodules that also have fn init() defined
+
+    thisguy::init(Arc::clone(&mgr)).await;
+}
diff --git a/src/modules/thisguy.rs b/src/modules/thisguy.rs
new file mode 100644
index 0000000..339d4c4
--- /dev/null
+++ b/src/modules/thisguy.rs
@@ -0,0 +1,68 @@
+use crate::core::botmodules::{ BotActionTrait, BotCommand, BotModule, Listener, ModulesManager};
+use crate::core::identity::UserRole::*;
+use crate::core::bot_actions::*;
+use crate::core::botlog;
+use std::sync::Arc;
+use tokio::time::{sleep, Duration};
+
+
+async fn tsg(params: ExecBodyParams){
+
+    
+
+    if params.msg.sender.name.to_lowercase() == "haruyuumei".to_lowercase()
+    //|| params.msg.sender.name.to_lowercase() == "ModulatingForce".to_lowercase()
+    {
+        botlog::debug(
+            "Oh god I love anime Girls!!",
+            Some("modules > thisguy()".to_string()),
+            Some(&params.msg),
+        );
+        let bot = Arc::clone(&params.bot);
+        let botlock = bot.read().await;
+
+        // uses chat.say_in_reply_to() for the bot controls for messages
+        botlock
+        .botmgrs
+        .chat
+        .say_in_reply_to(
+            &params.msg, 
+            String::from("Oh god I love anime Girls!!"),
+            params.clone()
+        ).await;
+        sleep(Duration::from_secs_f64(0.5)).await;
+    }
+    
+}
+
+pub async fn init(mgr:&Arc<ModulesManager>){
+
+    BotCommand{
+        module:BotModule(String::from("thisguy")),
+        command: String::from("this"),
+        alias: vec![String::from("tsg")],
+        exec_body: actions_util::asyncbox(tesst),
+        help: String::from("test"),
+        required_roles: vec![
+        BotAdmin,
+        ],
+    }.add_to_modmgr(Arc::clone(&mgr)).await;
+    
+
+
+    Listener {
+        module: BotModule(String::from("thisguy")),
+        name: String::from("This Guy Listener"),
+        exec_body: actions_util::asyncbox(tsg),
+        help: String::from(""),
+    }.add_to_modmgr(Arc::clone(&mgr)).await;
+}
+
+async fn tesst(params : ExecBodyParams) {
+    println!("tesst triggered!"); // NOTE : This test function intends to print (e.g., to stdout) at fn call
+    botlog::debug(
+        "tesst triggered!",
+        Some("modules > tesst()".to_string()),
+        Some(&params.msg),
+    );
+}

From f8de595290c5bfabb1e591373964e0edc85755d5 Mon Sep 17 00:00:00 2001
From: haruyuumei <luzivotto.erick@gmail.com>
Date: Thu, 28 Mar 2024 18:50:28 -0300
Subject: [PATCH 05/31] custom module update

---
 src/custom.rs                            |  4 +++-
 src/custom/experimental/experiment001.rs |  1 +
 src/{modules => custom}/thisguy.rs       | 28 +++++++++++++++---------
 src/lib.rs                               |  3 +--
 src/modules.rs                           | 10 ---------
 src/modules/test.rs                      | 17 --------------
 6 files changed, 23 insertions(+), 40 deletions(-)
 rename src/{modules => custom}/thisguy.rs (73%)
 delete mode 100644 src/modules.rs
 delete mode 100644 src/modules/test.rs

diff --git a/src/custom.rs b/src/custom.rs
index 6107797..56c6257 100644
--- a/src/custom.rs
+++ b/src/custom.rs
@@ -13,6 +13,7 @@ pub use crate::core::botmodules::ModulesManager;
 
 // mod experiments;
 mod experimental;
+mod thisguy;
 
 // [ ] init() function that accepts bot instance - this is passed to init() on submodules
 
@@ -21,5 +22,6 @@ pub async fn init(mgr: Arc<ModulesManager>) {
     // this is achieved by calling submodules that also have fn init() defined
 
     // experiments::init(mgr).await
-    experimental::init(mgr).await;
+    experimental::init(mgr.clone()).await;
+    thisguy::init(&mgr).await;
 }
diff --git a/src/custom/experimental/experiment001.rs b/src/custom/experimental/experiment001.rs
index 28d499b..92af44d 100644
--- a/src/custom/experimental/experiment001.rs
+++ b/src/custom/experimental/experiment001.rs
@@ -105,6 +105,7 @@ async fn good_girl(params : ExecBodyParams) {
 
     if params.msg.sender.name.to_lowercase() == "ModulatingForce".to_lowercase()
         || params.msg.sender.name.to_lowercase() == "mzNToRi".to_lowercase()
+        || params.msg.sender.name.to_lowercase() == "haruyuumei".to_lowercase()
     {
         botlog::debug(
             "Good Girl Detected > Pausechamp",
diff --git a/src/modules/thisguy.rs b/src/custom/thisguy.rs
similarity index 73%
rename from src/modules/thisguy.rs
rename to src/custom/thisguy.rs
index 339d4c4..b5e895f 100644
--- a/src/modules/thisguy.rs
+++ b/src/custom/thisguy.rs
@@ -3,16 +3,26 @@ use crate::core::identity::UserRole::*;
 use crate::core::bot_actions::*;
 use crate::core::botlog;
 use std::sync::Arc;
+use rand::Rng;
 use tokio::time::{sleep, Duration};
-
+//use rand::Rng;
 
 async fn tsg(params: ExecBodyParams){
 
-    
-
     if params.msg.sender.name.to_lowercase() == "haruyuumei".to_lowercase()
-    //|| params.msg.sender.name.to_lowercase() == "ModulatingForce".to_lowercase()
+    || params.msg.sender.name.to_lowercase() == "ModulatingForce".to_lowercase()
     {
+        let phrases: [String;5] = [
+        "Aware Weebs...".to_string(),
+        "AYAYA I love anime Girls!!".to_string(),
+        "I love 2d Girls ILOST".to_string(),
+        "UOOHHHHH!!! Anime Girlssss".to_string(),
+        "Anime girls u say? peepoShy".to_string(),
+        ];
+        
+        let r = rand::thread_rng().gen_range(0..=4);
+        let a = phrases[r].clone();
+
         botlog::debug(
             "Oh god I love anime Girls!!",
             Some("modules > thisguy()".to_string()),
@@ -26,8 +36,8 @@ async fn tsg(params: ExecBodyParams){
         .botmgrs
         .chat
         .say_in_reply_to(
-            &params.msg, 
-            String::from("Oh god I love anime Girls!!"),
+            &params.msg,
+        a,
             params.clone()
         ).await;
         sleep(Duration::from_secs_f64(0.5)).await;
@@ -39,16 +49,14 @@ pub async fn init(mgr:&Arc<ModulesManager>){
 
     BotCommand{
         module:BotModule(String::from("thisguy")),
-        command: String::from("this"),
-        alias: vec![String::from("tsg")],
+        command: String::from("anime"),
+        alias: vec![String::from("Anime")],
         exec_body: actions_util::asyncbox(tesst),
         help: String::from("test"),
         required_roles: vec![
         BotAdmin,
         ],
     }.add_to_modmgr(Arc::clone(&mgr)).await;
-    
-
 
     Listener {
         module: BotModule(String::from("thisguy")),
diff --git a/src/lib.rs b/src/lib.rs
index f01fd10..667ce02 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,3 +1,2 @@
 pub mod core;
-pub mod custom;
-pub mod modules;
\ No newline at end of file
+pub mod custom;
\ No newline at end of file
diff --git a/src/modules.rs b/src/modules.rs
deleted file mode 100644
index d0b1c6e..0000000
--- a/src/modules.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-use std::sync::Arc;
-pub use crate::core::botinstance::BotInstance;
-pub use crate::core::botmodules::ModulesManager;
-
-
-mod thisguy;
-
-pub async fn init(mgr:&Arc<ModulesManager>){
-    thisguy::init(mgr).await;
-}
\ No newline at end of file
diff --git a/src/modules/test.rs b/src/modules/test.rs
deleted file mode 100644
index ba7d68d..0000000
--- a/src/modules/test.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-use std::sync::Arc;
-
-// pub use crate::core::botinstance::BotInstance;
-pub use crate::core::botmodules::ModulesManager;
-
-// [ ] Load submodules
-
-mod thisguy;
-
-// [ ] init() function that accepts bot instance - this is passed to init() on submodules
-
-pub async fn init(mgr: Arc<ModulesManager>) {
-    // Modules initializer loads modules into the bot
-    // this is achieved by calling submodules that also have fn init() defined
-
-    thisguy::init(Arc::clone(&mgr)).await;
-}

From fda7afb1918c8b59c542577d480d1149884b8e81 Mon Sep 17 00:00:00 2001
From: haruyuumei <luzivotto.erick@gmail.com>
Date: Thu, 28 Mar 2024 19:33:06 -0300
Subject: [PATCH 06/31] custom module working

---
 src/custom/thisguy.rs | 63 +++++++++++++++++++++----------------------
 1 file changed, 31 insertions(+), 32 deletions(-)

diff --git a/src/custom/thisguy.rs b/src/custom/thisguy.rs
index b5e895f..cf31b34 100644
--- a/src/custom/thisguy.rs
+++ b/src/custom/thisguy.rs
@@ -1,25 +1,25 @@
-use crate::core::botmodules::{ BotActionTrait, BotCommand, BotModule, Listener, ModulesManager};
-use crate::core::identity::UserRole::*;
 use crate::core::bot_actions::*;
 use crate::core::botlog;
-use std::sync::Arc;
+use crate::core::botmodules::{BotActionTrait, BotCommand, BotModule, Listener, ModulesManager};
+use crate::core::identity::UserRole::*;
 use rand::Rng;
+use std::sync::Arc;
 use tokio::time::{sleep, Duration};
+
 //use rand::Rng;
 
-async fn tsg(params: ExecBodyParams){
-
-    if params.msg.sender.name.to_lowercase() == "haruyuumei".to_lowercase()
-    || params.msg.sender.name.to_lowercase() == "ModulatingForce".to_lowercase()
+async fn tsg(params: ExecBodyParams) {
+    if params.msg.message_text == String::from("anime")
+        || params.msg.message_text == String::from("Anime")
     {
-        let phrases: [String;5] = [
-        "Aware Weebs...".to_string(),
-        "AYAYA I love anime Girls!!".to_string(),
-        "I love 2d Girls ILOST".to_string(),
-        "UOOHHHHH!!! Anime Girlssss".to_string(),
-        "Anime girls u say? peepoShy".to_string(),
+        let phrases: [String; 5] = [
+            "Aware oh no! Weebs...".to_string(),
+            "AYAYA I love anime Girls!!".to_string(),
+            "I love 2d Girls ILOST ".to_string(),
+            "UOOHHHHH!!! Anime Girlssss".to_string(),
+            "Anime girls u say? peepoShy ".to_string(),
         ];
-        
+
         let r = rand::thread_rng().gen_range(0..=4);
         let a = phrases[r].clone();
 
@@ -33,40 +33,39 @@ async fn tsg(params: ExecBodyParams){
 
         // uses chat.say_in_reply_to() for the bot controls for messages
         botlock
-        .botmgrs
-        .chat
-        .say_in_reply_to(
-            &params.msg,
-        a,
-            params.clone()
-        ).await;
+            .botmgrs
+            .chat
+            .say_in_reply_to(&params.msg, a, params.clone())
+            .await;
         sleep(Duration::from_secs_f64(0.5)).await;
+    }else {
+        
     }
-    
 }
 
-pub async fn init(mgr:&Arc<ModulesManager>){
-
-    BotCommand{
-        module:BotModule(String::from("thisguy")),
+pub async fn init(mgr: &Arc<ModulesManager>) {
+    BotCommand {
+        module: BotModule(String::from("thisguy")),
         command: String::from("anime"),
         alias: vec![String::from("Anime")],
         exec_body: actions_util::asyncbox(tesst),
         help: String::from("test"),
-        required_roles: vec![
-        BotAdmin,
-        ],
-    }.add_to_modmgr(Arc::clone(&mgr)).await;
+        required_roles: vec![BotAdmin],
+    }
+    .add_to_modmgr(Arc::clone(&mgr))
+    .await;
 
     Listener {
         module: BotModule(String::from("thisguy")),
         name: String::from("This Guy Listener"),
         exec_body: actions_util::asyncbox(tsg),
         help: String::from(""),
-    }.add_to_modmgr(Arc::clone(&mgr)).await;
+    }
+    .add_to_modmgr(Arc::clone(&mgr))
+    .await;
 }
 
-async fn tesst(params : ExecBodyParams) {
+async fn tesst(params: ExecBodyParams) {
     println!("tesst triggered!"); // NOTE : This test function intends to print (e.g., to stdout) at fn call
     botlog::debug(
         "tesst triggered!",

From f2893791b9de1813b1e5d2e9ee7ea075f93d5c67 Mon Sep 17 00:00:00 2001
From: mzntori <mzntori@proton.me>
Date: Sat, 30 Mar 2024 01:42:06 +0100
Subject: [PATCH 07/31] add reply parent functionality

---
 src/core/bot_actions.rs | 58 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/src/core/bot_actions.rs b/src/core/bot_actions.rs
index 8941654..cf7557f 100644
--- a/src/core/bot_actions.rs
+++ b/src/core/bot_actions.rs
@@ -57,9 +57,67 @@ impl ExecBodyParams {
         requestor_badge_mut
     }
 
+    /// Returns some information about the message that was replied to by the `PrivmsgMessage` contained
+    /// in the `msg` field of this struct.
+    ///
+    /// If that message replied to message return that information in form of `Some<ReplyParent>`.
+    /// Otherwise, return `None`.
+    pub fn get_parent_reply(&self) -> Option<ReplyParent> {
+        let map = &self.msg.source.tags.0;
+        let tags = [
+            "reply-parent-user-id",
+            "reply-parent-user-login",
+            "reply-parent-display-name",
+            "reply-parent-msg-id",
+            "reply-parent-msg-body"
+        ];
 
+        // filter out all tags that do not have content.
+        let tag_contents: Vec<String> = tags.iter().filter_map(|tag| {
+            if let Some(&Some(ref t)) = map.get(*tag) {
+                Some(t.clone())
+            } else {
+                None
+            }
+        }).collect();
+
+        // if no tags got filtered out return the struct.
+        // else return `None`.
+        return if tag_contents.len() == 5 {
+            Some(ReplyParent {
+                sender: TwitchUserBasics {
+                    id: tag_contents[0].clone(),
+                    login: tag_contents[1].clone(),
+                    name: tag_contents[2].clone(),
+                },
+                message_id: tag_contents[3].clone(),
+                message_text: tag_contents[4].clone(),
+                channel_login: self.msg.channel_login.clone(),
+                channel_id: self.msg.channel_id.clone(),
+            })
+        } else {
+            None
+        }
+    }
 }
 
+/// Represents the message a `PrivmsgMessage` replies to.
+/// Similar to a less detailed `PrivmsgMessage`.
+///
+/// This should not be constructed manually but only from calling `get_parent_reply()` on
+/// `ExecBodyParams`.
+///
+/// Fields that will be the same as the `PrivmsgMessage` this was generated from:
+/// - `channel_login`
+/// - `channel_id`
+#[derive(Debug, Clone, PartialEq)]
+pub struct ReplyParent {
+    pub sender: TwitchUserBasics,
+    pub message_id: String,
+    pub message_text: String,
+    pub channel_login: String,
+    pub channel_id: String,
+}
 
 
 pub mod actions_util {

From a048003e93e7f1175ea38341439e4cec7ae7f8b3 Mon Sep 17 00:00:00 2001
From: mzntori <mzntori@proton.me>
Date: Sat, 30 Mar 2024 01:47:32 +0100
Subject: [PATCH 08/31] oops forgot to add the use statement

---
 src/core/bot_actions.rs | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/core/bot_actions.rs b/src/core/bot_actions.rs
index cf7557f..f5c8a66 100644
--- a/src/core/bot_actions.rs
+++ b/src/core/bot_actions.rs
@@ -1,5 +1,4 @@
-
-use twitch_irc::message::PrivmsgMessage;
+use twitch_irc::message::{PrivmsgMessage, TwitchUserBasics};
 use std::sync::Arc;
 use tokio::sync::RwLock;
 

From 72d4cf6d70924d9d2908f9aa69332a7f3b48d6e8 Mon Sep 17 00:00:00 2001
From: haruyuumei <luzivotto.erick@gmail.com>
Date: Sun, 31 Mar 2024 14:37:50 -0300
Subject: [PATCH 09/31] Small changes on thisguy.rs

---
 src/custom/thisguy.rs | 86 ++++++++++++++++++++++++++++++++++---------
 1 file changed, 69 insertions(+), 17 deletions(-)

diff --git a/src/custom/thisguy.rs b/src/custom/thisguy.rs
index cf31b34..2a8e445 100644
--- a/src/custom/thisguy.rs
+++ b/src/custom/thisguy.rs
@@ -6,25 +6,42 @@ use rand::Rng;
 use std::sync::Arc;
 use tokio::time::{sleep, Duration};
 
-//use rand::Rng;
 
+//using the env file to get bot prefix
+use std::env;
+use dotenv::dotenv;
+
+//bot function
 async fn tsg(params: ExecBodyParams) {
-    if params.msg.message_text == String::from("anime")
-        || params.msg.message_text == String::from("Anime")
+
+    //Defining a var prefix to the prefix on the env file
+    dotenv().ok();
+    let prefix = env::var("prefix").unwrap();
+    /*  
+        defining a text with the prefix + the command name (idk how to get the command)
+        so for now i'm typing the command
+    */
+    let text = String::from(&prefix) + "This";
+    let text2 = String::from(&prefix) + "this";
+
+    //comparing the text sent with the text (prefix + command name)
+    if params.msg.message_text == text
+        || params.msg.message_text == text2
     {
-        let phrases: [String; 5] = [
-            "Aware oh no! Weebs...".to_string(),
-            "AYAYA I love anime Girls!!".to_string(),
-            "I love 2d Girls ILOST ".to_string(),
-            "UOOHHHHH!!! Anime Girlssss".to_string(),
-            "Anime girls u say? peepoShy ".to_string(),
+        let phrases: [String; 6] = [
+            "Clueless".to_string(),
+            "ICANT This guy....".to_string(),
+            "He is right tho".to_string(),
+            "KEKW true!".to_string(),
+            "OMEGALUL wth man...".to_string(),
+            "PepeLaugh El no sabe".to_string(),
         ];
 
         let r = rand::thread_rng().gen_range(0..=4);
         let a = phrases[r].clone();
 
         botlog::debug(
-            "Oh god I love anime Girls!!",
+            "This guy works!",
             Some("modules > thisguy()".to_string()),
             Some(&params.msg),
         );
@@ -39,16 +56,16 @@ async fn tsg(params: ExecBodyParams) {
             .await;
         sleep(Duration::from_secs_f64(0.5)).await;
     }else {
-        
+        println!("didn't type the proper command");
     }
 }
 
 pub async fn init(mgr: &Arc<ModulesManager>) {
     BotCommand {
         module: BotModule(String::from("thisguy")),
-        command: String::from("anime"),
-        alias: vec![String::from("Anime")],
-        exec_body: actions_util::asyncbox(tesst),
+        command: String::from("thisguy"),
+        alias: vec![String::from("Thisguy")],
+        exec_body: actions_util::asyncbox(test),
         help: String::from("test"),
         required_roles: vec![BotAdmin],
     }
@@ -65,11 +82,46 @@ pub async fn init(mgr: &Arc<ModulesManager>) {
     .await;
 }
 
-async fn tesst(params: ExecBodyParams) {
-    println!("tesst triggered!"); // NOTE : This test function intends to print (e.g., to stdout) at fn call
+
+async fn test(params: ExecBodyParams) {
+    println!("Test triggered!"); // NOTE : This test function intends to print (e.g., to stdout) at fn call
     botlog::debug(
-        "tesst triggered!",
+        "test triggered!",
         Some("modules > tesst()".to_string()),
         Some(&params.msg),
     );
 }
+
+
+// just testing this area, not working atm
+async fn replyer(params: ExecBodyParams)
+{
+    /*
+        check if the command message was a reply
+        get reply message parent
+        reply to the parent
+     */
+
+    //let reply_parent_message;
+    let reply_message: &String = &params.msg.message_text;
+    let my_reply:String = String::from("test");
+
+    //println!("{:?}",reply_parent_message);
+    println!("{}",reply_message);
+
+    botlog::debug(
+        "Oh god I love anime Girls!!",
+        Some("modules > thisguy()".to_string()),
+        Some(&params.msg),
+    );
+    let bot = Arc::clone(&params.bot);
+    let botlock = bot.read().await;  
+
+    // uses chat.say_in_reply_to() for the bot controls for messages
+    botlock
+        .botmgrs
+        .chat
+        .say_in_reply_to(&params.msg, my_reply, params.clone())
+        .await;
+    sleep(Duration::from_secs_f64(0.5)).await;
+}
\ No newline at end of file

From d972eb77266dedf9cdfae2189dd586699e4ca080 Mon Sep 17 00:00:00 2001
From: haruyuumei <luzivotto.erick@gmail.com>
Date: Tue, 2 Apr 2024 20:11:01 -0300
Subject: [PATCH 10/31] Thisguy working partially

not fully implemented reply to the reply
---
 src/custom/thisguy.rs | 38 ++------------------------------------
 1 file changed, 2 insertions(+), 36 deletions(-)

diff --git a/src/custom/thisguy.rs b/src/custom/thisguy.rs
index 2a8e445..b539b3e 100644
--- a/src/custom/thisguy.rs
+++ b/src/custom/thisguy.rs
@@ -6,12 +6,12 @@ use rand::Rng;
 use std::sync::Arc;
 use tokio::time::{sleep, Duration};
 
-
 //using the env file to get bot prefix
 use std::env;
 use dotenv::dotenv;
 
 //bot function
+
 async fn tsg(params: ExecBodyParams) {
 
     //Defining a var prefix to the prefix on the env file
@@ -56,7 +56,7 @@ async fn tsg(params: ExecBodyParams) {
             .await;
         sleep(Duration::from_secs_f64(0.5)).await;
     }else {
-        println!("didn't type the proper command");
+        //println!("didn't type the proper command");
     }
 }
 
@@ -91,37 +91,3 @@ async fn test(params: ExecBodyParams) {
         Some(&params.msg),
     );
 }
-
-
-// just testing this area, not working atm
-async fn replyer(params: ExecBodyParams)
-{
-    /*
-        check if the command message was a reply
-        get reply message parent
-        reply to the parent
-     */
-
-    //let reply_parent_message;
-    let reply_message: &String = &params.msg.message_text;
-    let my_reply:String = String::from("test");
-
-    //println!("{:?}",reply_parent_message);
-    println!("{}",reply_message);
-
-    botlog::debug(
-        "Oh god I love anime Girls!!",
-        Some("modules > thisguy()".to_string()),
-        Some(&params.msg),
-    );
-    let bot = Arc::clone(&params.bot);
-    let botlock = bot.read().await;  
-
-    // uses chat.say_in_reply_to() for the bot controls for messages
-    botlock
-        .botmgrs
-        .chat
-        .say_in_reply_to(&params.msg, my_reply, params.clone())
-        .await;
-    sleep(Duration::from_secs_f64(0.5)).await;
-}
\ No newline at end of file

From 7e04699b67c4191b7b4ca8107057f3b6c6b109ce Mon Sep 17 00:00:00 2001
From: haruyuumei <luzivotto.erick@gmail.com>
Date: Wed, 3 Apr 2024 10:25:24 -0300
Subject: [PATCH 11/31] making changes

---
 src/custom/thisguy.rs | 104 ++++++++++++++----------------------------
 1 file changed, 35 insertions(+), 69 deletions(-)

diff --git a/src/custom/thisguy.rs b/src/custom/thisguy.rs
index b539b3e..0ca6de8 100644
--- a/src/custom/thisguy.rs
+++ b/src/custom/thisguy.rs
@@ -1,63 +1,44 @@
 use crate::core::bot_actions::*;
+use crate::core::botinstance::Channel;
 use crate::core::botlog;
-use crate::core::botmodules::{BotActionTrait, BotCommand, BotModule, Listener, ModulesManager};
+use crate::core::botmodules::{BotActionTrait, BotCommand, BotModule, ModulesManager};
 use crate::core::identity::UserRole::*;
 use rand::Rng;
 use std::sync::Arc;
 use tokio::time::{sleep, Duration};
-
-//using the env file to get bot prefix
-use std::env;
-use dotenv::dotenv;
-
-//bot function
+const OF_CMD_CHANNEL:Channel = Channel(String::new());
 
 async fn tsg(params: ExecBodyParams) {
 
-    //Defining a var prefix to the prefix on the env file
-    dotenv().ok();
-    let prefix = env::var("prefix").unwrap();
-    /*  
-        defining a text with the prefix + the command name (idk how to get the command)
-        so for now i'm typing the command
-    */
-    let text = String::from(&prefix) + "This";
-    let text2 = String::from(&prefix) + "this";
+    let phrases: [String; 6] = [
+        "Clueless ".to_string(),
+        "ICANT This guy....".to_string(),
+        "He is right tho".to_string(),
+        "KEKW true!".to_string(),
+        "OMEGALUL wth man...".to_string(),
+        "PepeLaugh El no sabe".to_string(),
+    ];
 
-    //comparing the text sent with the text (prefix + command name)
-    if params.msg.message_text == text
-        || params.msg.message_text == text2
-    {
-        let phrases: [String; 6] = [
-            "Clueless".to_string(),
-            "ICANT This guy....".to_string(),
-            "He is right tho".to_string(),
-            "KEKW true!".to_string(),
-            "OMEGALUL wth man...".to_string(),
-            "PepeLaugh El no sabe".to_string(),
-        ];
+    let r = rand::thread_rng().gen_range(0..=4);
+    let a = phrases[r].clone();
 
-        let r = rand::thread_rng().gen_range(0..=4);
-        let a = phrases[r].clone();
+    let test = params.get_parent_module();
 
-        botlog::debug(
-            "This guy works!",
-            Some("modules > thisguy()".to_string()),
-            Some(&params.msg),
-        );
-        let bot = Arc::clone(&params.bot);
-        let botlock = bot.read().await;
+    botlog::debug(
+        "This guy works!",
+        Some("modules > thisguy()".to_string()),
+        Some(&params.msg),
+    );
+    let bot = Arc::clone(&params.bot);
+    let botlock = bot.read().await;
 
-        // uses chat.say_in_reply_to() for the bot controls for messages
-        botlock
-            .botmgrs
-            .chat
-            .say_in_reply_to(&params.msg, a, params.clone())
-            .await;
-        sleep(Duration::from_secs_f64(0.5)).await;
-    }else {
-        //println!("didn't type the proper command");
-    }
+    // uses chat.say_in_reply_to() for the bot controls for messages
+    botlock
+        .botmgrs
+        .chat
+        .say_in_reply_to(&params.msg, a, params.clone())
+        .await;
+    sleep(Duration::from_secs_f64(0.5)).await;
 }
 
 pub async fn init(mgr: &Arc<ModulesManager>) {
@@ -65,29 +46,14 @@ pub async fn init(mgr: &Arc<ModulesManager>) {
         module: BotModule(String::from("thisguy")),
         command: String::from("thisguy"),
         alias: vec![String::from("Thisguy")],
-        exec_body: actions_util::asyncbox(test),
-        help: String::from("test"),
-        required_roles: vec![BotAdmin],
-    }
-    .add_to_modmgr(Arc::clone(&mgr))
-    .await;
-
-    Listener {
-        module: BotModule(String::from("thisguy")),
-        name: String::from("This Guy Listener"),
         exec_body: actions_util::asyncbox(tsg),
-        help: String::from(""),
+        help: String::from("test"),
+        required_roles: vec![
+            BotAdmin,
+            Mod(OF_CMD_CHANNEL),
+            Broadcaster
+            ],
     }
     .add_to_modmgr(Arc::clone(&mgr))
     .await;
-}
-
-
-async fn test(params: ExecBodyParams) {
-    println!("Test triggered!"); // NOTE : This test function intends to print (e.g., to stdout) at fn call
-    botlog::debug(
-        "test triggered!",
-        Some("modules > tesst()".to_string()),
-        Some(&params.msg),
-    );
-}
+}
\ No newline at end of file

From b43d6f8159cf9e107f44f8f648e2673dcc593dba Mon Sep 17 00:00:00 2001
From: haruyuumei <luzivotto.erick@gmail.com>
Date: Wed, 3 Apr 2024 10:26:14 -0300
Subject: [PATCH 12/31] Rewriten the code

working with command instead listener
---
 src/custom/thisguy.rs | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/custom/thisguy.rs b/src/custom/thisguy.rs
index 0ca6de8..052f601 100644
--- a/src/custom/thisguy.rs
+++ b/src/custom/thisguy.rs
@@ -22,8 +22,6 @@ async fn tsg(params: ExecBodyParams) {
     let r = rand::thread_rng().gen_range(0..=4);
     let a = phrases[r].clone();
 
-    let test = params.get_parent_module();
-
     botlog::debug(
         "This guy works!",
         Some("modules > thisguy()".to_string()),

From 345cf97922b3cf7729f1501bd04dabc9b4869d4a Mon Sep 17 00:00:00 2001
From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com>
Date: Wed, 3 Apr 2024 13:47:59 -0400
Subject: [PATCH 13/31] enh chat.say_in_reply

---
 src/core/chat.rs | 47 ++++++++++++++++++++++++++++++++++-------------
 1 file changed, 34 insertions(+), 13 deletions(-)

diff --git a/src/core/chat.rs b/src/core/chat.rs
index bb938cc..a3db701 100644
--- a/src/core/chat.rs
+++ b/src/core/chat.rs
@@ -4,7 +4,7 @@ use std::sync::Arc;
 use tokio::sync::Mutex;
 
 use twitch_irc::login::StaticLoginCredentials;
-use twitch_irc::message::PrivmsgMessage;
+use twitch_irc::message::{PrivmsgMessage, ReplyToMessage};
 use twitch_irc::transport::tcp::{TCPTransport, TLS};
 use twitch_irc::TwitchIRCClient;
 
@@ -34,9 +34,14 @@ pub struct Chat {
 }
 
 
-#[derive(Clone,Debug)]
-pub enum BotMsgType<'a> {
-    SayInReplyTo(&'a PrivmsgMessage,String),
+// #[derive(Clone,Debug)] // <-- [ ] 04.03 - was having issues using this
+#[derive(Clone)] 
+// pub enum BotMsgType<'a> {
+pub enum BotMsgType {
+    // SayInReplyTo(&'a PrivmsgMessage,String),
+    // SayInReplyTo(Arc<Box<dyn ReplyToMessage>>,String),
+    // SayInReplyTo(&'a dyn ReplyToMessage,String), // [ ] 04.03 - Having issues defining it this way?
+    SayInReplyTo((String,String),String), // ( Destination Channel , Message ID to reply to ) , OutMessage // https://docs.rs/twitch-irc/latest/twitch_irc/client/struct.TwitchIRCClient.html#method.say_in_reply_to
     Say(String,String),
     Notif(String), // For Bot Sent Notifications
 }
@@ -59,7 +64,8 @@ impl Chat {
     }
 
     #[async_recursion]
-    pub async fn send_botmsg(&self, msginput: BotMsgType<'async_recursion>, params : ExecBodyParams) {
+    // pub async fn send_botmsg(&self, msginput: BotMsgType<'async_recursion>, params : ExecBodyParams) {
+    pub async fn send_botmsg(&self, msginput: BotMsgType, params : ExecBodyParams) {
 
         
             
@@ -72,17 +78,21 @@ impl Chat {
 
          */
 
-        
-         botlog::trace(
+        /* // [ ] 04.03 - Was having issues withh this
+        botlog::trace(
             format!("send_bot_msg params : {:?}",msginput).as_str(),
             Some("chat.rs > send_botmsg ".to_string()),
             Some(&params.msg),
         );
         Log::flush();
+        */
 
         let (channel_login,mut outmsg) = match msginput.clone() {
             BotMsgType::SayInReplyTo(msg, outmsg) => {
-                (msg.channel_login.clone(),outmsg)
+                // (msg.channel_login.clone(),outmsg)
+                // (msg.clone().channel_login().to_string(),outmsg)
+                (msg.0, // Desintation Channel
+                    outmsg)
             },
             BotMsgType::Say(a,b ) => {
                 (a.clone(),b.clone())
@@ -340,7 +350,12 @@ impl Chat {
 
                 match msginput.clone() {
                     BotMsgType::SayInReplyTo(msg, _) => {
-                        self.client.say_in_reply_to(msg, outmsg).await.unwrap();
+
+                        dbg!(msg.clone().channel_login(),msg.message_id(),outmsg.clone());
+                        self.client.say_in_reply_to(&(
+                            msg.clone().channel_login().to_string(),
+                            msg.message_id().to_string()), 
+                            outmsg).await.unwrap();
                     },
                     BotMsgType::Say(a, _) => {
                         self.client.say(a, outmsg).await.unwrap();
@@ -357,11 +372,12 @@ impl Chat {
                     channel_login.clone(), "rate limit counter increase", contextratelimiter
                 );
 
-                if let BotMsgType::SayInReplyTo(msg,_ ) = msginput {
+                if let BotMsgType::SayInReplyTo(_,_ ) = msginput {
                     botlog::trace(
                         logstr.as_str(),
                         Some("Chat > send_botmsg".to_string()),
-                        Some(msg),
+                        // Some(msg),
+                        None,
                     );
                 } else {
                     botlog::trace(
@@ -390,7 +406,9 @@ impl Chat {
 
     // pub async fn say_in_reply_to(&self, msg: &PrivmsgMessage, outmsg: String) {
     // #[async_recursion]
-    pub async fn say_in_reply_to(&self, msg: &PrivmsgMessage, outmsg: String , params : ExecBodyParams) {
+    // pub async fn say_in_reply_to(&self, msg: &PrivmsgMessage, outmsg: String , params : ExecBodyParams) {
+    // pub async fn say_in_reply_to(&self, msg: &PrivmsgMessage, outmsg: String , params : ExecBodyParams) {
+        pub async fn say_in_reply_to(&self, msg: &impl ReplyToMessage, outmsg: String , params : ExecBodyParams) {
 
         // let params_clone = params.clone();
 
@@ -443,7 +461,10 @@ impl Chat {
         // Log::flush();
 
 
-        self.send_botmsg(BotMsgType::SayInReplyTo(msg, outmsg) , params).await;
+        self.send_botmsg(BotMsgType::SayInReplyTo(
+                (msg.channel_login().to_string(),
+                msg.message_id().to_string()), 
+            outmsg) , params).await;
 
     }
 

From 71997037667362d3bcde0810f0138e607893d1ae Mon Sep 17 00:00:00 2001
From: haruyuumei <luzivotto.erick@gmail.com>
Date: Wed, 3 Apr 2024 15:26:04 -0300
Subject: [PATCH 14/31] reply-to-parent working

---
 src/custom/experimental/experiment001.rs | 57 ++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/src/custom/experimental/experiment001.rs b/src/custom/experimental/experiment001.rs
index dd3cba4..65bae8b 100644
--- a/src/custom/experimental/experiment001.rs
+++ b/src/custom/experimental/experiment001.rs
@@ -95,8 +95,65 @@ pub async fn init(mgr: Arc<ModulesManager>) {
     // 2. Add the BotAction to ModulesManager
     botc1.add_to_modmgr(Arc::clone(&mgr)).await;
 
+    let bc1 = BotCommand {
+        module: BotModule(String::from("experiments001")),
+        command: String::from("rp1"), // command call name
+        alias: vec![
+            String::from("rp2"), 
+            String::from("rp3")], // String of alternative names
+        exec_body: actions_util::asyncbox(rp),
+        help: String::from("Test Command tester"),
+        required_roles: vec![
+            BotAdmin,
+            Mod(OF_CMD_CHANNEL),
+        ], 
+    };
+    bc1.add_core_to_modmgr(Arc::clone(&mgr)).await;
 }
 
+async fn rp(params : ExecBodyParams)
+{
+    //triggers if the message is a reply
+    if params.get_parent_reply().is_some(){
+
+        //getting the channel id where the message was sent
+        let channel_id = params.get_parent_reply().unwrap().channel_login;
+
+        //getting the first message id that was sent
+        let message_id = params.get_parent_reply().unwrap().message_id;
+
+        //just for testing purposes
+        //print!("{} , {}",channel_id, message_id); 
+
+        //creating a tuple with the channel id and message id
+        let answear =  
+        (
+            channel_id.clone(),
+            message_id.clone()
+        );
+
+        let bot = Arc::clone(&params.bot);
+        let botlock = bot.read().await;
+        // uses chat.say_in_reply_to() for the bot controls for messages
+        botlock
+        .botmgrs
+        .chat
+        .say_in_reply_to(
+            //using the tuple as param to the message being replied
+            &answear,
+            String::from("hey there"),
+            params.clone()
+        ).await; 
+    }   
+
+    else    
+    {
+        println!("no reply")
+    }
+}
+
+
+
 async fn good_girl(params : ExecBodyParams) {
 
     // [ ] Uses gen_ratio() to output bool based on a ratio probability .

From 6867cc7af8aee0d82baa24f1302a29005f92546a Mon Sep 17 00:00:00 2001
From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com>
Date: Wed, 3 Apr 2024 18:33:15 -0400
Subject: [PATCH 15/31] adj sayinreply to use channel & msgid

---
 src/core/chat.rs                         | 52 +++++++++++++++++-------
 src/custom/experimental/experiment001.rs | 16 +++++---
 src/custom/experimental/experiment002.rs |  4 +-
 3 files changed, 51 insertions(+), 21 deletions(-)

diff --git a/src/core/chat.rs b/src/core/chat.rs
index a3db701..003c617 100644
--- a/src/core/chat.rs
+++ b/src/core/chat.rs
@@ -41,7 +41,8 @@ pub enum BotMsgType {
     // SayInReplyTo(&'a PrivmsgMessage,String),
     // SayInReplyTo(Arc<Box<dyn ReplyToMessage>>,String),
     // SayInReplyTo(&'a dyn ReplyToMessage,String), // [ ] 04.03 - Having issues defining it this way?
-    SayInReplyTo((String,String),String), // ( Destination Channel , Message ID to reply to ) , OutMessage // https://docs.rs/twitch-irc/latest/twitch_irc/client/struct.TwitchIRCClient.html#method.say_in_reply_to
+    // SayInReplyTo((String,String),String), // ( Destination Channel , Message ID to reply to ) , OutMessage // https://docs.rs/twitch-irc/latest/twitch_irc/client/struct.TwitchIRCClient.html#method.say_in_reply_to
+    SayInReplyTo(Channel,String,String), // ( Destination Channel , Message ID to reply to , OutMessage ) // https://docs.rs/twitch-irc/latest/twitch_irc/client/struct.TwitchIRCClient.html#method.say_in_reply_to
     Say(String,String),
     Notif(String), // For Bot Sent Notifications
 }
@@ -88,10 +89,11 @@ impl Chat {
         */
 
         let (channel_login,mut outmsg) = match msginput.clone() {
-            BotMsgType::SayInReplyTo(msg, outmsg) => {
+            // BotMsgType::SayInReplyTo(msg, outmsg) => {
+            BotMsgType::SayInReplyTo(chnl, _, outmsg) => {
                 // (msg.channel_login.clone(),outmsg)
                 // (msg.clone().channel_login().to_string(),outmsg)
-                (msg.0, // Desintation Channel
+                (chnl.0.to_lowercase(), // Desintation Channel
                     outmsg)
             },
             BotMsgType::Say(a,b ) => {
@@ -123,13 +125,16 @@ impl Chat {
             ).await;
 
         if !params.bot.read().await.bot_channels.contains(&Channel(channel_login.clone())) {
+
+            dbg!("ISSUE : NONJOINED CHANNEL",&params.bot.read().await.bot_channels,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,
             );
 
-            if let BotMsgType::SayInReplyTo(_prvmsg,_outmsg) = msginput {
+            // if let BotMsgType::SayInReplyTo(_prvmsg,_outmsg) = msginput {
+            if let BotMsgType::SayInReplyTo(_chnl,_msgid, _outmsg) = msginput {
 
                 self.send_botmsg(BotMsgType::Notif(
                     "uuh Bot can't send to a channel it isn't joined".to_string(), 
@@ -177,7 +182,8 @@ impl Chat {
 
             match msginput {
                 BotMsgType::Notif(_) => (), // Do nothing with Notif > We'll validate the user later to handle
-                BotMsgType::SayInReplyTo(_, _) | BotMsgType::Say(_,_) => {
+                // BotMsgType::SayInReplyTo(_, _) | BotMsgType::Say(_,_) => {
+                BotMsgType::SayInReplyTo(_, _, _) | BotMsgType::Say(_,_) => {
                             
                         botlog::trace(
                             "BEFORE potential Async recursion",
@@ -276,7 +282,8 @@ impl Chat {
                             return;
                         }
                     },
-                    BotMsgType::SayInReplyTo(_,_ ) | BotMsgType::Say(_,_) => {
+                    // BotMsgType::SayInReplyTo(_,_ ) | BotMsgType::Say(_,_) => {
+                    BotMsgType::SayInReplyTo(_,_,_ ) | BotMsgType::Say(_,_) => {
                         // If the BotMsg a Say/SayInReplyTo (from Developer or Chatter) , and the Sender does not have Specific Roles in the Source Channel Sent
 
                         self.send_botmsg(BotMsgType::Notif(
@@ -349,18 +356,25 @@ impl Chat {
                 }
 
                 match msginput.clone() {
-                    BotMsgType::SayInReplyTo(msg, _) => {
+                    // BotMsgType::SayInReplyTo(msg, _) => {
+                    // BotMsgType::SayInReplyTo(msg, _, _) => {
+                    BotMsgType::SayInReplyTo(chnl,msgid, _) => {
+
+                        // dbg!(msg.clone().channel_login(),msg.message_id(),outmsg.clone());
+                        dbg!(chnl.clone(),msgid.clone(),outmsg.clone());
 
-                        dbg!(msg.clone().channel_login(),msg.message_id(),outmsg.clone());
                         self.client.say_in_reply_to(&(
-                            msg.clone().channel_login().to_string(),
-                            msg.message_id().to_string()), 
+                            chnl.0,
+                            msgid), 
                             outmsg).await.unwrap();
                     },
                     BotMsgType::Say(a, _) => {
                         self.client.say(a, outmsg).await.unwrap();
                     }
                     BotMsgType::Notif(outmsg) => {
+
+                        // dbg!(chnl.clone(),msgid.clone(),outmsg.clone());
+                        dbg!(params.msg.channel_login(),params.msg.message_id());
                         self.client.say_in_reply_to(&params.msg, outmsg).await.unwrap();
                     }
                 }
@@ -372,7 +386,8 @@ impl Chat {
                     channel_login.clone(), "rate limit counter increase", contextratelimiter
                 );
 
-                if let BotMsgType::SayInReplyTo(_,_ ) = msginput {
+                // if let BotMsgType::SayInReplyTo(_,_ ) = msginput {
+                if let BotMsgType::SayInReplyTo(_,_,_ ) = msginput {
                     botlog::trace(
                         logstr.as_str(),
                         Some("Chat > send_botmsg".to_string()),
@@ -408,7 +423,14 @@ impl Chat {
     // #[async_recursion]
     // pub async fn say_in_reply_to(&self, msg: &PrivmsgMessage, outmsg: String , params : ExecBodyParams) {
     // pub async fn say_in_reply_to(&self, msg: &PrivmsgMessage, outmsg: String , params : ExecBodyParams) {
-        pub async fn say_in_reply_to(&self, msg: &impl ReplyToMessage, outmsg: String , params : ExecBodyParams) {
+    // pub async fn say_in_reply_to(&self, msg: &impl ReplyToMessage, outmsg: String , params : ExecBodyParams) {
+    pub async fn say_in_reply_to(
+        &self, 
+        destination_channel : Channel , 
+        reply_message_id : String ,
+        outmsg: String , 
+        params : ExecBodyParams) 
+    {
 
         // let params_clone = params.clone();
 
@@ -462,9 +484,9 @@ impl Chat {
 
 
         self.send_botmsg(BotMsgType::SayInReplyTo(
-                (msg.channel_login().to_string(),
-                msg.message_id().to_string()), 
-            outmsg) , params).await;
+                destination_channel,
+                reply_message_id, 
+                outmsg) , params).await;
 
     }
 
diff --git a/src/custom/experimental/experiment001.rs b/src/custom/experimental/experiment001.rs
index 65bae8b..e774055 100644
--- a/src/custom/experimental/experiment001.rs
+++ b/src/custom/experimental/experiment001.rs
@@ -15,6 +15,7 @@ const OF_CMD_CHANNEL:Channel = Channel(String::new());
 
 
 use rand::Rng;
+use twitch_irc::message::ReplyToMessage;
 use std::sync::Arc;
 
 use crate::core::bot_actions::ExecBodyParams;
@@ -140,7 +141,8 @@ async fn rp(params : ExecBodyParams)
         .chat
         .say_in_reply_to(
             //using the tuple as param to the message being replied
-            &answear,
+            Channel(answear.0),
+            answear.1,
             String::from("hey there"),
             params.clone()
         ).await; 
@@ -188,7 +190,8 @@ async fn good_girl(params : ExecBodyParams) {
             .botmgrs
             .chat
             .say_in_reply_to(
-                &params.msg, 
+                Channel(params.clone().msg.channel_login().to_string()),
+                params.clone().msg.message_id().to_string(), 
                 String::from("GoodGirl xdd "),
                 params.clone()
             ).await;
@@ -228,7 +231,8 @@ async fn babygirl(params : ExecBodyParams) {
         .botmgrs
         .chat
         .say_in_reply_to(
-            &params.msg, 
+            Channel(params.clone().msg.channel_login().to_string()),
+            params.clone().msg.message_id().to_string(), 
             String::from("16:13 notohh: cafdk"),
             params.clone()
         ).await;
@@ -240,7 +244,8 @@ async fn babygirl(params : ExecBodyParams) {
     .botmgrs
     .chat
     .say_in_reply_to(
-        &params.msg, 
+        Channel(params.clone().msg.channel_login().to_string()),
+        params.clone().msg.message_id().to_string(), 
         String::from("16:13 notohh: have fun eating princess"),
         params.clone()
     ).await;
@@ -252,7 +257,8 @@ async fn babygirl(params : ExecBodyParams) {
     .botmgrs
     .chat
     .say_in_reply_to(
-        &params.msg, 
+        Channel(params.clone().msg.channel_login().to_string()),
+        params.clone().msg.message_id().to_string(), 
         String::from("16:13 notohh: baby girl"),
         params.clone()
     ).await;
diff --git a/src/custom/experimental/experiment002.rs b/src/custom/experimental/experiment002.rs
index a4ecb25..a7d1610 100644
--- a/src/custom/experimental/experiment002.rs
+++ b/src/custom/experimental/experiment002.rs
@@ -17,6 +17,7 @@ const OF_CMD_CHANNEL:Channel = Channel(String::new());
 use std::sync::Arc;
 
 use chrono::{TimeZone,Local};
+use twitch_irc::message::ReplyToMessage;
 
 
 use crate::core::bot_actions::ExecBodyParams;
@@ -180,7 +181,8 @@ async fn sayout(params : ExecBodyParams) {
             .botmgrs
             .chat
             .say_in_reply_to(
-                &params.msg, 
+                Channel(params.clone().msg.channel_login().to_string()),
+                params.clone().msg.message_id().to_string(), 
                 String::from("Invalid arguments"),
                 params.clone()
             ).await;

From 62b6399e69eb8cc6aba21d759d50f85ed4974ca3 Mon Sep 17 00:00:00 2001
From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com>
Date: Wed, 3 Apr 2024 19:04:21 -0400
Subject: [PATCH 16/31] chat.say_in_reply

---
 src/core/chat.rs                         | 22 ++++++++++++++++++++++
 src/custom/experimental/experiment001.rs | 20 ++++++++++++++------
 2 files changed, 36 insertions(+), 6 deletions(-)

diff --git a/src/core/chat.rs b/src/core/chat.rs
index 003c617..82bc3f6 100644
--- a/src/core/chat.rs
+++ b/src/core/chat.rs
@@ -418,6 +418,21 @@ impl Chat {
     }
 
 
+    pub async fn say_in_reply(
+        &self, 
+        destination_channel : Channel , 
+        outmsg: String , 
+        params : ExecBodyParams) 
+    {
+
+        self.send_botmsg(BotMsgType::SayInReplyTo(
+            destination_channel,
+            params.msg.message_id().to_string(), 
+            outmsg) , params).await;
+
+
+    }
+
 
     // pub async fn say_in_reply_to(&self, msg: &PrivmsgMessage, outmsg: String) {
     // #[async_recursion]
@@ -490,6 +505,9 @@ impl Chat {
 
     }
 
+
+
+
     // pub async fn say(&self, channel_login: String, message: String) {
     pub async fn say(&self, channel_login: String, message: String , params : ExecBodyParams) {
         // more info https://docs.rs/twitch-irc/latest/twitch_irc/client/struct.TwitchIRCClient.html#method.say
@@ -497,6 +515,10 @@ impl Chat {
         self.send_botmsg(BotMsgType::Say(channel_login.to_lowercase(), message), params).await;
     }
 
+
+
+
+
     async fn _me(&self, _: String, _: String) {
         // more info https://docs.rs/twitch-irc/latest/twitch_irc/client/struct.TwitchIRCClient.html#method.say
 
diff --git a/src/custom/experimental/experiment001.rs b/src/custom/experimental/experiment001.rs
index e774055..cb75ad2 100644
--- a/src/custom/experimental/experiment001.rs
+++ b/src/custom/experimental/experiment001.rs
@@ -230,9 +230,8 @@ async fn babygirl(params : ExecBodyParams) {
     botlock
         .botmgrs
         .chat
-        .say_in_reply_to(
+        .say_in_reply(
             Channel(params.clone().msg.channel_login().to_string()),
-            params.clone().msg.message_id().to_string(), 
             String::from("16:13 notohh: cafdk"),
             params.clone()
         ).await;
@@ -243,9 +242,8 @@ async fn babygirl(params : ExecBodyParams) {
     botlock
     .botmgrs
     .chat
-    .say_in_reply_to(
+    .say_in_reply(
         Channel(params.clone().msg.channel_login().to_string()),
-        params.clone().msg.message_id().to_string(), 
         String::from("16:13 notohh: have fun eating princess"),
         params.clone()
     ).await;
@@ -253,12 +251,22 @@ async fn babygirl(params : ExecBodyParams) {
 
     sleep(Duration::from_secs_f64(2.0)).await;
 
+    // botlock
+    // .botmgrs
+    // .chat
+    // .say_in_reply_to(
+    //     Channel(params.clone().msg.channel_login().to_string()),
+    //     params.clone().msg.message_id().to_string(), 
+    //     String::from("16:13 notohh: baby girl"),
+    //     params.clone()
+    // ).await;
+
+
     botlock
     .botmgrs
     .chat
-    .say_in_reply_to(
+    .say_in_reply(
         Channel(params.clone().msg.channel_login().to_string()),
-        params.clone().msg.message_id().to_string(), 
         String::from("16:13 notohh: baby girl"),
         params.clone()
     ).await;

From 8adab21761cd3c9bc6837518006140fbcc82f4f4 Mon Sep 17 00:00:00 2001
From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com>
Date: Wed, 3 Apr 2024 19:40:18 -0400
Subject: [PATCH 17/31] comments cleanup

---
 src/core/botlog.rs                       | 21 ++----
 src/core/botmodules.rs                   |  1 -
 src/core/chat.rs                         | 85 +-----------------------
 src/core/identity.rs                     |  4 --
 src/custom/experimental/experiment001.rs | 11 ---
 5 files changed, 10 insertions(+), 112 deletions(-)

diff --git a/src/core/botlog.rs b/src/core/botlog.rs
index 27272d2..48ae783 100644
--- a/src/core/botlog.rs
+++ b/src/core/botlog.rs
@@ -24,11 +24,10 @@ debug = "Checking bot actions",
 pub fn trace(in_msg: &str, in_module: Option<String>, in_prvmsg: Option<&PrivmsgMessage>) {
     let (chnl, chatter) = match in_prvmsg {
         Some(prvmsg) => {
-            //Log::trace(&format!("(#{}) {}: {}", prvmsg.channel_login, prvmsg.sender.name, prvmsg.message_text));
             (
                 Some(prvmsg.channel_login.clone()),
                 Some(prvmsg.sender.name.clone()),
-            ) // <-- Clone fine atm while we're just working with Strings
+            ) 
         }
         None => (None, None),
     };
@@ -45,11 +44,10 @@ pub fn trace(in_msg: &str, in_module: Option<String>, in_prvmsg: Option<&Privmsg
 pub fn debug(in_msg: &str, in_module: Option<String>, in_prvmsg: Option<&PrivmsgMessage>) {
     let (chnl, chatter) = match in_prvmsg {
         Some(prvmsg) => {
-            //Log::trace(&format!("(#{}) {}: {}", prvmsg.channel_login, prvmsg.sender.name, prvmsg.message_text));
             (
                 Some(prvmsg.channel_login.clone()),
                 Some(prvmsg.sender.name.clone()),
-            ) // <-- Clone fine atm while we're just working with Strings
+            ) 
         }
         None => (None, None),
     };
@@ -66,11 +64,10 @@ pub fn debug(in_msg: &str, in_module: Option<String>, in_prvmsg: Option<&Privmsg
 pub fn info(in_msg: &str, in_module: Option<String>, in_prvmsg: Option<&PrivmsgMessage>) {
     let (chnl, chatter) = match in_prvmsg {
         Some(prvmsg) => {
-            //Log::trace(&format!("(#{}) {}: {}", prvmsg.channel_login, prvmsg.sender.name, prvmsg.message_text));
             (
                 Some(prvmsg.channel_login.clone()),
                 Some(prvmsg.sender.name.clone()),
-            ) // <-- Clone fine atm while we're just working with Strings
+            ) 
         }
         None => (None, None),
     };
@@ -87,11 +84,10 @@ pub fn info(in_msg: &str, in_module: Option<String>, in_prvmsg: Option<&PrivmsgM
 pub fn notice(in_msg: &str, in_module: Option<String>, in_prvmsg: Option<&PrivmsgMessage>) {
     let (chnl, chatter) = match in_prvmsg {
         Some(prvmsg) => {
-            //Log::trace(&format!("(#{}) {}: {}", prvmsg.channel_login, prvmsg.sender.name, prvmsg.message_text));
             (
                 Some(prvmsg.channel_login.clone()),
                 Some(prvmsg.sender.name.clone()),
-            ) // <-- Clone fine atm while we're just working with Strings
+            ) 
         }
         None => (None, None),
     };
@@ -108,11 +104,10 @@ pub fn notice(in_msg: &str, in_module: Option<String>, in_prvmsg: Option<&Privms
 pub fn warn(in_msg: &str, in_module: Option<String>, in_prvmsg: Option<&PrivmsgMessage>) {
     let (chnl, chatter) = match in_prvmsg {
         Some(prvmsg) => {
-            //Log::trace(&format!("(#{}) {}: {}", prvmsg.channel_login, prvmsg.sender.name, prvmsg.message_text));
             (
                 Some(prvmsg.channel_login.clone()),
                 Some(prvmsg.sender.name.clone()),
-            ) // <-- Clone fine atm while we're just working with Strings
+            ) 
         }
         None => (None, None),
     };
@@ -129,11 +124,10 @@ pub fn warn(in_msg: &str, in_module: Option<String>, in_prvmsg: Option<&PrivmsgM
 pub fn error(in_msg: &str, in_module: Option<String>, in_prvmsg: Option<&PrivmsgMessage>) {
     let (chnl, chatter) = match in_prvmsg {
         Some(prvmsg) => {
-            //Log::trace(&format!("(#{}) {}: {}", prvmsg.channel_login, prvmsg.sender.name, prvmsg.message_text));
             (
                 Some(prvmsg.channel_login.clone()),
                 Some(prvmsg.sender.name.clone()),
-            ) // <-- Clone fine atm while we're just working with Strings
+            ) 
         }
         None => (None, None),
     };
@@ -154,11 +148,10 @@ pub fn fatal<'a>(
 ) -> &'a str {
     let (chnl, chatter) = match in_prvmsg {
         Some(prvmsg) => {
-            //Log::trace(&format!("(#{}) {}: {}", prvmsg.channel_login, prvmsg.sender.name, prvmsg.message_text));
             (
                 Some(prvmsg.channel_login.clone()),
                 Some(prvmsg.sender.name.clone()),
-            ) // <-- Clone fine atm while we're just working with Strings
+            ) 
         }
         None => (None, None),
     };
diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs
index c104fdd..408b2d5 100644
--- a/src/core/botmodules.rs
+++ b/src/core/botmodules.rs
@@ -253,7 +253,6 @@ pub async fn init(mgr: Arc<ModulesManager>) {
     // 2. Add the BotAction to ModulesManager
     botc1.add_core_to_modmgr(Arc::clone(&mgr)).await;
     
-    // async fn cmd_disable(bot: BotAR, msg: PrivmsgMessage) {
     async fn cmd_disable(params : ExecBodyParams) {
         /*
             There should be additional validation checks
diff --git a/src/core/chat.rs b/src/core/chat.rs
index 82bc3f6..3ed28ce 100644
--- a/src/core/chat.rs
+++ b/src/core/chat.rs
@@ -34,14 +34,8 @@ pub struct Chat {
 }
 
 
-// #[derive(Clone,Debug)] // <-- [ ] 04.03 - was having issues using this
-#[derive(Clone)] 
-// pub enum BotMsgType<'a> {
+#[derive(Clone,Debug)] 
 pub enum BotMsgType {
-    // SayInReplyTo(&'a PrivmsgMessage,String),
-    // SayInReplyTo(Arc<Box<dyn ReplyToMessage>>,String),
-    // SayInReplyTo(&'a dyn ReplyToMessage,String), // [ ] 04.03 - Having issues defining it this way?
-    // SayInReplyTo((String,String),String), // ( Destination Channel , Message ID to reply to ) , OutMessage // https://docs.rs/twitch-irc/latest/twitch_irc/client/struct.TwitchIRCClient.html#method.say_in_reply_to
     SayInReplyTo(Channel,String,String), // ( Destination Channel , Message ID to reply to , OutMessage ) // https://docs.rs/twitch-irc/latest/twitch_irc/client/struct.TwitchIRCClient.html#method.say_in_reply_to
     Say(String,String),
     Notif(String), // For Bot Sent Notifications
@@ -65,7 +59,6 @@ impl Chat {
     }
 
     #[async_recursion]
-    // pub async fn send_botmsg(&self, msginput: BotMsgType<'async_recursion>, params : ExecBodyParams) {
     pub async fn send_botmsg(&self, msginput: BotMsgType, params : ExecBodyParams) {
 
         
@@ -79,20 +72,16 @@ impl Chat {
 
          */
 
-        /* // [ ] 04.03 - Was having issues withh this
         botlog::trace(
             format!("send_bot_msg params : {:?}",msginput).as_str(),
             Some("chat.rs > send_botmsg ".to_string()),
             Some(&params.msg),
         );
         Log::flush();
-        */
+        
 
         let (channel_login,mut outmsg) = match msginput.clone() {
-            // BotMsgType::SayInReplyTo(msg, outmsg) => {
             BotMsgType::SayInReplyTo(chnl, _, outmsg) => {
-                // (msg.channel_login.clone(),outmsg)
-                // (msg.clone().channel_login().to_string(),outmsg)
                 (chnl.0.to_lowercase(), // Desintation Channel
                     outmsg)
             },
@@ -133,7 +122,6 @@ impl Chat {
                 None,
             );
 
-            // if let BotMsgType::SayInReplyTo(_prvmsg,_outmsg) = msginput {
             if let BotMsgType::SayInReplyTo(_chnl,_msgid, _outmsg) = msginput {
 
                 self.send_botmsg(BotMsgType::Notif(
@@ -182,7 +170,6 @@ impl Chat {
 
             match msginput {
                 BotMsgType::Notif(_) => (), // Do nothing with Notif > We'll validate the user later to handle
-                // BotMsgType::SayInReplyTo(_, _) | BotMsgType::Say(_,_) => {
                 BotMsgType::SayInReplyTo(_, _, _) | BotMsgType::Say(_,_) => {
                             
                         botlog::trace(
@@ -248,7 +235,7 @@ impl Chat {
              let botlock = botclone.read().await;
              let id = botlock.get_identity();
              let id = Arc::clone(&id);
-             let idlock = id.read().await; // <-- [x] 03.24 - seems to work
+             let idlock = id.read().await; 
              let user_roles = idlock.getspecialuserroles(
                 params.get_sender(), 
                 Some(Channel(channel_login.clone()))
@@ -282,7 +269,6 @@ impl Chat {
                             return;
                         }
                     },
-                    // BotMsgType::SayInReplyTo(_,_ ) | BotMsgType::Say(_,_) => {
                     BotMsgType::SayInReplyTo(_,_,_ ) | BotMsgType::Say(_,_) => {
                         // If the BotMsg a Say/SayInReplyTo (from Developer or Chatter) , and the Sender does not have Specific Roles in the Source Channel Sent
 
@@ -337,7 +323,6 @@ impl Chat {
         );
 
         let contextratelimiter = rllock
-            // .get_mut()
             .get_mut(&Channel(channel_login.to_lowercase().clone()))
             .expect("ERROR: Issue with Rate limiters");
 
@@ -356,11 +341,8 @@ impl Chat {
                 }
 
                 match msginput.clone() {
-                    // BotMsgType::SayInReplyTo(msg, _) => {
-                    // BotMsgType::SayInReplyTo(msg, _, _) => {
                     BotMsgType::SayInReplyTo(chnl,msgid, _) => {
 
-                        // dbg!(msg.clone().channel_login(),msg.message_id(),outmsg.clone());
                         dbg!(chnl.clone(),msgid.clone(),outmsg.clone());
 
                         self.client.say_in_reply_to(&(
@@ -373,7 +355,6 @@ impl Chat {
                     }
                     BotMsgType::Notif(outmsg) => {
 
-                        // dbg!(chnl.clone(),msgid.clone(),outmsg.clone());
                         dbg!(params.msg.channel_login(),params.msg.message_id());
                         self.client.say_in_reply_to(&params.msg, outmsg).await.unwrap();
                     }
@@ -386,12 +367,10 @@ impl Chat {
                     channel_login.clone(), "rate limit counter increase", contextratelimiter
                 );
 
-                // if let BotMsgType::SayInReplyTo(_,_ ) = msginput {
                 if let BotMsgType::SayInReplyTo(_,_,_ ) = msginput {
                     botlog::trace(
                         logstr.as_str(),
                         Some("Chat > send_botmsg".to_string()),
-                        // Some(msg),
                         None,
                     );
                 } else {
@@ -433,12 +412,6 @@ impl Chat {
 
     }
 
-
-    // pub async fn say_in_reply_to(&self, msg: &PrivmsgMessage, outmsg: String) {
-    // #[async_recursion]
-    // pub async fn say_in_reply_to(&self, msg: &PrivmsgMessage, outmsg: String , params : ExecBodyParams) {
-    // pub async fn say_in_reply_to(&self, msg: &PrivmsgMessage, outmsg: String , params : ExecBodyParams) {
-    // pub async fn say_in_reply_to(&self, msg: &impl ReplyToMessage, outmsg: String , params : ExecBodyParams) {
     pub async fn say_in_reply_to(
         &self, 
         destination_channel : Channel , 
@@ -447,57 +420,6 @@ impl Chat {
         params : ExecBodyParams) 
     {
 
-        // let params_clone = params.clone();
-
-        // let botclone = Arc::clone(&params_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(&params.msg),
-        // // );
-        // // Log::flush();
-
-        // botlog::trace(
-        //     "ACQUIRING READ LOCK : ID",
-        //     Some("Chat > send_botmsg".to_string()),
-        //     Some(&params.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(&params.msg),
-        // );
-        // Log::flush();
-        
-        
-
-        // // botlog::trace(
-        // //     "ACQUIRED WRITE LOCK : ID",
-        // //     Some("Chat > send_botmsg".to_string()),
-        // //     Some(&params.msg),
-        // // );
-        // // Log::flush();
-
-
-        
-        // botlog::trace(
-        //     "ACQUIRED READ LOCK : ID",
-        //     Some("Chat > send_botmsg".to_string()),
-        //     Some(&params.msg),
-        // );
-        // Log::flush();
-
-
         self.send_botmsg(BotMsgType::SayInReplyTo(
                 destination_channel,
                 reply_message_id, 
@@ -508,7 +430,6 @@ impl Chat {
 
 
 
-    // pub async fn say(&self, channel_login: String, message: String) {
     pub async fn say(&self, channel_login: String, message: String , params : ExecBodyParams) {
         // more info https://docs.rs/twitch-irc/latest/twitch_irc/client/struct.TwitchIRCClient.html#method.say
 
diff --git a/src/core/identity.rs b/src/core/identity.rs
index dc2da72..726bbdf 100644
--- a/src/core/identity.rs
+++ b/src/core/identity.rs
@@ -23,13 +23,10 @@ use std::env;
 
 fn adminvector() -> Vec<String> {
     vec![String::from("ModulatingForce")]
-    //vec![]
 }
 
 
 pub fn otherbots_vector() -> Vec<String> {
-    // vec![String::from("ModulatingForce")]
-    // //vec![]
 
     dotenv().ok();
     let mut other_bots = Vec::new();
@@ -1467,7 +1464,6 @@ impl IdentityManager {
                     return ChangeResult::NoChange("Already does not have VIP role".to_string());
                 } 
                 else {
-                    // self.affirm_chatter_in_db(trgchatter.clone()).await;
 
                     self.remove_role(trgchatter.clone(), UserRole::VIP(channel.clone())).await;
 
diff --git a/src/custom/experimental/experiment001.rs b/src/custom/experimental/experiment001.rs
index cb75ad2..897384d 100644
--- a/src/custom/experimental/experiment001.rs
+++ b/src/custom/experimental/experiment001.rs
@@ -251,17 +251,6 @@ async fn babygirl(params : ExecBodyParams) {
 
     sleep(Duration::from_secs_f64(2.0)).await;
 
-    // botlock
-    // .botmgrs
-    // .chat
-    // .say_in_reply_to(
-    //     Channel(params.clone().msg.channel_login().to_string()),
-    //     params.clone().msg.message_id().to_string(), 
-    //     String::from("16:13 notohh: baby girl"),
-    //     params.clone()
-    // ).await;
-
-
     botlock
     .botmgrs
     .chat

From fde96ac8956d35c884f51afb01140a3faeb92b80 Mon Sep 17 00:00:00 2001
From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com>
Date: Wed, 3 Apr 2024 19:45:18 -0400
Subject: [PATCH 18/31] clippy cleanup

---
 src/core/bot_actions.rs                  | 5 +++--
 src/core/chat.rs                         | 2 +-
 src/custom/experimental/experiment001.rs | 1 -
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/core/bot_actions.rs b/src/core/bot_actions.rs
index f5c8a66..7ab34a0 100644
--- a/src/core/bot_actions.rs
+++ b/src/core/bot_actions.rs
@@ -73,7 +73,8 @@ impl ExecBodyParams {
 
         // filter out all tags that do not have content.
         let tag_contents: Vec<String> = tags.iter().filter_map(|tag| {
-            if let Some(&Some(ref t)) = map.get(*tag) {
+            // if let Some(&Some(ref t)) = map.get(*tag) {
+                if let Some(Some(t)) = map.get(*tag) {
                 Some(t.clone())
             } else {
                 None
@@ -82,7 +83,7 @@ impl ExecBodyParams {
 
         // if no tags got filtered out return the struct.
         // else return `None`.
-        return if tag_contents.len() == 5 {
+        if tag_contents.len() == 5 {
             Some(ReplyParent {
                 sender: TwitchUserBasics {
                     id: tag_contents[0].clone(),
diff --git a/src/core/chat.rs b/src/core/chat.rs
index 3ed28ce..43984bc 100644
--- a/src/core/chat.rs
+++ b/src/core/chat.rs
@@ -4,7 +4,7 @@ use std::sync::Arc;
 use tokio::sync::Mutex;
 
 use twitch_irc::login::StaticLoginCredentials;
-use twitch_irc::message::{PrivmsgMessage, ReplyToMessage};
+use twitch_irc::message::ReplyToMessage;
 use twitch_irc::transport::tcp::{TCPTransport, TLS};
 use twitch_irc::TwitchIRCClient;
 
diff --git a/src/custom/experimental/experiment001.rs b/src/custom/experimental/experiment001.rs
index 897384d..18d7aaa 100644
--- a/src/custom/experimental/experiment001.rs
+++ b/src/custom/experimental/experiment001.rs
@@ -147,7 +147,6 @@ async fn rp(params : ExecBodyParams)
             params.clone()
         ).await; 
     }   
-
     else    
     {
         println!("no reply")

From 78634f3ffe8cfd373e70c8e718d0bff590398a70 Mon Sep 17 00:00:00 2001
From: WoodpeckerCI <woodpecker@flake.sh>
Date: Mon, 8 Apr 2024 13:59:49 +0000
Subject: [PATCH 19/31] flake.lock: update

---
 flake.lock | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/flake.lock b/flake.lock
index 67734d7..84f1b48 100644
--- a/flake.lock
+++ b/flake.lock
@@ -6,11 +6,11 @@
         "rust-analyzer-src": "rust-analyzer-src"
       },
       "locked": {
-        "lastModified": 1706768574,
-        "narHash": "sha256-4o6TMpzBHO659EiJTzd/EGQGUDdbgwKwhqf3u6b23U8=",
+        "lastModified": 1711952616,
+        "narHash": "sha256-WJvDdOph001fA1Ap3AyaQtz/afJAe7meSG5uJAdSE+A=",
         "owner": "nix-community",
         "repo": "fenix",
-        "rev": "668102037129923cd0fc239d864fce71eabdc6a3",
+        "rev": "209048d7c545905c470f6f8c05c5061f391031a8",
         "type": "github"
       },
       "original": {
@@ -22,11 +22,11 @@
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1706550542,
-        "narHash": "sha256-UcsnCG6wx++23yeER4Hg18CXWbgNpqNXcHIo5/1Y+hc=",
+        "lastModified": 1711703276,
+        "narHash": "sha256-iMUFArF0WCatKK6RzfUJknjem0H9m4KgorO/p3Dopkk=",
         "owner": "nixos",
         "repo": "nixpkgs",
-        "rev": "97b17f32362e475016f942bbdfda4a4a72a8a652",
+        "rev": "d8fe5e6c92d0d190646fb9f1056741a229980089",
         "type": "github"
       },
       "original": {
@@ -38,11 +38,11 @@
     },
     "nixpkgs_2": {
       "locked": {
-        "lastModified": 1708296515,
-        "narHash": "sha256-FyF489fYNAUy7b6dkYV6rGPyzp+4tThhr80KNAaF/yY=",
+        "lastModified": 1712439257,
+        "narHash": "sha256-aSpiNepFOMk9932HOax0XwNxbA38GOUVOiXfUVPOrck=",
         "owner": "nixos",
         "repo": "nixpkgs",
-        "rev": "b98a4e1746acceb92c509bc496ef3d0e5ad8d4aa",
+        "rev": "ff0dbd94265ac470dda06a657d5fe49de93b4599",
         "type": "github"
       },
       "original": {
@@ -61,11 +61,11 @@
     "rust-analyzer-src": {
       "flake": false,
       "locked": {
-        "lastModified": 1706735270,
-        "narHash": "sha256-IJk+UitcJsxzMQWm9pa1ZbJBriQ4ginXOlPyVq+Cu40=",
+        "lastModified": 1711885694,
+        "narHash": "sha256-dyezzeSbWMpflma+E9USmvSxuLgGcNGcGw3cOnX36ko=",
         "owner": "rust-lang",
         "repo": "rust-analyzer",
-        "rev": "42cb1a2bd79af321b0cc503d2960b73f34e2f92b",
+        "rev": "e4a405f877efd820bef9c0e77a02494e47c17512",
         "type": "github"
       },
       "original": {

From 087e76388d3c7a6052531dd8b514e6f621f55c7c Mon Sep 17 00:00:00 2001
From: notohh <github@notohh.dev>
Date: Mon, 8 Apr 2024 11:11:05 -0400
Subject: [PATCH 20/31] nix: init rewrite

first pass of my nix rewrite

nix: rename module

nix: update module

nix: update module

nix: update module

nix: refactor

nix: remove package option

nix: fix serviceConfig

nix: add package back to module

nix: update module

nix: update module

nix: update module

nix: update module

remove default.nix
---
 .gitignore     |  5 +++-
 flake.lock     | 30 +++++++++++++++-----
 flake.nix      | 77 ++++++++++++++++++++++++++++++++------------------
 nix/module.nix | 30 ++++++++++++++++++++
 4 files changed, 107 insertions(+), 35 deletions(-)
 create mode 100644 nix/module.nix

diff --git a/.gitignore b/.gitignore
index 5c5e6b4..51b0be2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,4 +22,7 @@ target/
 *.log
 
 # debug
-.vscode/
\ No newline at end of file
+.vscode/
+
+# nix
+result/
\ No newline at end of file
diff --git a/flake.lock b/flake.lock
index 84f1b48..f66c5b5 100644
--- a/flake.lock
+++ b/flake.lock
@@ -38,16 +38,16 @@
     },
     "nixpkgs_2": {
       "locked": {
-        "lastModified": 1712439257,
-        "narHash": "sha256-aSpiNepFOMk9932HOax0XwNxbA38GOUVOiXfUVPOrck=",
-        "owner": "nixos",
+        "lastModified": 1712543224,
+        "narHash": "sha256-9RSfZL1TKYdGxZwgDxwtBtsKMGR4Zgn+DAnF9s71/lU=",
+        "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "ff0dbd94265ac470dda06a657d5fe49de93b4599",
+        "rev": "b0dab7cc34ef4d8a1b2de36178da801090bcb271",
         "type": "github"
       },
       "original": {
-        "owner": "nixos",
-        "ref": "nixos-unstable",
+        "owner": "NixOS",
+        "ref": "nixpkgs-unstable",
         "repo": "nixpkgs",
         "type": "github"
       }
@@ -55,7 +55,8 @@
     "root": {
       "inputs": {
         "fenix": "fenix",
-        "nixpkgs": "nixpkgs_2"
+        "nixpkgs": "nixpkgs_2",
+        "systems": "systems"
       }
     },
     "rust-analyzer-src": {
@@ -74,6 +75,21 @@
         "repo": "rust-analyzer",
         "type": "github"
       }
+    },
+    "systems": {
+      "locked": {
+        "lastModified": 1689347949,
+        "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
+        "owner": "nix-systems",
+        "repo": "default-linux",
+        "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "default-linux",
+        "type": "github"
+      }
     }
   },
   "root": "root",
diff --git a/flake.nix b/flake.nix
index c6be631..f29c01a 100644
--- a/flake.nix
+++ b/flake.nix
@@ -1,39 +1,62 @@
 {
-  description = "forcebot_rs flake";
+  description = "A basic flake";
 
   inputs = {
-    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
+    systems.url = "github:nix-systems/default-linux";
+    nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
     fenix.url = "github:nix-community/fenix/monthly";
   };
+
   outputs = {
+    self,
+    systems,
     nixpkgs,
     fenix,
-    ...
   } @ inputs: let
-    system = "x86_64-linux";
-    overlays = [fenix.overlays.default];
-    pkgs = import nixpkgs {
-      inherit system overlays;
-    };
+    eachSystem = nixpkgs.lib.genAttrs (import systems);
+    pkgsFor = eachSystem (system:
+      import nixpkgs {
+        localSystem.system = system;
+        overlays = [fenix.overlays.default];
+      });
   in {
-    devShells.${system}.default = pkgs.mkShell {
-      name = "forcebot_rs-devenv";
-      nativeBuildInputs = [pkgs.pkg-config];
-      buildInputs = with pkgs; [openssl libiconv];
-      packages = with pkgs; [
-        nil
-        alejandra
-        rust-analyzer-nightly
-        (fenix.packages.${system}.complete.withComponents [
-          "cargo"
-          "clippy"
-          "rust-src"
-          "rustc"
-          "rustfmt"
-        ])
-      ];
-      RUST_BACKTRACE = 1;
-      RUST_SRC_PATH = "${fenix.packages.${system}.complete.rust-src}/lib/rustlib/src/rust/library";
-    };
+    packages = eachSystem (system: let
+      pkgs = nixpkgs.legacyPackages.${system};
+    in {
+      default = pkgsFor.${system}.rustPlatform.buildRustPackage {
+        pname = "forcebot_rs";
+        version = "v0.1";
+
+        src = self;
+
+        cargoLock = {
+          lockFile = ./Cargo.lock;
+        };
+
+        nativeBuildInputs = with pkgs; [pkg-config];
+        buildInputs = with pkgs; [openssl];
+
+        doCheck = false;
+      };
+    });
+    devShells = eachSystem (system: {
+      default = pkgsFor.${system}.mkShell {
+        packages = with pkgsFor.${system}; [
+          nil
+          alejandra
+          rust-analyzer-nightly
+          (fenix.packages.${system}.complete.withComponents [
+            "cargo"
+            "clippy"
+            "rust-src"
+            "rustc"
+            "rustfmt"
+          ])
+        ];
+        RUST_BACKTRACE = 1;
+        RUST_SRC_PATH = "${fenix.packages.${system}.complete.rust-src}/lib/rustlib/src/rust/library";
+      };
+    });
+    nixosModules.default = import ./nix/module.nix {inherit self;};
   };
 }
diff --git a/nix/module.nix b/nix/module.nix
new file mode 100644
index 0000000..b615be1
--- /dev/null
+++ b/nix/module.nix
@@ -0,0 +1,30 @@
+{self}: {
+  pkgs,
+  config,
+  lib,
+  ...
+}: let
+  inherit (lib) types;
+  inherit (lib.modules) mkIf;
+  inherit (lib.options) mkOption mkEnableOption;
+  inherit (pkgs.stdenv.hostPlatform) system;
+  cfg = config.services.forcebot_rs;
+in {
+  options.services.forcebot_rs = {
+    enable = mkEnableOption ''
+      Enable forcebot
+    '';
+
+    package = mkOption {
+      type = types.package;
+      default = self.packages.${system}.default;
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.forcebot_rs = {
+      wantedBy = ["multi-user.target"];
+      serviceConfig.ExecStart = "${cfg.package}/bin/forcebot_rs";
+    };
+  };
+}

From 604c26647e817b05feeeb75e5f300708e4f02291 Mon Sep 17 00:00:00 2001
From: notohh <github@notohh.dev>
Date: Mon, 8 Apr 2024 17:59:36 -0400
Subject: [PATCH 21/31] nix: read version from cargo.toml

fix spelling error
---
 flake.nix | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/flake.nix b/flake.nix
index f29c01a..bfd6561 100644
--- a/flake.nix
+++ b/flake.nix
@@ -22,10 +22,11 @@
   in {
     packages = eachSystem (system: let
       pkgs = nixpkgs.legacyPackages.${system};
+      version = (builtins.fromTOML (builtins.readFile ./Cargo.toml)).package.version;
     in {
       default = pkgsFor.${system}.rustPlatform.buildRustPackage {
         pname = "forcebot_rs";
-        version = "v0.1";
+        version = "${version}";
 
         src = self;
 

From 200d2a86d3f63191fbc28a335b13b928bd816f61 Mon Sep 17 00:00:00 2001
From: notohh <github@notohh.dev>
Date: Mon, 8 Apr 2024 18:45:30 -0400
Subject: [PATCH 22/31] nix: add pre-commit-hooks

---
 .gitignore     |   5 +-
 flake.lock     | 127 ++++++++++++++++++++++++++++++++++++++++++++++++-
 flake.nix      |  21 +++++++-
 nix/module.nix |   2 +-
 statix.toml    |   3 ++
 5 files changed, 153 insertions(+), 5 deletions(-)
 create mode 100644 statix.toml

diff --git a/.gitignore b/.gitignore
index 51b0be2..e602fce 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,4 +25,7 @@ target/
 .vscode/
 
 # nix
-result/
\ No newline at end of file
+result/
+
+# pre-commit
+/.pre-commit-config.yaml
diff --git a/flake.lock b/flake.lock
index f66c5b5..cf7dd31 100644
--- a/flake.lock
+++ b/flake.lock
@@ -20,6 +20,61 @@
         "type": "github"
       }
     },
+    "flake-compat": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1696426674,
+        "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
+        "type": "github"
+      },
+      "original": {
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "type": "github"
+      }
+    },
+    "flake-utils": {
+      "inputs": {
+        "systems": "systems"
+      },
+      "locked": {
+        "lastModified": 1710146030,
+        "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "type": "github"
+      }
+    },
+    "gitignore": {
+      "inputs": {
+        "nixpkgs": [
+          "pre-commit-hooks",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1709087332,
+        "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
+        "owner": "hercules-ci",
+        "repo": "gitignore.nix",
+        "rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
+        "type": "github"
+      },
+      "original": {
+        "owner": "hercules-ci",
+        "repo": "gitignore.nix",
+        "type": "github"
+      }
+    },
     "nixpkgs": {
       "locked": {
         "lastModified": 1711703276,
@@ -36,6 +91,22 @@
         "type": "github"
       }
     },
+    "nixpkgs-stable": {
+      "locked": {
+        "lastModified": 1710695816,
+        "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "614b4613980a522ba49f0d194531beddbb7220d3",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "ref": "nixos-23.11",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
     "nixpkgs_2": {
       "locked": {
         "lastModified": 1712543224,
@@ -52,11 +123,50 @@
         "type": "github"
       }
     },
+    "nixpkgs_3": {
+      "locked": {
+        "lastModified": 1710765496,
+        "narHash": "sha256-p7ryWEeQfMwTB6E0wIUd5V2cFTgq+DRRBz2hYGnJZyA=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "e367f7a1fb93137af22a3908f00b9a35e2d286a7",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "ref": "nixpkgs-unstable",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "pre-commit-hooks": {
+      "inputs": {
+        "flake-compat": "flake-compat",
+        "flake-utils": "flake-utils",
+        "gitignore": "gitignore",
+        "nixpkgs": "nixpkgs_3",
+        "nixpkgs-stable": "nixpkgs-stable"
+      },
+      "locked": {
+        "lastModified": 1712579741,
+        "narHash": "sha256-igpsH+pa6yFwYOdah3cFciCk8gw+ytniG9quf5f/q84=",
+        "owner": "cachix",
+        "repo": "pre-commit-hooks.nix",
+        "rev": "70f504012f0a132ac33e56988e1028d88a48855c",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "repo": "pre-commit-hooks.nix",
+        "type": "github"
+      }
+    },
     "root": {
       "inputs": {
         "fenix": "fenix",
         "nixpkgs": "nixpkgs_2",
-        "systems": "systems"
+        "pre-commit-hooks": "pre-commit-hooks",
+        "systems": "systems_2"
       }
     },
     "rust-analyzer-src": {
@@ -77,6 +187,21 @@
       }
     },
     "systems": {
+      "locked": {
+        "lastModified": 1681028828,
+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+        "owner": "nix-systems",
+        "repo": "default",
+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "default",
+        "type": "github"
+      }
+    },
+    "systems_2": {
       "locked": {
         "lastModified": 1689347949,
         "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
diff --git a/flake.nix b/flake.nix
index bfd6561..e645270 100644
--- a/flake.nix
+++ b/flake.nix
@@ -5,6 +5,7 @@
     systems.url = "github:nix-systems/default-linux";
     nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
     fenix.url = "github:nix-community/fenix/monthly";
+    pre-commit-hooks.url = "github:cachix/pre-commit-hooks.nix";
   };
 
   outputs = {
@@ -12,7 +13,8 @@
     systems,
     nixpkgs,
     fenix,
-  } @ inputs: let
+    pre-commit-hooks,
+  }: let
     eachSystem = nixpkgs.lib.genAttrs (import systems);
     pkgsFor = eachSystem (system:
       import nixpkgs {
@@ -22,7 +24,7 @@
   in {
     packages = eachSystem (system: let
       pkgs = nixpkgs.legacyPackages.${system};
-      version = (builtins.fromTOML (builtins.readFile ./Cargo.toml)).package.version;
+      inherit ((builtins.fromTOML (builtins.readFile ./Cargo.toml)).package) version;
     in {
       default = pkgsFor.${system}.rustPlatform.buildRustPackage {
         pname = "forcebot_rs";
@@ -40,8 +42,23 @@
         doCheck = false;
       };
     });
+    checks = eachSystem (system: {
+      pre-commit-check = pre-commit-hooks.lib.${system}.run {
+        src = ./.;
+        hooks = {
+          # rust
+          rustfmt.enable = true;
+          clippy.enable = true;
+          # nix
+          statix.enable = true;
+          alejandra.enable = true;
+          deadnix.enable = true;
+        };
+      };
+    });
     devShells = eachSystem (system: {
       default = pkgsFor.${system}.mkShell {
+        inherit (self.checks.${system}.pre-commit-check) shellHook;
         packages = with pkgsFor.${system}; [
           nil
           alejandra
diff --git a/nix/module.nix b/nix/module.nix
index b615be1..cdc3706 100644
--- a/nix/module.nix
+++ b/nix/module.nix
@@ -17,7 +17,7 @@ in {
 
     package = mkOption {
       type = types.package;
-      default = self.packages.${system}.default;
+      inherit (self.packages.${system}) default;
     };
   };
 
diff --git a/statix.toml b/statix.toml
new file mode 100644
index 0000000..fbe25a9
--- /dev/null
+++ b/statix.toml
@@ -0,0 +1,3 @@
+disabled = []
+nix_version = '2.4'
+ignore = ['.direnv']

From dd2670c7664410c4e31ddc4cbd01675523823fd3 Mon Sep 17 00:00:00 2001
From: WoodpeckerCI <woodpecker@flake.sh>
Date: Tue, 9 Apr 2024 01:02:55 +0000
Subject: [PATCH 23/31] flake.lock: update

---
 flake.lock | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/flake.lock b/flake.lock
index cf7dd31..7da4bc6 100644
--- a/flake.lock
+++ b/flake.lock
@@ -109,11 +109,11 @@
     },
     "nixpkgs_2": {
       "locked": {
-        "lastModified": 1712543224,
-        "narHash": "sha256-9RSfZL1TKYdGxZwgDxwtBtsKMGR4Zgn+DAnF9s71/lU=",
+        "lastModified": 1712573573,
+        "narHash": "sha256-xxon7WwNm4/EadMKg1eF40/5s0O78nXUy2ILZt6vT7E=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "b0dab7cc34ef4d8a1b2de36178da801090bcb271",
+        "rev": "0d28066770464d19d637f6e8e42e8688420b6ac6",
         "type": "github"
       },
       "original": {

From 74d938751fd44234057a1882e1850a348f83d7fd Mon Sep 17 00:00:00 2001
From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com>
Date: Tue, 9 Apr 2024 10:00:01 -0400
Subject: [PATCH 24/31] cucked promote alt

---
 src/core/identity.rs | 96 +++++++++++++++++++++++++++++++++++++-------
 1 file changed, 81 insertions(+), 15 deletions(-)

diff --git a/src/core/identity.rs b/src/core/identity.rs
index 726bbdf..a6e623d 100644
--- a/src/core/identity.rs
+++ b/src/core/identity.rs
@@ -8,6 +8,7 @@ use std::sync::Arc;
 
 use tokio::sync::RwLock;
 
+use tokio::time::{sleep,Duration};
 use twitch_irc::message::PrivmsgMessage;
 
 use casual_logger::Log;
@@ -59,7 +60,10 @@ pub async fn init(mgr: Arc<ModulesManager>) {
     let tempb = BotCommand {
         module: BotModule(String::from("identity")),
         command: String::from("promote"), // command call name
-        alias: vec![],                    // String of alternative names
+        alias: vec![
+            "cucked".to_string(),
+            "cuck".to_string(),
+        ],                    // String of alternative names
         exec_body: actions_util::asyncbox(cmd_promote),
         help: String::from("promote"),
         required_roles: vec![
@@ -164,7 +168,7 @@ async fn cmd_promote(params : ExecBodyParams) {
 
     let mut argv = params.msg.message_text.split(' ');
 
-    argv.next(); // Skip the command name
+    let cmdname = argv.next(); // Skip the command name
 
     let arg1 = argv.next();
 
@@ -202,7 +206,7 @@ async fn cmd_promote(params : ExecBodyParams) {
     // [x] 1. Get trgusr (regardless of -admin flag)
 
     // let targetusr = if arg1 == Some("-admin") { arg2 } else { arg1 };
-    let targetusr = if 
+    let mut targetusr = if 
             arg1 == Some("-admin") 
             || arg1 == Some("-v") 
             || arg1 == Some("-vip") 
@@ -222,6 +226,50 @@ async fn cmd_promote(params : ExecBodyParams) {
             }
             else { arg1 };
 
+
+    // [x] Check if target is an existing user
+    targetusr = if let Some(chkusr) = targetusr {
+        match twitch_irc::validate::validate_login(chkusr.to_lowercase().as_str()) {
+            Ok(_) => Some(chkusr),
+            Err(_) => None,
+        }
+    } else { None } ;
+
+
+    // [x] Check if cmd passed is cucked, then go through special cucked handling
+    if let Some(cmd_to_check) = cmdname {
+        if cmd_to_check.to_lowercase() == String::from(botlock.get_prefix()) + "cucked" 
+        || cmd_to_check.to_lowercase() == String::from(botlock.get_prefix()) + "cuck"
+        {
+
+            let idlock = botlock.botmgrs.identity.read().await;
+            let senderroles = idlock.getspecialuserroles(sendername.clone(), Some(Channel(targetchnl.to_lowercase()))).await;
+
+            if senderroles.contains(&UserRole::BotAdmin) && targetusr.is_none() {
+                targetusr = Some(sendername.as_str())
+            }
+
+            botlock.botmgrs.chat.send_botmsg(super::chat::BotMsgType::Notif(
+                "uuh ".to_string()
+                ),
+            params.clone(),
+            ).await;
+
+            sleep(Duration::from_secs_f64(1.0)).await;
+
+            
+            botlock.botmgrs.chat.send_botmsg(super::chat::BotMsgType::Notif(
+                "... ".to_string()
+                ),
+            params.clone(),
+            ).await;
+
+            sleep(Duration::from_secs_f64(2.0)).await;
+
+        }
+    }
+
+
     // [x] 2. promote trguser
 
     // [x] Get a required lock first
@@ -272,14 +320,23 @@ async fn cmd_promote(params : ExecBodyParams) {
     // [x] 3. Output resulting change
 
     let outmsg = match rslt {
-        ChangeResult::Success(a) => {
-            format!("o7 Successfully promoted : {a}")
+        ChangeResult::Success(rsltstr) => {
+            format!("o7 Successfully promoted {} : {}",
+            targetusr.unwrap().to_string(),
+            rsltstr
+            )
         }
-        ChangeResult::Failed(a) => {
-            format!("PoroSad failed to promote : {a}")
+        ChangeResult::Failed(rsltstr) => {
+            format!("PoroSad failed to promote {} : {}",
+            targetusr.unwrap().to_string(),
+            rsltstr
+            )
         }
-        ChangeResult::NoChange(a) => {
-            format!("uuh No Promotion Change : {a}")
+        ChangeResult::NoChange(rsltstr) => {
+            format!("uuh No Promotion Change {} : {}",
+            targetusr.unwrap().to_string(),
+            rsltstr
+            )
         }
     };
 
@@ -499,14 +556,23 @@ async fn cmd_demote(params : ExecBodyParams) {
      */
 
     let outmsg = match rslt {
-        ChangeResult::Success(a) => {
-            format!("o7 Successfully demoted : {a}")
+        ChangeResult::Success(rsltstr) => {
+            format!("o7 Successfully demoted {} : {}",
+            targetusr.unwrap().to_string(),
+            rsltstr
+            )
         }
-        ChangeResult::Failed(a) => {
-            format!("PoroSad failed to demote : {a}")
+        ChangeResult::Failed(rsltstr) => {
+            format!("PoroSad failed to demote {} : {}",
+            targetusr.unwrap().to_string(),
+            rsltstr
+            )
         }
-        ChangeResult::NoChange(a) => {
-            format!("uuh No Demotion Change : {a}")
+        ChangeResult::NoChange(rsltstr) => {
+            format!("uuh No Demotion Change {} : {}",
+            targetusr.unwrap().to_string(),
+            rsltstr
+            )
         }
     };
 

From 16c6b0eebb3670fd398c4f8eb0d085faa2eb6b69 Mon Sep 17 00:00:00 2001
From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com>
Date: Tue, 9 Apr 2024 12:32:02 -0400
Subject: [PATCH 25/31] self-invoking identity methods

---
 src/core/identity.rs | 27 +++++++++++++++++++--------
 1 file changed, 19 insertions(+), 8 deletions(-)

diff --git a/src/core/identity.rs b/src/core/identity.rs
index a6e623d..59f6eed 100644
--- a/src/core/identity.rs
+++ b/src/core/identity.rs
@@ -255,16 +255,16 @@ async fn cmd_promote(params : ExecBodyParams) {
             params.clone(),
             ).await;
 
-            sleep(Duration::from_secs_f64(1.0)).await;
+            sleep(Duration::from_secs_f64(2.0)).await;
 
             
             botlock.botmgrs.chat.send_botmsg(super::chat::BotMsgType::Notif(
-                "... ".to_string()
+                "... chatter getting cucked ...".to_string()
                 ),
             params.clone(),
             ).await;
 
-            sleep(Duration::from_secs_f64(2.0)).await;
+            sleep(Duration::from_secs_f64(1.0)).await;
 
         }
     }
@@ -608,6 +608,8 @@ async fn getroles(params : ExecBodyParams) {
 
      */
 
+    let sendername = params.msg.clone().sender.name;
+
 
     let mut argv = params.msg.message_text.split(' ');
 
@@ -615,11 +617,17 @@ async fn getroles(params : ExecBodyParams) {
 
     let arg1 = argv.next();
 
-    let targetuser = match arg1 {
-        None => return, // exit if no arguments
+    let mut targetuser = match arg1 {
+        // None => return, // exit if no arguments
+        None => sendername.as_str(), // self-invoke in this case
         Some(arg) => arg,
     };
 
+    targetuser = match twitch_irc::validate::validate_login(targetuser.to_lowercase().as_str()) {
+        Ok(_) => targetuser,
+        Err(_) => sendername.as_str(), // self-invoke in this case
+    };
+
     let arg2 = argv.next();
 
     let targetchnl = arg2;
@@ -703,7 +711,9 @@ async fn getroles(params : ExecBodyParams) {
             params.msg.channel_login.to_lowercase(),
         ))) || sproles.contains(&UserRole::BotAdmin)
         {
-            outmsg += format!("Target chatter's user roles are : {:?}", sproles).as_str();
+            // targetuser
+            // outmsg += format!("Target chatter's user roles are : {:?}", sproles).as_str();
+            outmsg += format!("{}'s user roles are : {:?}", targetuser, sproles).as_str();
         }
         outmsg
     } else if sproles.contains(&UserRole::Mod(Channel(
@@ -712,9 +722,10 @@ async fn getroles(params : ExecBodyParams) {
         params.msg.channel_login.to_lowercase(),
     ))) || sproles.contains(&UserRole::BotAdmin)
     {
-        format!("Target chatter's user roles are : {:?}", sproles)
+        // format!("Target chatter's user roles are : {:?}", sproles)
+        format!("{}'s user roles are : {:?}", targetuser, sproles)
     } else {
-        "Target chatter has no special roles LULE ".to_string()
+        format!("{} has no special roles LULE ",targetuser)
     };
 
     botlog::debug(

From dfb37717b38cec08ad96faad8454d7dd81852ef7 Mon Sep 17 00:00:00 2001
From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com>
Date: Tue, 9 Apr 2024 12:36:46 -0400
Subject: [PATCH 26/31] clippy

---
 src/core/identity.rs | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/core/identity.rs b/src/core/identity.rs
index 59f6eed..0e092e0 100644
--- a/src/core/identity.rs
+++ b/src/core/identity.rs
@@ -322,19 +322,19 @@ async fn cmd_promote(params : ExecBodyParams) {
     let outmsg = match rslt {
         ChangeResult::Success(rsltstr) => {
             format!("o7 Successfully promoted {} : {}",
-            targetusr.unwrap().to_string(),
+            targetusr.unwrap(),
             rsltstr
             )
         }
         ChangeResult::Failed(rsltstr) => {
             format!("PoroSad failed to promote {} : {}",
-            targetusr.unwrap().to_string(),
+            targetusr.unwrap(),
             rsltstr
             )
         }
         ChangeResult::NoChange(rsltstr) => {
             format!("uuh No Promotion Change {} : {}",
-            targetusr.unwrap().to_string(),
+            targetusr.unwrap(),
             rsltstr
             )
         }
@@ -558,19 +558,19 @@ async fn cmd_demote(params : ExecBodyParams) {
     let outmsg = match rslt {
         ChangeResult::Success(rsltstr) => {
             format!("o7 Successfully demoted {} : {}",
-            targetusr.unwrap().to_string(),
+            targetusr.unwrap(),
             rsltstr
             )
         }
         ChangeResult::Failed(rsltstr) => {
             format!("PoroSad failed to demote {} : {}",
-            targetusr.unwrap().to_string(),
+            targetusr.unwrap(),
             rsltstr
             )
         }
         ChangeResult::NoChange(rsltstr) => {
             format!("uuh No Demotion Change {} : {}",
-            targetusr.unwrap().to_string(),
+            targetusr.unwrap(),
             rsltstr
             )
         }

From 4b849cfed64984355a8141bb245db3d7c5ac378a Mon Sep 17 00:00:00 2001
From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com>
Date: Tue, 9 Apr 2024 12:51:53 -0400
Subject: [PATCH 27/31] comments cleanup

---
 src/core/identity.rs | 12 ------------
 1 file changed, 12 deletions(-)

diff --git a/src/core/identity.rs b/src/core/identity.rs
index 42bc4c7..effb317 100644
--- a/src/core/identity.rs
+++ b/src/core/identity.rs
@@ -15,21 +15,9 @@ use dotenv::dotenv;
 use std::env;
 
 fn adminvector() -> Vec<String> {
-    // vec![String::from("ModulatingForce")]
-    // //vec![]
     dotenv().ok();
     let mut admins = Vec::new();
 
-    // for admin in env::var("bot_admins").unwrap().split(',') {
-    //     admins.push(String::from(admin))
-    // }
-
-    // 03.17 - Forcen - Suggesting below instead : 
-    /*
-        - this will push only if env::var() returns Ok() ; 
-            otherwise (like in Err(_)) do nothing
-     */
-
     if let Ok(value) = env::var("bot_admins") {
         for admin in value.split(',') {
             admins.push(String::from(admin))        

From f86f48178d1a522b1d0f1c89133bb394450221e7 Mon Sep 17 00:00:00 2001
From: notohh <github@notohh.dev>
Date: Tue, 9 Apr 2024 13:27:25 -0400
Subject: [PATCH 28/31] ci: fix branch naming

---
 .woodpecker/cargo-checks.yml | 2 +-
 .woodpecker/flake-update.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.woodpecker/cargo-checks.yml b/.woodpecker/cargo-checks.yml
index 1d698f2..fa5ecae 100644
--- a/.woodpecker/cargo-checks.yml
+++ b/.woodpecker/cargo-checks.yml
@@ -1,5 +1,5 @@
 when:
-  branch: main
+  branch: master
   event: [push, pull_request]
   path:
     include:
diff --git a/.woodpecker/flake-update.yml b/.woodpecker/flake-update.yml
index 56c672a..37d88de 100644
--- a/.woodpecker/flake-update.yml
+++ b/.woodpecker/flake-update.yml
@@ -37,7 +37,7 @@ steps:
       owner: ${CI_REPO_OWNER}
       repo: ${CI_REPO_NAME}
       branch: flake-lock-update
-      base_branch: main
+      base_branch: master
       pr_title: "flake.lock: update"
       pr_body: PR automatically created by Woodpecker CI
       close_pr_if_empty: true

From 7f49693a942366a9efe05215e16629ae1b872b58 Mon Sep 17 00:00:00 2001
From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com>
Date: Tue, 9 Apr 2024 13:47:06 -0400
Subject: [PATCH 29/31] clippy

---
 src/core/identity.rs | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/src/core/identity.rs b/src/core/identity.rs
index 5f7fac1..61c09dc 100644
--- a/src/core/identity.rs
+++ b/src/core/identity.rs
@@ -21,9 +21,6 @@ use crate::core::botmodules::{BotActionTrait, BotCommand, BotModule, ModulesMana
 use dotenv::dotenv;
 use std::env;
 
-use dotenv::dotenv;
-use std::env;
-
 fn adminvector() -> Vec<String> {
     dotenv().ok();
     let mut admins = Vec::new();

From 55aeaa7fc15c124ec2d0923aa5a547125bda0452 Mon Sep 17 00:00:00 2001
From: haruyuumei <luzivotto.erick@gmail.com>
Date: Tue, 9 Apr 2024 16:22:11 -0300
Subject: [PATCH 30/31] changed reply message on thisguy

---
 src/custom/thisguy.rs | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/custom/thisguy.rs b/src/custom/thisguy.rs
index 052f601..8616580 100644
--- a/src/custom/thisguy.rs
+++ b/src/custom/thisguy.rs
@@ -4,6 +4,7 @@ use crate::core::botlog;
 use crate::core::botmodules::{BotActionTrait, BotCommand, BotModule, ModulesManager};
 use crate::core::identity::UserRole::*;
 use rand::Rng;
+use twitch_irc::message::ReplyToMessage;
 use std::sync::Arc;
 use tokio::time::{sleep, Duration};
 const OF_CMD_CHANNEL:Channel = Channel(String::new());
@@ -34,7 +35,11 @@ async fn tsg(params: ExecBodyParams) {
     botlock
         .botmgrs
         .chat
-        .say_in_reply_to(&params.msg, a, params.clone())
+        .say_in_reply(
+            Channel(params.clone().msg.channel_login().to_string()),
+             a,
+              params.clone()
+            )
         .await;
     sleep(Duration::from_secs_f64(0.5)).await;
 }

From e41f7b0524c19ebf321bc3455125cddd333e7214 Mon Sep 17 00:00:00 2001
From: haruyuumei <luzivotto.erick@gmail.com>
Date: Tue, 9 Apr 2024 16:44:58 -0300
Subject: [PATCH 31/31] warning changed

---
 src/custom/thisguy.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/custom/thisguy.rs b/src/custom/thisguy.rs
index 8616580..cc53129 100644
--- a/src/custom/thisguy.rs
+++ b/src/custom/thisguy.rs
@@ -57,6 +57,6 @@ pub async fn init(mgr: &Arc<ModulesManager>) {
             Broadcaster
             ],
     }
-    .add_to_modmgr(Arc::clone(&mgr))
+    .add_to_modmgr(Arc::clone(mgr))
     .await;
 }
\ No newline at end of file