2023-12-21 00:48:09 -05:00
/*
2024-02-25 10:40:54 -05:00
ModulesManager is used to manage Modules and BotActions associated with those modules
2023-12-22 09:52:01 -05:00
pub struct ModulesManager {
statusdb : HashMap < ModType , Vec < ModStatusType > > ,
2024-02-25 10:40:54 -05:00
botactions : HashMap < ModType , Vec < BotAction > > ,
2023-12-22 09:52:01 -05:00
}
- statusdb : HashMap < ModType , Vec < ModStatusType > > - Defines Modules and their ModStatusType ( e . g . , Enabled at an Instance level , Disabled at a Channel Level )
2024-02-25 10:40:54 -05:00
- botactions : HashMap < ModType , Vec < BotAction > > - Defines Modules and their BotActions ( e . g . , BotCommand , Listener , Routine )
2023-12-21 00:48:09 -05:00
Example
{
2024-02-25 10:40:54 -05:00
ModulesManager {
statusdb : { BotModule ( " experiments 004 " ) : [ Enabled ( Instance ) ] } ,
2023-12-22 09:52:01 -05:00
botactions : { BotModule ( " experiments 004 " ) : [ C ( BotCommand { module : BotModule ( " experiments 004 " ) , command : " DUPCMD4 " , alias : [ " DUPALIAS4A " , " DUPALIAS4B " ] , help : " DUPCMD4 tester " } ) ] } }
2023-12-21 00:48:09 -05:00
}
* /
2024-03-02 10:24:13 -05:00
use core ::panic ;
2023-12-21 00:48:09 -05:00
2024-03-02 10:24:13 -05:00
use std ::collections ::HashMap ;
2024-03-21 00:05:52 -04:00
// use std::error::Error;
2024-03-02 10:24:13 -05:00
use std ::sync ::Arc ;
2023-12-21 00:48:09 -05:00
2024-03-21 09:37:08 -04:00
// use futures::stream::iter;
2023-12-26 20:00:32 -05:00
use twitch_irc ::message ::PrivmsgMessage ;
2023-12-21 00:48:09 -05:00
2024-03-22 17:06:09 -04:00
use casual_logger ::Log ;
2024-03-21 14:01:54 -04:00
2024-03-02 10:24:13 -05:00
use tokio ::sync ::RwLock ;
use async_trait ::async_trait ;
2024-03-02 11:41:24 -05:00
use self ::bot_actions ::actions_util ::BotAR ;
2024-03-21 21:20:16 -04:00
use crate ::core ::bot_actions ::actions_util ;
2024-03-21 00:05:52 -04:00
use crate ::core ::botinstance ::{ BotInstance , ChType , ChangeResult } ;
2024-03-02 10:24:13 -05:00
use crate ::core ::botlog ;
2024-03-22 17:06:09 -04:00
use crate ::core ::identity ::{ self , Permissible , IdentityManager } ;
2024-02-12 01:25:12 -05:00
2024-03-02 12:21:18 -05:00
use crate ::core ::bot_actions ;
2024-03-02 10:24:13 -05:00
pub use ChType ::Channel ;
pub use ModType ::BotModule ;
2024-03-21 21:20:16 -04:00
use super ::identity ::ChatBadge ;
2024-03-21 00:05:52 -04:00
// use super::identity::ChangeResult;
2024-03-21 21:20:16 -04:00
pub async fn init ( mgr : Arc < ModulesManager > ) {
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
2024-03-22 08:21:10 -04:00
- If BotAdmins need to enable / disable at Channel level , they must Promote themselves to be a Mod at least
2024-03-21 21:20:16 -04:00
- Other Special Roles ( Mod , SupMod , Broadcaster ) can run without issues to enable the module at Channel Level
* /
/*
enable - i < module > // enables at Instance
enable < module > // 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 )
3 a . , and is not - i ( to instance ) , return a Failure recommending BotAdmin promote themselves first
3 b . , and is - i ( to instance ) , return a Success
4. If CmdSender not a BotAdmin but is ( Mod , SupMod , Broadcaster )
4 a . , and is not - i ( to instance ) , return a Success
4 b . , and is - i ( to instance ) , return a Failure they are not allowed
5. If CmdSender is ( Mod , SupMod , Broadcaster ) and a BotAdmin
5 a . , and is not - i ( to instance ) , return a Success
5 b . , and is - i ( to instance ) , return a Success
* /
2024-03-22 08:21:10 -04:00
// [ ] 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 < ChatBadge > ,
trg_module : ModType ,
// channel: Option<ChType>,
trg_level : StatusLvl ,
bot : BotAR ,
) -> ChangeResult
2024-03-21 21:20:16 -04:00
* /
2024-03-22 08:21:10 -04:00
// [ ] requestor: String,
let requester = msg . clone ( ) . sender . name ;
// [ ] requestor_badge: Option<ChatBadge>,
let mut requestor_badge_mut : Option < ChatBadge > = 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 ) ) }
;
2024-03-21 21:20:16 -04:00
}
// 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
2024-03-22 08:21:10 -04:00
- 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
2024-03-21 21:20:16 -04:00
- Other Special Roles ( Mod , SupMod , Broadcaster ) can run without issues to disable the module at Channel Level
2024-03-22 08:21:10 -04:00
* /
2024-03-21 21:20:16 -04:00
/*
disable - i < module > // disables at Instance
disable < module > // disables at Channel
disable - f < module > // force disables (instance and enabled are removed)
* /
2024-03-22 08:21:10 -04:00
/*
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 )
1 a . , and has no special flags ( - i / - f ) , return a Failure recommending BotAdmin promote themselves first
1 b . , and is - i ( to instance ) , return a Success
1 c . , 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 )
2 a . , and has no special flags ( - i / - f ) , return a Success
2 b . , and is - i ( to instance ) , return a Failure they are not allowed
2 c . , 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
3 a . , and has no special flags ( - i / - f ) , return a Success
3 b . , and is - i ( to instance ) , return a Success
3 c . , and is - f ( forced ) , return a Success
* /
2024-03-21 21:20:16 -04:00
}
}
2024-03-22 08:40:09 -04:00
// #[derive(Debug, PartialEq, Eq, Hash, Clone)]
#[ derive(Debug, Hash, Clone) ]
2024-03-02 10:24:13 -05:00
pub enum ModType {
BotModule ( String ) ,
}
2024-03-22 08:40:09 -04:00
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 { }
2024-03-20 23:20:46 -04:00
#[ derive(Debug, PartialEq, Eq, Hash, Clone) ]
pub enum ModGroup {
Core ,
Custom ,
}
2024-03-21 02:13:23 -04:00
#[ derive(Debug, PartialEq, Eq, Hash, Clone) ]
2024-03-01 23:36:37 -05:00
pub enum StatusLvl {
2023-12-21 00:48:09 -05:00
Instance ,
2024-03-21 02:13:23 -04:00
Ch ( ChType ) ,
2023-12-21 00:48:09 -05:00
}
2024-03-21 02:13:23 -04:00
#[ derive(Debug, PartialEq, Eq, Hash, Clone) ]
2024-03-20 23:35:56 -04:00
pub enum StatusType {
2023-12-21 00:48:09 -05:00
Enabled ( StatusLvl ) ,
Disabled ( StatusLvl ) ,
}
2024-02-04 14:28:37 -05:00
2024-02-25 10:40:54 -05:00
pub enum BotAction {
C ( BotCommand ) ,
2024-01-29 01:13:56 -05:00
L ( Listener ) ,
2024-02-25 10:40:54 -05:00
R ( Routine ) ,
2023-12-21 00:48:09 -05:00
}
2023-12-26 20:00:32 -05:00
2024-01-29 02:27:11 -05:00
impl BotAction {
2024-03-01 23:36:37 -05:00
pub async fn execute ( & self , m : BotAR , n : PrivmsgMessage ) {
2024-01-29 02:27:11 -05:00
match self {
2024-02-25 10:40:54 -05:00
BotAction ::L ( a ) = > a . execute ( m , n ) . await ,
BotAction ::C ( a ) = > a . execute ( m , n ) . await ,
2024-01-29 02:27:11 -05:00
_ = > ( ) ,
}
}
}
2024-02-04 14:28:37 -05:00
#[ async_trait ]
2024-02-25 10:40:54 -05:00
pub trait BotActionTrait {
async fn add_to_bot ( self , bot : BotInstance ) ;
async fn add_to_modmgr ( self , modmgr : Arc < ModulesManager > ) ;
2024-03-20 23:20:46 -04:00
async fn add_core_to_bot ( self , bot : BotInstance ) ;
async fn add_core_to_modmgr ( self , modmgr : Arc < ModulesManager > ) ;
2023-12-26 20:00:32 -05:00
}
2024-01-29 04:09:53 -05:00
pub struct BotCommand {
2024-02-25 10:40:54 -05:00
pub module : ModType ,
pub command : String , // command call name
pub alias : Vec < String > , // String of alternative names
pub exec_body : bot_actions ::actions_util ::ExecBody ,
pub help : String ,
pub required_roles : Vec < identity ::UserRole > ,
2024-01-29 04:09:53 -05:00
}
2024-02-25 10:40:54 -05:00
impl BotCommand {
2024-03-01 23:36:37 -05:00
pub async fn execute ( & self , m : BotAR , n : PrivmsgMessage ) {
( * self . exec_body ) ( m , n ) . await ;
2024-01-29 04:09:53 -05:00
}
}
2024-02-04 14:28:37 -05:00
#[ async_trait ]
2024-02-25 10:40:54 -05:00
impl BotActionTrait for BotCommand {
async fn add_to_bot ( self , bot : BotInstance ) {
2024-02-12 05:25:38 -05:00
self . add_to_modmgr ( bot . botmodules ) . await ;
2024-01-29 04:09:53 -05:00
}
2024-02-25 10:40:54 -05:00
async fn add_to_modmgr ( self , modmgr : Arc < ModulesManager > ) {
modmgr
. add_botaction ( self . module . clone ( ) , BotAction ::C ( self ) )
. await
2024-01-29 04:09:53 -05:00
}
2024-03-20 23:20:46 -04:00
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 < ModulesManager > ) {
modmgr
. add_core_act ( self . module . clone ( ) , BotAction ::C ( self ) )
. await
}
2024-01-29 04:09:53 -05:00
}
2024-02-25 10:40:54 -05:00
pub struct Listener {
pub module : ModType ,
pub name : String ,
pub exec_body : bot_actions ::actions_util ::ExecBody ,
pub help : String ,
2023-12-21 00:48:09 -05:00
}
2024-02-25 10:40:54 -05:00
impl Listener {
2024-03-01 23:36:37 -05:00
pub async fn execute ( & self , m : BotAR , n : PrivmsgMessage ) {
( self . exec_body ) ( m , n ) . await ;
2023-12-26 20:00:32 -05:00
}
}
2024-02-04 14:28:37 -05:00
#[ async_trait ]
2024-02-25 10:40:54 -05:00
impl BotActionTrait for Listener {
async fn add_to_bot ( self , bot : BotInstance ) {
2024-03-02 10:06:26 -05:00
botlog ::trace (
2024-02-25 10:40:54 -05:00
" Adding action to bot " ,
Some ( " BotModules > BotActionTrait > add_to_bot() " . to_string ( ) ) ,
None ,
) ;
2024-02-12 02:34:32 -05:00
self . add_to_modmgr ( bot . botmodules ) . await ;
2023-12-26 20:00:32 -05:00
}
2024-02-25 10:40:54 -05:00
async fn add_to_modmgr ( self , modmgr : Arc < ModulesManager > ) {
2024-03-02 10:06:26 -05:00
botlog ::trace (
2024-02-25 10:40:54 -05:00
" Adding action to module manager " ,
Some ( " BotModules > BotActionTrait > add_to_bot() " . to_string ( ) ) ,
None ,
) ;
2024-02-13 07:54:35 -05:00
2024-02-25 10:40:54 -05:00
modmgr
. add_botaction ( self . module . clone ( ) , BotAction ::L ( self ) )
. await ;
2023-12-26 20:00:32 -05:00
}
2024-03-20 23:20:46 -04:00
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 < ModulesManager > ) {
modmgr
. add_core_act ( self . module . clone ( ) , BotAction ::L ( self ) )
. await
}
2023-12-26 20:00:32 -05:00
}
2023-12-21 00:48:09 -05:00
#[ derive(Debug) ]
2024-03-01 23:36:37 -05:00
pub struct Routine { }
2023-12-21 00:48:09 -05:00
2024-02-25 10:40:54 -05:00
pub struct ModulesManager {
2024-03-20 23:20:46 -04:00
// statusdb: Arc<RwLock<HashMap<ModType, Vec<ModStatusType>>>>,
2024-03-21 00:11:24 -04:00
// statusdb: Arc<RwLock<HashMap<(ModType,ModGroup), Vec<StatusType>>>>,
statusdb : Arc < RwLock < HashMap < ModType , ( ModGroup , Vec < StatusType > ) > > > ,
2024-02-25 10:40:54 -05:00
pub botactions : Arc < RwLock < HashMap < ModType , Vec < BotAction > > > > ,
2023-12-21 00:48:09 -05:00
}
2024-02-18 15:23:58 -05:00
/*
statusdb
2024-02-25 10:40:54 -05:00
< HashMap
< ModType , < - - e . g . , BotModule ( String ::from ( " experiments001 " ) )
2024-02-18 15:23:58 -05:00
Vec < ModStatusType > < - - shows Enabled / Disabled per Status level
2024-02-25 10:40:54 -05:00
botactions
2024-02-18 15:23:58 -05:00
HashMap <
2024-02-25 10:40:54 -05:00
ModType , < - - e . g . , BotModule ( String ::from ( " experiments001 " ) )
2024-02-18 15:23:58 -05:00
Vec < BotAction > > BotCommand , Listener
* /
2024-02-25 10:40:54 -05:00
impl ModulesManager {
pub async fn init ( ) -> Arc < ModulesManager > {
2024-03-01 23:36:37 -05:00
let mgr = ModulesManager {
2024-03-02 11:55:16 -05:00
statusdb : Arc ::new ( RwLock ::new ( HashMap ::new ( ) ) ) ,
botactions : Arc ::new ( RwLock ::new ( HashMap ::new ( ) ) ) ,
2023-12-21 00:48:09 -05:00
} ;
2024-02-04 14:28:37 -05:00
// :: [x] initialize core modules
2024-03-02 12:21:18 -05:00
botlog ::trace (
2024-02-25 10:40:54 -05:00
" ModulesManager > init() > Adding modules " ,
2024-02-13 10:11:49 -05:00
Some ( " ModulesManager > init() " . to_string ( ) ) ,
2024-02-25 10:40:54 -05:00
None ,
2024-02-13 10:11:49 -05:00
) ;
2023-12-22 09:21:49 -05:00
2024-03-02 11:55:16 -05:00
let mgrarc = Arc ::new ( mgr ) ;
2024-03-02 12:21:18 -05:00
2024-03-02 11:55:16 -05:00
// 1. load core modules
crate ::core ::identity ::init ( Arc ::clone ( & mgrarc ) ) . await ;
// 2. load custom modules
crate ::custom ::init ( Arc ::clone ( & mgrarc ) ) . await ;
2024-02-25 10:40:54 -05:00
botlog ::trace (
" >> Modules Manager : End of Init " ,
2024-02-13 10:11:49 -05:00
Some ( " ModulesManager > init() " . to_string ( ) ) ,
2024-02-25 10:40:54 -05:00
None ,
2024-02-13 10:11:49 -05:00
) ;
2023-12-21 00:48:09 -05:00
2024-03-02 11:55:16 -05:00
mgrarc
2024-02-25 10:40:54 -05:00
}
2023-12-21 00:48:09 -05:00
2024-03-22 08:21:10 -04:00
pub async fn moduleslist ( & self ) -> HashMap < ModType , ModGroup >
{
// 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
}
2024-03-21 12:21:00 -04:00
pub async fn modstatus ( & self , in_module : ModType , in_chnl : ChType ) -> StatusType {
2023-12-21 00:48:09 -05:00
// Example usage : botmanager.modstatus(
// BotModule("GambaCore"),
// Channel("modulatingforce")
2024-02-25 10:40:54 -05:00
// )
// - The ModStatusType checks in the context of the given channel ,
2023-12-21 00:48:09 -05:00
// but also validates based on wheher the module is disabled at a bot instance
// level as well
2024-03-21 12:21:00 -04:00
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)
2023-12-21 00:48:09 -05:00
}
2024-03-21 00:05:52 -04:00
// 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<dyn Error>> {
// // sets the status based given ModSatusType
// // e.g., b.setstatus(BodModule("GambaCore"), Enabled(Channel("modulatingforce"))).expect("ERROR")
// Ok("")
// }
2024-03-21 21:20:16 -04:00
/*
exec_enable ( self , requestor , requestor_badge , trg_module , Channel ) -> ChangeResult
* /
pub async fn exec_enable (
& self ,
requestor : String ,
requestor_badge : Option < ChatBadge > ,
trg_module : ModType ,
// channel: Option<ChType>,
trg_level : StatusLvl ,
2024-03-22 17:06:09 -04:00
// bot: BotAR,
id : Arc < RwLock < IdentityManager > > ,
2024-03-21 21:20:16 -04:00
) -> 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 )
1 a . , and is not - i ( to instance ) , return a Failure recommending BotAdmin promote themselves first
1 b . , 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 )
2 a . , and is not - i ( to instance ) , return a Success
2 b . , 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
3 a . , and is not - i ( to instance ) , return a Success
3 b . , 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 )
1 a . , and is - i ( to instance ) , return a Success
1 b . , and is not - i ( to instance ) , return a Failure recommending BotAdmin promote themselves first
* /
2024-03-22 17:06:09 -04:00
// [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();
2024-03-21 21:20:16 -04:00
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 ;
2024-03-22 17:06:09 -04:00
// 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,
// );
2024-03-21 21:20:16 -04:00
if let Permissible ::Allow = admin_level_access {
if let Permissible ::Block = chnl_elevated_access {
2024-03-22 17:06:09 -04:00
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 ,
) ;
2024-03-21 21:20:16 -04:00
match trg_level {
StatusLvl ::Instance = > {
self . set_instance_enabled ( trg_module . clone ( ) ) . await ;
2024-03-22 17:06:09 -04:00
return ChangeResult ::Success ( " Enabled at Instance Level " . to_string ( ) ) ;
2024-03-21 21:20:16 -04:00
} ,
StatusLvl ::Ch ( _ ) = > {
2024-03-22 17:06:09 -04:00
return ChangeResult ::Failed ( " Promote yourself Temporarily First " . to_string ( ) ) ;
2024-03-21 21:20:16 -04:00
} ,
} ;
2024-03-22 17:06:09 -04:00
2024-03-21 21:20:16 -04:00
}
}
/*
[ ] 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 )
2 a . , and is - i ( to instance ) , return a Failure they are not allowed
2 b . , 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 = > {
2024-03-22 17:06:09 -04:00
return ChangeResult ::Failed ( " You're not allowed " . to_string ( ) ) ;
2024-03-21 21:20:16 -04:00
} ,
StatusLvl ::Ch ( in_chnl ) = > {
self . set_ch_enabled ( trg_module . clone ( ) , in_chnl ) . await ;
2024-03-22 17:06:09 -04:00
return ChangeResult ::Success ( " Enabled at Channel Level " . to_string ( ) ) ;
2024-03-21 21:20:16 -04:00
} ,
} ;
}
}
/*
[ ] 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
3 a . , and is not - i ( to instance ) , return a Success
3 b . , 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 ;
2024-03-22 17:06:09 -04:00
return ChangeResult ::Success ( " Enabled at Instance Level " . to_string ( ) ) ;
2024-03-21 21:20:16 -04:00
} ,
StatusLvl ::Ch ( in_chnl ) = > {
self . set_ch_enabled ( trg_module . clone ( ) , in_chnl ) . await ;
2024-03-22 17:06:09 -04:00
return ChangeResult ::Success ( " Enabled at Channel Level " . to_string ( ) ) ;
2024-03-21 21:20:16 -04:00
} ,
} ;
}
}
2024-03-22 17:06:09 -04:00
// 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 ( ) ) ;
} ,
} ;
}
}
2024-03-21 21:20:16 -04:00
// =======================
// =======================
// =======================
// /*
// 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))
// {
// }
2024-03-22 17:06:09 -04:00
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 ,
) ;
2024-03-21 21:20:16 -04:00
2024-03-22 17:06:09 -04:00
Log ::flush ( ) ;
2024-03-21 21:20:16 -04:00
2024-03-22 08:21:10 -04:00
ChangeResult ::Failed ( " ERROR : Not implemented yet " . to_string ( ) )
}
pub async fn exec_disable (
& self ,
requestor : String ,
requestor_badge : Option < ChatBadge > ,
trg_module : ModType ,
// channel: Option<ChType>,
trg_level : StatusLvl ,
force : bool ,
2024-03-22 17:06:09 -04:00
// bot: BotAR,
id : Arc < RwLock < IdentityManager > > ,
2024-03-22 08:21:10 -04:00
) -> 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 )
1 a . , and has no special flags ( - i / - f ) , return a Failure recommending BotAdmin promote themselves first
1 b . , and is - i ( to instance ) , return a Success
1 c . , 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 )
2 a . , and has no special flags ( - i / - f ) , return a Success
2 b . , and is - i ( to instance ) , return a Failure they are not allowed
2 c . , 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
3 a . , and has no special flags ( - i / - f ) , return a Success
3 b . , and is - i ( to instance ) , return a Success
3 c . , and is - f ( forced ) , return a Success
* /
2024-03-22 17:06:09 -04:00
// [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 ( ) ) ;
}
2024-03-22 08:21:10 -04:00
2024-03-22 17:06:09 -04:00
// let botlock = bot.read().await;
// let id = botlock.get_identity();
2024-03-22 08:21:10 -04:00
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 )
1 a . , and is - f ( forced ) , return a Success
1 b . , and is - i ( to instance ) , return a Success
1 c . , 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 ;
2024-03-22 17:06:09 -04:00
return ChangeResult ::Success ( " Disabled at Instance Level " . to_string ( ) ) ;
2024-03-22 08:21:10 -04:00
} ,
StatusLvl ::Ch ( _ ) = > {
2024-03-22 17:06:09 -04:00
return ChangeResult ::Failed ( " Promote yourself Temporarily First " . to_string ( ) ) ;
2024-03-22 08:21:10 -04:00
} ,
} ;
}
}
}
/*
[ ] 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 )
2 a . , and is - f ( forced ) , return a Failure they are not allowed
2 b . , and is - i ( to instance ) , return a Failure they are not allowed
2 c . , 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 = > {
2024-03-22 17:06:09 -04:00
return ChangeResult ::Failed ( " You're not allowed " . to_string ( ) ) ;
2024-03-22 08:21:10 -04:00
} ,
StatusLvl ::Ch ( in_chnl ) = > {
self . set_ch_disabled ( trg_module . clone ( ) , in_chnl ) . await ;
2024-03-22 17:06:09 -04:00
return ChangeResult ::Success ( " Disabled at Channel Level " . to_string ( ) ) ;
2024-03-22 08:21:10 -04:00
} ,
} ;
}
}
}
/*
[ ] 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
3 a . , and is - f ( forced ) , return a Success
3 b . , and is - i ( to instance ) , return a Success
3 c . , 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 ;
2024-03-22 17:06:09 -04:00
return ChangeResult ::Success ( " Disabled at Instance Level " . to_string ( ) ) ;
2024-03-22 08:21:10 -04:00
} ,
StatusLvl ::Ch ( in_chnl ) = > {
self . set_ch_disabled ( trg_module . clone ( ) , in_chnl ) . await ;
2024-03-22 17:06:09 -04:00
return ChangeResult ::Success ( " Disabled at Channel Level " . to_string ( ) ) ;
2024-03-22 08:21:10 -04:00
} ,
} ;
}
}
}
2024-03-22 17:06:09 -04:00
// 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 ( ) ) ;
} ,
} ;
}
}
2024-03-22 08:21:10 -04:00
ChangeResult ::Failed ( " ERROR : Not implemented yet " . to_string ( ) )
2024-03-21 21:20:16 -04:00
}
2024-03-21 02:13:23 -04:00
pub async fn set_instance_disabled ( & self , in_module : ModType ) -> ( StatusType , ChangeResult ) {
2024-03-21 00:05:52 -04:00
// at Instance level
// - If core module, do nothing
2024-03-21 02:13:23 -04:00
// 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 ) ,
2024-03-21 12:21:00 -04:00
ChangeResult ::Success ( " Set Disabled at Instance " . to_string ( ) )
2024-03-21 02:13:23 -04:00
)
} ,
}
// (StatusType::Disabled(StatusLvl::Instance),ChangeResult::NoChange("Nothing needed".to_string()))
2023-12-21 00:48:09 -05:00
}
2024-03-21 02:13:23 -04:00
pub async fn force_disable ( & self , in_module : ModType ) -> ( StatusType , ChangeResult ) {
// Disables the module at Instance level, and removes all Enabled at Channel level
2024-03-21 00:05:52 -04:00
// - Bot Moderators MUST Re-enable if they were enabled before
// - If core module, do nothing
2024-03-21 02:13:23 -04:00
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 ) ,
2024-03-21 09:37:08 -04:00
ChangeResult ::Success ( " Forced Disabled " . to_string ( ) )
2024-03-21 02:13:23 -04:00
)
} ,
}
// (StatusType::Disabled(StatusLvl::Instance),ChangeResult::NoChange("Nothing needed".to_string()))
2023-12-21 00:48:09 -05:00
}
2024-03-21 12:21:00 -04:00
pub async fn set_instance_enabled ( & self , in_module : ModType ) -> ( StatusType , ChangeResult ) {
2024-03-21 00:05:52 -04:00
// at Instance level
// - If core module, do nothing
2024-03-21 12:21:00 -04:00
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()))
2024-03-21 00:05:52 -04:00
}
2024-03-21 12:21:00 -04:00
pub async fn set_ch_disabled ( & self , in_module : ModType , in_chnl : ChType ) -> ( StatusType , ChangeResult ) {
2024-03-21 00:05:52 -04:00
// at Instance level
// - If core module, do nothing
2024-03-21 12:21:00 -04:00
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()))
2024-03-21 00:05:52 -04:00
}
2024-03-21 12:21:00 -04:00
pub async fn set_ch_enabled ( & self , in_module : ModType , in_chnl : ChType ) -> ( StatusType , ChangeResult ) {
2024-03-21 00:05:52 -04:00
// at Instance level
// - If core module, do nothing
2024-03-21 12:21:00 -04:00
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()))
2024-03-21 00:05:52 -04:00
}
2024-02-25 10:40:54 -05:00
pub async fn add_botaction ( & self , in_module : ModType , in_action : BotAction ) {
2024-03-20 23:20:46 -04:00
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 ;
}
2024-03-21 02:13:23 -04:00
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 ) ) ,
}
}
}
2024-03-20 23:20:46 -04:00
async fn int_add_botaction ( & self , in_module : ModType , in_modgroup : ModGroup , in_action : BotAction ) {
2024-02-25 10:40:54 -05:00
botlog ::trace (
" Add botaction called " ,
Some ( " ModulesManager > init() " . to_string ( ) ) ,
None ,
2024-02-13 10:11:49 -05:00
) ;
2023-12-21 20:11:32 -05:00
/*
adds a BotAction to the Modules Manager - This will require a BotModule passed as well
This will including the logic of a valid add
If it fails to add , either a PANIC or some default coded business rules that handles the botaction add
For example , this Should PANIC ( ideally Panic ? ) if it does not successfully add a bot module
- - Being unable to indicates a Programming / Developer code logic issue : They cannot add botactions that already exists ( ? )
- - In particular to BotCommands , which must have Unique command call names and aliases that to not conflict with any other
already BotCommand added name or alias
Other types might be fine ? For example , if 2 modules have their own listeners but each have the name " targetchatter " ,
2024-02-25 10:40:54 -05:00
both would be called separately , even if they both have the same or different logic
2023-12-21 20:11:32 -05:00
* /
2024-02-25 10:40:54 -05:00
// [x] Before Adding, validate the following :
// - If BotAction to Add is a BotCommand , In Module Manager DB (botactions),
2023-12-21 20:11:32 -05:00
// Check All Other BotAction Command Names & Aliases to ensure they don't conflict
2024-02-25 10:40:54 -05:00
async fn find_conflict_module ( mgr : & ModulesManager , act : & BotAction ) -> Option < ModType > {
2024-01-29 04:28:58 -05:00
if let BotAction ::C ( incmd ) = act {
2024-03-02 11:55:16 -05:00
let actdb = mgr . botactions . read ( ) . await ;
2024-03-02 12:21:18 -05:00
2024-03-02 11:55:16 -05:00
for ( module , moduleactions ) in & ( * actdb ) {
2024-01-29 04:28:58 -05:00
for modact in moduleactions . iter ( ) {
if let BotAction ::C ( dbcmd ) = & modact {
// At this point, there is an command incmd and looked up dbcmd
2023-12-21 20:11:32 -05:00
2024-01-29 04:28:58 -05:00
// [x] check if given botcommand c.command:String conflicts with any in botactions
2023-12-21 20:11:32 -05:00
2024-01-29 04:28:58 -05:00
if incmd . command . to_lowercase ( ) = = dbcmd . command . to_lowercase ( ) {
// Returning State - with the identified module
return Some ( module . clone ( ) ) ; // works
2024-02-25 10:40:54 -05:00
}
2023-12-21 20:11:32 -05:00
2024-01-29 04:28:58 -05:00
for a in & dbcmd . alias {
if incmd . command . to_lowercase ( ) = = a . to_lowercase ( ) {
// Returning State - with the identified module
2024-03-02 12:21:18 -05:00
2024-01-29 04:28:58 -05:00
return Some ( module . clone ( ) ) ; // works
2024-02-25 10:40:54 -05:00
}
}
2023-12-21 20:11:32 -05:00
2024-01-29 04:28:58 -05:00
// [x] Then do the same check except for each c.alias
2023-12-21 20:11:32 -05:00
2024-01-29 04:28:58 -05:00
for inalias in & incmd . alias {
if inalias . to_lowercase ( ) = = dbcmd . command . to_lowercase ( ) {
// Returning State - with the identified module
2024-03-02 12:21:18 -05:00
2024-01-29 04:28:58 -05:00
return Some ( module . clone ( ) ) ; // works
2024-02-25 10:40:54 -05:00
}
2023-12-21 20:11:32 -05:00
2024-01-29 04:28:58 -05:00
for a in & dbcmd . alias {
if inalias . to_lowercase ( ) = = a . to_lowercase ( ) {
// Returning State - with the identified module
2024-03-02 12:21:18 -05:00
2024-01-29 04:28:58 -05:00
return Some ( module . clone ( ) ) ; // works
2024-02-25 10:40:54 -05:00
}
}
2024-01-29 04:28:58 -05:00
}
}
}
}
}
2023-12-21 20:11:32 -05:00
// for all other scenarios (e.g., Listener, Routine), find no conflicts
None
}
2024-03-01 23:36:37 -05:00
if let Some ( c ) = find_conflict_module ( self , & in_action ) . await {
panic! (
2024-02-25 10:40:54 -05:00
" ERROR: Could not add module; there was a conflict with existing module {:?} " ,
c
2024-03-01 23:36:37 -05:00
)
2023-12-21 20:11:32 -05:00
}
2024-03-21 02:13:23 -04:00
// let mut dbt = self.statusdb.write().await;
// //
// let statusvector = dbt.entry(in_module.clone()).or_insert((in_modgroup.clone(),Vec::new()));
2023-12-21 17:22:40 -05:00
2024-03-21 02:13:23 -04:00
// 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)),
// }
2024-03-20 23:32:05 -04:00
// statusvector.push(ModStatusType::Enabled(StatusLvl::Instance)); // Pushes the Module as Enabled at Instance Level
2023-12-21 17:22:40 -05:00
2024-03-21 02:13:23 -04:00
self . affirm_in_statusdb ( in_module . clone ( ) , in_modgroup ) . await ;
2024-02-12 01:25:12 -05:00
let mut a = self . botactions . write ( ) . await ;
2024-03-02 12:21:18 -05:00
let modactions = a . entry ( in_module . clone ( ) ) . or_insert ( Vec ::new ( ) ) ;
2023-12-21 17:22:40 -05:00
2023-12-21 20:11:32 -05:00
modactions . push ( in_action ) ;
2023-12-21 17:22:40 -05:00
2024-02-25 10:40:54 -05:00
botlog ::trace (
2024-03-02 12:21:18 -05:00
format! (
" Modules Manager> add_botaction called - botactions size : {} " ,
modactions . len ( )
)
. as_str ( ) ,
2024-02-25 10:40:54 -05:00
Some ( " ModulesManager > init() " . to_string ( ) ) ,
None ,
2024-02-13 10:11:49 -05:00
) ;
2023-12-21 17:22:40 -05:00
}
2024-03-01 23:36:37 -05:00
fn _statuscleanup ( & self , _ : Option < ChType > ) {
2024-02-25 10:40:54 -05:00
// internal cleans up statusdb . For example :
2023-12-21 12:10:50 -05:00
// - remove redudancies . If we see several Enabled("m"), only keep 1x
// - Clarify Conflict. If we see Enabled("m") and Disabled("m") , we remove Enabled("m") and keep Disabled("m")
// the IDEAL is that this is ran before every read/update operation to ensure quality
// Option<ChType> can pass Some(Channel("m")) (as an example) so statuscleanup only works on the given channel
// Passing None to chnl may be a heavy operation, as this will review and look at the whole table
}
2024-02-25 10:40:54 -05:00
}
2024-03-21 14:01:54 -04:00
// =====================
// =====================
// =====================
// =====================
// =====================
#[ cfg(test) ]
mod core_modulesmanager {
use casual_logger ::Log ;
use casual_logger ::Extension ;
use super ::* ;
2024-03-22 08:21:10 -04:00
#[ test ]
2024-03-22 08:40:09 -04:00
fn case_insensitive_test ( ) {
2024-03-22 08:21:10 -04:00
Log ::set_file_ext ( Extension ::Log ) ;
assert_eq! (
2024-03-22 17:06:09 -04:00
BotModule ( " TEST " . to_string ( ) ) ,
BotModule ( " test " . to_string ( ) )
2024-03-22 08:21:10 -04:00
) ;
}
2024-03-21 14:01:54 -04:00
/*
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 ;
}
2024-03-22 17:06:09 -04:00
/*
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 < ModulesManager > )
{
/*
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<ChatBadge>,
// [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<RwLock<IdentityManager>>,
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<ChatBadge>,
// 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 < ChatBadge > ,
trg_module : ModType ,
trg_level : StatusLvl ,
id : Arc < RwLock < IdentityManager > > ,
) -> 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<ChatBadge>,
// [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<RwLock<IdentityManager>>,
// 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<ChatBadge>,
// 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 ( ) ) ) ;
}
2024-03-21 14:01:54 -04:00
}