2024-01-29 06:18:27 -05:00
use std ::collections ::HashMap ;
2024-01-29 12:41:26 -05:00
use std ::error ::Error ;
2024-01-29 11:09:33 -05:00
use crate ::core ::botmodules ::{ ModulesManager , Listener , BotModule , BotActionTrait , BotCommand } ;
use crate ::core ::botmodules ::bot_actions ::actions_util ;
use crate ::core ::botinstance ::{ self } ;
2024-01-29 22:57:07 -05:00
use twitch_irc ::message ::{ Badge , PrivmsgMessage } ;
2024-01-29 11:09:33 -05:00
2024-01-29 12:41:26 -05:00
use crate ::core ::botmodules ::ChType ;
2024-01-29 06:18:27 -05:00
fn adminvector ( ) -> Vec < String > {
vec! [ String ::from ( " ModulatingForce " ) ]
}
2024-01-29 11:09:33 -05:00
pub fn init ( mgr :& mut ModulesManager )
{
BotCommand {
module : BotModule ( String ::from ( " identity " ) ) ,
command : String ::from ( " promote " ) , // command call name
alias : vec ! [ ] , // String of alternative names
exec_body : actions_util ::asyncbox ( cmd_promote ) ,
help : String ::from ( " promote " ) ,
2024-01-30 09:13:59 -05:00
required_roles : vec ! [
UserRole ::Mod ( ChType ::Channel ( String ::new ( ) ) ) ,
UserRole ::SupMod ( ChType ::Channel ( String ::new ( ) ) ) ,
UserRole ::Broadcaster ,
UserRole ::BotAdmin ,
] ,
2024-01-29 11:09:33 -05:00
} . add_to_modmgr ( mgr ) ;
async fn cmd_promote ( mut _chat :botinstance ::Chat , _msg :PrivmsgMessage ) {
//println!("(#{}) {}: {}", msg.channel_login, msg.sender.name, msg.message_text);
2024-01-29 22:57:07 -05:00
println! ( " Called cmd promote " ) ;
2024-01-29 12:41:26 -05:00
2024-01-30 15:07:40 -05:00
// -- If the BotCommand.command was called (e.g., promote), this is the current function body to execute
/*
- ` promote ` / ` demote `
- [ ] ` SupMod ` & ` Broadcaster ` & ` BotAdmin ` can run
- [ ] ` UserRole ` s that can run , can
- [ ] run ` promote ` on a regular ` Chatter ` to make them a ` Mod `
- [ ] run ` demote ` on a ` Mod ` to make them a ` Chatter `
- [ ] Only ` BotAdmin ` can :
- [ ] target themselves to ` promote ` / ` demote ` , in the case that they want to make themselves either a ` Mod ` or ` SupMod ` for the channel temporarily
- [ ] ` promote admin < Chatter > ` to assign them ` BotAdmin ` role
- ` [ ] Broadcaster ` & ` BotAdmin ` can ` demote ` a ` SupMod ` to make them a ` Mod `
* /
// [ ] Split message based on arguments
2024-01-29 11:09:33 -05:00
}
BotCommand {
module : BotModule ( String ::from ( " identity " ) ) ,
command : String ::from ( " demote " ) , // command call name
alias : vec ! [ ] , // String of alternative names
exec_body : actions_util ::asyncbox ( cmd_demote ) ,
help : String ::from ( " demote " ) ,
2024-01-30 09:13:59 -05:00
required_roles : vec ! [
UserRole ::Mod ( ChType ::Channel ( String ::new ( ) ) ) ,
UserRole ::SupMod ( ChType ::Channel ( String ::new ( ) ) ) ,
UserRole ::Broadcaster ,
UserRole ::BotAdmin ,
] ,
2024-01-29 11:09:33 -05:00
} . add_to_modmgr ( mgr ) ;
async fn cmd_demote ( mut _chat :botinstance ::Chat , _msg :PrivmsgMessage ) {
2024-01-29 22:57:07 -05:00
println! ( " Called cmd demote " ) ;
2024-01-29 11:09:33 -05:00
}
}
2024-01-29 22:57:07 -05:00
// #[derive(Debug, PartialEq, Eq, Hash, Clone)]
// pub enum ChType {
// Channel(String),
// }
#[ derive(Debug, PartialEq, Eq , Clone) ]
2024-01-29 11:09:33 -05:00
pub enum UserRole {
2024-01-29 06:18:27 -05:00
Chatter ,
2024-01-29 13:08:35 -05:00
Mod ( ChType ) , // String specifies Channel
SupMod ( ChType ) , // String specifies Channel
2024-01-29 06:18:27 -05:00
Broadcaster ,
BotAdmin ,
2024-01-29 12:41:26 -05:00
2024-01-29 06:18:27 -05:00
}
2024-01-29 22:57:07 -05:00
pub enum Permissible {
2024-01-29 12:41:26 -05:00
Allow ,
Block
}
2024-01-29 22:57:07 -05:00
#[ derive(Clone) ]
2024-01-29 06:18:27 -05:00
pub struct IdentityManager {
2024-01-29 22:57:07 -05:00
special_roles_users : HashMap < String , Vec < UserRole > > , // # <-- (!) This must be String instead of ChType because we're checking a User not a Channel
2024-01-29 06:18:27 -05:00
}
2024-01-29 22:57:07 -05:00
pub enum ChatBadge {
2024-01-29 12:41:26 -05:00
Broadcaster ,
Mod ,
}
2024-01-29 06:18:27 -05:00
impl IdentityManager {
pub fn init ( ) -> IdentityManager {
let mut a = HashMap ::new ( ) ;
for admn in adminvector ( ) {
2024-01-29 11:09:33 -05:00
a . insert ( admn . to_lowercase ( ) , vec! [ UserRole ::BotAdmin ] ) ;
2024-01-29 06:18:27 -05:00
} ;
IdentityManager {
2024-01-29 11:09:33 -05:00
special_roles_users : a ,
2024-01-29 06:18:27 -05:00
}
}
2024-01-29 12:41:26 -05:00
2024-01-29 22:57:07 -05:00
// [ ] Maybe I should create a can_user_run version that simply takes PrvMsg, but then calls can_user_run directly
// pub fn can_user_run_PRVMSG(self,msg:&PrivmsgMessage,cmdreqroles:Vec<UserRole>) -> Result<Permissible,Box<dyn Error>>
pub fn can_user_run_PRVMSG ( self , msg :& PrivmsgMessage , cmdreqroles :Vec < UserRole > ) -> Permissible
{
// println!("(#{}) {}: {}", msg.channel_login, msg.sender.name, msg.message_text);
// [ ] Check what Badges in PrivmsgMessage
let mut sender_badge :Option < ChatBadge > = None ;
for b in & msg . badges {
if b . name = = " moderator " {
sender_badge = Some ( ChatBadge ::Mod ) ;
} else if b . name = = " broadcaster " {
sender_badge = Some ( ChatBadge ::Broadcaster ) ;
}
}
// if &msg.badges.contains(Badge{}) {
// }
if let Some ( sender_badge ) = sender_badge {
return self . can_user_run ( msg . sender . name . to_owned ( ) ,
ChType ::Channel ( msg . channel_login . to_owned ( ) ) ,
sender_badge ,
cmdreqroles
) ;
}
// [ ] Call can_user_run()
Permissible ::Block
}
pub fn can_user_run ( mut self ,
2024-01-29 12:41:26 -05:00
usr :String ,
channelname :ChType ,
2024-01-29 22:57:07 -05:00
chat_badge :ChatBadge ,
2024-01-29 12:41:26 -05:00
cmdreqroles :Vec < UserRole >
2024-01-29 22:57:07 -05:00
// ) -> Result<Permissible,Box<dyn Error>> {
) -> Permissible {
2024-01-29 12:41:26 -05:00
/*
canUserRun -
Input :
usr :String ,
channelname :ChType ,
2024-01-29 22:57:07 -05:00
chat_badge :ChatBadge ,
2024-01-29 12:41:26 -05:00
cmdreqroles :Vec < UserRole >
Output : Result < Permissible , Box < dyn Error > >
Some Possible outcomes : Ok ( Permissible ::Allow ) , Ok ( Permissible ::Block )
Description
For a Given Chatter ( with any special ChatBadge ) who ran the Command at a Given Channel , check if that user can
run the command based on the given cmdreqroles required by the command
Inputs and business logic determine if the user can run the command based on the command ' s required roles
* /
2024-01-29 13:08:35 -05:00
// Requirements
/*
2024-01-29 22:57:07 -05:00
[ x ] If cmdreqroles is empty vector , automatically assume Ok ( Permissible ::Allow )
[ x ] If chatBadge ::Broadcaster .. .
[ x ] and cmdreqroles includes UserRole ::Broadcaster , Ok ( Permissible ::Allow )
[ x ] and cmdreqroles includes UserRole ::Mod ( " " ) OR UserRole ::SupMod ( " " ) , Ok ( Permissible ::Allow )
[ x ] If chatBadge ::Mod .. .
[ x ] Check if they have either UserRole ::Mod ( channelname ::ChType ) or UserRole ::SupMod ( channelname ::ChType )
[ x ] If not , assign them UserRole ::Mod ( channelname ::ChType )
[ x ] If cmdreqroles includes UserRole ::Mod ( " " ) , checks if chatter has UserRole ::Mod ( channelname ::ChType ) or UserRole ::SupMod ( channelname ::ChType ) to determine if Ok ( Permissible ::Allow )
[ x ] If cmdreqroles includes UserRole ::SupMod ( " " ) , checks if chatter has UserRole ::SupMod ( channelname ::ChType ) to determine if Ok ( Permissible ::Allow )
[ x ] If cmdreqroles includes UserRole ::BotAdmin and chatter has UserRole ::BotAdmin , Ok ( Permissible ::Allow )
[ x ] Otherwise , Ok ( Permissible ::Block )
2024-01-29 13:08:35 -05:00
* /
2024-01-29 12:41:26 -05:00
2024-01-29 22:57:07 -05:00
// [x] If cmdreqroles is empty vector , automatically assume Ok(Permissible::Allow)
2024-01-29 12:41:26 -05:00
2024-01-29 22:57:07 -05:00
if cmdreqroles . len ( ) = = 0 {
// return Ok(Permissible::Allow)
return Permissible ::Allow
}
match chat_badge {
// [x] If chatBadge::Broadcaster ...
// [x] and cmdreqroles includes UserRole::Broadcaster , Ok(Permissible::Allow)
// [x] and cmdreqroles includes UserRole::Mod("") OR UserRole::SupMod("") , Ok(Permissible::Allow)
ChatBadge ::Broadcaster = > {
if cmdreqroles . contains ( & UserRole ::Broadcaster ) | |
cmdreqroles . contains ( & UserRole ::Mod ( ChType ::Channel ( String ::new ( ) ) ) ) | |
cmdreqroles . contains ( & UserRole ::SupMod ( ChType ::Channel ( String ::new ( ) ) ) ) {
// return Ok(Permissible::Allow)
return Permissible ::Allow
}
} ,
// [x] If chatBadge::Mod ...
// [x] Check if they have either UserRole::Mod(channelname::ChType) or UserRole::SupMod(channelname::ChType)
// [x] If not, assign them UserRole::Mod(channelname::ChType)
ChatBadge ::Mod = > {
2024-01-30 09:13:59 -05:00
// println!("Mod Chatbadge detected");
2024-01-29 22:57:07 -05:00
2024-01-30 09:13:59 -05:00
// println!("debug special roles : {:?}",self.special_roles_users);
// println!("debug usr : {}",&usr.to_lowercase());
2024-01-29 22:57:07 -05:00
// let Some((k,v)) = self.special_roles_users.get_key_value(usr);
match self . special_roles_users . get_mut ( & usr . to_lowercase ( ) ) {
Some ( usrroles ) = > {
2024-01-30 09:13:59 -05:00
// println!("contains mod : {}", usrroles.contains(&UserRole::Mod(channelname.clone())));
// println!("contains supmod : {}", usrroles.contains(&UserRole::SupMod(channelname.clone())));
2024-01-29 22:57:07 -05:00
if usrroles . contains ( & UserRole ::Mod ( channelname . clone ( ) ) ) | |
usrroles . contains ( & UserRole ::SupMod ( channelname . clone ( ) ) ) {
// Do nothing - this is expected
} else {
// in this case, they have a ChatBadge::Mod but should have this for the channel
usrroles . push ( UserRole ::Mod ( channelname . clone ( ) ) ) ;
2024-01-30 09:13:59 -05:00
// println!("debug special roles : {:?}",self.special_roles_users);
2024-01-29 22:57:07 -05:00
}
} ,
_ = > ( )
}
} ,
// _ => (),
}
// [x] If cmdreqroles includes UserRole::Mod("") , checks if chatter has UserRole::Mod(channelname::ChType) or UserRole::SupMod(channelname::ChType) to determine if Ok(Permissible::Allow)
println! ( " cmd required roles : {:?} " , cmdreqroles ) ;
if cmdreqroles . contains ( & UserRole ::Mod ( ChType ::Channel ( String ::new ( ) ) ) ) {
// match self.special_roles_users.get(&channelname) {
// Some(usrroles) => {},
// None => (),
// }
println! ( " Mod Role required " ) ;
if let Some ( a ) = self . special_roles_users . get ( & usr . to_lowercase ( ) ) {
if a . contains ( & UserRole ::Mod ( channelname . clone ( ) ) ) | | a . contains ( & UserRole ::SupMod ( channelname . clone ( ) ) ) {
// return Ok(Permissible::Allow);
return Permissible ::Allow
}
}
}
// [x] If cmdreqroles includes UserRole::SupMod("") , checks if chatter has UserRole::SupMod(channelname::ChType) to determine if Ok(Permissible::Allow)
if cmdreqroles . contains ( & UserRole ::SupMod ( ChType ::Channel ( String ::new ( ) ) ) ) {
if let Some ( a ) = self . special_roles_users . get ( & usr . to_lowercase ( ) ) {
if a . contains ( & UserRole ::SupMod ( channelname . clone ( ) ) ) {
// return Ok(Permissible::Allow);
return Permissible ::Allow
}
}
}
// [x] If cmdreqroles includes UserRole::BotAdmin and chatter has UserRole::BotAdmin , Ok(Permissible::Allow)
println! ( " Eval cmdreqroles with botadmin : {} " , cmdreqroles . contains ( & UserRole ::BotAdmin ) ) ;
if cmdreqroles . contains ( & UserRole ::BotAdmin ) {
println! ( " special roles get : {:?} " , self . special_roles_users . get ( & usr . to_lowercase ( ) ) ) ;
if let Some ( a ) = self . special_roles_users . get ( & usr . to_lowercase ( ) ) {
println! ( " special roles contains BotAdmin: {} " , a . contains ( & UserRole ::BotAdmin ) ) ;
if a . contains ( & UserRole ::BotAdmin ) {
// return Ok(Permissible::Allow);
return Permissible ::Allow
}
}
}
Permissible ::Block
2024-01-29 12:41:26 -05:00
}
2024-01-29 06:18:27 -05:00
}