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 {
2024-03-22 15:55:56 -04:00
statusdb : HashMap < BotModule , Vec < ModStatusType > > ,
botactions : HashMap < BotModule , Vec < BotAction > > ,
2023-12-22 09:52:01 -05:00
}
2024-03-22 15:55:56 -04:00
- statusdb : HashMap < BotModule , Vec < ModStatusType > > - Defines Modules and their ModStatusType ( e . g . , Enabled at an Instance level , Disabled at a Channel Level )
- botactions : HashMap < BotModule , 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 ;
use std ::sync ::Arc ;
2023-12-21 00:48:09 -05:00
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-24 14:09:08 -04:00
// use self::bot_actions::actions_util::BotAR;
use crate ::core ::bot_actions ::BotAR ;
2024-03-21 21:20:16 -04:00
use crate ::core ::bot_actions ::actions_util ;
2024-03-24 14:38:09 -04:00
use crate ::core ::bot_actions ::ExecBodyParams ;
2024-03-22 15:55:56 -04:00
use crate ::core ::botinstance ::{ BotInstance , Channel , 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-22 15:55:56 -04:00
2024-03-22 20:18:02 -04:00
use std ::hash ::{ Hash , Hasher } ;
2024-03-21 21:20:16 -04:00
use super ::identity ::ChatBadge ;
2024-03-21 00:05:52 -04:00
2024-03-21 21:20:16 -04:00
pub async fn init ( mgr : Arc < ModulesManager > ) {
2024-03-22 15:55:56 -04:00
const OF_CMD_CHANNEL :Channel = Channel ( String ::new ( ) ) ;
2024-03-21 21:20:16 -04:00
// 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 ;
2024-03-24 14:38:09 -04:00
// async fn cmd_enable(bot: BotAR, msg: PrivmsgMessage) {
async fn cmd_enable ( params : ExecBodyParams ) {
2024-03-21 21:20:16 -04:00
/*
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-24 16:59:50 -04:00
/*
Get parent module
* /
let params_clone = Arc ::clone ( & params . parent_act ) ;
let actlock = params_clone . read ( ) . await ;
let act = & ( * actlock ) ;
let parent_module = match act {
BotAction ::C ( c ) = > Some ( & ( * c ) . module ) ,
BotAction ::L ( l ) = > Some ( & ( * l ) . module ) ,
_ = > None ,
} ;
2024-03-21 21:20:16 -04:00
2024-03-22 08:21:10 -04:00
2024-03-22 18:02:31 -04:00
// [x] Unwraps arguments from message
2024-03-22 08:21:10 -04:00
let ( arg1 , arg2 ) = {
2024-03-24 14:38:09 -04:00
let mut argv = params . msg . message_text . split ( ' ' ) ;
2024-03-22 08:21:10 -04:00
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 > ,
2024-03-22 15:55:56 -04:00
trg_module : BotModule ,
// channel: Option<Channel>,
2024-03-22 08:21:10 -04:00
trg_level : StatusLvl ,
bot : BotAR ,
) -> ChangeResult
2024-03-21 21:20:16 -04:00
* /
2024-03-22 18:02:31 -04:00
// [x] requestor: String,
2024-03-24 14:38:09 -04:00
let requestor = params . msg . clone ( ) . sender . name ;
2024-03-22 08:21:10 -04:00
2024-03-22 18:02:31 -04:00
// [x] requestor_badge: Option<ChatBadge>,
2024-03-22 08:21:10 -04:00
let mut requestor_badge_mut : Option < ChatBadge > = None ;
2024-03-24 14:38:09 -04:00
for b in & params . msg . badges {
2024-03-22 08:21:10 -04:00
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 ;
2024-03-22 15:55:56 -04:00
// [x] trg_module: BotModule,
// - [x] Need to validate an actual BotModule - otherwise, fail or exit the cmd
2024-03-22 08:21:10 -04:00
let trg_module = if ( arg1 = = Some ( " -i " ) ) | | ( arg1 = = Some ( " -f " ) ) { arg2 } else { arg1 } ;
2024-03-22 18:02:31 -04:00
// if no trg_module was passed
2024-03-22 20:18:02 -04:00
// if let None = trg_module {
if trg_module . is_none ( ) {
2024-03-22 08:21:10 -04:00
2024-03-24 14:38:09 -04:00
let botlock = params . bot . read ( ) . await ;
2024-03-22 18:02:31 -04:00
let outmsg = " uuh You need to pass a module " ;
2024-03-22 08:21:10 -04:00
2024-03-22 18:02:31 -04:00
botlog ::debug (
outmsg ,
Some ( " botmodules.rs > cmd_enable() " . to_string ( ) ) ,
2024-03-24 14:38:09 -04:00
Some ( & params . msg ) ,
2024-03-22 18:02:31 -04:00
) ;
2024-03-24 16:59:50 -04:00
// Only call Say if there is a parent module passed
if parent_module . is_some ( ) {
botlock
. botmgrs
. chat
. say_in_reply_to ( & params . msg , outmsg . to_string ( ) , parent_module . unwrap ( ) . clone ( ) )
. await ;
}
2024-03-22 08:21:10 -04:00
2024-03-22 18:02:31 -04:00
return ;
2024-03-22 08:21:10 -04:00
}
2024-03-22 18:02:31 -04:00
// [x] trg_level: StatusLvl,
2024-03-22 08:21:10 -04:00
2024-03-24 14:38:09 -04:00
let currchnl = params . msg . channel_login . to_lowercase ( ) ;
2024-03-22 08:21:10 -04:00
let trg_level =
2024-03-22 20:18:02 -04:00
if arg1 = = Some ( " -i " ) | | arg1 = = Some ( " -f " ) { StatusLvl ::Instance }
// else if arg1 == Some("-f") { StatusLvl::Instance }
2024-03-22 15:55:56 -04:00
else { StatusLvl ::Ch ( Channel ( currchnl ) ) }
2024-03-22 08:21:10 -04:00
;
2024-03-22 18:02:31 -04:00
2024-03-24 14:38:09 -04:00
let botlock = params . bot . read ( ) . await ;
2024-03-22 18:02:31 -04:00
let modmgr = Arc ::clone ( & botlock . botmodules ) ;
let id = botlock . get_identity ( ) ;
2024-03-22 08:21:10 -04:00
2024-03-22 18:02:31 -04:00
// modmgr.exec_enable(requestor, requestor_badge, trg_module, trg_level, id)
let rslt = modmgr . exec_enable (
requestor ,
requestor_badge ,
2024-03-22 15:55:56 -04:00
BotModule ( trg_module . unwrap ( ) . to_string ( ) ) ,
2024-03-22 18:02:31 -04:00
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 ) ,
} ;
2024-03-22 08:21:10 -04:00
2024-03-24 16:59:50 -04:00
// Only call Say if there is a parent module passed
if parent_module . is_some ( ) {
botlock
. botmgrs
. chat
. say_in_reply_to ( & params . msg , outmsg . to_string ( ) , parent_module . unwrap ( ) . clone ( ) )
. await ;
}
2024-03-22 08:21:10 -04:00
2024-03-22 18:16:41 -04:00
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 ;
2024-03-24 14:38:09 -04:00
// async fn cmd_disable(bot: BotAR, msg: PrivmsgMessage) {
async fn cmd_disable ( params : ExecBodyParams ) {
2024-03-21 21:20:16 -04:00
/*
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-24 16:59:50 -04:00
/*
[ x ] Get the parent module
* /
let params_clone = Arc ::clone ( & params . parent_act ) ;
let actlock = params_clone . read ( ) . await ;
let act = & ( * actlock ) ;
let parent_module = match act {
BotAction ::C ( c ) = > Some ( & ( * c ) . module ) ,
BotAction ::L ( l ) = > Some ( & ( * l ) . module ) ,
_ = > None ,
} ;
2024-03-22 18:16:41 -04:00
// [x] Unwraps arguments from message
let ( arg1 , arg2 ) = {
2024-03-24 14:38:09 -04:00
let mut argv = params . msg . message_text . split ( ' ' ) ;
2024-03-22 18:16:41 -04:00
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 < ChatBadge > ,
2024-03-22 15:55:56 -04:00
trg_module : BotModule ,
// channel: Option<Channel>,
2024-03-22 18:16:41 -04:00
trg_level : StatusLvl ,
force : bool ,
// bot: BotAR,
id : Arc < RwLock < IdentityManager > > ,
) -> ChangeResult
* /
// [x] requestor: String,
2024-03-24 14:38:09 -04:00
let requestor = params . msg . clone ( ) . sender . name ;
2024-03-22 18:16:41 -04:00
// [x] requestor_badge: Option<ChatBadge>,
let mut requestor_badge_mut : Option < ChatBadge > = None ;
2024-03-24 14:38:09 -04:00
for b in & params . msg . badges {
2024-03-22 18:16:41 -04:00
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 ;
2024-03-22 15:55:56 -04:00
// [x] trg_module: BotModule,
// - [x] Need to validate an actual BotModule - otherwise, fail or exit the cmd
2024-03-22 18:16:41 -04:00
let trg_module = if ( arg1 = = Some ( " -i " ) ) | | ( arg1 = = Some ( " -f " ) ) { arg2 } else { arg1 } ;
// if no trg_module was passed
2024-03-22 20:18:02 -04:00
// if let None = trg_module {
if trg_module . is_none ( ) {
2024-03-22 18:16:41 -04:00
2024-03-24 14:38:09 -04:00
let botlock = params . bot . read ( ) . await ;
2024-03-22 18:16:41 -04:00
let outmsg = " uuh You need to pass a module " ;
botlog ::debug (
outmsg ,
Some ( " botmodules.rs > cmd_disable() " . to_string ( ) ) ,
2024-03-24 14:38:09 -04:00
Some ( & params . msg ) ,
2024-03-22 18:16:41 -04:00
) ;
2024-03-24 16:59:50 -04:00
// let params_clone = Arc::clone(¶ms.parent_act);
// let actlock = params_clone.read().await;
// let act = &(*actlock);
// let parent_module = match act {
// BotAction::C(c) => Some(&(*c).module),
// BotAction::L(l) => Some(&(*l).module),
// _ => None,
// };
// Only call Say if there is a parent module passed
if parent_module . is_some ( ) {
botlock
2024-03-22 18:16:41 -04:00
. botmgrs
. chat
2024-03-24 16:59:50 -04:00
. say_in_reply_to ( & params . msg , outmsg . to_string ( ) , parent_module . unwrap ( ) . clone ( ) )
2024-03-22 18:16:41 -04:00
. await ;
2024-03-24 16:59:50 -04:00
}
2024-03-22 18:16:41 -04:00
return ;
}
// [x] trg_level: StatusLvl,
2024-03-24 14:38:09 -04:00
let currchnl = params . msg . channel_login . to_lowercase ( ) ;
2024-03-22 18:16:41 -04:00
let trg_level =
2024-03-22 20:18:02 -04:00
if arg1 = = Some ( " -i " ) | | arg1 = = Some ( " -f " ) { StatusLvl ::Instance }
// else if arg1 == Some("-f") { StatusLvl::Instance }
2024-03-22 15:55:56 -04:00
else { StatusLvl ::Ch ( Channel ( currchnl ) ) }
2024-03-22 18:16:41 -04:00
;
2024-03-24 14:38:09 -04:00
let botlock = params . bot . read ( ) . await ;
2024-03-22 18:16:41 -04:00
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 ,
2024-03-22 15:55:56 -04:00
BotModule ( trg_module . unwrap ( ) . to_string ( ) ) ,
2024-03-22 18:16:41 -04:00
trg_level ,
force ,
id ) . await ;
2024-03-22 18:49:07 -04:00
2024-03-22 18:16:41 -04:00
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 ) ,
} ;
2024-03-24 16:59:50 -04:00
// let actlock = params.parent_act.read().await;
// let act = *actlock;
// let parent_module = match act {
// BotAction::C(c) => Some(c.module),
// BotAction::L(l) => Some(l.module),
// _ => None,
// };
// let params_clone = Arc::clone(¶ms.parent_act);
// let actlock = params_clone.read().await;
// let act = &(*actlock);
// let parent_module = match act {
// BotAction::C(c) => Some(&(*c).module),
// BotAction::L(l) => Some(&(*l).module),
// _ => None,
// };
// Only call Say if there is a parent module passed
if parent_module . is_some ( ) {
botlock
. botmgrs
. chat
. say_in_reply_to ( & params . msg , outmsg . to_string ( ) , parent_module . unwrap ( ) . clone ( ) )
. await ;
}
2024-03-22 18:16:41 -04:00
2024-03-21 21:20:16 -04:00
}
}
2024-03-22 20:18:02 -04:00
#[ derive(Debug, Clone) ]
2024-03-23 14:00:20 -04:00
pub struct BotModule ( pub String ) ;
2024-03-23 13:33:45 -04:00
2024-03-22 15:55:56 -04:00
impl PartialEq for BotModule {
2024-03-22 08:40:09 -04:00
fn eq ( & self , other : & Self ) -> bool {
let BotModule ( name1 ) = self . clone ( ) ;
let BotModule ( name2 ) = other . clone ( ) ;
name1 . to_lowercase ( ) = = name2 . to_lowercase ( )
}
}
2024-03-22 15:55:56 -04:00
impl Eq for BotModule { }
2024-03-22 08:40:09 -04:00
2024-03-22 15:55:56 -04:00
impl Hash for BotModule {
2024-03-22 20:18:02 -04:00
fn hash < H : Hasher > ( & self , state : & mut H ) {
// self.id.hash(state);
// self.phone.hash(state);
let BotModule ( name ) = self . clone ( ) ;
name . to_lowercase ( ) . hash ( state ) ;
}
}
2024-03-22 08:40:09 -04:00
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-22 15:55:56 -04:00
Ch ( Channel ) ,
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-24 14:38:09 -04:00
// pub async fn execute(&self, m: BotAR, n: PrivmsgMessage) {
pub async fn execute ( & self , params : ExecBodyParams ) {
2024-01-29 02:27:11 -05:00
match self {
2024-03-24 14:38:09 -04:00
BotAction ::L ( a ) = > a . execute ( params ) . await ,
BotAction ::C ( a ) = > a . execute ( params ) . 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-03-22 15:55:56 -04:00
pub module : BotModule ,
2024-02-25 10:40:54 -05:00
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-24 14:38:09 -04:00
// pub async fn execute(&self, m: BotAR, n: PrivmsgMessage) {
pub async fn execute ( & self , params : ExecBodyParams ) {
( * self . exec_body ) ( params ) . 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 {
2024-03-22 15:55:56 -04:00
pub module : BotModule ,
2024-02-25 10:40:54 -05:00
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-24 14:38:09 -04:00
// pub async fn execute(&self, m: BotAR, n: PrivmsgMessage) {
pub async fn execute ( & self , params : ExecBodyParams ) {
( self . exec_body ) ( params ) . 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-03-22 20:18:02 -04:00
type StatusdbEntry = ( ModGroup , Vec < StatusType > ) ;
2024-03-24 15:46:08 -04:00
type ModuleActions = Vec < Arc < RwLock < BotAction > > > ;
2024-03-22 20:18:02 -04:00
2024-02-25 10:40:54 -05:00
pub struct ModulesManager {
2024-03-22 15:55:56 -04:00
statusdb : Arc < RwLock < HashMap < BotModule , StatusdbEntry > > > ,
2024-03-24 15:46:08 -04:00
pub botactions : Arc < RwLock < HashMap < BotModule , ModuleActions > > > ,
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
2024-03-22 15:55:56 -04:00
< BotModule , < - - 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-03-22 15:55:56 -04:00
BotModule , < - - 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 ;
2024-03-22 18:49:07 -04:00
crate ::core ::botmodules ::init ( Arc ::clone ( & mgrarc ) ) . await ;
2024-03-02 11:55:16 -05:00
// 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
2024-03-22 15:55:56 -04:00
pub async fn moduleslist ( & self ) -> HashMap < BotModule , ModGroup >
2024-03-22 08:21:10 -04:00
{
// 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-22 15:55:56 -04:00
pub async fn modstatus ( & self , in_module : BotModule , in_chnl : Channel ) -> 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 = > {
/*
[ 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 21:20:16 -04:00
pub async fn exec_enable (
& self ,
requestor : String ,
requestor_badge : Option < ChatBadge > ,
2024-03-22 15:55:56 -04:00
trg_module : BotModule ,
2024-03-21 21:20:16 -04:00
trg_level : StatusLvl ,
2024-03-22 17:06:09 -04:00
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
* /
/*
2024-03-22 21:06:15 -04:00
[ x ] 1. If CmdSender is BotAdmin but not ( Mod , SupMod , Broadcaster )
2024-03-21 21:20:16 -04:00
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 modlist = self . moduleslist ( ) . await ;
let rslt = modlist . get ( & trg_module ) ;
2024-03-22 20:18:02 -04:00
if rslt . is_none ( ) {
2024-03-22 17:06:09 -04:00
return ChangeResult ::Failed ( " Module doesn't exist " . to_string ( ) ) ;
}
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 ( ) {
2024-03-22 15:55:56 -04:00
StatusLvl ::Instance = > Channel ( requestor . to_lowercase ( ) ) ,
2024-03-21 21:20:16 -04:00
StatusLvl ::Ch ( a ) = > a ,
} ;
2024-03-22 15:55:56 -04:00
const OF_CMD_CHANNEL :Channel = Channel ( String ::new ( ) ) ;
2024-03-21 21:20:16 -04:00
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
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
}
}
/*
2024-03-22 21:06:15 -04:00
[ x ] 2. If CmdSender not a BotAdmin but is ( Mod , SupMod , Broadcaster )
2024-03-21 21:20:16 -04:00
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
} ,
} ;
}
}
/*
2024-03-22 21:06:15 -04:00
[ x ] 3. If CmdSender is ( Mod , SupMod , Broadcaster ) and a BotAdmin
2024-03-21 21:20:16 -04:00
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
// =======================
// =======================
// =======================
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 > ,
2024-03-22 15:55:56 -04:00
trg_module : BotModule ,
2024-03-22 08:21:10 -04:00
trg_level : StatusLvl ,
force : bool ,
2024-03-22 17:06:09 -04:00
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 modlist = self . moduleslist ( ) . await ;
let rslt = modlist . get ( & trg_module ) ;
2024-03-22 20:18:02 -04:00
if rslt . is_none ( ) {
2024-03-22 17:06:09 -04:00
return ChangeResult ::Failed ( " Module doesn't exist " . to_string ( ) ) ;
}
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 ( ) {
2024-03-22 15:55:56 -04:00
StatusLvl ::Instance = > Channel ( requestor . to_lowercase ( ) ) ,
2024-03-22 08:21:10 -04:00
StatusLvl ::Ch ( a ) = > a ,
} ;
2024-03-22 15:55:56 -04:00
const OF_CMD_CHANNEL :Channel = Channel ( String ::new ( ) ) ;
2024-03-22 08:21:10 -04:00
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 21:06:15 -04:00
[ x ] 1. If CmdSender is BotAdmin but not ( Mod , SupMod , Broadcaster )
2024-03-22 08:21:10 -04:00
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
} ,
} ;
}
}
}
/*
2024-03-22 21:06:15 -04:00
[ 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 )
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
2024-03-22 08:21:10 -04:00
* /
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
} ,
} ;
}
}
}
/*
2024-03-22 21:06:15 -04:00
[ 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
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
2024-03-22 08:21:10 -04:00
* /
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-22 15:55:56 -04:00
pub async fn set_instance_disabled ( & self , in_module : BotModule ) -> ( 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
let mut dbt = self . statusdb . write ( ) . await ;
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-22 15:55:56 -04:00
pub async fn force_disable ( & self , in_module : BotModule ) -> ( StatusType , ChangeResult ) {
2024-03-21 02:13:23 -04:00
// 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 ( 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
2024-03-22 20:18:02 -04:00
} else {
matches! ( ( * x ) . clone ( ) , StatusType ::Enabled ( StatusLvl ::Ch ( _ ) ) )
}
2024-03-21 02:13:23 -04:00
)
{
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-22 15:55:56 -04:00
pub async fn set_instance_enabled ( & self , in_module : BotModule ) -> ( 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 ( 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-22 15:55:56 -04:00
pub async fn set_ch_disabled ( & self , in_module : BotModule , in_chnl : Channel ) -> ( 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 ( 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-22 15:55:56 -04:00
pub async fn set_ch_enabled ( & self , in_module : BotModule , in_chnl : Channel ) -> ( 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 ( 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-03-22 15:55:56 -04:00
pub async fn add_botaction ( & self , in_module : BotModule , in_action : BotAction ) {
2024-03-20 23:20:46 -04:00
self . int_add_botaction ( in_module , ModGroup ::Custom , in_action ) . await ;
}
2024-03-22 15:55:56 -04:00
pub async fn add_core_act ( & self , in_module : BotModule , in_action : BotAction ) {
2024-03-20 23:20:46 -04:00
self . int_add_botaction ( in_module , ModGroup ::Core , in_action ) . await ;
}
2024-03-21 02:13:23 -04:00
2024-03-22 15:55:56 -04:00
pub async fn affirm_in_statusdb ( & self , in_module :BotModule , in_modgroup : ModGroup ) {
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 ( ) ) ) ;
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-22 15:55:56 -04:00
async fn int_add_botaction ( & self , in_module : BotModule , 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-03-22 15:55:56 -04:00
async fn find_conflict_module ( mgr : & ModulesManager , act : & BotAction ) -> Option < BotModule > {
2024-03-24 15:46:08 -04:00
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-03-24 15:46:08 -04:00
// for modact in moduleactions.iter() {
for modact_prelock in moduleactions . iter ( ) {
let modact = modact_prelock . read ( ) . await ;
// if let BotAction::C(dbcmd) = &modact {
if let BotAction ::C ( dbcmd ) = & ( * modact ) {
2024-01-29 04:28:58 -05:00
// 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
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
2024-03-24 15:46:08 -04:00
modactions . push ( Arc ::new ( RwLock ::new ( 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-22 15:55:56 -04:00
fn _statuscleanup ( & self , _ : Option < Channel > ) {
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
2024-03-22 15:55:56 -04:00
// Option<Channel> can pass Some(Channel("m")) (as an example) so statuscleanup only works on the given channel
2023-12-21 12:10:50 -05:00
// 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 (
2024-03-22 15:55:56 -04:00
in_module : BotModule ,
2024-03-21 14:01:54 -04:00
in_modgroup : ModGroup ,
2024-03-22 15:55:56 -04:00
in_chnl1 : Channel ,
in_chnl2 : Channel )
2024-03-21 14:01:54 -04:00
{
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 ) =
2024-03-22 15:55:56 -04:00
( Channel ( " TestChannel01 " . to_string ( ) ) , Channel ( " TestChannel02 " . to_string ( ) ) ) ;
2024-03-21 14:01:54 -04:00
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 ) =
2024-03-22 15:55:56 -04:00
( Channel ( " TestChannel01 " . to_string ( ) ) , Channel ( " TestChannel02 " . to_string ( ) ) ) ;
2024-03-21 14:01:54 -04:00
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 ,
2024-03-22 15:55:56 -04:00
channel :Channel ,
2024-03-22 17:06:09 -04:00
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 mut idlock = idmgr . clone ( ) ;
let requestor_badge = None ; // If they are a Mod on the Given Channel already, that can be evaluated without the current badge
2024-03-22 15:55:56 -04:00
const OF_CMD_CHANNEL :Channel = Channel ( String ::new ( ) ) ;
2024-03-22 17:06:09 -04:00
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 ;
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
* /
// [-] requestor_badge: Option<ChatBadge>,
2024-03-22 15:55:56 -04:00
// [x] trg_module: BotModule,
2024-03-22 17:06:09 -04:00
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 ;
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 ( ) ) ) ,
}
/*
[ 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>,
2024-03-22 21:06:15 -04:00
2024-03-22 17:06:09 -04:00
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
} ;
let rslt = modsmgr . exec_enable ( requestor . clone ( ) ,
requestor_badge ,
trg_module . clone ( ) ,
trg_level . clone ( ) ,
id . clone ( ) ) . await ;
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 ( ) ) ) ,
}
/*
[ 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
} ;
let rslt = modsmgr . exec_enable ( requestor . clone ( ) ,
requestor_badge , // passing based on scenario
trg_module . clone ( ) ,
trg_level . clone ( ) ,
id . clone ( ) ) . await ;
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 ( ) ) ) ,
}
/*
[ 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 ;
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 ( ) ) ) ,
}
/*
[ 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
2024-03-22 21:06:15 -04:00
2024-03-22 17:06:09 -04:00
let requestor_badge = match current_test_scenario {
TestScenarios ::BotadminUser = >
None ,
TestScenarios ::ModUser = >
Some ( ChatBadge ::Mod ) ,
TestScenarios ::RegularChatter = >
None , // setting badge to None
} ;
let rslt : ChangeResult = modsmgr . exec_disable ( requestor . clone ( ) ,
requestor_badge ,
trg_module . clone ( ) ,
trg_level . clone ( ) ,
false ,
id . clone ( ) ) . await ;
2024-03-22 21:06:15 -04:00
2024-03-22 17:06:09 -04:00
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 ( ) ) ) ,
}
/*
[ x ] 4. affirm when BotAdmin attempts to exec_disable on the following
c . Instance Level
* /
let trg_level = StatusLvl ::Instance ; // setting to Instance level
2024-03-22 21:06:15 -04:00
2024-03-22 17:06:09 -04:00
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 ;
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 ( ) ) ) ,
}
/*
[ ] 4. affirm when BotAdmin attempts to exec_disable on the following
d . force disable
* /
let trg_level = StatusLvl ::Instance ; // setting to Instance level
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 ;
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 ( ) ) ) ,
}
}
#[ 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 ] 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 ( ) ;
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 ) ) ;
2024-03-22 15:55:56 -04:00
let channel = Channel ( " somechannel " . to_string ( ) ) ;
2024-03-22 17:06:09 -04:00
inner_enable_disable_complex ( requestor , channel , idmgr , modsmgr ) . await ;
}
#[ 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;
2024-03-22 15:55:56 -04:00
let channel = Channel ( " somechannel " . to_string ( ) ) ;
2024-03-22 17:06:09 -04:00
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 ( ) ;
2024-03-22 15:55:56 -04:00
let channel = Channel ( " somechannel " . to_string ( ) ) ;
2024-03-22 17:06:09 -04:00
idmgr . affirm_chatter_in_db ( requestor . clone ( ) ) . await ;
2024-03-22 21:06:15 -04:00
2024-03-22 17:06:09 -04:00
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 ( ) ;
2024-03-22 21:06:15 -04:00
2024-03-22 15:55:56 -04:00
let channel = Channel ( " somechannel " . to_string ( ) ) ;
2024-03-22 17:06:09 -04:00
idmgr . affirm_chatter_in_db ( requestor . clone ( ) ) . await ;
2024-03-22 21:06:15 -04:00
2024-03-22 17:06:09 -04:00
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 ( ) ) ) ;
2024-03-22 21:06:15 -04:00
// [x] Test with Non Existing module > disable
2024-03-22 17:06:09 -04:00
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
}