From eb8877f0c1b154288f0c2343ec076ec18ae0fb50 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Wed, 20 Mar 2024 23:20:46 -0400 Subject: [PATCH 01/22] ModGroup enum --- src/core/botmodules.rs | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 0bfe4fa..2fa8945 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -45,6 +45,12 @@ pub enum ModType { BotModule(String), } +#[derive(Debug, PartialEq, Eq, Hash, Clone)] +pub enum ModGroup { + Core, + Custom, +} + #[derive(Debug)] pub enum StatusLvl { Instance, @@ -77,6 +83,8 @@ impl BotAction { pub trait BotActionTrait { async fn add_to_bot(self, bot: BotInstance); async fn add_to_modmgr(self, modmgr: Arc); + async fn add_core_to_bot(self, bot: BotInstance); + async fn add_core_to_modmgr(self, modmgr: Arc); } pub struct BotCommand { @@ -105,6 +113,16 @@ impl BotActionTrait for BotCommand { .add_botaction(self.module.clone(), BotAction::C(self)) .await } + + async fn add_core_to_bot(self, bot: BotInstance) { + self.add_core_to_modmgr(bot.botmodules).await; + } + + async fn add_core_to_modmgr(self, modmgr: Arc) { + modmgr + .add_core_act(self.module.clone(), BotAction::C(self)) + .await + } } pub struct Listener { @@ -142,13 +160,24 @@ impl BotActionTrait for Listener { .add_botaction(self.module.clone(), BotAction::L(self)) .await; } + + async fn add_core_to_bot(self, bot: BotInstance) { + self.add_core_to_modmgr(bot.botmodules).await; + } + + async fn add_core_to_modmgr(self, modmgr: Arc) { + modmgr + .add_core_act(self.module.clone(), BotAction::L(self)) + .await + } } #[derive(Debug)] pub struct Routine {} pub struct ModulesManager { - statusdb: Arc>>>, + // statusdb: Arc>>>, + statusdb: Arc>>>, pub botactions: Arc>>>, } @@ -220,6 +249,14 @@ impl ModulesManager { } pub async fn add_botaction(&self, in_module: ModType, in_action: BotAction) { + self.int_add_botaction(in_module,ModGroup::Custom,in_action).await; + } + + pub async fn add_core_act(&self, in_module: ModType, in_action: BotAction) { + self.int_add_botaction(in_module,ModGroup::Core,in_action).await; + } + + async fn int_add_botaction(&self, in_module: ModType, in_modgroup: ModGroup, in_action: BotAction) { botlog::trace( "Add botaction called", Some("ModulesManager > init()".to_string()), @@ -300,7 +337,8 @@ impl ModulesManager { } let mut dbt = self.statusdb.write().await; - let statusvector = dbt.entry(in_module.clone()).or_insert(Vec::new()); + // + let statusvector = dbt.entry((in_module.clone(),in_modgroup.clone())).or_insert(Vec::new()); statusvector.push(ModStatusType::Enabled(StatusLvl::Instance)); // Pushes the Module as Enabled at Instance Level From dda0050513926fea695379823b871504219ad8a3 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Wed, 20 Mar 2024 23:26:05 -0400 Subject: [PATCH 02/22] identity adds core modules --- src/core/identity.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/core/identity.rs b/src/core/identity.rs index f5e710b..b302a7e 100644 --- a/src/core/identity.rs +++ b/src/core/identity.rs @@ -67,7 +67,8 @@ pub async fn init(mgr: Arc) { ], }; - tempb.add_to_modmgr(Arc::clone(&mgr)).await; + // tempb.add_to_modmgr(Arc::clone(&mgr)).await; + tempb.add_core_to_modmgr(Arc::clone(&mgr)).await; async fn cmd_promote(bot: BotAR, msg: PrivmsgMessage) { botlog::trace( @@ -238,7 +239,9 @@ pub async fn init(mgr: Arc) { ], }; - tempb.add_to_modmgr(Arc::clone(&mgr)).await; + // tempb.add_to_modmgr(Arc::clone(&mgr)).await; + // add_core_to_modmgr + tempb.add_core_to_modmgr(Arc::clone(&mgr)).await; async fn cmd_demote(bot: BotAR, msg: PrivmsgMessage) { botlog::debug( @@ -428,7 +431,9 @@ pub async fn init(mgr: Arc) { ], }; - tempcomm.add_to_modmgr(Arc::clone(&mgr)).await; + // tempcomm.add_to_modmgr(Arc::clone(&mgr)).await; + // add_core_to_modmgr + tempcomm.add_core_to_modmgr(Arc::clone(&mgr)).await; async fn getroles(bot: BotAR, msg: PrivmsgMessage) { botlog::debug( From ca3bca9ae6e67fa2a564243bf8f54bfd671c50ed Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Wed, 20 Mar 2024 23:32:05 -0400 Subject: [PATCH 03/22] modgroup default statuses --- src/core/botmodules.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 2fa8945..870fc98 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -340,7 +340,12 @@ impl ModulesManager { // let statusvector = dbt.entry((in_module.clone(),in_modgroup.clone())).or_insert(Vec::new()); - statusvector.push(ModStatusType::Enabled(StatusLvl::Instance)); // Pushes the Module as Enabled at Instance Level + match in_modgroup { + ModGroup::Core => statusvector.push(ModStatusType::Enabled(StatusLvl::Instance)) , // Pushes the Module as Enabled at Instance Level + ModGroup::Custom => statusvector.push(ModStatusType::Disabled(StatusLvl::Instance)), + } + + // statusvector.push(ModStatusType::Enabled(StatusLvl::Instance)); // Pushes the Module as Enabled at Instance Level let mut a = self.botactions.write().await; let modactions = a.entry(in_module.clone()).or_insert(Vec::new()); From b353589576e2bb224555ab4e626321fa675e5617 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Wed, 20 Mar 2024 23:35:56 -0400 Subject: [PATCH 04/22] refactor statustype --- src/core/botmodules.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 870fc98..fdbddcf 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -58,7 +58,7 @@ pub enum StatusLvl { } #[derive(Debug)] -pub enum ModStatusType { +pub enum StatusType { Enabled(StatusLvl), Disabled(StatusLvl), } @@ -177,7 +177,7 @@ pub struct Routine {} pub struct ModulesManager { // statusdb: Arc>>>, - statusdb: Arc>>>, + statusdb: Arc>>>, pub botactions: Arc>>>, } @@ -226,7 +226,7 @@ impl ModulesManager { mgrarc } - pub fn modstatus(&self, _: ModType, _: ChType) -> ModStatusType { + pub fn modstatus(&self, _: ModType, _: ChType) -> StatusType { // Example usage : botmanager.modstatus( // BotModule("GambaCore"), // Channel("modulatingforce") @@ -234,15 +234,15 @@ impl ModulesManager { // - The ModStatusType checks in the context of the given channel , // but also validates based on wheher the module is disabled at a bot instance // level as well - ModStatusType::Enabled(StatusLvl::Instance) + StatusType::Enabled(StatusLvl::Instance) } - pub fn togglestatus(&self, _: ModType, _: ChType) -> ModStatusType { + pub fn togglestatus(&self, _: ModType, _: ChType) -> StatusType { // enables or disables based on current status - ModStatusType::Enabled(StatusLvl::Instance) + StatusType::Enabled(StatusLvl::Instance) } - pub fn setstatus(&self, _: ModType, _: ModStatusType) -> Result<&str, Box> { + pub fn setstatus(&self, _: ModType, _: StatusType) -> Result<&str, Box> { // sets the status based given ModSatusType // e.g., b.setstatus(BodModule("GambaCore"), Enabled(Channel("modulatingforce"))).expect("ERROR") Ok("") @@ -341,8 +341,8 @@ impl ModulesManager { let statusvector = dbt.entry((in_module.clone(),in_modgroup.clone())).or_insert(Vec::new()); match in_modgroup { - ModGroup::Core => statusvector.push(ModStatusType::Enabled(StatusLvl::Instance)) , // Pushes the Module as Enabled at Instance Level - ModGroup::Custom => statusvector.push(ModStatusType::Disabled(StatusLvl::Instance)), + ModGroup::Core => statusvector.push(StatusType::Enabled(StatusLvl::Instance)) , // Pushes the Module as Enabled at Instance Level + ModGroup::Custom => statusvector.push(StatusType::Disabled(StatusLvl::Instance)), } // statusvector.push(ModStatusType::Enabled(StatusLvl::Instance)); // Pushes the Module as Enabled at Instance Level From a066329730529a475a467fa1ea13f8495b834717 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Thu, 21 Mar 2024 00:05:52 -0400 Subject: [PATCH 05/22] botmodules helper fns --- src/core/botinstance.rs | 11 ++++++++- src/core/botmodules.rs | 54 ++++++++++++++++++++++++++++++++++------- src/core/identity.rs | 14 +++++------ 3 files changed, 62 insertions(+), 17 deletions(-) diff --git a/src/core/botinstance.rs b/src/core/botinstance.rs index 144e8ee..2e30421 100644 --- a/src/core/botinstance.rs +++ b/src/core/botinstance.rs @@ -19,12 +19,21 @@ use crate::core::ratelimiter::RateLimiter; use crate::core::bot_actions::actions_util::BotAR; use crate::core::botmodules::ModulesManager; -use crate::core::identity::{ChangeResult, IdentityManager, Permissible}; +use crate::core::identity::{IdentityManager, Permissible}; use crate::core::botlog; use crate::core::chat::Chat; +#[derive(Debug, PartialEq, Eq)] +pub enum ChangeResult { + Success(String), + Failed(String), + NoChange(String), +} + + + #[derive(Debug, PartialEq, Eq, Hash, Clone)] pub enum ChType { Channel(String), diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index fdbddcf..746c673 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -22,7 +22,7 @@ Example use core::panic; use std::collections::HashMap; -use std::error::Error; +// use std::error::Error; use std::sync::Arc; use twitch_irc::message::PrivmsgMessage; @@ -32,7 +32,7 @@ use tokio::sync::RwLock; use async_trait::async_trait; use self::bot_actions::actions_util::BotAR; -use crate::core::botinstance::{BotInstance, ChType}; +use crate::core::botinstance::{BotInstance, ChType,ChangeResult}; use crate::core::botlog; use crate::core::identity; @@ -40,6 +40,9 @@ use crate::core::bot_actions; pub use ChType::Channel; pub use ModType::BotModule; +// use super::identity::ChangeResult; + + #[derive(Debug, PartialEq, Eq, Hash, Clone)] pub enum ModType { BotModule(String), @@ -237,17 +240,50 @@ impl ModulesManager { StatusType::Enabled(StatusLvl::Instance) } - pub fn togglestatus(&self, _: ModType, _: ChType) -> StatusType { - // enables or disables based on current status - StatusType::Enabled(StatusLvl::Instance) + // pub fn togglestatus(&self, _: ModType, _: ChType) -> StatusType { + // // enables or disables based on current status + // StatusType::Enabled(StatusLvl::Instance) + // } + + // pub fn setstatus(&self, _: ModType, _: StatusType) -> Result<&str, Box> { + // // sets the status based given ModSatusType + // // e.g., b.setstatus(BodModule("GambaCore"), Enabled(Channel("modulatingforce"))).expect("ERROR") + // Ok("") + // } + + pub fn set_instance_disabled(&self, _in_module: ModType) -> (StatusType,ChangeResult) { + // at Instance level + // - If core module, do nothing + (StatusType::Disabled(StatusLvl::Instance),ChangeResult::NoChange("Nothing needed".to_string())) } - pub fn setstatus(&self, _: ModType, _: StatusType) -> Result<&str, Box> { - // sets the status based given ModSatusType - // e.g., b.setstatus(BodModule("GambaCore"), Enabled(Channel("modulatingforce"))).expect("ERROR") - Ok("") + pub fn force_disabled(&self, _in_module: ModType) -> (StatusType,ChangeResult) { + // Disables the module at Instance level, and removes all Enabled/Disabled at Channel level + // - Bot Moderators MUST Re-enable if they were enabled before + // - If core module, do nothing + (StatusType::Disabled(StatusLvl::Instance),ChangeResult::NoChange("Nothing needed".to_string())) } + pub fn set_instance_enabled(&self, _in_module: ModType) -> (StatusType,ChangeResult) { + // at Instance level + // - If core module, do nothing + (StatusType::Enabled(StatusLvl::Instance),ChangeResult::NoChange("Nothing needed".to_string())) + } + + pub fn set_ch_disabled(&self, _in_module: ModType , _in_chnl: ChType) -> (StatusType,ChangeResult) { + // at Instance level + // - If core module, do nothing + (StatusType::Disabled(StatusLvl::Instance),ChangeResult::NoChange("Nothing needed".to_string())) + } + + pub fn set_ch_enabled(&self, _in_module: ModType , _in_chnl: ChType) -> (StatusType,ChangeResult) { + // at Instance level + // - If core module, do nothing + (StatusType::Enabled(StatusLvl::Instance),ChangeResult::NoChange("Nothing needed".to_string())) + } + + + pub async fn add_botaction(&self, in_module: ModType, in_action: BotAction) { self.int_add_botaction(in_module,ModGroup::Custom,in_action).await; } diff --git a/src/core/identity.rs b/src/core/identity.rs index b302a7e..65a5088 100644 --- a/src/core/identity.rs +++ b/src/core/identity.rs @@ -8,7 +8,7 @@ use twitch_irc::message::PrivmsgMessage; use casual_logger::Log; use crate::core::bot_actions::actions_util::{self, BotAR}; -use crate::core::botinstance::ChType; +use crate::core::botinstance::{ChType,ChangeResult}; use crate::core::botlog; use crate::core::botmodules::{BotActionTrait, BotCommand, BotModule, ModulesManager}; @@ -608,12 +608,12 @@ pub enum ChatBadge { Mod, } -#[derive(Debug, PartialEq, Eq)] -pub enum ChangeResult { - Success(String), - Failed(String), - NoChange(String), -} +// #[derive(Debug, PartialEq, Eq)] +// pub enum ChangeResult { +// Success(String), +// Failed(String), +// NoChange(String), +// } impl IdentityManager { pub fn init() -> IdentityManager { From 1b44ec4f4c62196de64efea9e90cdd6a8da6a524 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Thu, 21 Mar 2024 00:11:24 -0400 Subject: [PATCH 06/22] reorg statusdb --- src/core/botmodules.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 746c673..8fdf96c 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -180,7 +180,8 @@ pub struct Routine {} pub struct ModulesManager { // statusdb: Arc>>>, - statusdb: Arc>>>, + // statusdb: Arc>>>, + statusdb: Arc)>>>, pub botactions: Arc>>>, } @@ -374,11 +375,11 @@ impl ModulesManager { let mut dbt = self.statusdb.write().await; // - let statusvector = dbt.entry((in_module.clone(),in_modgroup.clone())).or_insert(Vec::new()); + let statusvector = dbt.entry(in_module.clone()).or_insert((in_modgroup.clone(),Vec::new())); match in_modgroup { - ModGroup::Core => statusvector.push(StatusType::Enabled(StatusLvl::Instance)) , // Pushes the Module as Enabled at Instance Level - ModGroup::Custom => statusvector.push(StatusType::Disabled(StatusLvl::Instance)), + ModGroup::Core => statusvector.1.push(StatusType::Enabled(StatusLvl::Instance)) , // Pushes the Module as Enabled at Instance Level + ModGroup::Custom => statusvector.1.push(StatusType::Disabled(StatusLvl::Instance)), } // statusvector.push(ModStatusType::Enabled(StatusLvl::Instance)); // Pushes the Module as Enabled at Instance Level From 5280d18702e767d380007ff2e1e965aa10c1440e Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Thu, 21 Mar 2024 02:13:23 -0400 Subject: [PATCH 07/22] cont helper fns --- src/core/botmodules.rs | 120 +++++++++++++++++++++++++++++++++++------ 1 file changed, 105 insertions(+), 15 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 8fdf96c..78db77e 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -25,6 +25,7 @@ use std::collections::HashMap; // use std::error::Error; use std::sync::Arc; +use futures::stream::iter; use twitch_irc::message::PrivmsgMessage; use tokio::sync::RwLock; @@ -54,13 +55,13 @@ pub enum ModGroup { Custom, } -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq, Hash, Clone)] pub enum StatusLvl { Instance, - _Ch(ChType), + Ch(ChType), } -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq, Hash, Clone)] pub enum StatusType { Enabled(StatusLvl), Disabled(StatusLvl), @@ -252,17 +253,87 @@ impl ModulesManager { // Ok("") // } - pub fn set_instance_disabled(&self, _in_module: ModType) -> (StatusType,ChangeResult) { + pub async fn set_instance_disabled(&self, in_module: ModType) -> (StatusType,ChangeResult) { // at Instance level // - If core module, do nothing - (StatusType::Disabled(StatusLvl::Instance),ChangeResult::NoChange("Nothing needed".to_string())) + + // self.satusdb. + + let mut dbt = self.statusdb.write().await; + + // let a = dbt.entry(in_module.clone()).; + let (mgrp,statusvector) = dbt.get_mut(&in_module).unwrap(); + + match mgrp { + ModGroup::Core => { + ( + StatusType::Enabled(StatusLvl::Instance), + ChangeResult::Failed("Core Modules cannot be disabled".to_string()) + ) + }, + ModGroup::Custom => { + // remove all instance level pattern for the module + while let Some(index) = statusvector + .iter() + .position(|x| (*x == StatusType::Enabled(StatusLvl::Instance)) || (*x == StatusType::Disabled(StatusLvl::Instance))) { + + statusvector.remove(index); + } + statusvector.push(StatusType::Disabled(StatusLvl::Instance)); + + ( + StatusType::Disabled(StatusLvl::Instance), + ChangeResult::Success("Disabled at Instance".to_string()) + ) + }, + } + + // (StatusType::Disabled(StatusLvl::Instance),ChangeResult::NoChange("Nothing needed".to_string())) } - pub fn force_disabled(&self, _in_module: ModType) -> (StatusType,ChangeResult) { - // Disables the module at Instance level, and removes all Enabled/Disabled at Channel level + pub async fn force_disable(&self, in_module: ModType) -> (StatusType,ChangeResult) { + // Disables the module at Instance level, and removes all Enabled at Channel level // - Bot Moderators MUST Re-enable if they were enabled before // - If core module, do nothing - (StatusType::Disabled(StatusLvl::Instance),ChangeResult::NoChange("Nothing needed".to_string())) + + let mut dbt = self.statusdb.write().await; + + // let a = dbt.entry(in_module.clone()).; + let (mgrp,statusvector) = dbt.get_mut(&in_module).unwrap(); + + match mgrp { + ModGroup::Core => { + ( + StatusType::Enabled(StatusLvl::Instance), + ChangeResult::Failed("Core Modules cannot be disabled".to_string()) + ) + }, + ModGroup::Custom => { + // remove all instance level pattern & Enabled Channel patterns for the module + // Disabled at Channel level might be fine? That way if it gets Enabled at instance level, channel level disables are uninterrupted + while let Some(index) = statusvector + .iter() + .position(|x| + if (*x == StatusType::Enabled(StatusLvl::Instance)) + || (*x == StatusType::Disabled(StatusLvl::Instance)) { + true + } else if let StatusType::Enabled(StatusLvl::Ch(_)) = (*x).clone() { + true + } else {false} + ) + { + statusvector.remove(index); + } + statusvector.push(StatusType::Disabled(StatusLvl::Instance)); + + ( + StatusType::Disabled(StatusLvl::Instance), + ChangeResult::Success("Disabled at Instance".to_string()) + ) + }, + } + + // (StatusType::Disabled(StatusLvl::Instance),ChangeResult::NoChange("Nothing needed".to_string())) } pub fn set_instance_enabled(&self, _in_module: ModType) -> (StatusType,ChangeResult) { @@ -293,6 +364,23 @@ impl ModulesManager { self.int_add_botaction(in_module,ModGroup::Core,in_action).await; } + + pub async fn affirm_in_statusdb(&self,in_module:ModType,in_modgroup: ModGroup) { + + let mut dbt = self.statusdb.write().await; + + let (_,statusvector) = dbt.entry(in_module.clone()).or_insert((in_modgroup.clone(),Vec::new())); + + if !statusvector.contains(&StatusType::Enabled(StatusLvl::Instance)) && !statusvector.contains(&StatusType::Disabled(StatusLvl::Instance)) + { + match in_modgroup { + ModGroup::Core => statusvector.push(StatusType::Enabled(StatusLvl::Instance)) , // Pushes the Module as Enabled at Instance Level + ModGroup::Custom => statusvector.push(StatusType::Disabled(StatusLvl::Instance)), + } + } + + } + async fn int_add_botaction(&self, in_module: ModType, in_modgroup: ModGroup, in_action: BotAction) { botlog::trace( "Add botaction called", @@ -373,17 +461,19 @@ impl ModulesManager { ) } - let mut dbt = self.statusdb.write().await; - // - let statusvector = dbt.entry(in_module.clone()).or_insert((in_modgroup.clone(),Vec::new())); + // let mut dbt = self.statusdb.write().await; + // // + // let statusvector = dbt.entry(in_module.clone()).or_insert((in_modgroup.clone(),Vec::new())); - match in_modgroup { - ModGroup::Core => statusvector.1.push(StatusType::Enabled(StatusLvl::Instance)) , // Pushes the Module as Enabled at Instance Level - ModGroup::Custom => statusvector.1.push(StatusType::Disabled(StatusLvl::Instance)), - } + // match in_modgroup { + // ModGroup::Core => statusvector.1.push(StatusType::Enabled(StatusLvl::Instance)) , // Pushes the Module as Enabled at Instance Level + // ModGroup::Custom => statusvector.1.push(StatusType::Disabled(StatusLvl::Instance)), + // } // statusvector.push(ModStatusType::Enabled(StatusLvl::Instance)); // Pushes the Module as Enabled at Instance Level + self.affirm_in_statusdb(in_module.clone(),in_modgroup).await; + let mut a = self.botactions.write().await; let modactions = a.entry(in_module.clone()).or_insert(Vec::new()); From 23f12b395624d70d421fe9d6e6eb749d3e616054 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Thu, 21 Mar 2024 09:37:08 -0400 Subject: [PATCH 08/22] smol --- src/core/botmodules.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 78db77e..6332ab6 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -25,7 +25,7 @@ use std::collections::HashMap; // use std::error::Error; use std::sync::Arc; -use futures::stream::iter; +// use futures::stream::iter; use twitch_irc::message::PrivmsgMessage; use tokio::sync::RwLock; @@ -328,7 +328,7 @@ impl ModulesManager { ( StatusType::Disabled(StatusLvl::Instance), - ChangeResult::Success("Disabled at Instance".to_string()) + ChangeResult::Success("Forced Disabled".to_string()) ) }, } From 619cdd192390940c7b34712215e22370d1af9c23 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Thu, 21 Mar 2024 12:21:00 -0400 Subject: [PATCH 09/22] complete helper fns --- src/core/botmodules.rs | 191 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 182 insertions(+), 9 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 6332ab6..1bffc07 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -231,7 +231,7 @@ impl ModulesManager { mgrarc } - pub fn modstatus(&self, _: ModType, _: ChType) -> StatusType { + pub async fn modstatus(&self, in_module: ModType, in_chnl: ChType) -> StatusType { // Example usage : botmanager.modstatus( // BotModule("GambaCore"), // Channel("modulatingforce") @@ -239,7 +239,84 @@ impl ModulesManager { // - The ModStatusType checks in the context of the given channel , // but also validates based on wheher the module is disabled at a bot instance // level as well - StatusType::Enabled(StatusLvl::Instance) + + let dbt = self.statusdb.read().await; + + // let a = dbt.entry(in_module.clone()).; + let (mgrp,statusvector) = dbt.get(&in_module).unwrap(); + + match mgrp { + ModGroup::Core => { + StatusType::Enabled(StatusLvl::Instance) // This forces core to be validated as Enabled, even if undesired scenario of missing StatusLvl::Instance or empty vectors + }, + ModGroup::Custom => { + // // remove all instance level pattern for the module + // while let Some(index) = statusvector + // .iter() + // .position(|x| (*x == StatusType::Enabled(StatusLvl::Instance)) || (*x == StatusType::Disabled(StatusLvl::Instance))) { + + // statusvector.remove(index); + // } + // statusvector.push(StatusType::Disabled(StatusLvl::Instance)); + + // ( + // StatusType::Disabled(StatusLvl::Instance), + // ChangeResult::Success("Set Disabled at Instance".to_string()) + // ) + + /* + + [x] 1. If Disabled at Instance Level , + [x] a. And Enabled at a Channel Level > return Enabled(Channel) + [x] b. And Disabled at a Channel Level > return Disabled(Channel) + [x] c. And Not Defined at Channel Level > return Disabled(Instance) + [x] 2. If Enabled at Instance Level , + [x] a. And Enabled at a Channel Level > return Enabled(Channel) + [x] b. And Disabled at a Channel Level > return Disabled(Channel) + [x] c. And Not Defined at Channel Level > return Enabled(Instance) + */ + + + + if statusvector.contains(&StatusType::Disabled(StatusLvl::Instance)) { + // [x] 1. If Disabled at Instance Level , + + + if statusvector.contains(&StatusType::Enabled(StatusLvl::Ch(in_chnl.clone()))) { + // [x] a. And Enabled at a Channel Level > return Enabled(Channel) + StatusType::Enabled(StatusLvl::Ch(in_chnl.clone())) + } else if statusvector.contains(&StatusType::Disabled(StatusLvl::Ch(in_chnl.clone()))) { + // [x] b. And Disabled at a Channel Level > return Disabled(Channel) + StatusType::Disabled(StatusLvl::Ch(in_chnl.clone())) + } else { + // [x] c. And Not Defined at Channel Level > return Disabled(Instance) + StatusType::Disabled(StatusLvl::Instance) + } + + } else if statusvector.contains(&StatusType::Enabled(StatusLvl::Instance)) { + // [x] 2. If Enabled at Instance Level , + + if statusvector.contains(&StatusType::Enabled(StatusLvl::Ch(in_chnl.clone()))) { + // [x] a. And Enabled at a Channel Level > return Enabled(Channel) + StatusType::Enabled(StatusLvl::Ch(in_chnl.clone())) + } else if statusvector.contains(&StatusType::Disabled(StatusLvl::Ch(in_chnl.clone()))) { + // [x] b. And Disabled at a Channel Level > return Disabled(Channel) + StatusType::Disabled(StatusLvl::Ch(in_chnl.clone())) + } else { + // [x] c. And Not Defined at Channel Level > return Enabled(Instance) + StatusType::Enabled(StatusLvl::Instance) + } + + } else { + // ? In some unexpected scenario (e.g., not define at instance level), assume Disabled at Instance level and set as this way + self.set_instance_disabled(in_module).await; + StatusType::Disabled(StatusLvl::Instance) + } + }, + } + + + //StatusType::Enabled(StatusLvl::Instance) } // pub fn togglestatus(&self, _: ModType, _: ChType) -> StatusType { @@ -283,7 +360,7 @@ impl ModulesManager { ( StatusType::Disabled(StatusLvl::Instance), - ChangeResult::Success("Disabled at Instance".to_string()) + ChangeResult::Success("Set Disabled at Instance".to_string()) ) }, } @@ -336,22 +413,118 @@ impl ModulesManager { // (StatusType::Disabled(StatusLvl::Instance),ChangeResult::NoChange("Nothing needed".to_string())) } - pub fn set_instance_enabled(&self, _in_module: ModType) -> (StatusType,ChangeResult) { + pub async fn set_instance_enabled(&self, in_module: ModType) -> (StatusType,ChangeResult) { // at Instance level // - If core module, do nothing - (StatusType::Enabled(StatusLvl::Instance),ChangeResult::NoChange("Nothing needed".to_string())) + + let mut dbt = self.statusdb.write().await; + + // let a = dbt.entry(in_module.clone()).; + let (mgrp,statusvector) = dbt.get_mut(&in_module).unwrap(); + + match mgrp { + ModGroup::Core => { + ( + StatusType::Enabled(StatusLvl::Instance), + ChangeResult::NoChange("Core Modules are always Enabled".to_string()) + ) + }, + ModGroup::Custom => { + // remove all instance level pattern for the module + while let Some(index) = statusvector + .iter() + .position(|x| (*x == StatusType::Enabled(StatusLvl::Instance)) || (*x == StatusType::Disabled(StatusLvl::Instance))) { + + statusvector.remove(index); + } + statusvector.push(StatusType::Enabled(StatusLvl::Instance)); + + ( + StatusType::Enabled(StatusLvl::Instance), + ChangeResult::Success("Set Enabled at Instance".to_string()) + ) + }, + } + + // (StatusType::Enabled(StatusLvl::Instance),ChangeResult::NoChange("Nothing needed".to_string())) } - pub fn set_ch_disabled(&self, _in_module: ModType , _in_chnl: ChType) -> (StatusType,ChangeResult) { + pub async fn set_ch_disabled(&self, in_module: ModType , in_chnl: ChType) -> (StatusType,ChangeResult) { // at Instance level // - If core module, do nothing - (StatusType::Disabled(StatusLvl::Instance),ChangeResult::NoChange("Nothing needed".to_string())) + + + let mut dbt = self.statusdb.write().await; + + // let a = dbt.entry(in_module.clone()).; + let (mgrp,statusvector) = dbt.get_mut(&in_module).unwrap(); + + match mgrp { + ModGroup::Core => { + ( + StatusType::Enabled(StatusLvl::Instance), + ChangeResult::Failed("Core Modules cannot be disabled".to_string()) + ) + }, + ModGroup::Custom => { + // remove all channel level pattern for the module + while let Some(index) = statusvector + .iter() + .position(|x| + (*x == StatusType::Enabled(StatusLvl::Ch(in_chnl.clone()))) || (*x == StatusType::Disabled(StatusLvl::Ch(in_chnl.clone())))) + { + + statusvector.remove(index); + } + statusvector.push(StatusType::Disabled(StatusLvl::Ch(in_chnl.clone()))); + + ( + StatusType::Disabled(StatusLvl::Ch(in_chnl.clone())), + ChangeResult::Success("Set Disabled at Channel Level".to_string()) + ) + }, + } + + // (StatusType::Disabled(StatusLvl::Instance),ChangeResult::NoChange("Nothing needed".to_string())) } - pub fn set_ch_enabled(&self, _in_module: ModType , _in_chnl: ChType) -> (StatusType,ChangeResult) { + pub async fn set_ch_enabled(&self, in_module: ModType , in_chnl: ChType) -> (StatusType,ChangeResult) { // at Instance level // - If core module, do nothing - (StatusType::Enabled(StatusLvl::Instance),ChangeResult::NoChange("Nothing needed".to_string())) + + let mut dbt = self.statusdb.write().await; + + // let a = dbt.entry(in_module.clone()).; + let (mgrp,statusvector) = dbt.get_mut(&in_module).unwrap(); + + match mgrp { + ModGroup::Core => { + ( + StatusType::Enabled(StatusLvl::Instance), + ChangeResult::NoChange("Core Modules are always Enabled".to_string()) + ) + }, + ModGroup::Custom => { + // remove all channel level pattern for the module + while let Some(index) = statusvector + .iter() + .position(|x| + (*x == StatusType::Enabled(StatusLvl::Ch(in_chnl.clone()))) || (*x == StatusType::Disabled(StatusLvl::Ch(in_chnl.clone())))) + { + + statusvector.remove(index); + } + statusvector.push(StatusType::Enabled(StatusLvl::Ch(in_chnl.clone()))); + + ( + StatusType::Enabled(StatusLvl::Ch(in_chnl.clone())), + ChangeResult::Success("Set Enabled at Channel Level".to_string()) + ) + }, + } + + + // (StatusType::Enabled(StatusLvl::Instance),ChangeResult::NoChange("Nothing needed".to_string())) } From 68f9be496887377e951147c302b128f8cc595801 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Thu, 21 Mar 2024 14:01:54 -0400 Subject: [PATCH 10/22] unit tests --- src/core/botmodules.rs | 257 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 257 insertions(+) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 1bffc07..fadfdab 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -28,6 +28,8 @@ use std::sync::Arc; // use futures::stream::iter; use twitch_irc::message::PrivmsgMessage; +// use casual_logger::Log; + use tokio::sync::RwLock; use async_trait::async_trait; @@ -672,3 +674,258 @@ impl ModulesManager { // Passing None to chnl may be a heavy operation, as this will review and look at the whole table } } + + +// ===================== +// ===================== +// ===================== +// ===================== +// ===================== + +#[cfg(test)] +mod core_modulesmanager { + + + use casual_logger::Log; + use casual_logger::Extension; + + use super::*; + + + /* + Possible Tests + + [x] Test 1 - Custom ModGroup Workflow + 1. affirm_in_statusdb(Experiments01,Custom) + 2. modstatus(Experiments01,TestChannel01) & modstatus(Experiments01,TestChannel02) + 3. set_instance_enabled(Experiments01) + 4. modstatus(Experiments01,TestChannel01) & modstatus(Experiments01,TestChannel02) + 5. set_ch_disabled(Experiments01,TestChannel01) + 6. modstatus(Experiments01,TestChannel01) & modstatus(Experiments01,TestChannel02) + 7. set_ch_enabled(Experiments01,TestChannel01) & set_ch_disabled(Experiments01,TestChannel02) + 8. modstatus(Experiments01,TestChannel01) & modstatus(Experiments01,TestChannel02) + 9. set_instance_disabled(Experiments01) + 10. modstatus(Experiments01,TestChannel01) & modstatus(Experiments01,TestChannel02) + 11. force_disable(Experiments01) + 12. modstatus(Experiments01,TestChannel01) & modstatus(Experiments01,TestChannel02) + + + [x] Test 2 - Core ModGroup Workflow + 1. affirm_in_statusdb(CoreModule01,Core) + 2. modstatus(CoreModule01,TestChannel01) & modstatus(CoreModule01,TestChannel02) + 3. set_instance_enabled(CoreModule01) + 4. modstatus(CoreModule01,TestChannel01) & modstatus(CoreModule01,TestChannel02) + 5. set_ch_disabled(CoreModule01,TestChannel01) + 6. modstatus(CoreModule01,TestChannel01) & modstatus(CoreModule01,TestChannel02) + 7. set_ch_enabled(CoreModule01,TestChannel01) & set_ch_disabled(CoreModule01,TestChannel02) + 8. modstatus(CoreModule01,TestChannel01) & modstatus(CoreModule01,TestChannel02) + 9. set_instance_disabled(CoreModule01) + 10. modstatus(CoreModule01,TestChannel01) & modstatus(CoreModule01,TestChannel02) + 11. force_disable(CoreModule01) + 12. modstatus(CoreModule01,TestChannel01) & modstatus(CoreModule01,TestChannel02) + + + */ + + async fn complex_workflow( + in_module: ModType , + in_modgroup : ModGroup , + in_chnl1 : ChType, + in_chnl2 : ChType) + { + + + let mgr = ModulesManager::init().await; + + /* + 1. affirm_in_statusdb(Experiments01,Custom) + 2. modstatus(Experiments01,TestChannel01) & modstatus(Experiments01,TestChannel02) + */ + + mgr.affirm_in_statusdb(in_module.clone(), in_modgroup.clone()).await; + + match in_modgroup { + ModGroup::Custom => { + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl1.clone()).await, + StatusType::Disabled(StatusLvl::Instance)); + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl2.clone()).await, + StatusType::Disabled(StatusLvl::Instance)); + }, + ModGroup::Core => { + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl1.clone()).await, + StatusType::Enabled(StatusLvl::Instance)); + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl2.clone()).await, + StatusType::Enabled(StatusLvl::Instance)); + }, + } + + + /* + 3. set_instance_enabled(Experiments01) + 4. modstatus(Experiments01,TestChannel01) & modstatus(Experiments01,TestChannel02) + */ + mgr.set_instance_enabled(in_module.clone()).await; + + match in_modgroup { + ModGroup::Custom => { + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl1.clone()).await, + StatusType::Enabled(StatusLvl::Instance)); + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl2.clone()).await, + StatusType::Enabled(StatusLvl::Instance)); + }, + ModGroup::Core => { + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl1.clone()).await, + StatusType::Enabled(StatusLvl::Instance)); + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl2.clone()).await, + StatusType::Enabled(StatusLvl::Instance)); + }, + } + + /* + 5. set_ch_disabled(Experiments01,TestChannel01) + 6. modstatus(Experiments01,TestChannel01) & modstatus(Experiments01,TestChannel02) + */ + + mgr.set_ch_disabled(in_module.clone(),in_chnl1.clone()).await; + + //StatusType::Disabled(StatusLvl::Ch(in_chnl1.clone())) + + match in_modgroup { + ModGroup::Custom => { + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl1.clone()).await, + StatusType::Disabled(StatusLvl::Ch(in_chnl1.clone()))); + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl2.clone()).await, + StatusType::Enabled(StatusLvl::Instance)); + }, + ModGroup::Core => { + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl1.clone()).await, + StatusType::Enabled(StatusLvl::Instance)); + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl2.clone()).await, + StatusType::Enabled(StatusLvl::Instance)); + }, + } + + + /* + 7. set_ch_enabled(Experiments01,TestChannel01) & set_ch_disabled(Experiments01,TestChannel02) + 8. modstatus(Experiments01,TestChannel01) & modstatus(Experiments01,TestChannel02) + */ + + mgr.set_ch_enabled(in_module.clone(),in_chnl1.clone()).await; + + //StatusType::Disabled(StatusLvl::Ch(in_chnl1.clone())) + + match in_modgroup { + ModGroup::Custom => { + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl1.clone()).await, + StatusType::Enabled(StatusLvl::Ch(in_chnl1.clone()))); + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl2.clone()).await, + StatusType::Enabled(StatusLvl::Instance)); + }, + ModGroup::Core => { + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl1.clone()).await, + StatusType::Enabled(StatusLvl::Instance)); + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl2.clone()).await, + StatusType::Enabled(StatusLvl::Instance)); + }, + } + + /* + 9. set_instance_disabled(Experiments01) + 10. modstatus(Experiments01,TestChannel01) & modstatus(Experiments01,TestChannel02) + */ + + mgr.set_instance_disabled(in_module.clone()).await; + + // StatusType::Disabled(StatusLvl::Ch(in_chnl1.clone())) + + match in_modgroup { + ModGroup::Custom => { + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl1.clone()).await, + StatusType::Enabled(StatusLvl::Ch(in_chnl1.clone()))); + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl2.clone()).await, + StatusType::Disabled(StatusLvl::Instance)); + }, + ModGroup::Core => { + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl1.clone()).await, + StatusType::Enabled(StatusLvl::Instance)); + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl2.clone()).await, + StatusType::Enabled(StatusLvl::Instance)); + }, + } + /* + 11. force_disable(Experiments01) + 12. modstatus(Experiments01,TestChannel01) & modstatus(Experiments01,TestChannel02) + */ + + mgr.force_disable(in_module.clone()).await; + + match in_modgroup { + ModGroup::Custom => { + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl1.clone()).await, + StatusType::Disabled(StatusLvl::Instance)); + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl2.clone()).await, + StatusType::Disabled(StatusLvl::Instance)); + }, + ModGroup::Core => { + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl1.clone()).await, + StatusType::Enabled(StatusLvl::Instance)); + assert_eq!(mgr.modstatus(in_module.clone(), in_chnl2.clone()).await, + StatusType::Enabled(StatusLvl::Instance)); + }, + } + + } + + + #[tokio::test] + async fn custom_modgroup_workflow() { + Log::set_file_ext(Extension::Log); + + /* + + + [x] Test 1 - Custom ModGroup Workflow + 1. affirm_in_statusdb(Experiments01,Custom) + 2. modstatus(Experiments01,TestChannel01) & modstatus(Experiments01,TestChannel02) + 3. set_instance_enabled(Experiments01) + 4. modstatus(Experiments01,TestChannel01) & modstatus(Experiments01,TestChannel02) + 5. set_ch_disabled(Experiments01,TestChannel01) + 6. modstatus(Experiments01,TestChannel01) & modstatus(Experiments01,TestChannel02) + 7. set_ch_enabled(Experiments01,TestChannel01) & set_ch_disabled(Experiments01,TestChannel02) + 8. modstatus(Experiments01,TestChannel01) & modstatus(Experiments01,TestChannel02) + 9. set_instance_disabled(Experiments01) + 10. modstatus(Experiments01,TestChannel01) & modstatus(Experiments01,TestChannel02) + 11. force_disable(Experiments01) + 12. modstatus(Experiments01,TestChannel01) & modstatus(Experiments01,TestChannel02) + + */ + + let in_module = BotModule("Experiments01".to_string()); + let in_modgroup = ModGroup::Custom; + let (in_chnl1,in_chnl2) = + (ChType::Channel("TestChannel01".to_string()),ChType::Channel("TestChannel02".to_string())); + + complex_workflow(in_module, in_modgroup, in_chnl1, in_chnl2).await; + + + } + + + #[tokio::test] + async fn core_modgroup_workflow() { + Log::set_file_ext(Extension::Log); + + + let in_module = BotModule("CoreModule01".to_string()); + let in_modgroup = ModGroup::Core; + let (in_chnl1,in_chnl2) = + (ChType::Channel("TestChannel01".to_string()),ChType::Channel("TestChannel02".to_string())); + + complex_workflow(in_module, in_modgroup, in_chnl1, in_chnl2).await; + + + } + + +} From 2cf44bb6ca28be318fb726a5b94e00b8f597d06f Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Thu, 21 Mar 2024 21:20:16 -0400 Subject: [PATCH 11/22] (init) modulesmgr commands --- src/core/botmodules.rs | 314 ++++++++++++++++++++++++++++++++++++++++- src/core/identity.rs | 2 +- 2 files changed, 314 insertions(+), 2 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index fadfdab..fb57dfc 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -35,17 +35,132 @@ use tokio::sync::RwLock; use async_trait::async_trait; use self::bot_actions::actions_util::BotAR; +use crate::core::bot_actions::actions_util; use crate::core::botinstance::{BotInstance, ChType,ChangeResult}; use crate::core::botlog; -use crate::core::identity; +use crate::core::identity::{self, Permissible}; use crate::core::bot_actions; pub use ChType::Channel; pub use ModType::BotModule; +use super::identity::ChatBadge; + // use super::identity::ChangeResult; +pub async fn init(mgr: Arc) { + + const OF_CMD_CHANNEL:ChType = Channel(String::new()); + + // 1. Define the BotAction + let botc1 = BotCommand { + module: BotModule(String::from("core")), + command: String::from("enable"), // command call name + alias: vec![ + String::from("e"), + String::from("en")], // String of alternative names + exec_body: actions_util::asyncbox(cmd_enable), + help: String::from("Test Command tester"), + required_roles: vec![ + identity::UserRole::BotAdmin, + identity::UserRole::Mod(OF_CMD_CHANNEL), + identity::UserRole::SupMod(OF_CMD_CHANNEL), + identity::UserRole::Broadcaster, + ], + }; + + // 2. Add the BotAction to ModulesManager + botc1.add_core_to_modmgr(Arc::clone(&mgr)).await; + + async fn cmd_enable(bot: BotAR, msg: PrivmsgMessage) { + /* + There should be additional validation checks + - BotAdmins can only run instance level (-i) enables + - If BotAdmins need to enable/disable at instance level, they must Promote themselves to be a Mod at least + - Other Special Roles (Mod,SupMod,Broadcaster) can run without issues to enable the module at Channel Level + */ + + /* + enable -i // enables at Instance + enable // enables at Channel + */ + + /* + + 1. Parse out Message Arguments + + + exec_enable() + + 2. Get Special Roles of CmdSender + 3. If CmdSender is BotAdmin but not (Mod,SupMod,Broadcaster) + 3a. , and is not -i (to instance) , return a Failure recommending BotAdmin promote themselves first + 3b. , and is -i (to instance) , return a Success + 4. If CmdSender not a BotAdmin but is (Mod,SupMod,Broadcaster) + 4a. , and is not -i (to instance) , return a Success + 4b. , and is -i (to instance) , return a Failure they are not allowed + 5. If CmdSender is (Mod,SupMod,Broadcaster) and a BotAdmin + 5a. , and is not -i (to instance) , return a Success + 5b. , and is -i (to instance) , return a Success + + */ + + + /* + exec_enable(Self,requestor,requestor_badge,trg_module,Channel) -> ChangeResult + */ + + + } + + + + // 1. Define the BotAction + let botc1 = BotCommand { + module: BotModule(String::from("core")), + command: String::from("disable"), // command call name + alias: vec![ + String::from("d")], // String of alternative names + exec_body: actions_util::asyncbox(cmd_disable), + help: String::from("Test Command tester"), + required_roles: vec![ + identity::UserRole::BotAdmin, + identity::UserRole::Mod(OF_CMD_CHANNEL), + identity::UserRole::SupMod(OF_CMD_CHANNEL), + identity::UserRole::Broadcaster, + ], + }; + + // 2. Add the BotAction to ModulesManager + botc1.add_core_to_modmgr(Arc::clone(&mgr)).await; + + async fn cmd_disable(bot: BotAR, msg: PrivmsgMessage) { + /* + There should be additional validation checks + - BotAdmins can only run instance level (-i) disables + - If BotAdmins need to enable/disable at instance level, they must Promote themselves to be a Mod at least + - Other Special Roles (Mod,SupMod,Broadcaster) can run without issues to disable the module at Channel Level + */ + + /* + disable -i // disables at Instance + disable // disables at Channel + disable -f // force disables (instance and enabled are removed) + */ + + + } + + +} + + + + + + + #[derive(Debug, PartialEq, Eq, Hash, Clone)] pub enum ModType { BotModule(String), @@ -332,6 +447,203 @@ impl ModulesManager { // Ok("") // } + /* + exec_enable(self,requestor,requestor_badge,trg_module,Channel) -> ChangeResult + */ + + pub async fn exec_enable( + &self, + requestor: String, + requestor_badge: Option, + trg_module: ModType, + // channel: Option, + trg_level: StatusLvl, + bot: BotAR, + ) -> ChangeResult + { + + /* + + 1. If CmdSender is BotAdmin but not (Mod,SupMod,Broadcaster) + 1. can_user_run for cmdreqRoles including BotAdmin & not can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) + 1a. , and is not -i (to instance) , return a Failure recommending BotAdmin promote themselves first + 1b. , and is -i (to instance) , return a Success + + 2. If CmdSender not a BotAdmin but is (Mod,SupMod,Broadcaster) + 2. not can_user_run for cmdreqRoles including BotAdmin & can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) + 2a. , and is not -i (to instance) , return a Success + 2b. , and is -i (to instance) , return a Failure they are not allowed + + 3. If CmdSender is (Mod,SupMod,Broadcaster) and a BotAdmin + 3. can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) & can_user_run for cmdreqRoles including BotAdmin + 3a. , and is not -i (to instance) , return a Success + 3b. , and is -i (to instance) , return a Success + */ + + + /* + [ ] 1. If CmdSender is BotAdmin but not (Mod,SupMod,Broadcaster) + 1. can_user_run for cmdreqRoles including BotAdmin & not can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) + 1a. , and is -i (to instance) , return a Success + 1b. , and is not -i (to instance) , return a Failure recommending BotAdmin promote themselves first + + + */ + + + let botlock = bot.read().await; + let id = botlock.get_identity(); + let mut idlock = id.write().await; + + // if trg_level = StatusLvl::Instance , the temp_chnl = the broadcaster's or the chatter's + + let arb_chnl = match trg_level.clone() { + StatusLvl::Instance => ChType::Channel(requestor.to_lowercase()), + StatusLvl::Ch(a) => a, + }; + + const OF_CMD_CHANNEL:ChType = Channel(String::new()); + + let (admin_level_access,_) = idlock.can_user_run(requestor.clone(), arb_chnl.clone(), requestor_badge.clone(), + vec![ + identity::UserRole::BotAdmin, + ]).await; + + + let (chnl_elevated_access,_) = idlock.can_user_run(requestor, arb_chnl, requestor_badge.clone(), + vec![ + identity::UserRole::Mod(OF_CMD_CHANNEL), + identity::UserRole::SupMod(OF_CMD_CHANNEL), + identity::UserRole::Broadcaster, + ]).await; + + if let Permissible::Allow = admin_level_access { + if let Permissible::Block = chnl_elevated_access { + match trg_level { + StatusLvl::Instance => { + self.set_instance_enabled(trg_module.clone()).await; + ChangeResult::Success("Enabled at Instance Level".to_string()) + }, + StatusLvl::Ch(_) => { + ChangeResult::Failed("Promote yourself Temporarily First".to_string()) + }, + }; + } + } + + + /* + [ ] 2. If CmdSender not a BotAdmin but is (Mod,SupMod,Broadcaster) + 2. not can_user_run for cmdreqRoles including BotAdmin & can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) + 2a. , and is -i (to instance) , return a Failure they are not allowed + 2b. , and is not -i (to instance) , return a Success + + */ + + if let Permissible::Block = admin_level_access { + if let Permissible::Allow = chnl_elevated_access { + match trg_level.clone() { + StatusLvl::Instance => { + ChangeResult::Failed("You're not allowed".to_string()) + }, + StatusLvl::Ch(in_chnl) => { + self.set_ch_enabled(trg_module.clone(), in_chnl).await; + ChangeResult::Success("Enabled at Channel Level".to_string()) + }, + }; + } + } + + + /* + + [ ] 3. If CmdSender is (Mod,SupMod,Broadcaster) and a BotAdmin + 3. can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) & can_user_run for cmdreqRoles including BotAdmin + 3a. , and is not -i (to instance) , return a Success + 3b. , and is -i (to instance) , return a Success + */ + + + if let Permissible::Allow = admin_level_access { + if let Permissible::Allow = chnl_elevated_access { + match trg_level { + StatusLvl::Instance => { + self.set_instance_enabled(trg_module.clone()).await; + ChangeResult::Success("Enabled at Instance Level".to_string()) + }, + StatusLvl::Ch(in_chnl) => { + self.set_ch_enabled(trg_module.clone(), in_chnl).await; + ChangeResult::Success("Enabled at Channel Level".to_string()) + }, + }; + } + } + + + + + // ======================= + + // ======================= + + // ======================= + + + // /* + + // 2. Get Special Roles of CmdSender + // 3. If CmdSender is BotAdmin but not (Mod,SupMod,Broadcaster) + // 3a. , and is not -i (to instance) , return a Failure recommending BotAdmin promote themselves first + // 3b. , and is -i (to instance) , return a Success + // 4. If CmdSender not a BotAdmin but is (Mod,SupMod,Broadcaster) + // 4a. , and is not -i (to instance) , return a Success + // 4b. , and is -i (to instance) , return a Failure they are not allowed + // 5. If CmdSender is (Mod,SupMod,Broadcaster) and a BotAdmin + // 5a. , and is not -i (to instance) , return a Success + // 5b. , and is -i (to instance) , return a Success + + + // */ + + // // [ ] 2. Get Special Roles of CmdSender + + // let botlock = bot.read().await; + // let id = botlock.get_identity(); + // let idlock = id.read().await; + + + // let trgchnl = { + // match trg_level { + // StatusLvl::Instance => None, + // StatusLvl::Ch(a) => Some(a), + // } + // }; + + // let requestor_roles = idlock + // .getspecialuserroles( + // requestor.to_lowercase(), + // trgchnl, + // ) + // .await; + + // /* + // [ ] 3. If CmdSender is BotAdmin but not (Mod,SupMod,Broadcaster) + // 3a. , and is not -i (to instance) , return a Failure recommending BotAdmin promote themselves first + // 3b. , and is -i (to instance) , return a Success + // */ + + // if requestor_roles.contains(&identity::UserRole::BotAdmin) + // && !requestor_roles.contains(&identity::UserRole::Broadcaster) + // && !requestor_roles.contains(&identity::UserRole::Mod(trgchnl)) + // { + + // } + + + + ChangeResult::NoChange("ERROR : Not implemented yet".to_string()) + } + pub async fn set_instance_disabled(&self, in_module: ModType) -> (StatusType,ChangeResult) { // at Instance level // - If core module, do nothing diff --git a/src/core/identity.rs b/src/core/identity.rs index 65a5088..84905cc 100644 --- a/src/core/identity.rs +++ b/src/core/identity.rs @@ -602,7 +602,7 @@ pub struct IdentityManager { > */ -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum ChatBadge { Broadcaster, Mod, From 0d6cc132ea6e5ff73745fa240767e628178823ad Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Fri, 22 Mar 2024 08:21:10 -0400 Subject: [PATCH 12/22] (cont) enable/disable logic --- src/core/botmodules.rs | 308 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 301 insertions(+), 7 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index fb57dfc..568683a 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -77,7 +77,7 @@ pub async fn init(mgr: Arc) { /* There should be additional validation checks - BotAdmins can only run instance level (-i) enables - - If BotAdmins need to enable/disable at instance level, they must Promote themselves to be a Mod at least + - If BotAdmins need to enable/disable at Channel level, they must Promote themselves to be a Mod at least - Other Special Roles (Mod,SupMod,Broadcaster) can run without issues to enable the module at Channel Level */ @@ -107,11 +107,102 @@ pub async fn init(mgr: Arc) { */ - /* - exec_enable(Self,requestor,requestor_badge,trg_module,Channel) -> ChangeResult + + // [ ] Unwraps arguments from message + + let (arg1, arg2) = { + + let mut argv = msg.message_text.split(' '); + + argv.next(); // Skip the command name + + let arg1 = argv.next(); + + let arg2 = argv.next(); + + (arg1, arg2) + }; + + + /* -- Related function to call later + exec_enable( + &self, + requestor: String, + requestor_badge: Option, + trg_module: ModType, + // channel: Option, + trg_level: StatusLvl, + bot: BotAR, + ) -> ChangeResult */ + // [ ] requestor: String, + let requester = msg.clone().sender.name; + + + // [ ] requestor_badge: Option, + + let mut requestor_badge_mut: Option = None; + + for b in &msg.badges { + if b.name == "moderator" { + requestor_badge_mut = Some(ChatBadge::Mod); + } else if b.name == "broadcaster" { + requestor_badge_mut = Some(ChatBadge::Broadcaster); + } + } + + let requestor_badge = requestor_badge_mut; + + + // [ ] trg_module: ModType, + // - [ ] Need to validate an actual ModType - otherwise, fail or exit the cmd + + let trg_module = if (arg1 == Some("-i")) || (arg1 == Some("-f")) { arg2 } else { arg1 }; + + if let Some(trg_module_str) = trg_module { + + let botlock = bot.read().await; + let modmgr = Arc::clone(&botlock.botmodules); + let modlist = modmgr.moduleslist().await; + let rslt = modlist.get(&ModType::BotModule(trg_module_str.to_string())); + + if let None = rslt { + + let outmsg = "uuh module doesn't exist"; + + botlog::debug( + outmsg, + Some("botmodules.rs > cmd_enable()".to_string()), + Some(&msg), + ); + + botlock + .botmgrs + .chat + .say_in_reply_to(&msg, outmsg.to_string()) + .await; + + return; + } + + } + + + // [ ] trg_level: StatusLvl, + + let currchnl = msg.channel_login.to_lowercase(); + + let trg_level = + if arg1 == Some("-i") { StatusLvl::Instance } + else if arg1 == Some("-f") { StatusLvl::Instance } + else { StatusLvl::Ch(ChType::Channel(currchnl)) } + ; + + + + } @@ -138,10 +229,10 @@ pub async fn init(mgr: Arc) { async fn cmd_disable(bot: BotAR, msg: PrivmsgMessage) { /* There should be additional validation checks - - BotAdmins can only run instance level (-i) disables - - If BotAdmins need to enable/disable at instance level, they must Promote themselves to be a Mod at least + - BotAdmins can only run instance level (-i) disables and (-f) force disable + - If BotAdmins need to enable/disable at Channel level, they must Promote themselves to be a Mod at least - Other Special Roles (Mod,SupMod,Broadcaster) can run without issues to disable the module at Channel Level - */ + */ /* disable -i // disables at Instance @@ -149,6 +240,26 @@ pub async fn init(mgr: Arc) { disable -f // force disables (instance and enabled are removed) */ + /* + + 1. If CmdSender is BotAdmin but not (Mod,SupMod,Broadcaster) + 1. can_user_run for cmdreqRoles including BotAdmin & not can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) + 1a. , and has no special flags (-i / -f) , return a Failure recommending BotAdmin promote themselves first + 1b. , and is -i (to instance) , return a Success + 1c. , and is -f (forced) , return a Success + + 2. If CmdSender not a BotAdmin but is (Mod,SupMod,Broadcaster) + 2. not can_user_run for cmdreqRoles including BotAdmin & can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) + 2a. , and has no special flags (-i / -f) , return a Success + 2b. , and is -i (to instance) , return a Failure they are not allowed + 2c. , and is -f (forced) , return a Failure they are not allowed + + 3. If CmdSender is (Mod,SupMod,Broadcaster) and a BotAdmin + 3. can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) & can_user_run for cmdreqRoles including BotAdmin + 3a. , and has no special flags (-i / -f) , return a Success + 3b. , and is -i (to instance) , return a Success + 3c. , and is -f (forced) , return a Success + */ } @@ -348,6 +459,24 @@ impl ModulesManager { mgrarc } + + pub async fn moduleslist(&self) -> HashMap + { + + // let db = Arc::clone(&self.statusdb); + let db = self.statusdb.clone(); + let dblock = db.read().await; + + let mut outmap = HashMap::new(); + + for (k,v) in &(*dblock) { + let (mgrp,_) = v; + let mtype = k; + outmap.insert((*mtype).clone(), (*mgrp).clone()); + } + outmap + } + pub async fn modstatus(&self, in_module: ModType, in_chnl: ChType) -> StatusType { // Example usage : botmanager.modstatus( // BotModule("GambaCore"), @@ -641,7 +770,161 @@ impl ModulesManager { - ChangeResult::NoChange("ERROR : Not implemented yet".to_string()) + ChangeResult::Failed("ERROR : Not implemented yet".to_string()) + } + + + pub async fn exec_disable( + &self, + requestor: String, + requestor_badge: Option, + trg_module: ModType, + // channel: Option, + trg_level: StatusLvl, + force: bool, + bot: BotAR, + ) -> ChangeResult + { + + /* + + 1. If CmdSender is BotAdmin but not (Mod,SupMod,Broadcaster) + 1. can_user_run for cmdreqRoles including BotAdmin & not can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) + 1a. , and has no special flags (-i / -f) , return a Failure recommending BotAdmin promote themselves first + 1b. , and is -i (to instance) , return a Success + 1c. , and is -f (forced) , return a Success + + 2. If CmdSender not a BotAdmin but is (Mod,SupMod,Broadcaster) + 2. not can_user_run for cmdreqRoles including BotAdmin & can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) + 2a. , and has no special flags (-i / -f) , return a Success + 2b. , and is -i (to instance) , return a Failure they are not allowed + 2c. , and is -f (forced) , return a Failure they are not allowed + + 3. If CmdSender is (Mod,SupMod,Broadcaster) and a BotAdmin + 3. can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) & can_user_run for cmdreqRoles including BotAdmin + 3a. , and has no special flags (-i / -f) , return a Success + 3b. , and is -i (to instance) , return a Success + 3c. , and is -f (forced) , return a Success + */ + + + + let botlock = bot.read().await; + let id = botlock.get_identity(); + let mut idlock = id.write().await; + + // if trg_level = StatusLvl::Instance , the temp_chnl = the broadcaster's or the chatter's + + let arb_chnl = match trg_level.clone() { + StatusLvl::Instance => ChType::Channel(requestor.to_lowercase()), + StatusLvl::Ch(a) => a, + }; + + const OF_CMD_CHANNEL:ChType = Channel(String::new()); + + let (admin_level_access,_) = idlock.can_user_run(requestor.clone(), arb_chnl.clone(), requestor_badge.clone(), + vec![ + identity::UserRole::BotAdmin, + ]).await; + + + let (chnl_elevated_access,_) = idlock.can_user_run(requestor, arb_chnl, requestor_badge.clone(), + vec![ + identity::UserRole::Mod(OF_CMD_CHANNEL), + identity::UserRole::SupMod(OF_CMD_CHANNEL), + identity::UserRole::Broadcaster, + ]).await; + + + /* + + [ ] 1. If CmdSender is BotAdmin but not (Mod,SupMod,Broadcaster) + 1. can_user_run for cmdreqRoles including BotAdmin & not can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) + 1a. , and is -f (forced) , return a Success + 1b. , and is -i (to instance) , return a Success + 1c. , and has no special flags (-i / -f) , return a Failure recommending BotAdmin promote themselves first + + */ + + if let Permissible::Allow = admin_level_access { + if let Permissible::Block = chnl_elevated_access { + if force { + self.force_disable(trg_module.clone()).await; + return ChangeResult::Success("Forced Disable".to_string()); + } else { + match trg_level { + StatusLvl::Instance => { + self.set_instance_disabled(trg_module.clone()).await; + ChangeResult::Success("Disabled at Instance Level".to_string()) + }, + StatusLvl::Ch(_) => { + ChangeResult::Failed("Promote yourself Temporarily First".to_string()) + }, + }; + } + } + } + + + /* + [ ] 2. If CmdSender not a BotAdmin but is (Mod,SupMod,Broadcaster) + 2. not can_user_run for cmdreqRoles including BotAdmin & can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) + 2a. , and is -f (forced) , return a Failure they are not allowed + 2b. , and is -i (to instance) , return a Failure they are not allowed + 2c. , and has no special flags (-i / -f) , return a Success + + */ + + if let Permissible::Block = admin_level_access { + if let Permissible::Allow = chnl_elevated_access { + if force { + return ChangeResult::Failed("You're not allowed".to_string()); + } else { + match trg_level.clone() { + StatusLvl::Instance => { + ChangeResult::Failed("You're not allowed".to_string()) + }, + StatusLvl::Ch(in_chnl) => { + self.set_ch_disabled(trg_module.clone(), in_chnl).await; + ChangeResult::Success("Disabled at Channel Level".to_string()) + }, + }; + } + } + } + + + /* + [ ] 3. If CmdSender is (Mod,SupMod,Broadcaster) and a BotAdmin + 3. can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) & can_user_run for cmdreqRoles including BotAdmin + 3a. , and is -f (forced) , return a Success + 3b. , and is -i (to instance) , return a Success + 3c. , and has no special flags (-i / -f) , return a Success + + */ + + if let Permissible::Allow = admin_level_access { + if let Permissible::Allow = chnl_elevated_access { + if force { + self.force_disable(trg_module.clone()).await; + return ChangeResult::Success("Forced Disable".to_string()); + } else { + match trg_level { + StatusLvl::Instance => { + self.set_instance_disabled(trg_module.clone()).await; + ChangeResult::Success("Disabled at Instance Level".to_string()) + }, + StatusLvl::Ch(in_chnl) => { + self.set_ch_disabled(trg_module.clone(), in_chnl).await; + ChangeResult::Success("Disabled at Channel Level".to_string()) + }, + }; + } + } + } + + + ChangeResult::Failed("ERROR : Not implemented yet".to_string()) } pub async fn set_instance_disabled(&self, in_module: ModType) -> (StatusType,ChangeResult) { @@ -1003,6 +1286,17 @@ mod core_modulesmanager { use super::*; + #[test] + fn WIP_case_insensitive_test() { + Log::set_file_ext(Extension::Log); + assert_eq!( + BotModule("test".to_string()), + BotModule("Test".to_lowercase()) + ); + } + + + /* Possible Tests From 072903882de4e57ec297ce41606b2a98b168b153 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Fri, 22 Mar 2024 08:40:09 -0400 Subject: [PATCH 13/22] botmodule case insensitive --- src/core/botmodules.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 568683a..cc4b1aa 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -272,11 +272,22 @@ pub async fn init(mgr: Arc) { -#[derive(Debug, PartialEq, Eq, Hash, Clone)] +// #[derive(Debug, PartialEq, Eq, Hash, Clone)] +#[derive(Debug, Hash, Clone)] pub enum ModType { BotModule(String), } +impl PartialEq for ModType { + fn eq(&self, other: &Self) -> bool { + let BotModule(name1) = self.clone(); + let BotModule(name2) = other.clone(); + name1.to_lowercase() == name2.to_lowercase() + } +} +impl Eq for ModType {} + + #[derive(Debug, PartialEq, Eq, Hash, Clone)] pub enum ModGroup { Core, @@ -1287,10 +1298,10 @@ mod core_modulesmanager { use super::*; #[test] - fn WIP_case_insensitive_test() { + fn case_insensitive_test() { Log::set_file_ext(Extension::Log); assert_eq!( - BotModule("test".to_string()), + BotModule("Test".to_string()), BotModule("Test".to_lowercase()) ); } From 8b4c21ba58604332c307cd94e0d4bc8cd4d32e83 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Fri, 22 Mar 2024 17:06:09 -0400 Subject: [PATCH 14/22] unit tests --- src/core/botmodules.rs | 904 ++++++++++++++++++++++++++++++++++++++++- src/core/identity.rs | 6 +- 2 files changed, 886 insertions(+), 24 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index cc4b1aa..a3866dd 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -28,7 +28,7 @@ use std::sync::Arc; // use futures::stream::iter; use twitch_irc::message::PrivmsgMessage; -// use casual_logger::Log; +use casual_logger::Log; use tokio::sync::RwLock; @@ -38,7 +38,7 @@ use self::bot_actions::actions_util::BotAR; use crate::core::bot_actions::actions_util; use crate::core::botinstance::{BotInstance, ChType,ChangeResult}; use crate::core::botlog; -use crate::core::identity::{self, Permissible}; +use crate::core::identity::{self, Permissible,IdentityManager}; use crate::core::bot_actions; pub use ChType::Channel; @@ -598,7 +598,8 @@ impl ModulesManager { trg_module: ModType, // channel: Option, trg_level: StatusLvl, - bot: BotAR, + // bot: BotAR, + id: Arc>, ) -> ChangeResult { @@ -631,8 +632,20 @@ impl ModulesManager { */ - let botlock = bot.read().await; - let id = botlock.get_identity(); + // [x] Validate in trg_module first + + // let botlock = bot.read().await; + // let modmgr = Arc::clone(&botlock.botmodules); + let modlist = self.moduleslist().await; + let rslt = modlist.get(&trg_module); + + if let None = rslt { + return ChangeResult::Failed("Module doesn't exist".to_string()); + } + + + // let botlock = bot.read().await; + // let id = botlock.get_identity(); let mut idlock = id.write().await; // if trg_level = StatusLvl::Instance , the temp_chnl = the broadcaster's or the chatter's @@ -657,17 +670,37 @@ impl ModulesManager { identity::UserRole::Broadcaster, ]).await; + + // botlog::debug( + // &format!("FAILURE BEFORE Let statements involves : + // admin_level_access : {:?} ; chnl_elevated_access : {:?}", + // admin_level_access , chnl_elevated_access), + // Some("botmodules.rs > exec_enable()".to_string()), + // None, + // ); + + + if let Permissible::Allow = admin_level_access { if let Permissible::Block = chnl_elevated_access { + + botlog::debug( + &format!("?? REACHED INNER TIER : + admin_level_access : {:?} ; chnl_elevated_access : {:?}", + admin_level_access , chnl_elevated_access), + Some("botmodules.rs > exec_enable()".to_string()), + None, + ); match trg_level { StatusLvl::Instance => { self.set_instance_enabled(trg_module.clone()).await; - ChangeResult::Success("Enabled at Instance Level".to_string()) + return ChangeResult::Success("Enabled at Instance Level".to_string()); }, StatusLvl::Ch(_) => { - ChangeResult::Failed("Promote yourself Temporarily First".to_string()) + return ChangeResult::Failed("Promote yourself Temporarily First".to_string()); }, }; + } } @@ -684,11 +717,11 @@ impl ModulesManager { if let Permissible::Allow = chnl_elevated_access { match trg_level.clone() { StatusLvl::Instance => { - ChangeResult::Failed("You're not allowed".to_string()) + return ChangeResult::Failed("You're not allowed".to_string()); }, StatusLvl::Ch(in_chnl) => { self.set_ch_enabled(trg_module.clone(), in_chnl).await; - ChangeResult::Success("Enabled at Channel Level".to_string()) + return ChangeResult::Success("Enabled at Channel Level".to_string()); }, }; } @@ -709,17 +742,39 @@ impl ModulesManager { match trg_level { StatusLvl::Instance => { self.set_instance_enabled(trg_module.clone()).await; - ChangeResult::Success("Enabled at Instance Level".to_string()) + return ChangeResult::Success("Enabled at Instance Level".to_string()); }, StatusLvl::Ch(in_chnl) => { self.set_ch_enabled(trg_module.clone(), in_chnl).await; - ChangeResult::Success("Enabled at Channel Level".to_string()) + return ChangeResult::Success("Enabled at Channel Level".to_string()); }, }; } } + // Respond in case of General Chatter + // The below should NOT be required , as current internal logic would prevent + // a BotCommand to be ran by a Chatter if it requires any special roles and + // that chatter does not have htose roles + // However, below is added to satisfy unit tests + + + if let Permissible::Block = admin_level_access { + if let Permissible::Block = chnl_elevated_access { + match trg_level { + StatusLvl::Instance => { + return ChangeResult::Failed("You're not allowed".to_string()); + }, + StatusLvl::Ch(_) => { + return ChangeResult::Failed("You're not allowed".to_string()); + }, + }; + } + } + + + // ======================= @@ -779,8 +834,17 @@ impl ModulesManager { // } + botlog::debug( + &format!("FAILURE involves : + admin_level_access : {:?} ; chnl_elevated_access : {:?}", + admin_level_access , chnl_elevated_access), + Some("botmodules.rs > exec_enable()".to_string()), + None, + ); + Log::flush(); + ChangeResult::Failed("ERROR : Not implemented yet".to_string()) } @@ -793,7 +857,8 @@ impl ModulesManager { // channel: Option, trg_level: StatusLvl, force: bool, - bot: BotAR, + // bot: BotAR, + id: Arc>, ) -> ChangeResult { @@ -818,10 +883,21 @@ impl ModulesManager { 3c. , and is -f (forced) , return a Success */ + // [x] Validate in trg_module first + + // let botlock = bot.read().await; + // let modmgr = Arc::clone(&botlock.botmodules); + let modlist = self.moduleslist().await; + let rslt = modlist.get(&trg_module); + + if let None = rslt { + return ChangeResult::Failed("Module doesn't exist".to_string()); + } + - let botlock = bot.read().await; - let id = botlock.get_identity(); + // let botlock = bot.read().await; + // let id = botlock.get_identity(); let mut idlock = id.write().await; // if trg_level = StatusLvl::Instance , the temp_chnl = the broadcaster's or the chatter's @@ -866,10 +942,10 @@ impl ModulesManager { match trg_level { StatusLvl::Instance => { self.set_instance_disabled(trg_module.clone()).await; - ChangeResult::Success("Disabled at Instance Level".to_string()) + return ChangeResult::Success("Disabled at Instance Level".to_string()); }, StatusLvl::Ch(_) => { - ChangeResult::Failed("Promote yourself Temporarily First".to_string()) + return ChangeResult::Failed("Promote yourself Temporarily First".to_string()); }, }; } @@ -893,11 +969,11 @@ impl ModulesManager { } else { match trg_level.clone() { StatusLvl::Instance => { - ChangeResult::Failed("You're not allowed".to_string()) + return ChangeResult::Failed("You're not allowed".to_string()); }, StatusLvl::Ch(in_chnl) => { self.set_ch_disabled(trg_module.clone(), in_chnl).await; - ChangeResult::Success("Disabled at Channel Level".to_string()) + return ChangeResult::Success("Disabled at Channel Level".to_string()); }, }; } @@ -923,11 +999,11 @@ impl ModulesManager { match trg_level { StatusLvl::Instance => { self.set_instance_disabled(trg_module.clone()).await; - ChangeResult::Success("Disabled at Instance Level".to_string()) + return ChangeResult::Success("Disabled at Instance Level".to_string()); }, StatusLvl::Ch(in_chnl) => { self.set_ch_disabled(trg_module.clone(), in_chnl).await; - ChangeResult::Success("Disabled at Channel Level".to_string()) + return ChangeResult::Success("Disabled at Channel Level".to_string()); }, }; } @@ -935,6 +1011,29 @@ impl ModulesManager { } + + // Respond in case of General Chatter + // The below should NOT be required , as current internal logic would prevent + // a BotCommand to be ran by a Chatter if it requires any special roles and + // that chatter does not have htose roles + // However, below is added to satisfy unit tests + + + if let Permissible::Block = admin_level_access { + if let Permissible::Block = chnl_elevated_access { + match trg_level { + StatusLvl::Instance => { + return ChangeResult::Failed("You're not allowed".to_string()); + }, + StatusLvl::Ch(_) => { + return ChangeResult::Failed("You're not allowed".to_string()); + }, + }; + } + } + + + ChangeResult::Failed("ERROR : Not implemented yet".to_string()) } @@ -1301,8 +1400,8 @@ mod core_modulesmanager { fn case_insensitive_test() { Log::set_file_ext(Extension::Log); assert_eq!( - BotModule("Test".to_string()), - BotModule("Test".to_lowercase()) + BotModule("TEST".to_string()), + BotModule("test".to_string()) ); } @@ -1545,4 +1644,765 @@ mod core_modulesmanager { } + + + /* + 1. Create new ModulesManager & Identity Manager + 2. modmgr.affirm_in_statusdb(Experiments01,Custom) + + 3. affirm when BotAdmin attempts to exec_enable on the following + a. Channel Level , where they are not a Mod + b. Channel Level , when they are a Mod + c. Instance Level + 4. affirm when BotAdmin attempts to exec_disable on the following + a. Channel Level , where they are not a Mod + b. Channel Level , when they are a Mod + c. Instance Level + d. force disable + + + 1. Create new ModulesManager & Identity Manager + 2. modmgr.affirm_in_statusdb(Experiments01,Custom) + + 3. affirm when Mod attempts to exec_enable on the following + a. Channel Level , where they are not a Mod + b. Channel Level , when they are a Mod + c. Instance Level + 4. affirm when Mod attempts to exec_disable on the following + a. Channel Level , where they are not a Mod + b. Channel Level , when they are a Mod + c. Instance Level + d. force disable + + */ + + async fn inner_enable_disable_complex( + requestor:String, + channel:ChType, + idmgr:IdentityManager, + modsmgr:Arc) + { + + /* + Parent Tests would involve : + - Testing with a BotAdmin User + - Testing with a Mod User + - Testing with a Regular Chatter + */ + + enum TestScenarios { + BotadminUser, + ModUser, + RegularChatter, + // ModuleDoesNotExist, // preferring instead to handle in it's own smaller test + } + + + // let channel = ChType::Channel("somechannel".to_string()); + + + // let mut idlock = idmgr.write().await; + let mut idlock = idmgr.clone(); + + // if trg_level = StatusLvl::Instance , the temp_chnl = the broadcaster's or the chatter's + + // let arb_chnl = match trg_level.clone() { + // StatusLvl::Instance => ChType::Channel(requestor.to_lowercase()), + // StatusLvl::Ch(a) => a, + // }; + + let requestor_badge = None; // If they are a Mod on the Given Channel already, that can be evaluated without the current badge + + const OF_CMD_CHANNEL:ChType = Channel(String::new()); + + let (admin_level_access,_) = idlock.can_user_run(requestor.clone(), channel.clone(), requestor_badge.clone(), + vec![ + identity::UserRole::BotAdmin, + ]).await; + + + let (chnl_elevated_access,_) = idlock.can_user_run(requestor.clone(), channel.clone(), requestor_badge.clone(), + vec![ + identity::UserRole::Mod(OF_CMD_CHANNEL), + identity::UserRole::SupMod(OF_CMD_CHANNEL), + identity::UserRole::Broadcaster, + ]).await; + + + let current_test_scenario = + match admin_level_access { + Permissible::Allow => { + match chnl_elevated_access { + Permissible::Allow => { TestScenarios::BotadminUser }, + Permissible::Block => { TestScenarios::BotadminUser } + } + }, + Permissible::Block => { + match chnl_elevated_access { + Permissible::Allow => { TestScenarios::ModUser }, + Permissible::Block => { TestScenarios::RegularChatter } + } + } + }; + + + + // [x] 2. modmgr.affirm_in_statusdb(Experiments01,Custom) + + let in_module = BotModule("Experiments01".to_string()); + let in_modgroup = ModGroup::Custom; + + // match current_test_scenario { + // TestScenarios::BotadminUser => modsmgr.affirm_in_statusdb(in_module.clone(), in_modgroup.clone()).await, + // _ => self::panic!("Scenario not handled"), + // } + + modsmgr.affirm_in_statusdb(in_module.clone(), in_modgroup.clone()).await; + + let in_module = match current_test_scenario { + // TestScenarios::ModuleDoesNotExist => BotModule("NonExisting_Module".to_string()), + _ => in_module, + }; + + + /* + [x] 3. affirm when BotAdmin attempts to exec_enable on the following + a. Channel Level , where they are not a Mod + */ + + + // [-] requestor_badge: Option, + + // [x] trg_module: ModType, + let trg_module = in_module; + + // [x] trg_level: StatusLvl, + + let trg_level = StatusLvl::Ch(channel.clone()); // setting to Channel Level + + + // [x] id: Arc>, + let id = Arc::new(RwLock::new(idmgr.clone())); + + + let rslt = modsmgr.exec_enable(requestor.clone(), + None, + trg_module.clone(), + trg_level.clone(), + id.clone()).await; + + // assert_eq!(rslt,ChangeResult::Failed("Promote yourself Temporarily First".to_string())); + + match current_test_scenario { + TestScenarios::BotadminUser => + assert_eq!(rslt,ChangeResult::Failed("Promote yourself Temporarily First".to_string())), + TestScenarios::ModUser => + assert_eq!(rslt,ChangeResult::Success("Enabled at Channel Level".to_string())), + TestScenarios::RegularChatter => + assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), + // TestScenarios::ModuleDoesNotExist => + // assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), + // _ => + // self::panic!("Scenario not handled"), + } + + + /* + [x] 3. affirm when BotAdmin attempts to exec_enable on the following + b. Channel Level , when they are a Mod + */ + + // [x] requestor_badge: Option, + // let requestor_badge = ChatBadge::Mod; // setting badge to Mod + let requestor_badge = match current_test_scenario { + TestScenarios::BotadminUser => + Some(ChatBadge::Mod), // setting badge to Mod -- for the Problem Scenario . They are both BotAdmin & Mod + TestScenarios::ModUser => + Some(ChatBadge::Mod), // setting badge to Mod + TestScenarios::RegularChatter => + None, // setting badge to None + // TestScenarios::ModuleDoesNotExist => + // None, + // _ => + // self::panic!("Scenario not handled"), + } ; + + + let rslt = modsmgr.exec_enable(requestor.clone(), + requestor_badge, + trg_module.clone(), + trg_level.clone(), + id.clone()).await; + + // assert_eq!(rslt,ChangeResult::Success("Enabled at Channel Level".to_string())); + + match current_test_scenario { + TestScenarios::BotadminUser => + assert_eq!(rslt,ChangeResult::Success("Enabled at Channel Level".to_string())), + TestScenarios::ModUser => + assert_eq!(rslt,ChangeResult::Success("Enabled at Channel Level".to_string())), + TestScenarios::RegularChatter => + assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), + // TestScenarios::ModuleDoesNotExist => + // assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), + // _ => + // self::panic!("Scenario not handled"), + } + + /* + [x] 3. affirm when BotAdmin attempts to exec_enable on the following + c. Instance Level + */ + + let trg_level = StatusLvl::Instance; // setting to Instance level + + let requestor_badge = match current_test_scenario { + TestScenarios::BotadminUser => + None, + TestScenarios::ModUser => + Some(ChatBadge::Mod), + TestScenarios::RegularChatter => + None, // setting badge to None + // TestScenarios::ModuleDoesNotExist => + // None, // setting badge to None + // _ => + // self::panic!("Scenario not handled"), + }; + + let rslt = modsmgr.exec_enable(requestor.clone(), + requestor_badge, // passing based on scenario + trg_module.clone(), + trg_level.clone(), + id.clone()).await; + + // assert_eq!(rslt,ChangeResult::Success("Enabled at Instance Level".to_string())); + + match current_test_scenario { + TestScenarios::BotadminUser => + assert_eq!(rslt,ChangeResult::Success("Enabled at Instance Level".to_string())), + TestScenarios::ModUser => + assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), + TestScenarios::RegularChatter => + assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), + // TestScenarios::ModuleDoesNotExist => + // assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), + // _ => + // self::panic!("Scenario not handled"), + } + + /* + [x] 4. affirm when BotAdmin attempts to exec_disable on the following + a. Channel Level , where they are not a Mod + */ + + let trg_level = StatusLvl::Ch(channel.clone()); // setting to Channel Level + + let rslt: ChangeResult = modsmgr.exec_disable(requestor.clone(), + None, // Does not have a ChatBadge like Mod + trg_module.clone(), + trg_level.clone(), + false, + id.clone()).await; + + // assert_eq!(rslt,ChangeResult::Success("Disabled at Channel Level".to_string())); + match current_test_scenario { + TestScenarios::BotadminUser => + assert_eq!(rslt,ChangeResult::Success("Disabled at Channel Level".to_string())), + TestScenarios::ModUser => + assert_eq!(rslt,ChangeResult::Success("Disabled at Channel Level".to_string())), + TestScenarios::RegularChatter => + assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), + // TestScenarios::ModuleDoesNotExist => + // assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), + // _ => + // self::panic!("Scenario not handled"), + } + + + /* + [x] 4. affirm when BotAdmin attempts to exec_disable on the following + b. Channel Level , when they are a Mod + */ + + + let trg_level = StatusLvl::Ch(channel.clone()); // setting to Channel Level + // let requestor_badge = ChatBadge::Mod; // setting badge to Mod + let requestor_badge = match current_test_scenario { + TestScenarios::BotadminUser => + None, + TestScenarios::ModUser => + Some(ChatBadge::Mod), + TestScenarios::RegularChatter => + None, // setting badge to None + // TestScenarios::ModuleDoesNotExist => + // None, + // _ => + // self::panic!("Scenario not handled"), + }; + + let rslt: ChangeResult = modsmgr.exec_disable(requestor.clone(), + requestor_badge, + trg_module.clone(), + trg_level.clone(), + false, + id.clone()).await; + + // assert_eq!(rslt,ChangeResult::Success("Disabled at Channel Level".to_string())); + match current_test_scenario { + TestScenarios::BotadminUser => + assert_eq!(rslt,ChangeResult::Success("Disabled at Channel Level".to_string())), + TestScenarios::ModUser => + assert_eq!(rslt,ChangeResult::Success("Disabled at Channel Level".to_string())), + TestScenarios::RegularChatter => + assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), + // TestScenarios::ModuleDoesNotExist => + // assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), + // _ => + // self::panic!("Scenario not handled"), + } + + + /* + [x] 4. affirm when BotAdmin attempts to exec_disable on the following + c. Instance Level + */ + + let trg_level = StatusLvl::Instance; // setting to Instance level + // let requestor_badge = ChatBadge::Mod; // setting badge to Mod + + let rslt: ChangeResult = modsmgr.exec_disable(requestor.clone(), + None, // Does not have a ChatBadge like Mod + trg_module.clone(), + trg_level.clone(), + false, + id.clone()).await; + + // assert_eq!(rslt,ChangeResult::Success("Disabled at Instance Level".to_string())); + match current_test_scenario { + TestScenarios::BotadminUser => + assert_eq!(rslt,ChangeResult::Success("Disabled at Instance Level".to_string())), + TestScenarios::ModUser => + assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), + TestScenarios::RegularChatter => + assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), + // TestScenarios::ModuleDoesNotExist => + // assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), + // _ => + // self::panic!("Scenario not handled"), + } + + /* + [ ] 4. affirm when BotAdmin attempts to exec_disable on the following + d. force disable + */ + + let trg_level = StatusLvl::Instance; // setting to Instance level + // let requestor_badge = ChatBadge::Mod; // setting badge to Mod + + let rslt: ChangeResult = modsmgr.exec_disable(requestor.clone(), + None, // Does not have a ChatBadge like Mod + trg_module.clone(), + trg_level.clone(), + true, // force flag - true + id.clone()).await; + + // assert_eq!(rslt,ChangeResult::Success("Forced Disable".to_string())); + match current_test_scenario { + TestScenarios::BotadminUser => + assert_eq!(rslt,ChangeResult::Success("Forced Disable".to_string())), + TestScenarios::ModUser => + assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), + TestScenarios::RegularChatter => + assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), + // TestScenarios::ModuleDoesNotExist => + // assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), + // _ => + // self::panic!("Scenario not handled"), + } + + + } + + + #[tokio::test] + async fn enable_disable_bot_admin_workflow() { + Log::set_file_ext(Extension::Log); + /* + + 1. Create new ModulesManager & Identity Manager + 2. modmgr.affirm_in_statusdb(Experiments01,Custom) + + 3. affirm when BotAdmin attempts to exec_enable on the following + a. Channel Level , where they are not a Mod + b. Channel Level , when they are a Mod + c. Instance Level + 4. affirm when BotAdmin attempts to exec_disable on the following + a. Channel Level , where they are not a Mod + b. Channel Level , when they are a Mod + c. Instance Level + d. force disable + + */ + + + // [x] 1. Create new ModulesManager & Identity Manager + let idmgr = IdentityManager::init(); + let modsmgr = ModulesManager::init().await; + + // // [x] 2. modmgr.affirm_in_statusdb(Experiments01,Custom) + + // let in_module = BotModule("Experiments01".to_string()); + // let in_modgroup = ModGroup::Custom; + + // modsmgr.affirm_in_statusdb(in_module.clone(), in_modgroup.clone()).await; + + + /* + [x] 3. affirm when BotAdmin attempts to exec_enable on the following + a. Channel Level , where they are not a Mod + */ + + // [x] Create BotAdmin first + + let requestor = "botadministrator".to_string(); + // let botadmin_badge = &None; + + idmgr.affirm_chatter_in_db(requestor.clone()).await; + idmgr + .add_role(requestor.clone(), identity::UserRole::BotAdmin) + .await; + + let rslt = idmgr + .getspecialuserroles(requestor.clone(), None) + .await; + + assert!(rslt.contains(&identity::UserRole::BotAdmin)); + + let channel = ChType::Channel("somechannel".to_string()); + + + inner_enable_disable_complex(requestor, channel, idmgr, modsmgr).await; + + + /* + pub async fn exec_enable( + &self, + requestor: String, + requestor_badge: Option, + trg_module: ModType, + trg_level: StatusLvl, + id: Arc>, + ) -> ChangeResult + + */ + + /* + [x] 3. affirm when BotAdmin attempts to exec_enable on the following + a. Channel Level , where they are not a Mod + */ + + + // [-] requestor_badge: Option, + + // [x] trg_module: ModType, + // let trg_module = in_module; + + // [x] trg_level: StatusLvl, + + // let channel = ChType::Channel("somechannel".to_string()); + // let trg_level = StatusLvl::Ch(channel.clone()); // setting to Channel Level + + + // // [x] id: Arc>, + // let id = Arc::new(RwLock::new(idmgr)); + + + // let rslt = modsmgr.exec_enable(requestor.clone(), + // None, + // trg_module.clone(), + // trg_level.clone(), + // id.clone()).await; + + // assert_eq!(rslt,ChangeResult::Failed("Promote yourself Temporarily First".to_string())); + + // /* + // [x] 3. affirm when BotAdmin attempts to exec_enable on the following + // b. Channel Level , when they are a Mod + // */ + + // // [x] requestor_badge: Option, + // let requestor_badge = ChatBadge::Mod; // setting badge to Mod + + // let rslt = modsmgr.exec_enable(requestor.clone(), + // Some(requestor_badge), + // trg_module.clone(), + // trg_level.clone(), + // id.clone()).await; + + // assert_eq!(rslt,ChangeResult::Success("Enabled at Channel Level".to_string())); + + // /* + // [x] 3. affirm when BotAdmin attempts to exec_enable on the following + // c. Instance Level + // */ + + // let trg_level = StatusLvl::Instance; // setting to Instance level + + // let rslt = modsmgr.exec_enable(requestor.clone(), + // None, // setting them back to Non-Mod + // trg_module.clone(), + // trg_level.clone(), + // id.clone()).await; + + // assert_eq!(rslt,ChangeResult::Success("Enabled at Instance Level".to_string())); + + // /* + // [x] 4. affirm when BotAdmin attempts to exec_disable on the following + // a. Channel Level , where they are not a Mod + // */ + + // let trg_level = StatusLvl::Ch(channel.clone()); // setting to Channel Level + + // let rslt: ChangeResult = modsmgr.exec_disable(requestor.clone(), + // None, // Does not have a ChatBadge like Mod + // trg_module.clone(), + // trg_level.clone(), + // false, + // id.clone()).await; + + // assert_eq!(rslt,ChangeResult::Success("Disabled at Channel Level".to_string())); + + + // /* + // [x] 4. affirm when BotAdmin attempts to exec_disable on the following + // b. Channel Level , when they are a Mod + // */ + + + // let trg_level = StatusLvl::Ch(channel.clone()); // setting to Channel Level + // let requestor_badge = ChatBadge::Mod; // setting badge to Mod + + // let rslt: ChangeResult = modsmgr.exec_disable(requestor.clone(), + // Some(requestor_badge), + // trg_module.clone(), + // trg_level.clone(), + // false, + // id.clone()).await; + + // assert_eq!(rslt,ChangeResult::Success("Disabled at Channel Level".to_string())); + + // /* + // [x] 4. affirm when BotAdmin attempts to exec_disable on the following + // c. Instance Level + // */ + + // let trg_level = StatusLvl::Instance; // setting to Instance level + // // let requestor_badge = ChatBadge::Mod; // setting badge to Mod + + // let rslt: ChangeResult = modsmgr.exec_disable(requestor.clone(), + // None, // Does not have a ChatBadge like Mod + // trg_module.clone(), + // trg_level.clone(), + // false, + // id.clone()).await; + + // assert_eq!(rslt,ChangeResult::Success("Disabled at Instance Level".to_string())); + + // /* + // [ ] 4. affirm when BotAdmin attempts to exec_disable on the following + // d. force disable + // */ + + // let trg_level = StatusLvl::Instance; // setting to Instance level + // // let requestor_badge = ChatBadge::Mod; // setting badge to Mod + + // let rslt: ChangeResult = modsmgr.exec_disable(requestor.clone(), + // None, // Does not have a ChatBadge like Mod + // trg_module.clone(), + // trg_level.clone(), + // true, // force flag - true + // id.clone()).await; + + // assert_eq!(rslt,ChangeResult::Success("Forced Disable".to_string())); + + + + + } + + + + #[tokio::test] + async fn enable_disable_mod_workflow() { + Log::set_file_ext(Extension::Log); + + /* + 1. Create new ModulesManager & Identity Manager + 2. modmgr.affirm_in_statusdb(Experiments01,Custom) + + 3. affirm when Mod attempts to exec_enable on the following + a. Channel Level , where they are not a Mod + b. Channel Level , when they are a Mod + c. Instance Level + 4. affirm when Mod attempts to exec_disable on the following + a. Channel Level , where they are not a Mod + b. Channel Level , when they are a Mod + c. Instance Level + d. force disable + */ + + + // [x] 1. Create new ModulesManager & Identity Manager + let idmgr = IdentityManager::init(); + let modsmgr = ModulesManager::init().await; + + + let requestor = "mod_user".to_string(); + // let botadmin_badge = &None; + let channel = ChType::Channel("somechannel".to_string()); + + + idmgr.affirm_chatter_in_db(requestor.clone()).await; + idmgr + .add_role(requestor.clone(), identity::UserRole::Mod(channel.clone())) + .await; + + let rslt = idmgr + .getspecialuserroles( + requestor.clone(), + Some(channel.clone()) // None if BotAdmin ; Otherwise, pass Some(Channel) + ) + .await; + + assert!(rslt.contains(&identity::UserRole::Mod(channel.clone()))); + + + inner_enable_disable_complex(requestor, channel, idmgr, modsmgr).await; + + + + } + + #[tokio::test] + async fn enable_disable_chatter_workflow() { + Log::set_file_ext(Extension::Log); + + + /* + 1. Create new ModulesManager & Identity Manager + 2. modmgr.affirm_in_statusdb(Experiments01,Custom) + + 3. affirm when Mod attempts to exec_enable on the following + a. Channel Level , where they are not a Mod + b. Channel Level , when they are a Mod + c. Instance Level + 4. affirm when Mod attempts to exec_disable on the following + a. Channel Level , where they are not a Mod + b. Channel Level , when they are a Mod + c. Instance Level + d. force disable + */ + + + // [x] 1. Create new ModulesManager & Identity Manager + let idmgr = IdentityManager::init(); + let modsmgr = ModulesManager::init().await; + + + let requestor = "regular_user".to_string(); + // let botadmin_badge = &None; + let channel = ChType::Channel("somechannel".to_string()); + + + idmgr.affirm_chatter_in_db(requestor.clone()).await; + // idmgr + // .add_role(requestor.clone(), identity::UserRole::Mod(channel.clone())) + // .await; + + let rslt = idmgr + .getspecialuserroles( + requestor.clone(), + Some(channel.clone()) // None if BotAdmin ; Otherwise, pass Some(Channel) + ) + .await; + + assert!(!rslt.contains(&identity::UserRole::Mod(channel.clone())) || + !rslt.contains(&identity::UserRole::BotAdmin)); + + + inner_enable_disable_complex(requestor, channel, idmgr, modsmgr).await; + + } + + + #[tokio::test] + async fn enable_disable_modulenotexist_workflow() { + Log::set_file_ext(Extension::Log); + + + // [x] 1. Create new ModulesManager & Identity Manager + let idmgr = IdentityManager::init(); + let modsmgr = ModulesManager::init().await; + + + let requestor = "regular_user".to_string(); + // let botadmin_badge = &None; + let channel = ChType::Channel("somechannel".to_string()); + + + idmgr.affirm_chatter_in_db(requestor.clone()).await; + // idmgr + // .add_role(requestor.clone(), identity::UserRole::Mod(channel.clone())) + // .await; + + let rslt = idmgr + .getspecialuserroles( + requestor.clone(), + Some(channel.clone()) // None if BotAdmin ; Otherwise, pass Some(Channel) + ) + .await; + + assert!(!rslt.contains(&identity::UserRole::Mod(channel.clone())) || + !rslt.contains(&identity::UserRole::BotAdmin)); + + // After above, regular chatter is created + + // [x] 2. modmgr.affirm_in_statusdb(Existing_Module,Custom) + + let in_module = BotModule("Existing_Module".to_string()); + let in_modgroup = ModGroup::Custom; + + modsmgr.affirm_in_statusdb(in_module.clone(), in_modgroup.clone()).await; + + + let trg_level = StatusLvl::Ch(channel.clone()); // setting to Channel Level + + + // [x] Test with Non Existing module > exec + + let trg_module = BotModule("Non_Existent_Module".to_string()); + + let rslt = modsmgr.exec_enable(requestor.clone(), + None, + trg_module.clone(), + trg_level.clone(), + Arc::new(RwLock::new(idmgr.clone()))).await; + + assert_eq!(rslt,ChangeResult::Failed("Module doesn't exist".to_string())); + + // [ ] Test with Non Existing module > disable + + let trg_module = BotModule("Non_Existent_Module".to_string()); + + let rslt = modsmgr.exec_disable(requestor.clone(), + None, + trg_module.clone(), + trg_level.clone(), + false, + Arc::new(RwLock::new(idmgr))).await; + + assert_eq!(rslt,ChangeResult::Failed("Module doesn't exist".to_string())); + + } + } diff --git a/src/core/identity.rs b/src/core/identity.rs index 84905cc..accda4f 100644 --- a/src/core/identity.rs +++ b/src/core/identity.rs @@ -630,7 +630,8 @@ impl IdentityManager { } } - async fn add_role(&self, trgchatter: String, trg_role: UserRole) { + // => 03.22 - Force - Made public because botmodules unit tests + pub async fn add_role(&self, trgchatter: String, trg_role: UserRole) { let mut srulock = self.special_roles_users.write().await; let mut usrrolelock = srulock .get_mut(&trgchatter) @@ -652,7 +653,8 @@ impl IdentityManager { } } - async fn affirm_chatter_in_db(&self, trgchatter: String) { + // => 03.22 - Force - Made public because botmodules unit tests + pub async fn affirm_chatter_in_db(&self, trgchatter: String) { let mut srulock = self.special_roles_users.write().await; srulock .entry(trgchatter.clone()) From 7757dd18200bfceb69980b4a5a8511a8b34e090b Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Fri, 22 Mar 2024 18:02:31 -0400 Subject: [PATCH 15/22] (cont) enable cmd logic --- src/core/botinstance.rs | 2 +- src/core/botmodules.rs | 76 ++++++++++++++++++++++++++--------------- 2 files changed, 49 insertions(+), 29 deletions(-) diff --git a/src/core/botinstance.rs b/src/core/botinstance.rs index 2e30421..733b89a 100644 --- a/src/core/botinstance.rs +++ b/src/core/botinstance.rs @@ -25,7 +25,7 @@ use crate::core::botlog; use crate::core::chat::Chat; -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Clone)] pub enum ChangeResult { Success(String), Failed(String), diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index a3866dd..a199481 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -108,7 +108,7 @@ pub async fn init(mgr: Arc) { - // [ ] Unwraps arguments from message + // [x] Unwraps arguments from message let (arg1, arg2) = { @@ -137,11 +137,11 @@ pub async fn init(mgr: Arc) { */ - // [ ] requestor: String, - let requester = msg.clone().sender.name; + // [x] requestor: String, + let requestor = msg.clone().sender.name; - // [ ] requestor_badge: Option, + // [x] requestor_badge: Option, let mut requestor_badge_mut: Option = None; @@ -156,41 +156,36 @@ pub async fn init(mgr: Arc) { let requestor_badge = requestor_badge_mut; - // [ ] trg_module: ModType, - // - [ ] Need to validate an actual ModType - otherwise, fail or exit the cmd + // [x] trg_module: ModType, + // - [x] Need to validate an actual ModType - otherwise, fail or exit the cmd let trg_module = if (arg1 == Some("-i")) || (arg1 == Some("-f")) { arg2 } else { arg1 }; - if let Some(trg_module_str) = trg_module { + // if no trg_module was passed + if let None = trg_module { let botlock = bot.read().await; - let modmgr = Arc::clone(&botlock.botmodules); - let modlist = modmgr.moduleslist().await; - let rslt = modlist.get(&ModType::BotModule(trg_module_str.to_string())); + + let outmsg = "uuh You need to pass a module"; - if let None = rslt { + botlog::debug( + outmsg, + Some("botmodules.rs > cmd_enable()".to_string()), + Some(&msg), + ); + + botlock + .botmgrs + .chat + .say_in_reply_to(&msg, outmsg.to_string()) + .await; - let outmsg = "uuh module doesn't exist"; - - botlog::debug( - outmsg, - Some("botmodules.rs > cmd_enable()".to_string()), - Some(&msg), - ); - - botlock - .botmgrs - .chat - .say_in_reply_to(&msg, outmsg.to_string()) - .await; - - return; - } + return; } - // [ ] trg_level: StatusLvl, + // [x] trg_level: StatusLvl, let currchnl = msg.channel_login.to_lowercase(); @@ -200,8 +195,33 @@ pub async fn init(mgr: Arc) { else { StatusLvl::Ch(ChType::Channel(currchnl)) } ; + + + let botlock = bot.read().await; + let modmgr = Arc::clone(&botlock.botmodules); + let id = botlock.get_identity(); + // modmgr.exec_enable(requestor, requestor_badge, trg_module, trg_level, id) + let rslt = modmgr.exec_enable( + requestor, + requestor_badge, + ModType::BotModule(trg_module.unwrap().to_string()), + trg_level, + id).await; + + + let outmsg = match rslt.clone() { + ChangeResult::Failed(a) => format!("Stare Failed : {}",a), + ChangeResult::NoChange(a) => format!("Hmm No Change : {}",a), + ChangeResult::Success(a) => format!("YAAY Success : {}",a), + }; + + botlock + .botmgrs + .chat + .say_in_reply_to(&msg, outmsg.to_string()) + .await; } From 29c8f745319ffae0a8959861aaeda82aa5dcd7b4 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Fri, 22 Mar 2024 18:16:41 -0400 Subject: [PATCH 16/22] (cont) disable cmd logic --- src/core/botmodules.rs | 123 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index a199481..df0595f 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -223,6 +223,7 @@ pub async fn init(mgr: Arc) { .say_in_reply_to(&msg, outmsg.to_string()) .await; + } @@ -281,6 +282,128 @@ pub async fn init(mgr: Arc) { 3c. , and is -f (forced) , return a Success */ + + // [x] Unwraps arguments from message + + let (arg1, arg2) = { + + let mut argv = msg.message_text.split(' '); + + argv.next(); // Skip the command name + + let arg1 = argv.next(); + + let arg2 = argv.next(); + + (arg1, arg2) + }; + + + /* -- Related function to call later + exec_disable( + &self, + requestor: String, + requestor_badge: Option, + trg_module: ModType, + // channel: Option, + trg_level: StatusLvl, + force: bool, + // bot: BotAR, + id: Arc>, + ) -> ChangeResult + */ + + + // [x] requestor: String, + let requestor = msg.clone().sender.name; + + + // [x] requestor_badge: Option, + + let mut requestor_badge_mut: Option = None; + + for b in &msg.badges { + if b.name == "moderator" { + requestor_badge_mut = Some(ChatBadge::Mod); + } else if b.name == "broadcaster" { + requestor_badge_mut = Some(ChatBadge::Broadcaster); + } + } + + let requestor_badge = requestor_badge_mut; + + // [x] trg_module: ModType, + // - [x] Need to validate an actual ModType - otherwise, fail or exit the cmd + + let trg_module = if (arg1 == Some("-i")) || (arg1 == Some("-f")) { arg2 } else { arg1 }; + + // if no trg_module was passed + if let None = trg_module { + + let botlock = bot.read().await; + + let outmsg = "uuh You need to pass a module"; + + botlog::debug( + outmsg, + Some("botmodules.rs > cmd_disable()".to_string()), + Some(&msg), + ); + + botlock + .botmgrs + .chat + .say_in_reply_to(&msg, outmsg.to_string()) + .await; + + return; + + } + + + + // [x] trg_level: StatusLvl, + + let currchnl = msg.channel_login.to_lowercase(); + + let trg_level = + if arg1 == Some("-i") { StatusLvl::Instance } + else if arg1 == Some("-f") { StatusLvl::Instance } + else { StatusLvl::Ch(ChType::Channel(currchnl)) } + ; + + + + let botlock = bot.read().await; + let modmgr = Arc::clone(&botlock.botmodules); + let id = botlock.get_identity(); + + let force = arg1 == Some("-f"); + + // modmgr.exec_enable(requestor, requestor_badge, trg_module, trg_level, id) + let rslt = modmgr.exec_disable( + requestor, + requestor_badge, + ModType::BotModule(trg_module.unwrap().to_string()), + trg_level, + force, + id).await; + + + let outmsg = match rslt.clone() { + ChangeResult::Failed(a) => format!("Stare Failed : {}",a), + ChangeResult::NoChange(a) => format!("Hmm No Change : {}",a), + ChangeResult::Success(a) => format!("YAAY Success : {}",a), + }; + + botlock + .botmgrs + .chat + .say_in_reply_to(&msg, outmsg.to_string()) + .await; + + + } From ba6117d6925fd5ebc5d4a0f3724b8e5fdd486860 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Fri, 22 Mar 2024 18:32:03 -0400 Subject: [PATCH 17/22] validate status --- src/core/botinstance.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/core/botinstance.rs b/src/core/botinstance.rs index 733b89a..5e70806 100644 --- a/src/core/botinstance.rs +++ b/src/core/botinstance.rs @@ -41,6 +41,8 @@ pub enum ChType { pub use ChType::Channel; +use super::botmodules::StatusType; + #[derive(Clone)] pub struct BotManagers { pub identity: Arc>, @@ -293,6 +295,23 @@ impl BotInstance { let botlock = bot.read().await; let id = botlock.get_identity(); + // [ ] Check first if the Module for that Given Command is Enabled or Disabled on the given Channel + let modmgr = Arc::clone(&botlock.botmodules); + let modstatus = modmgr.modstatus( + c.module.clone(), + ChType::Channel(msg.channel_login.to_string())).await; + + + if let StatusType::Disabled(a) = modstatus { + let botlock = bot.read().await; + let outstr = + format!("sadg Module is disabled : {:?}",a); + botlock.botmgrs.chat.say_in_reply_to(msg, outstr).await; + return; + }; + + + let eval = { let mut idlock = id.write().await; let (permissability, chngrslt) = idlock From 582702fab23879b85c5a205d80d745ca6bf0b011 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Fri, 22 Mar 2024 18:49:07 -0400 Subject: [PATCH 18/22] load botmodules module --- src/core/botmodules.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index df0595f..e790029 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -388,7 +388,7 @@ pub async fn init(mgr: Arc) { trg_level, force, id).await; - + let outmsg = match rslt.clone() { ChangeResult::Failed(a) => format!("Stare Failed : {}",a), @@ -600,6 +600,7 @@ impl ModulesManager { // 1. load core modules crate::core::identity::init(Arc::clone(&mgrarc)).await; + crate::core::botmodules::init(Arc::clone(&mgrarc)).await; // 2. load custom modules crate::custom::init(Arc::clone(&mgrarc)).await; From 2c298663b1ae519a4503d94196eab3aa2fb29dff Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Fri, 22 Mar 2024 19:07:19 -0400 Subject: [PATCH 19/22] rsp only to elevated users --- src/core/botinstance.rs | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/src/core/botinstance.rs b/src/core/botinstance.rs index 5e70806..2f1548c 100644 --- a/src/core/botinstance.rs +++ b/src/core/botinstance.rs @@ -19,7 +19,7 @@ use crate::core::ratelimiter::RateLimiter; use crate::core::bot_actions::actions_util::BotAR; use crate::core::botmodules::ModulesManager; -use crate::core::identity::{IdentityManager, Permissible}; +use crate::core::identity::{IdentityManager, Permissible,self}; use crate::core::botlog; use crate::core::chat::Chat; @@ -295,7 +295,7 @@ impl BotInstance { let botlock = bot.read().await; let id = botlock.get_identity(); - // [ ] Check first if the Module for that Given Command is Enabled or Disabled on the given Channel + // [x] Check first if the Module for that Given Command is Enabled or Disabled on the given Channel let modmgr = Arc::clone(&botlock.botmodules); let modstatus = modmgr.modstatus( c.module.clone(), @@ -303,15 +303,40 @@ impl BotInstance { if let StatusType::Disabled(a) = modstatus { - let botlock = bot.read().await; - let outstr = - format!("sadg Module is disabled : {:?}",a); - botlock.botmgrs.chat.say_in_reply_to(msg, outstr).await; + + // [x] Should only respond if a BotAdmin , Mod , SupMod , BroadCaster + // - Specifically it should respond only to those who may be able to enable the module + + + const OF_CMD_CHANNEL:ChType = Channel(String::new()); + + let elevated_access = { + let mut idlock = id.write().await; + let (permissability, _) = idlock + .can_user_run_prvmsg(msg, + vec![ + identity::UserRole::BotAdmin, + identity::UserRole::Mod(OF_CMD_CHANNEL), + identity::UserRole::SupMod(OF_CMD_CHANNEL), + identity::UserRole::Broadcaster, + ]) + .await; + + permissability + }; + + if let Permissible::Allow = elevated_access { + let botlock = bot.read().await; + let outstr = + format!("sadg Module is disabled : {:?}",a); + botlock.botmgrs.chat.say_in_reply_to(msg, outstr).await; + } + return; }; - + let eval = { let mut idlock = id.write().await; let (permissability, chngrslt) = idlock @@ -350,7 +375,7 @@ impl BotInstance { match eval { Permissible::Allow => { botlog::debug( - "Executed as permissible", + "Executing as permissible", Some("BotInstance > listener_main_prvmsg()".to_string()), Some(msg), ); From 4b0d51a6749d8c080c4b40ad64d665a57ec23075 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Fri, 22 Mar 2024 19:50:25 -0400 Subject: [PATCH 20/22] listener modules validated --- src/core/botinstance.rs | 64 +++++++++++++++++++++++++++++++++++++-- src/custom/experiments.rs | 2 +- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/src/core/botinstance.rs b/src/core/botinstance.rs index 2f1548c..1452860 100644 --- a/src/core/botinstance.rs +++ b/src/core/botinstance.rs @@ -307,6 +307,12 @@ impl BotInstance { // [x] Should only respond if a BotAdmin , Mod , SupMod , BroadCaster // - Specifically it should respond only to those who may be able to enable the module + botlog::trace( + &format!("Identified cmd is associated with Disabled Module : StatusLvl = {:?}", a), + Some("BotInstance > listener_main_prvmsg()".to_string()), + Some(msg), + ); + const OF_CMD_CHANNEL:ChType = Channel(String::new()); @@ -403,8 +409,62 @@ impl BotInstance { } crate::core::botmodules::BotAction::L(l) => { - let a = Arc::clone(&bot); - l.execute(a, msg.clone()).await; + + let botlock = bot.read().await; + // let id = botlock.get_identity(); + + // [x] Check first if the Module for that Given Command is Enabled or Disabled on the given Channel + let modmgr = Arc::clone(&botlock.botmodules); + let modstatus = modmgr.modstatus( + l.module.clone(), + ChType::Channel(msg.channel_login.to_string())).await; + + + if let StatusType::Disabled(a) = modstatus { + + // [x] Should only respond if a BotAdmin , Mod , SupMod , BroadCaster + // - Specifically it should respond only to those who may be able to enable the module + + botlog::trace( + &format!("Identified listener is associated with Disabled Module : StatusLvl = {:?}", a), + Some("BotInstance > listener_main_prvmsg()".to_string()), + Some(msg), + ); + + + // const OF_CMD_CHANNEL:ChType = Channel(String::new()); + + // let elevated_access = { + // let mut idlock = id.write().await; + // let (permissability, _) = idlock + // .can_user_run_prvmsg(msg, + // vec![ + // identity::UserRole::BotAdmin, + // identity::UserRole::Mod(OF_CMD_CHANNEL), + // identity::UserRole::SupMod(OF_CMD_CHANNEL), + // identity::UserRole::Broadcaster, + // ]) + // .await; + + // permissability + // }; + + // if let Permissible::Allow = elevated_access { + // let botlock = bot.read().await; + // let outstr = + // format!("sadg Module is disabled : {:?}",a); + // botlock.botmgrs.chat.say_in_reply_to(msg, outstr).await; + // } + + //return; + } else { + let a = Arc::clone(&bot); + l.execute(a, msg.clone()).await; + } + + + // let a = Arc::clone(&bot); + // l.execute(a, msg.clone()).await; } _ => (), diff --git a/src/custom/experiments.rs b/src/custom/experiments.rs index de2f424..529e551 100644 --- a/src/custom/experiments.rs +++ b/src/custom/experiments.rs @@ -125,7 +125,7 @@ async fn good_girl(bot: BotAR, msg: PrivmsgMessage) { Some(&msg), ); - let rollwin = rand::thread_rng().gen_ratio(1, 8); + let rollwin = rand::thread_rng().gen_ratio(1, 1); if rollwin { botlog::debug( From 06e182df556942bf852c35b024822552ad712e41 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Fri, 22 Mar 2024 20:18:02 -0400 Subject: [PATCH 21/22] clippy adj --- src/core/botmodules.rs | 55 +++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index e790029..d716ec5 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -44,6 +44,8 @@ use crate::core::bot_actions; pub use ChType::Channel; pub use ModType::BotModule; +use std::hash::{Hash, Hasher}; + use super::identity::ChatBadge; // use super::identity::ChangeResult; @@ -162,7 +164,8 @@ pub async fn init(mgr: Arc) { let trg_module = if (arg1 == Some("-i")) || (arg1 == Some("-f")) { arg2 } else { arg1 }; // if no trg_module was passed - if let None = trg_module { + // if let None = trg_module { + if trg_module.is_none() { let botlock = bot.read().await; @@ -190,8 +193,8 @@ pub async fn init(mgr: Arc) { let currchnl = msg.channel_login.to_lowercase(); let trg_level = - if arg1 == Some("-i") { StatusLvl::Instance } - else if arg1 == Some("-f") { StatusLvl::Instance } + if arg1 == Some("-i") || arg1 == Some("-f") { StatusLvl::Instance } + // else if arg1 == Some("-f") { StatusLvl::Instance } else { StatusLvl::Ch(ChType::Channel(currchnl)) } ; @@ -338,7 +341,8 @@ pub async fn init(mgr: Arc) { let trg_module = if (arg1 == Some("-i")) || (arg1 == Some("-f")) { arg2 } else { arg1 }; // if no trg_module was passed - if let None = trg_module { + // if let None = trg_module { + if trg_module.is_none() { let botlock = bot.read().await; @@ -367,8 +371,8 @@ pub async fn init(mgr: Arc) { let currchnl = msg.channel_login.to_lowercase(); let trg_level = - if arg1 == Some("-i") { StatusLvl::Instance } - else if arg1 == Some("-f") { StatusLvl::Instance } + if arg1 == Some("-i") || arg1 == Some("-f") { StatusLvl::Instance } + // else if arg1 == Some("-f") { StatusLvl::Instance } else { StatusLvl::Ch(ChType::Channel(currchnl)) } ; @@ -416,7 +420,8 @@ pub async fn init(mgr: Arc) { // #[derive(Debug, PartialEq, Eq, Hash, Clone)] -#[derive(Debug, Hash, Clone)] +// #[derive(Debug, Hash, Clone)] +#[derive(Debug, Clone)] pub enum ModType { BotModule(String), } @@ -430,6 +435,15 @@ impl PartialEq for ModType { } impl Eq for ModType {} +impl Hash for ModType{ + fn hash(&self, state: &mut H) { + // self.id.hash(state); + // self.phone.hash(state); + let BotModule(name) = self.clone(); + name.to_lowercase().hash(state); + } +} + #[derive(Debug, PartialEq, Eq, Hash, Clone)] pub enum ModGroup { @@ -561,10 +575,13 @@ impl BotActionTrait for Listener { #[derive(Debug)] pub struct Routine {} +type StatusdbEntry = (ModGroup, Vec); + pub struct ModulesManager { // statusdb: Arc>>>, // statusdb: Arc>>>, - statusdb: Arc)>>>, + // statusdb: Arc)>>>, + statusdb: Arc>>, pub botactions: Arc>>>, } @@ -783,7 +800,8 @@ impl ModulesManager { let modlist = self.moduleslist().await; let rslt = modlist.get(&trg_module); - if let None = rslt { + // if let None = rslt { + if rslt.is_none() { return ChangeResult::Failed("Module doesn't exist".to_string()); } @@ -1034,7 +1052,7 @@ impl ModulesManager { let modlist = self.moduleslist().await; let rslt = modlist.get(&trg_module); - if let None = rslt { + if rslt.is_none() { return ChangeResult::Failed("Module doesn't exist".to_string()); } @@ -1245,9 +1263,12 @@ impl ModulesManager { if (*x == StatusType::Enabled(StatusLvl::Instance)) || (*x == StatusType::Disabled(StatusLvl::Instance)) { true - } else if let StatusType::Enabled(StatusLvl::Ch(_)) = (*x).clone() { - true - } else {false} + // } else if let StatusType::Enabled(StatusLvl::Ch(_)) = (*x).clone() { + // true + // } else {false} + } else { + matches!((*x).clone(), StatusType::Enabled(StatusLvl::Ch(_))) + } ) { statusvector.remove(index); @@ -1903,10 +1924,10 @@ mod core_modulesmanager { modsmgr.affirm_in_statusdb(in_module.clone(), in_modgroup.clone()).await; - let in_module = match current_test_scenario { - // TestScenarios::ModuleDoesNotExist => BotModule("NonExisting_Module".to_string()), - _ => in_module, - }; + // let in_module = match current_test_scenario { + // // TestScenarios::ModuleDoesNotExist => BotModule("NonExisting_Module".to_string()), + // _ => in_module, + // }; /* From 72ebd5193c4912c2f3bfbc9714c77df745f7bce1 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Fri, 22 Mar 2024 21:06:15 -0400 Subject: [PATCH 22/22] comments cleanup --- src/core/botinstance.rs | 31 +-- src/core/botmodules.rs | 418 +++------------------------------------- src/core/identity.rs | 54 +----- 3 files changed, 25 insertions(+), 478 deletions(-) diff --git a/src/core/botinstance.rs b/src/core/botinstance.rs index 1452860..1aa0e49 100644 --- a/src/core/botinstance.rs +++ b/src/core/botinstance.rs @@ -246,7 +246,7 @@ impl BotInstance { /* BotCommand handling - - [x] Checks if the input message is a prefix with command name or alias - - [ ] Validate User can run based on identityModule(From_Bot)::can_user_run( + - [x] Validate User can run based on identityModule(From_Bot)::can_user_run( _usr:String, _channelname:ChType, _chat_badge:ChatBadge, @@ -431,40 +431,11 @@ impl BotInstance { Some(msg), ); - - // const OF_CMD_CHANNEL:ChType = Channel(String::new()); - - // let elevated_access = { - // let mut idlock = id.write().await; - // let (permissability, _) = idlock - // .can_user_run_prvmsg(msg, - // vec![ - // identity::UserRole::BotAdmin, - // identity::UserRole::Mod(OF_CMD_CHANNEL), - // identity::UserRole::SupMod(OF_CMD_CHANNEL), - // identity::UserRole::Broadcaster, - // ]) - // .await; - - // permissability - // }; - - // if let Permissible::Allow = elevated_access { - // let botlock = bot.read().await; - // let outstr = - // format!("sadg Module is disabled : {:?}",a); - // botlock.botmgrs.chat.say_in_reply_to(msg, outstr).await; - // } - - //return; } else { let a = Arc::clone(&bot); l.execute(a, msg.clone()).await; } - - // let a = Arc::clone(&bot); - // l.execute(a, msg.clone()).await; } _ => (), diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index d716ec5..cef3b2f 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -22,10 +22,8 @@ Example use core::panic; use std::collections::HashMap; -// use std::error::Error; use std::sync::Arc; -// use futures::stream::iter; use twitch_irc::message::PrivmsgMessage; use casual_logger::Log; @@ -48,8 +46,6 @@ use std::hash::{Hash, Hasher}; use super::identity::ChatBadge; -// use super::identity::ChangeResult; - pub async fn init(mgr: Arc) { @@ -91,7 +87,6 @@ pub async fn init(mgr: Arc) { /* 1. Parse out Message Arguments - exec_enable() @@ -415,12 +410,6 @@ pub async fn init(mgr: Arc) { - - - - -// #[derive(Debug, PartialEq, Eq, Hash, Clone)] -// #[derive(Debug, Hash, Clone)] #[derive(Debug, Clone)] pub enum ModType { BotModule(String), @@ -578,9 +567,6 @@ pub struct Routine {} type StatusdbEntry = (ModGroup, Vec); pub struct ModulesManager { - // statusdb: Arc>>>, - // statusdb: Arc>>>, - // statusdb: Arc)>>>, statusdb: Arc>>, pub botactions: Arc>>>, } @@ -668,19 +654,6 @@ impl ModulesManager { StatusType::Enabled(StatusLvl::Instance) // This forces core to be validated as Enabled, even if undesired scenario of missing StatusLvl::Instance or empty vectors }, ModGroup::Custom => { - // // remove all instance level pattern for the module - // while let Some(index) = statusvector - // .iter() - // .position(|x| (*x == StatusType::Enabled(StatusLvl::Instance)) || (*x == StatusType::Disabled(StatusLvl::Instance))) { - - // statusvector.remove(index); - // } - // statusvector.push(StatusType::Disabled(StatusLvl::Instance)); - - // ( - // StatusType::Disabled(StatusLvl::Instance), - // ChangeResult::Success("Set Disabled at Instance".to_string()) - // ) /* @@ -737,29 +710,12 @@ impl ModulesManager { //StatusType::Enabled(StatusLvl::Instance) } - // pub fn togglestatus(&self, _: ModType, _: ChType) -> StatusType { - // // enables or disables based on current status - // StatusType::Enabled(StatusLvl::Instance) - // } - - // pub fn setstatus(&self, _: ModType, _: StatusType) -> Result<&str, Box> { - // // sets the status based given ModSatusType - // // e.g., b.setstatus(BodModule("GambaCore"), Enabled(Channel("modulatingforce"))).expect("ERROR") - // Ok("") - // } - - /* - exec_enable(self,requestor,requestor_badge,trg_module,Channel) -> ChangeResult - */ - pub async fn exec_enable( &self, requestor: String, requestor_badge: Option, trg_module: ModType, - // channel: Option, trg_level: StatusLvl, - // bot: BotAR, id: Arc>, ) -> ChangeResult { @@ -784,7 +740,7 @@ impl ModulesManager { /* - [ ] 1. If CmdSender is BotAdmin but not (Mod,SupMod,Broadcaster) + [x] 1. If CmdSender is BotAdmin but not (Mod,SupMod,Broadcaster) 1. can_user_run for cmdreqRoles including BotAdmin & not can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) 1a. , and is -i (to instance) , return a Success 1b. , and is not -i (to instance) , return a Failure recommending BotAdmin promote themselves first @@ -795,19 +751,14 @@ impl ModulesManager { // [x] Validate in trg_module first - // let botlock = bot.read().await; - // let modmgr = Arc::clone(&botlock.botmodules); let modlist = self.moduleslist().await; let rslt = modlist.get(&trg_module); - // if let None = rslt { if rslt.is_none() { return ChangeResult::Failed("Module doesn't exist".to_string()); } - // let botlock = bot.read().await; - // let id = botlock.get_identity(); let mut idlock = id.write().await; // if trg_level = StatusLvl::Instance , the temp_chnl = the broadcaster's or the chatter's @@ -833,16 +784,6 @@ impl ModulesManager { ]).await; - // botlog::debug( - // &format!("FAILURE BEFORE Let statements involves : - // admin_level_access : {:?} ; chnl_elevated_access : {:?}", - // admin_level_access , chnl_elevated_access), - // Some("botmodules.rs > exec_enable()".to_string()), - // None, - // ); - - - if let Permissible::Allow = admin_level_access { if let Permissible::Block = chnl_elevated_access { @@ -868,7 +809,7 @@ impl ModulesManager { /* - [ ] 2. If CmdSender not a BotAdmin but is (Mod,SupMod,Broadcaster) + [x] 2. If CmdSender not a BotAdmin but is (Mod,SupMod,Broadcaster) 2. not can_user_run for cmdreqRoles including BotAdmin & can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) 2a. , and is -i (to instance) , return a Failure they are not allowed 2b. , and is not -i (to instance) , return a Success @@ -892,7 +833,7 @@ impl ModulesManager { /* - [ ] 3. If CmdSender is (Mod,SupMod,Broadcaster) and a BotAdmin + [x] 3. If CmdSender is (Mod,SupMod,Broadcaster) and a BotAdmin 3. can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) & can_user_run for cmdreqRoles including BotAdmin 3a. , and is not -i (to instance) , return a Success 3b. , and is -i (to instance) , return a Success @@ -937,64 +878,11 @@ impl ModulesManager { - - // ======================= - // ======================= - // ======================= - // /* - - // 2. Get Special Roles of CmdSender - // 3. If CmdSender is BotAdmin but not (Mod,SupMod,Broadcaster) - // 3a. , and is not -i (to instance) , return a Failure recommending BotAdmin promote themselves first - // 3b. , and is -i (to instance) , return a Success - // 4. If CmdSender not a BotAdmin but is (Mod,SupMod,Broadcaster) - // 4a. , and is not -i (to instance) , return a Success - // 4b. , and is -i (to instance) , return a Failure they are not allowed - // 5. If CmdSender is (Mod,SupMod,Broadcaster) and a BotAdmin - // 5a. , and is not -i (to instance) , return a Success - // 5b. , and is -i (to instance) , return a Success - - - // */ - - // // [ ] 2. Get Special Roles of CmdSender - - // let botlock = bot.read().await; - // let id = botlock.get_identity(); - // let idlock = id.read().await; - - - // let trgchnl = { - // match trg_level { - // StatusLvl::Instance => None, - // StatusLvl::Ch(a) => Some(a), - // } - // }; - - // let requestor_roles = idlock - // .getspecialuserroles( - // requestor.to_lowercase(), - // trgchnl, - // ) - // .await; - - // /* - // [ ] 3. If CmdSender is BotAdmin but not (Mod,SupMod,Broadcaster) - // 3a. , and is not -i (to instance) , return a Failure recommending BotAdmin promote themselves first - // 3b. , and is -i (to instance) , return a Success - // */ - - // if requestor_roles.contains(&identity::UserRole::BotAdmin) - // && !requestor_roles.contains(&identity::UserRole::Broadcaster) - // && !requestor_roles.contains(&identity::UserRole::Mod(trgchnl)) - // { - - // } botlog::debug( &format!("FAILURE involves : @@ -1016,10 +904,8 @@ impl ModulesManager { requestor: String, requestor_badge: Option, trg_module: ModType, - // channel: Option, trg_level: StatusLvl, force: bool, - // bot: BotAR, id: Arc>, ) -> ChangeResult { @@ -1047,8 +933,6 @@ impl ModulesManager { // [x] Validate in trg_module first - // let botlock = bot.read().await; - // let modmgr = Arc::clone(&botlock.botmodules); let modlist = self.moduleslist().await; let rslt = modlist.get(&trg_module); @@ -1057,9 +941,6 @@ impl ModulesManager { } - - // let botlock = bot.read().await; - // let id = botlock.get_identity(); let mut idlock = id.write().await; // if trg_level = StatusLvl::Instance , the temp_chnl = the broadcaster's or the chatter's @@ -1087,7 +968,7 @@ impl ModulesManager { /* - [ ] 1. If CmdSender is BotAdmin but not (Mod,SupMod,Broadcaster) + [x] 1. If CmdSender is BotAdmin but not (Mod,SupMod,Broadcaster) 1. can_user_run for cmdreqRoles including BotAdmin & not can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) 1a. , and is -f (forced) , return a Success 1b. , and is -i (to instance) , return a Success @@ -1116,11 +997,11 @@ impl ModulesManager { /* - [ ] 2. If CmdSender not a BotAdmin but is (Mod,SupMod,Broadcaster) - 2. not can_user_run for cmdreqRoles including BotAdmin & can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) - 2a. , and is -f (forced) , return a Failure they are not allowed - 2b. , and is -i (to instance) , return a Failure they are not allowed - 2c. , and has no special flags (-i / -f) , return a Success + [x] 2. If CmdSender not a BotAdmin but is (Mod,SupMod,Broadcaster) + 2. not can_user_run for cmdreqRoles including BotAdmin & can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) + 2a. , and is -f (forced) , return a Failure they are not allowed + 2b. , and is -i (to instance) , return a Failure they are not allowed + 2c. , and has no special flags (-i / -f) , return a Success */ @@ -1144,11 +1025,11 @@ impl ModulesManager { /* - [ ] 3. If CmdSender is (Mod,SupMod,Broadcaster) and a BotAdmin - 3. can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) & can_user_run for cmdreqRoles including BotAdmin - 3a. , and is -f (forced) , return a Success - 3b. , and is -i (to instance) , return a Success - 3c. , and has no special flags (-i / -f) , return a Success + [x] 3. If CmdSender is (Mod,SupMod,Broadcaster) and a BotAdmin + 3. can_user_run for cmdreqRoles (Mod,SupMod,Broadcaster) & can_user_run for cmdreqRoles including BotAdmin + 3a. , and is -f (forced) , return a Success + 3b. , and is -i (to instance) , return a Success + 3c. , and has no special flags (-i / -f) , return a Success */ @@ -1203,11 +1084,8 @@ impl ModulesManager { // at Instance level // - If core module, do nothing - // self.satusdb. - let mut dbt = self.statusdb.write().await; - // let a = dbt.entry(in_module.clone()).; let (mgrp,statusvector) = dbt.get_mut(&in_module).unwrap(); match mgrp { @@ -1244,7 +1122,6 @@ impl ModulesManager { let mut dbt = self.statusdb.write().await; - // let a = dbt.entry(in_module.clone()).; let (mgrp,statusvector) = dbt.get_mut(&in_module).unwrap(); match mgrp { @@ -1263,9 +1140,6 @@ impl ModulesManager { if (*x == StatusType::Enabled(StatusLvl::Instance)) || (*x == StatusType::Disabled(StatusLvl::Instance)) { true - // } else if let StatusType::Enabled(StatusLvl::Ch(_)) = (*x).clone() { - // true - // } else {false} } else { matches!((*x).clone(), StatusType::Enabled(StatusLvl::Ch(_))) } @@ -1291,7 +1165,6 @@ impl ModulesManager { let mut dbt = self.statusdb.write().await; - // let a = dbt.entry(in_module.clone()).; let (mgrp,statusvector) = dbt.get_mut(&in_module).unwrap(); match mgrp { @@ -1328,7 +1201,6 @@ impl ModulesManager { let mut dbt = self.statusdb.write().await; - // let a = dbt.entry(in_module.clone()).; let (mgrp,statusvector) = dbt.get_mut(&in_module).unwrap(); match mgrp { @@ -1366,7 +1238,6 @@ impl ModulesManager { let mut dbt = self.statusdb.write().await; - // let a = dbt.entry(in_module.clone()).; let (mgrp,statusvector) = dbt.get_mut(&in_module).unwrap(); match mgrp { @@ -1506,17 +1377,6 @@ impl ModulesManager { ) } - // let mut dbt = self.statusdb.write().await; - // // - // let statusvector = dbt.entry(in_module.clone()).or_insert((in_modgroup.clone(),Vec::new())); - - // match in_modgroup { - // ModGroup::Core => statusvector.1.push(StatusType::Enabled(StatusLvl::Instance)) , // Pushes the Module as Enabled at Instance Level - // ModGroup::Custom => statusvector.1.push(StatusType::Disabled(StatusLvl::Instance)), - // } - - // statusvector.push(ModStatusType::Enabled(StatusLvl::Instance)); // Pushes the Module as Enabled at Instance Level - self.affirm_in_statusdb(in_module.clone(),in_modgroup).await; let mut a = self.botactions.write().await; @@ -1571,8 +1431,6 @@ mod core_modulesmanager { } - - /* Possible Tests @@ -1862,20 +1720,8 @@ mod core_modulesmanager { // ModuleDoesNotExist, // preferring instead to handle in it's own smaller test } - - // let channel = ChType::Channel("somechannel".to_string()); - - - // let mut idlock = idmgr.write().await; let mut idlock = idmgr.clone(); - // if trg_level = StatusLvl::Instance , the temp_chnl = the broadcaster's or the chatter's - - // let arb_chnl = match trg_level.clone() { - // StatusLvl::Instance => ChType::Channel(requestor.to_lowercase()), - // StatusLvl::Ch(a) => a, - // }; - let requestor_badge = None; // If they are a Mod on the Given Channel already, that can be evaluated without the current badge const OF_CMD_CHANNEL:ChType = Channel(String::new()); @@ -1917,19 +1763,8 @@ mod core_modulesmanager { let in_module = BotModule("Experiments01".to_string()); let in_modgroup = ModGroup::Custom; - // match current_test_scenario { - // TestScenarios::BotadminUser => modsmgr.affirm_in_statusdb(in_module.clone(), in_modgroup.clone()).await, - // _ => self::panic!("Scenario not handled"), - // } - modsmgr.affirm_in_statusdb(in_module.clone(), in_modgroup.clone()).await; - // let in_module = match current_test_scenario { - // // TestScenarios::ModuleDoesNotExist => BotModule("NonExisting_Module".to_string()), - // _ => in_module, - // }; - - /* [x] 3. affirm when BotAdmin attempts to exec_enable on the following a. Channel Level , where they are not a Mod @@ -1956,8 +1791,6 @@ mod core_modulesmanager { trg_level.clone(), id.clone()).await; - // assert_eq!(rslt,ChangeResult::Failed("Promote yourself Temporarily First".to_string())); - match current_test_scenario { TestScenarios::BotadminUser => assert_eq!(rslt,ChangeResult::Failed("Promote yourself Temporarily First".to_string())), @@ -1965,10 +1798,6 @@ mod core_modulesmanager { assert_eq!(rslt,ChangeResult::Success("Enabled at Channel Level".to_string())), TestScenarios::RegularChatter => assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), - // TestScenarios::ModuleDoesNotExist => - // assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), - // _ => - // self::panic!("Scenario not handled"), } @@ -1978,7 +1807,7 @@ mod core_modulesmanager { */ // [x] requestor_badge: Option, - // let requestor_badge = ChatBadge::Mod; // setting badge to Mod + let requestor_badge = match current_test_scenario { TestScenarios::BotadminUser => Some(ChatBadge::Mod), // setting badge to Mod -- for the Problem Scenario . They are both BotAdmin & Mod @@ -1986,10 +1815,6 @@ mod core_modulesmanager { Some(ChatBadge::Mod), // setting badge to Mod TestScenarios::RegularChatter => None, // setting badge to None - // TestScenarios::ModuleDoesNotExist => - // None, - // _ => - // self::panic!("Scenario not handled"), } ; @@ -1999,8 +1824,6 @@ mod core_modulesmanager { trg_level.clone(), id.clone()).await; - // assert_eq!(rslt,ChangeResult::Success("Enabled at Channel Level".to_string())); - match current_test_scenario { TestScenarios::BotadminUser => assert_eq!(rslt,ChangeResult::Success("Enabled at Channel Level".to_string())), @@ -2008,10 +1831,6 @@ mod core_modulesmanager { assert_eq!(rslt,ChangeResult::Success("Enabled at Channel Level".to_string())), TestScenarios::RegularChatter => assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), - // TestScenarios::ModuleDoesNotExist => - // assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), - // _ => - // self::panic!("Scenario not handled"), } /* @@ -2028,10 +1847,6 @@ mod core_modulesmanager { Some(ChatBadge::Mod), TestScenarios::RegularChatter => None, // setting badge to None - // TestScenarios::ModuleDoesNotExist => - // None, // setting badge to None - // _ => - // self::panic!("Scenario not handled"), }; let rslt = modsmgr.exec_enable(requestor.clone(), @@ -2040,7 +1855,6 @@ mod core_modulesmanager { trg_level.clone(), id.clone()).await; - // assert_eq!(rslt,ChangeResult::Success("Enabled at Instance Level".to_string())); match current_test_scenario { TestScenarios::BotadminUser => @@ -2049,10 +1863,6 @@ mod core_modulesmanager { assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), TestScenarios::RegularChatter => assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), - // TestScenarios::ModuleDoesNotExist => - // assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), - // _ => - // self::panic!("Scenario not handled"), } /* @@ -2069,7 +1879,6 @@ mod core_modulesmanager { false, id.clone()).await; - // assert_eq!(rslt,ChangeResult::Success("Disabled at Channel Level".to_string())); match current_test_scenario { TestScenarios::BotadminUser => assert_eq!(rslt,ChangeResult::Success("Disabled at Channel Level".to_string())), @@ -2077,10 +1886,6 @@ mod core_modulesmanager { assert_eq!(rslt,ChangeResult::Success("Disabled at Channel Level".to_string())), TestScenarios::RegularChatter => assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), - // TestScenarios::ModuleDoesNotExist => - // assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), - // _ => - // self::panic!("Scenario not handled"), } @@ -2091,7 +1896,7 @@ mod core_modulesmanager { let trg_level = StatusLvl::Ch(channel.clone()); // setting to Channel Level - // let requestor_badge = ChatBadge::Mod; // setting badge to Mod + let requestor_badge = match current_test_scenario { TestScenarios::BotadminUser => None, @@ -2099,10 +1904,6 @@ mod core_modulesmanager { Some(ChatBadge::Mod), TestScenarios::RegularChatter => None, // setting badge to None - // TestScenarios::ModuleDoesNotExist => - // None, - // _ => - // self::panic!("Scenario not handled"), }; let rslt: ChangeResult = modsmgr.exec_disable(requestor.clone(), @@ -2112,7 +1913,7 @@ mod core_modulesmanager { false, id.clone()).await; - // assert_eq!(rslt,ChangeResult::Success("Disabled at Channel Level".to_string())); + match current_test_scenario { TestScenarios::BotadminUser => assert_eq!(rslt,ChangeResult::Success("Disabled at Channel Level".to_string())), @@ -2120,10 +1921,6 @@ mod core_modulesmanager { assert_eq!(rslt,ChangeResult::Success("Disabled at Channel Level".to_string())), TestScenarios::RegularChatter => assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), - // TestScenarios::ModuleDoesNotExist => - // assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), - // _ => - // self::panic!("Scenario not handled"), } @@ -2133,8 +1930,8 @@ mod core_modulesmanager { */ let trg_level = StatusLvl::Instance; // setting to Instance level - // let requestor_badge = ChatBadge::Mod; // setting badge to Mod - + + let rslt: ChangeResult = modsmgr.exec_disable(requestor.clone(), None, // Does not have a ChatBadge like Mod trg_module.clone(), @@ -2142,7 +1939,6 @@ mod core_modulesmanager { false, id.clone()).await; - // assert_eq!(rslt,ChangeResult::Success("Disabled at Instance Level".to_string())); match current_test_scenario { TestScenarios::BotadminUser => assert_eq!(rslt,ChangeResult::Success("Disabled at Instance Level".to_string())), @@ -2150,10 +1946,6 @@ mod core_modulesmanager { assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), TestScenarios::RegularChatter => assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), - // TestScenarios::ModuleDoesNotExist => - // assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), - // _ => - // self::panic!("Scenario not handled"), } /* @@ -2162,7 +1954,6 @@ mod core_modulesmanager { */ let trg_level = StatusLvl::Instance; // setting to Instance level - // let requestor_badge = ChatBadge::Mod; // setting badge to Mod let rslt: ChangeResult = modsmgr.exec_disable(requestor.clone(), None, // Does not have a ChatBadge like Mod @@ -2171,7 +1962,6 @@ mod core_modulesmanager { true, // force flag - true id.clone()).await; - // assert_eq!(rslt,ChangeResult::Success("Forced Disable".to_string())); match current_test_scenario { TestScenarios::BotadminUser => assert_eq!(rslt,ChangeResult::Success("Forced Disable".to_string())), @@ -2179,10 +1969,6 @@ mod core_modulesmanager { assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), TestScenarios::RegularChatter => assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), - // TestScenarios::ModuleDoesNotExist => - // assert_eq!(rslt,ChangeResult::Failed("You're not allowed".to_string())), - // _ => - // self::panic!("Scenario not handled"), } @@ -2214,14 +2000,6 @@ mod core_modulesmanager { let idmgr = IdentityManager::init(); let modsmgr = ModulesManager::init().await; - // // [x] 2. modmgr.affirm_in_statusdb(Experiments01,Custom) - - // let in_module = BotModule("Experiments01".to_string()); - // let in_modgroup = ModGroup::Custom; - - // modsmgr.affirm_in_statusdb(in_module.clone(), in_modgroup.clone()).await; - - /* [x] 3. affirm when BotAdmin attempts to exec_enable on the following a. Channel Level , where they are not a Mod @@ -2230,7 +2008,6 @@ mod core_modulesmanager { // [x] Create BotAdmin first let requestor = "botadministrator".to_string(); - // let botadmin_badge = &None; idmgr.affirm_chatter_in_db(requestor.clone()).await; idmgr @@ -2249,149 +2026,6 @@ mod core_modulesmanager { inner_enable_disable_complex(requestor, channel, idmgr, modsmgr).await; - /* - pub async fn exec_enable( - &self, - requestor: String, - requestor_badge: Option, - trg_module: ModType, - trg_level: StatusLvl, - id: Arc>, - ) -> ChangeResult - - */ - - /* - [x] 3. affirm when BotAdmin attempts to exec_enable on the following - a. Channel Level , where they are not a Mod - */ - - - // [-] requestor_badge: Option, - - // [x] trg_module: ModType, - // let trg_module = in_module; - - // [x] trg_level: StatusLvl, - - // let channel = ChType::Channel("somechannel".to_string()); - // let trg_level = StatusLvl::Ch(channel.clone()); // setting to Channel Level - - - // // [x] id: Arc>, - // let id = Arc::new(RwLock::new(idmgr)); - - - // let rslt = modsmgr.exec_enable(requestor.clone(), - // None, - // trg_module.clone(), - // trg_level.clone(), - // id.clone()).await; - - // assert_eq!(rslt,ChangeResult::Failed("Promote yourself Temporarily First".to_string())); - - // /* - // [x] 3. affirm when BotAdmin attempts to exec_enable on the following - // b. Channel Level , when they are a Mod - // */ - - // // [x] requestor_badge: Option, - // let requestor_badge = ChatBadge::Mod; // setting badge to Mod - - // let rslt = modsmgr.exec_enable(requestor.clone(), - // Some(requestor_badge), - // trg_module.clone(), - // trg_level.clone(), - // id.clone()).await; - - // assert_eq!(rslt,ChangeResult::Success("Enabled at Channel Level".to_string())); - - // /* - // [x] 3. affirm when BotAdmin attempts to exec_enable on the following - // c. Instance Level - // */ - - // let trg_level = StatusLvl::Instance; // setting to Instance level - - // let rslt = modsmgr.exec_enable(requestor.clone(), - // None, // setting them back to Non-Mod - // trg_module.clone(), - // trg_level.clone(), - // id.clone()).await; - - // assert_eq!(rslt,ChangeResult::Success("Enabled at Instance Level".to_string())); - - // /* - // [x] 4. affirm when BotAdmin attempts to exec_disable on the following - // a. Channel Level , where they are not a Mod - // */ - - // let trg_level = StatusLvl::Ch(channel.clone()); // setting to Channel Level - - // let rslt: ChangeResult = modsmgr.exec_disable(requestor.clone(), - // None, // Does not have a ChatBadge like Mod - // trg_module.clone(), - // trg_level.clone(), - // false, - // id.clone()).await; - - // assert_eq!(rslt,ChangeResult::Success("Disabled at Channel Level".to_string())); - - - // /* - // [x] 4. affirm when BotAdmin attempts to exec_disable on the following - // b. Channel Level , when they are a Mod - // */ - - - // let trg_level = StatusLvl::Ch(channel.clone()); // setting to Channel Level - // let requestor_badge = ChatBadge::Mod; // setting badge to Mod - - // let rslt: ChangeResult = modsmgr.exec_disable(requestor.clone(), - // Some(requestor_badge), - // trg_module.clone(), - // trg_level.clone(), - // false, - // id.clone()).await; - - // assert_eq!(rslt,ChangeResult::Success("Disabled at Channel Level".to_string())); - - // /* - // [x] 4. affirm when BotAdmin attempts to exec_disable on the following - // c. Instance Level - // */ - - // let trg_level = StatusLvl::Instance; // setting to Instance level - // // let requestor_badge = ChatBadge::Mod; // setting badge to Mod - - // let rslt: ChangeResult = modsmgr.exec_disable(requestor.clone(), - // None, // Does not have a ChatBadge like Mod - // trg_module.clone(), - // trg_level.clone(), - // false, - // id.clone()).await; - - // assert_eq!(rslt,ChangeResult::Success("Disabled at Instance Level".to_string())); - - // /* - // [ ] 4. affirm when BotAdmin attempts to exec_disable on the following - // d. force disable - // */ - - // let trg_level = StatusLvl::Instance; // setting to Instance level - // // let requestor_badge = ChatBadge::Mod; // setting badge to Mod - - // let rslt: ChangeResult = modsmgr.exec_disable(requestor.clone(), - // None, // Does not have a ChatBadge like Mod - // trg_module.clone(), - // trg_level.clone(), - // true, // force flag - true - // id.clone()).await; - - // assert_eq!(rslt,ChangeResult::Success("Forced Disable".to_string())); - - - } @@ -2475,15 +2109,11 @@ mod core_modulesmanager { let requestor = "regular_user".to_string(); - // let botadmin_badge = &None; let channel = ChType::Channel("somechannel".to_string()); idmgr.affirm_chatter_in_db(requestor.clone()).await; - // idmgr - // .add_role(requestor.clone(), identity::UserRole::Mod(channel.clone())) - // .await; - + let rslt = idmgr .getspecialuserroles( requestor.clone(), @@ -2511,14 +2141,12 @@ mod core_modulesmanager { let requestor = "regular_user".to_string(); - // let botadmin_badge = &None; + let channel = ChType::Channel("somechannel".to_string()); idmgr.affirm_chatter_in_db(requestor.clone()).await; - // idmgr - // .add_role(requestor.clone(), identity::UserRole::Mod(channel.clone())) - // .await; + let rslt = idmgr .getspecialuserroles( @@ -2555,7 +2183,7 @@ mod core_modulesmanager { assert_eq!(rslt,ChangeResult::Failed("Module doesn't exist".to_string())); - // [ ] Test with Non Existing module > disable + // [x] Test with Non Existing module > disable let trg_module = BotModule("Non_Existent_Module".to_string()); diff --git a/src/core/identity.rs b/src/core/identity.rs index accda4f..0a27b60 100644 --- a/src/core/identity.rs +++ b/src/core/identity.rs @@ -696,59 +696,6 @@ impl IdentityManager { } } - // if &msg.badges.contains(Badge{}) { - - // } - - // if let Some(sender_badge) = sender_badge { - // match sender_badge { - // Some(sender_badge) => { - // return &self.can_user_run(msg.sender.name.to_owned(), - // ChType::Channel(msg.channel_login.to_owned()), - // sender_badge, - // cmdreqroles - // return self.can_user_run(msg.sender.name.to_owned(), - // let a = Arc::new(Mutex::new(self)); - // let mut a = a.lock().await; - // let a = **a; - // let a = a.can_user_run(msg.sender.name.to_owned(), - // ChType::Channel(msg.channel_login.to_owned()), - // sender_badge, - // cmdreqroles - // ) ; - // let a = *self; - // let a = Arc::new(Mutex::new(a)); - // let a = a.lock().await.can_user_run(msg.sender.name.to_owned(), - // ChType::Channel(msg.channel_login.to_owned()), - // sender_badge, - // cmdreqroles - // ) ; - // return a; - // return self.can_user_run(msg.sender.name.to_owned(), - // ChType::Channel(msg.channel_login.to_owned()), - // sender_badge, - // cmdreqroles - // ).await - - // * NOTE : We're preferring to pass the ChangeResult up , where we have access to Chat via BotInstance - // that have more strained chatting rules - // let evalpermissible = self.can_user_run(msg.sender.name.to_owned(), - // ChType::Channel(msg.channel_login.to_owned()), - // sender_badge, - // cmdreqroles - // ).await ; - // evalpermissible - // // } - // None => { - - // } - // here , sender_badge is likely None - // This could be a regular chatter, BotAdmin,SupserMod - - // [ ] Call can_user_run() - // (self,Permissible::Block) - // (Permissible::Block,ChangeResult::NoChange("".to_string())) - self.can_user_run( msg.sender.name.to_owned(), ChType::Channel(msg.channel_login.to_owned()), @@ -756,6 +703,7 @@ impl IdentityManager { cmdreqroles, ) .await + } pub async fn can_user_run(