diff --git a/src/core/botinstance.rs b/src/core/botinstance.rs index 4bcb352..07b481d 100644 --- a/src/core/botinstance.rs +++ b/src/core/botinstance.rs @@ -465,12 +465,42 @@ impl BotInstance { }; - botlock.botmgrs.chat.say_in_reply_to( - msg, - outstr, - // c.module.clone(), - params + botlock.botmgrs.chat.send_botmsg(super::chat::BotMsgType::Notif( + outstr.to_string() + ), + params.clone(), ).await; + + } + + if innerstr + .to_lowercase() + .contains(&"Auto Promoted VIP".to_lowercase()) + { + botlog::notice( + "Assigning VIP UserRole to VIP", + Some("botinstance > listener_main_prvmsg()".to_string()), + Some(msg), + ); + + let botlock = bot.read().await; + let outstr = + "❤️ a VIP - love ya!".to_string(); + + + let params = ExecBodyParams { + bot : Arc::clone(&bot), + msg : (*msg).clone(), + parent_act : Arc::clone(&act_clone), + + }; + + botlock.botmgrs.chat.send_botmsg(super::chat::BotMsgType::Notif( + outstr.to_string() + ), + params.clone(), + ).await; + } } diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 25206df..c104fdd 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -19,6 +19,10 @@ Example */ + +const OF_CMD_CHANNEL:Channel = Channel(String::new()); + + use core::panic; use std::collections::HashMap; @@ -45,8 +49,6 @@ use super::identity::ChatBadge; pub async fn init(mgr: Arc) { - const OF_CMD_CHANNEL:Channel = Channel(String::new()); - // 1. Define the BotAction let botc1 = BotCommand { module: BotModule(String::from("core")), @@ -143,6 +145,8 @@ pub async fn init(mgr: Arc) { requestor_badge_mut = Some(ChatBadge::Mod); } else if b.name == "broadcaster" { requestor_badge_mut = Some(ChatBadge::Broadcaster); + } else if b.name == "vip" { + requestor_badge_mut = Some(ChatBadge::VIP); } } @@ -330,6 +334,8 @@ pub async fn init(mgr: Arc) { requestor_badge_mut = Some(ChatBadge::Mod); } else if b.name == "broadcaster" { requestor_badge_mut = Some(ChatBadge::Broadcaster); + } else if b.name == "vip" { + requestor_badge_mut = Some(ChatBadge::VIP); } } diff --git a/src/core/chat.rs b/src/core/chat.rs index 27d36e3..bb938cc 100644 --- a/src/core/chat.rs +++ b/src/core/chat.rs @@ -249,10 +249,12 @@ impl Chat { // [x] If user has any of the following target roles, they will be allowed - otherwise, they will not be allowed to send // - Otherwise if not (checked here) , this will not run // - NOTE : For now, I've removed BotAdmin just for curiosity - BotAdmins can always elevate themselves if they want + // - Will be adding VIP to this as this should include Channel_Level Roles if !(user_roles.contains(&identity::UserRole::Mod(Channel(channel_login.clone()))) || user_roles.contains(&identity::UserRole::SupMod(Channel(channel_login.clone()))) || user_roles.contains(&identity::UserRole::Broadcaster) + || user_roles.contains(&identity::UserRole::VIP(Channel(channel_login.clone()))) ) { diff --git a/src/core/identity.rs b/src/core/identity.rs index 2fbf56e..dc2da72 100644 --- a/src/core/identity.rs +++ b/src/core/identity.rs @@ -1,3 +1,8 @@ + + +const OF_CMD_CHANNEL:Channel = Channel(String::new()); + + use std::collections::HashMap; use std::sync::Arc; @@ -61,171 +66,15 @@ pub async fn init(mgr: Arc) { exec_body: actions_util::asyncbox(cmd_promote), help: String::from("promote"), required_roles: vec![ - UserRole::Mod(Channel(String::new())), - UserRole::SupMod(Channel(String::new())), + UserRole::Mod(OF_CMD_CHANNEL), + UserRole::SupMod(OF_CMD_CHANNEL), UserRole::Broadcaster, UserRole::BotAdmin, ], }; tempb.add_core_to_modmgr(Arc::clone(&mgr)).await; - - async fn cmd_promote(params : ExecBodyParams) { - botlog::trace( - "Called cmd promote", - Some("identity.rs > cmd_prommote()".to_string()), - Some(¶ms.msg), - ); - - // -- If the BotCommand.command was called (e.g., promote) & required roles were validated OUTSIDE of this call - // , 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 ` to assign them `BotAdmin` role - - `[ ] Broadcaster` & `BotAdmin` can `demote` a `SupMod` to make them a `Mod` or `promote` the other way - */ - - /* - Usage : - - promote - - demote - - promote -admin - - */ - - // println!("{}",params.msg.message_text); - botlog::trace( - format!("Twich Message > {}", params.msg.message_text).as_str(), - Some("identity.rs > cmd_promote()".to_string()), - None, - ); - - let sendername = params.msg.clone().sender.name; - - let mut argv = params.msg.message_text.split(' '); - - argv.next(); // Skip the command name - - let arg1 = argv.next(); - - let arg2 = argv.next(); - - let mut sender_badge: Option = None; - - for b in ¶ms.msg.badges { - if b.name == "moderator" { - sender_badge = Some(ChatBadge::Mod); - } else if b.name == "broadcaster" { - sender_badge = Some(ChatBadge::Broadcaster); - } - } - - let targetchnl = params.msg.channel_login.to_lowercase(); - - /* - - [x] 1. Get trgusr (regardless of -admin flag) - [x] 2. promote trguser - [x] 3. Output resulting change - - */ - - // [x] 1. Get trgusr (regardless of -admin flag) - - let targetusr = if arg1 == Some("-admin") { arg2 } else { arg1 }; - - // [x] 2. promote trguser - - // [x] Get a required lock first - - let botlock = params.bot.read().await; - let id = botlock.get_identity(); - let idlock = id.read().await; - - let rslt = match targetusr { - Some(targetusr) => { - botlog::debug( - "running promote()", - Some("identity.rs > cmd_promote()".to_string()), - None, - ); - Log::flush(); - - let target_bot_admin_role = if arg1 == Some("-admin") { - Some(UserRole::BotAdmin) - } else { - None - }; - - idlock - .promote( - sendername.clone(), - &sender_badge, - targetusr.to_string(), - Some(Channel(targetchnl.clone())), - target_bot_admin_role, - ) - .await - } - - None => { - botlog::debug( - "No Targer User argument", - Some("identity.rs > cmd_demote()".to_string()), - None, - ); - Log::flush(); - - ChangeResult::NoChange("No Targer User".to_string()) - } - }; - - // [x] 3. Output resulting change - - let outmsg = match rslt { - ChangeResult::Success(a) => { - format!("o7 Successfully promoted : {a}") - } - ChangeResult::Failed(a) => { - format!("PoroSad failed to promote : {a}") - } - ChangeResult::NoChange(a) => { - format!("uuh No Promotion Change : {a}") - } - }; - - botlog::debug( - outmsg.as_str(), - Some("identity.rs > cmd_prommote()".to_string()), - Some(¶ms.msg), - ); - - // We should call a notification around here - - botlock.botmgrs.chat.send_botmsg(super::chat::BotMsgType::Notif( - outmsg.to_string() - ), - params.clone(), - ).await; - - - botlog::trace( - "End of cmd_promote()", - Some("identity.rs > cmd_prommote()".to_string()), - None, - ); - } - + let tempb = BotCommand { module: BotModule(String::from("identity")), command: String::from("demote"), // command call name @@ -233,189 +82,15 @@ pub async fn init(mgr: Arc) { exec_body: actions_util::asyncbox(cmd_demote), help: String::from("demote"), required_roles: vec![ - UserRole::Mod(Channel(String::new())), - UserRole::SupMod(Channel(String::new())), + UserRole::Mod(OF_CMD_CHANNEL), + UserRole::SupMod(OF_CMD_CHANNEL), UserRole::Broadcaster, UserRole::BotAdmin, ], }; tempb.add_core_to_modmgr(Arc::clone(&mgr)).await; - - async fn cmd_demote(params : ExecBodyParams) { - botlog::debug( - "Called cmd demote", - Some("identity.rs > cmd_demote()".to_string()), - Some(¶ms.msg), - ); - Log::flush(); - - // -- If the BotCommand.command was called (e.g., demote) & required roles were validated OUTSIDE of this call - // , 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 ` to assign them `BotAdmin` role - - `[ ] Broadcaster` & `BotAdmin` can `demote` a `SupMod` to make them a `Mod` or `promote` the other way - */ - - /* - Usage : - - promote - - demote - - promote -admin - - */ - - // [x] Unwraps arguments from message - - let (arg1, _arg2) = { - let mut argv = params.msg.message_text.split(' '); - - argv.next(); // Skip the command name - - let arg1 = argv.next(); - - let arg2 = argv.next(); - - (arg1, arg2) - }; - - // --- - - /* - - [x] 1. Parse out the following - - Sender (e.g., Name & Badge) - - Target User (arg1) - - Target Channel (current channel) - - Msg or Msg.Message_Text (for later) - - - [x] 2. Run Demote() - - within demote(), getspecialuserroles() is called on both the sender and the target - - getspecialuserroles() only sends current db , while canuserrun() may change db depending on the most current state of the sender - - getspecialuserroles also borrows the sender's badge to evaluate - - - [x] 3. Take ChangeResult and output response - - */ - - /* - - - [x] 1. Parse out the following - - Sender (e.g., Name & Badge) - - Target User (arg1) - - Target Channel (current channel) - - (no need) Msg or Msg.Message_Text (for later) - - */ - - let sendername = params.msg.clone().sender.name; - - let mut sender_badge_mut: Option = None; - - for b in ¶ms.msg.badges { - if b.name == "moderator" { - sender_badge_mut = Some(ChatBadge::Mod); - } else if b.name == "broadcaster" { - sender_badge_mut = Some(ChatBadge::Broadcaster); - } - } - - let sender_badge = sender_badge_mut; - - let targetusr = arg1; - - let targetchnl = params.msg.channel_login.to_lowercase(); - - /* - - - [x] 2. Run Demote() - - within demote(), getspecialuserroles() is called on both the sender and the target - - getspecialuserroles() only sends current db , while canuserrun() may change db depending on the most current state of the sender - - getspecialuserroles also borrows the sender's badge to evaluate - - - */ - - // [x] Get a required lock first - - let botlock = params.bot.read().await; - let id = botlock.get_identity(); - let idlock = id.read().await; - - let rslt = match targetusr { - Some(targetusr) => { - botlog::debug( - "running demote()", - Some("identity.rs > cmd_demote()".to_string()), - None, - ); - Log::flush(); - - idlock - .demote( - sendername.clone(), - &sender_badge, - targetusr.to_string(), - Some(Channel(targetchnl.clone())), - ) - .await - } - - None => { - botlog::debug( - "No Targer User argument", - Some("identity.rs > cmd_demote()".to_string()), - None, - ); - Log::flush(); - - ChangeResult::NoChange("No Targer User".to_string()) - } - }; - - /* - - - [x] 3. Take ChangeResult and output response - - */ - - let outmsg = match rslt { - ChangeResult::Success(a) => { - format!("o7 Successfully demoted : {a}") - } - ChangeResult::Failed(a) => { - format!("PoroSad failed to demote : {a}") - } - ChangeResult::NoChange(a) => { - format!("uuh No Demotion Change : {a}") - } - }; - - botlog::debug( - outmsg.as_str(), - Some("identity.rs > cmd_demote()".to_string()), - Some(¶ms.msg), - ); - - botlock.botmgrs.chat.send_botmsg(super::chat::BotMsgType::Notif( - outmsg.to_string() - ), - params.clone(), - ).await; - - - } - + let tempcomm = BotCommand { module: BotModule(String::from("identity")), command: String::from("getroles"), // command call name @@ -423,151 +98,15 @@ pub async fn init(mgr: Arc) { exec_body: actions_util::asyncbox(getroles), help: String::from("getroles"), required_roles: vec![ - UserRole::Mod(Channel(String::new())), - UserRole::SupMod(Channel(String::new())), + UserRole::Mod(OF_CMD_CHANNEL), + UserRole::SupMod(OF_CMD_CHANNEL), UserRole::Broadcaster, UserRole::BotAdmin, ], }; tempcomm.add_core_to_modmgr(Arc::clone(&mgr)).await; - - async fn getroles(params : ExecBodyParams) { - botlog::debug( - "Called cmd getroles", - Some("identity.rs > cmd_getroles()".to_string()), - Some(¶ms.msg), - ); - - /* - Usage - - getroles - - If channel is provided, provide roles for that channel specifically - - */ - - - let mut argv = params.msg.message_text.split(' '); - - argv.next(); // Skip the command name - - let arg1 = argv.next(); - - let targetuser = match arg1 { - None => return, // exit if no arguments - Some(arg) => arg, - }; - - let arg2 = argv.next(); - - let targetchnl = arg2; - - let botlock = params.bot.read().await; - - let id = botlock.get_identity(); - - let idlock = id.read().await; - - let sproles = match targetchnl { - None => { - // [ ] If targetchnl is not provided, default to pulling the current channel - idlock - .getspecialuserroles( - String::from(targetuser), - Some(Channel(params.msg.channel_login.to_lowercase())), - ) - .await - } - Some(targetchnl) => { - // [x] gets special roles for caller - let callersproles = idlock - .getspecialuserroles( - params.msg.sender.name.to_lowercase(), - Some(Channel(targetchnl.to_lowercase().to_string())), - ) - .await; - - if callersproles.contains(&UserRole::Mod(Channel( - targetchnl.to_lowercase().to_string(), - ))) || callersproles.contains(&UserRole::SupMod(Channel( - targetchnl.to_lowercase().to_string(), - ))) || callersproles.contains(&UserRole::Broadcaster) - { - idlock - .getspecialuserroles( - String::from(targetuser), - Some(Channel(targetchnl.to_lowercase())), - ) - .await - } else { - // Otherwise, don't get the target channel, return the current channel instead - idlock - .getspecialuserroles( - String::from(targetuser), - Some(Channel(params.msg.channel_login.to_lowercase())), - ) - .await - } - } - }; - - botlog::debug( - &format!("User roles of Target Chatter >> {:?}", sproles), - Some("identity.rs > init > getroles()".to_string()), - Some(¶ms.msg), - ); - - botlog::trace( - "Evaluating special roles", - Some("identity.rs > init > getroles()".to_string()), - Some(¶ms.msg), - ); - - let outmsg = if ((targetuser.to_lowercase() == params.msg.channel_login.to_lowercase()) - && arg2.is_none()) - || (arg2.is_some() && arg2.unwrap() == targetuser.to_lowercase()) - { - // First evaluates if they're broadcaster - - let mut outmsg = "FeelsWowMan they're the broadcaster. ".to_string(); - - if sproles.contains(&UserRole::Mod(Channel( - params.msg.channel_login.to_lowercase(), - ))) || sproles.contains(&UserRole::SupMod(Channel( - params.msg.channel_login.to_lowercase(), - ))) || sproles.contains(&UserRole::BotAdmin) - { - outmsg += format!("Target chatter's user roles are : {:?}", sproles).as_str(); - } - outmsg - } else if sproles.contains(&UserRole::Mod(Channel( - params.msg.channel_login.to_lowercase(), - ))) || sproles.contains(&UserRole::SupMod(Channel( - params.msg.channel_login.to_lowercase(), - ))) || sproles.contains(&UserRole::BotAdmin) - { - format!("Target chatter's user roles are : {:?}", sproles) - } else { - "Target chatter has no special roles LULE ".to_string() - }; - - botlog::debug( - format!("Chat Say Reply message : {}", outmsg).as_str(), - Some("identity.rs > init > getroles()".to_string()), - Some(¶ms.msg), - ); - - botlock.botmgrs.chat.send_botmsg(super::chat::BotMsgType::Notif( - outmsg.to_string() - ), - params.clone(), - ).await; - - - // [ ] NOTE : After the above, I should receive only the roles in the context of the current channel I received this ideally and maybe BotAdmin ; not outside - } - + botlog::trace( "End of Init MOdule add", Some("identity.rs > init ".to_string()), @@ -577,11 +116,568 @@ pub async fn init(mgr: Arc) { Log::flush(); } + + +async fn cmd_promote(params : ExecBodyParams) { + botlog::trace( + "Called cmd promote", + Some("identity.rs > cmd_prommote()".to_string()), + Some(¶ms.msg), + ); + + // -- If the BotCommand.command was called (e.g., promote) & required roles were validated OUTSIDE of this call + // , 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 ` to assign them `BotAdmin` role + - `[ ] Broadcaster` & `BotAdmin` can `demote` a `SupMod` to make them a `Mod` or `promote` the other way + */ + + /* + Usage : + + promote + promote -m + promote -mod + + demote + + promote -v + promote -vip + + promote -admin + + */ + + // println!("{}",params.msg.message_text); + botlog::trace( + format!("Twich Message > {}", params.msg.message_text).as_str(), + Some("identity.rs > cmd_promote()".to_string()), + None, + ); + + let sendername = params.msg.clone().sender.name; + + let mut argv = params.msg.message_text.split(' '); + + argv.next(); // Skip the command name + + let arg1 = argv.next(); + + let arg2 = argv.next(); + + let mut sender_badge: Option = None; + + for b in ¶ms.msg.badges { + if b.name == "moderator" { + sender_badge = Some(ChatBadge::Mod); + } else if b.name == "broadcaster" { + sender_badge = Some(ChatBadge::Broadcaster); + } else if b.name == "vip" { + sender_badge = Some(ChatBadge::VIP); + } + }; + + let targetchnl = params.msg.channel_login.to_lowercase(); + + /* + + [x] 1. Get trgusr (regardless of -admin flag) + [x] 2. promote trguser + [x] 3. Output resulting change + + */ + + + + let botlock = params.bot.read().await; + let id = botlock.get_identity(); + let idlock = id.read().await; + + + // [x] 1. Get trgusr (regardless of -admin flag) + + // let targetusr = if arg1 == Some("-admin") { arg2 } else { arg1 }; + let targetusr = if + arg1 == Some("-admin") + || arg1 == Some("-v") + || arg1 == Some("-vip") + || arg1 == Some("-m") + || arg1 == Some("-mod") + { arg2 } + else if let Some(a) = arg1 { + if a.starts_with('-') { + botlock.botmgrs.chat.send_botmsg( + super::chat::BotMsgType::Notif( + "Invalid Argument Flag".to_string() + ), + params.clone(), + ).await; + return + } else { arg1 } + } + else { arg1 }; + + // [x] 2. promote trguser + + // [x] Get a required lock first + let rslt = match targetusr { + Some(targetusr) => { + botlog::debug( + "running promote()", + Some("identity.rs > cmd_promote()".to_string()), + None, + ); + + Log::flush(); + + + // // Believe this is just using this as a Constaint depending on input + let target_role = + if arg1 == Some("-admin") { + Some(UserRole::BotAdmin) + } else if arg1 == Some("-vip") || arg1 == Some("-v") { + Some(UserRole::VIP(Channel(targetchnl.clone()))) + } else { + None // [x] Internal promote() logic automatically considers trg_role targetting -mod or -m + }; + + idlock + .promote( + sendername.clone(), + &sender_badge, + targetusr.to_string(), + Some(Channel(targetchnl.clone())), + target_role, + ) + .await + } + + None => { + botlog::debug( + "No Targer User argument", + Some("identity.rs > cmd_demote()".to_string()), + None, + ); + Log::flush(); + + ChangeResult::NoChange("No Targer User".to_string()) + } + }; + + // [x] 3. Output resulting change + + let outmsg = match rslt { + ChangeResult::Success(a) => { + format!("o7 Successfully promoted : {a}") + } + ChangeResult::Failed(a) => { + format!("PoroSad failed to promote : {a}") + } + ChangeResult::NoChange(a) => { + format!("uuh No Promotion Change : {a}") + } + }; + + botlog::debug( + outmsg.as_str(), + Some("identity.rs > cmd_prommote()".to_string()), + Some(¶ms.msg), + ); + + // We should call a notification around here + + botlock.botmgrs.chat.send_botmsg(super::chat::BotMsgType::Notif( + outmsg.to_string() + ), + params.clone(), + ).await; + + + botlog::trace( + "End of cmd_promote()", + Some("identity.rs > cmd_prommote()".to_string()), + None, + ); +} + + + +async fn cmd_demote(params : ExecBodyParams) { + botlog::debug( + "Called cmd demote", + Some("identity.rs > cmd_demote()".to_string()), + Some(¶ms.msg), + ); + Log::flush(); + + // -- If the BotCommand.command was called (e.g., demote) & required roles were validated OUTSIDE of this call + // , 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 ` to assign them `BotAdmin` role + - `[ ] Broadcaster` & `BotAdmin` can `demote` a `SupMod` to make them a `Mod` or `promote` the other way + */ + + /* + Usage : + + promote + + demote + + demote -m + demote -mod + + demote -v + demote -vip + + // promote -admin + + + + */ + + // [x] Unwraps arguments from message + + let (arg1, arg2) = { + let mut argv = params.msg.message_text.split(' '); + + argv.next(); // Skip the command name + + let arg1 = argv.next(); + + let arg2 = argv.next(); + + (arg1, arg2) + }; + + // --- + + /* + - [x] 1. Parse out the following + - Sender (e.g., Name & Badge) + - Target User (arg1) + - Target Channel (current channel) + - Msg or Msg.Message_Text (for later) + + - [x] 2. Run Demote() + - within demote(), getspecialuserroles() is called on both the sender and the target + - getspecialuserroles() only sends current db , while canuserrun() may change db depending on the most current state of the sender + - getspecialuserroles also borrows the sender's badge to evaluate + + - [x] 3. Take ChangeResult and output response + + */ + + /* + + - [x] 1. Parse out the following + - Sender (e.g., Name & Badge) + - Target User (arg1) + - Target Channel (current channel) + - (no need) Msg or Msg.Message_Text (for later) + + */ + + + + // [x] Get a required lock first + + let botlock = params.bot.read().await; + let id = botlock.get_identity(); + let idlock = id.read().await; + + + let sendername = params.msg.clone().sender.name; + + let mut sender_badge_mut: Option = None; + + for b in ¶ms.msg.badges { + if b.name == "moderator" { + sender_badge_mut = Some(ChatBadge::Mod); + } else if b.name == "broadcaster" { + sender_badge_mut = Some(ChatBadge::Broadcaster); + } else if b.name == "vip" { + sender_badge_mut = Some(ChatBadge::VIP); + } + }; + + let sender_badge = sender_badge_mut; + + + let targetchnl = params.msg.channel_login.to_lowercase(); + + + // let targetusr = arg1; + let targetusr = if + arg1 == Some("-v") + || arg1 == Some("-vip") + || arg1 == Some("-m") + || arg1 == Some("-mod") + { arg2 } + else if let Some(a) = arg1 { + if a.starts_with('-') { + botlock.botmgrs.chat.send_botmsg( + super::chat::BotMsgType::Notif( + "Invalid Argument Flag".to_string() + ), + params.clone(), + ).await; + return + } else { arg1 } + } + else { arg1 }; + + // Note : At the moment, no handling of -admin + let target_role = + if arg1 == Some("-vip") || arg1 == Some("-v") { + Some(UserRole::VIP(Channel(targetchnl.clone()))) + } else { + None // [x] Internal promote() logic automatically considers trg_role targetting -mod or -m + }; + + + + /* + + - [x] 2. Run Demote() + - within demote(), getspecialuserroles() is called on both the sender and the target + - getspecialuserroles() only sends current db , while canuserrun() may change db depending on the most current state of the sender + - getspecialuserroles also borrows the sender's badge to evaluate + + + */ + + let rslt = match targetusr { + Some(targetusr) => { + botlog::debug( + "running demote()", + Some("identity.rs > cmd_demote()".to_string()), + None, + ); + Log::flush(); + + idlock + .demote( + sendername.clone(), + &sender_badge, + targetusr.to_string(), + Some(Channel(targetchnl.clone())), + target_role, + ) + .await + } + + None => { + botlog::debug( + "No Targer User argument", + Some("identity.rs > cmd_demote()".to_string()), + None, + ); + Log::flush(); + + ChangeResult::NoChange("No Targer User".to_string()) + } + }; + + /* + + - [x] 3. Take ChangeResult and output response + + */ + + let outmsg = match rslt { + ChangeResult::Success(a) => { + format!("o7 Successfully demoted : {a}") + } + ChangeResult::Failed(a) => { + format!("PoroSad failed to demote : {a}") + } + ChangeResult::NoChange(a) => { + format!("uuh No Demotion Change : {a}") + } + }; + + botlog::debug( + outmsg.as_str(), + Some("identity.rs > cmd_demote()".to_string()), + Some(¶ms.msg), + ); + + botlock.botmgrs.chat.send_botmsg(super::chat::BotMsgType::Notif( + outmsg.to_string() + ), + params.clone(), + ).await; + + +} + + + +async fn getroles(params : ExecBodyParams) { + botlog::debug( + "Called cmd getroles", + Some("identity.rs > cmd_getroles()".to_string()), + Some(¶ms.msg), + ); + + /* + Usage + + getroles + - If channel is provided, provide roles for that channel specifically + + */ + + + let mut argv = params.msg.message_text.split(' '); + + argv.next(); // Skip the command name + + let arg1 = argv.next(); + + let targetuser = match arg1 { + None => return, // exit if no arguments + Some(arg) => arg, + }; + + let arg2 = argv.next(); + + let targetchnl = arg2; + + let botlock = params.bot.read().await; + + let id = botlock.get_identity(); + + let idlock = id.read().await; + + let sproles = match targetchnl { + None => { + // [ ] If targetchnl is not provided, default to pulling the current channel + idlock + .getspecialuserroles( + String::from(targetuser), + Some(Channel(params.msg.channel_login.to_lowercase())), + ) + .await + } + Some(targetchnl) => { + // [x] gets special roles for caller + let callersproles = idlock + .getspecialuserroles( + params.msg.sender.name.to_lowercase(), + Some(Channel(targetchnl.to_lowercase().to_string())), + ) + .await; + + // Below appears to be validating if getroles() should run based on caller's specific roles + // - No Need to add VIP here + if callersproles.contains(&UserRole::Mod(Channel( + targetchnl.to_lowercase().to_string(), + ))) || callersproles.contains(&UserRole::SupMod(Channel( + targetchnl.to_lowercase().to_string(), + ))) || callersproles.contains(&UserRole::Broadcaster) + { + idlock + .getspecialuserroles( + String::from(targetuser), + Some(Channel(targetchnl.to_lowercase())), + ) + .await + } else { + // Otherwise, don't get the target channel, return the current channel instead + idlock + .getspecialuserroles( + String::from(targetuser), + Some(Channel(params.msg.channel_login.to_lowercase())), + ) + .await + } + } + }; + + botlog::debug( + &format!("User roles of Target Chatter >> {:?}", sproles), + Some("identity.rs > init > getroles()".to_string()), + Some(¶ms.msg), + ); + + botlog::trace( + "Evaluating special roles", + Some("identity.rs > init > getroles()".to_string()), + Some(¶ms.msg), + ); + + let outmsg = if ((targetuser.to_lowercase() == params.msg.channel_login.to_lowercase()) + && arg2.is_none()) + || (arg2.is_some() && arg2.unwrap() == targetuser.to_lowercase()) + { + // First evaluates if they're broadcaster + + let mut outmsg = "FeelsWowMan they're the broadcaster. ".to_string(); + + // Below appears to be validating if getroles() should run based on caller's specific roles + // - No Need to add VIP here + if sproles.contains(&UserRole::Mod(Channel( + params.msg.channel_login.to_lowercase(), + ))) || sproles.contains(&UserRole::SupMod(Channel( + params.msg.channel_login.to_lowercase(), + ))) || sproles.contains(&UserRole::BotAdmin) + { + outmsg += format!("Target chatter's user roles are : {:?}", sproles).as_str(); + } + outmsg + } else if sproles.contains(&UserRole::Mod(Channel( + params.msg.channel_login.to_lowercase(), + ))) || sproles.contains(&UserRole::SupMod(Channel( + params.msg.channel_login.to_lowercase(), + ))) || sproles.contains(&UserRole::BotAdmin) + { + format!("Target chatter's user roles are : {:?}", sproles) + } else { + "Target chatter has no special roles LULE ".to_string() + }; + + botlog::debug( + format!("Chat Say Reply message : {}", outmsg).as_str(), + Some("identity.rs > init > getroles()".to_string()), + Some(¶ms.msg), + ); + + botlock.botmgrs.chat.send_botmsg(super::chat::BotMsgType::Notif( + outmsg.to_string() + ), + params.clone(), + ).await; + + + // [ ] NOTE : After the above, I should receive only the roles in the context of the current channel I received this ideally and maybe BotAdmin ; not outside +} + + + #[derive(Debug, PartialEq, Eq, Clone)] pub enum UserRole { Chatter, - Mod(Channel), // String specifies Channel - SupMod(Channel), // String specifies Channel + Mod(Channel), + SupMod(Channel), + VIP(Channel), Broadcaster, BotAdmin, } @@ -608,6 +704,7 @@ pub struct IdentityManager { pub enum ChatBadge { Broadcaster, Mod, + VIP, } impl IdentityManager { @@ -687,8 +784,10 @@ impl IdentityManager { sender_badge = Some(ChatBadge::Mod); } else if b.name == "broadcaster" { sender_badge = Some(ChatBadge::Broadcaster); + } else if b.name == "vip" { + sender_badge = Some(ChatBadge::VIP); } - } + }; self.can_user_run( msg.sender.name.to_owned(), @@ -780,16 +879,18 @@ impl IdentityManager { ); } - let mut modrolechange = ChangeResult::NoChange("".to_string()); + let mut rolechange = ChangeResult::NoChange("".to_string()); 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) + + // If ChatBadge::Broadcaster is observed, + // Check if cmdreqroles contains Channel Level Roles . Broadcaster should have Permissible::Allow for any of these + Some(ChatBadge::Broadcaster) => { if cmdreqroles.contains(&UserRole::Broadcaster) - || cmdreqroles.contains(&UserRole::Mod(Channel(String::new()))) - || cmdreqroles.contains(&UserRole::SupMod(Channel(String::new()))) + || cmdreqroles.contains(&UserRole::Mod(OF_CMD_CHANNEL)) + || cmdreqroles.contains(&UserRole::SupMod(OF_CMD_CHANNEL)) + || cmdreqroles.contains(&UserRole::VIP(OF_CMD_CHANNEL)) { // return Ok(Permissible::Allow) return ( @@ -843,7 +944,48 @@ impl IdentityManager { usrroles_lock.push(UserRole::Mod(channelname.clone())); - modrolechange = ChangeResult::Success("Auto Promoted Mod".to_string()); + rolechange = ChangeResult::Success("Auto Promoted Mod".to_string()); + } + } + } + Some(ChatBadge::VIP) => { + botlog::info( + "VIP Chatbadge detected", + Some("identity.rs > can_user_run()".to_string()), + None, + ); + + let rolesdb = Arc::clone(&self.special_roles_users); + + self.affirm_chatter_in_db(usr.clone()).await; + + let rolesdb_lock = rolesdb.write().await; + + match (*rolesdb_lock).get(&usr.to_lowercase()) { + Some(usrroles) + if usrroles + .read() + .await + .contains(&UserRole::VIP(channelname.clone())) => + { + // Do nothing when theh have a VIP badge and have VIP badge for the channel + botlog::trace( + "Already a VIP in roles", + Some("identity.rs > can_user_run()".to_string()), + None, + ); + } + + _ => { + // In the event they have a VIP badge , are running a bot command, but don't have a channel mod role yet... + + let mut rolesdb_lock_mut = rolesdb_lock; + let usrroles = rolesdb_lock_mut.get_mut(&usr.to_lowercase()).unwrap(); + let mut usrroles_lock = usrroles.write().await; + + usrroles_lock.push(UserRole::VIP(channelname.clone())); + + rolechange = ChangeResult::Success("Auto Promoted VIP".to_string()); } } } @@ -858,7 +1000,7 @@ impl IdentityManager { None, ); - if cmdreqroles.contains(&UserRole::Mod(Channel(String::new()))) { + if cmdreqroles.contains(&UserRole::Mod(OF_CMD_CHANNEL)) { botlog::trace( "Command requires Mod Role", Some("identity.rs > can_user_run()".to_string()), @@ -887,14 +1029,14 @@ impl IdentityManager { Some("identity.rs > can_user_run()".to_string()), None, ); - return (Permissible::Allow, modrolechange); + return (Permissible::Allow, rolechange); } } } // [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(Channel(String::new()))) { + if cmdreqroles.contains(&UserRole::SupMod(OF_CMD_CHANNEL)) { if let Some(a) = self .special_roles_users .read() @@ -905,7 +1047,7 @@ impl IdentityManager { .await .contains(&UserRole::SupMod(channelname.clone())) { - return (Permissible::Allow, modrolechange); + return (Permissible::Allow, rolechange); } } } @@ -952,11 +1094,47 @@ impl IdentityManager { ); if a.read().await.contains(&UserRole::BotAdmin) { - return (Permissible::Allow, modrolechange); + return (Permissible::Allow, rolechange); } } } + // [x] If cmdreqroles includes UserRole::VIP and chatter has UserRole::VIP , Ok(Permissible::Allow) + + if cmdreqroles.contains(&UserRole::VIP(OF_CMD_CHANNEL)) { + + botlog::trace( + "Command requires VIP Role", + Some("identity.rs > can_user_run()".to_string()), + None, + ); + + if let Some(a) = self + .special_roles_users + .read() + .await + .get(&usr.to_lowercase()) + { + botlog::trace( + "Special roles found for user", + Some("identity.rs > can_user_run()".to_string()), + None, + ); + + if a.read().await.contains(&UserRole::VIP(channelname.clone())) + { + botlog::trace( + "> Special Role Identified : VIP ", + Some("identity.rs > can_user_run()".to_string()), + None, + ); + return (Permissible::Allow, rolechange); + } + } + + } + + ( Permissible::Block, ChangeResult::NoChange("Not any permissiable condition".to_string()), @@ -981,20 +1159,27 @@ impl IdentityManager { Log::flush(); /* + + + // [x] => 03.25 - Q. Would there need to be extra handling here for VIP? + + [x] 1. Check if Authorizer Mod Badge then Auto Promote to Mod if not Mod [x] 2. Get Authorizer & Target Chatter Roles with a Given Channel [x] 3. If the authorizer & Target Chatters are the same, and the Authorizer is not a Admin, return no change [x] 4a. If Authorizer is BotAdmin & trg_role is Some(BotAdmin) , set Target as BotAdmin and return - [x] 4b. If target is Broadcaster, return NoChange - [ ] 4c. If Authorizer is a SupMod,Broadcaster,BotAdmin , can Promote Target Chatter > Mod + [x] 4b. If Authorizer is a Mod,SupMod,Broadcaster & trg_role is Some(VIP(channel)), can Promote a Target Chatter > VIP + [x] 4c. If target is Broadcaster, return NoChange + [x] 4d. If Authorizer is a SupMod,Broadcaster,BotAdmin , can Promote Target Chatter > Mod - NOTE : We do not validate trg_role here - app logic requires you to promote 1 to Mod and 1 more to SupMod - [ ] 4d. If Authorizer is a Broadcaster,BotAdmin , can Promote a Target Mod > SupMod + [x] 4e. If Authorizer is a Broadcaster,BotAdmin , can Promote a Target Mod > SupMod - NOTE : We do not validate trg_role here - app logic requires you to promote 1 to Mod and 1 more to SupMod + */ - // [x] 1. Check if Authorizer Mod Badge then Auto Promote to Mod if not Mod + // [x] 1. Check if Authorizer Mod or VIP Badge then Auto Promote to matching UserRole if not already assigned let trgchatter = trgchatter.to_lowercase(); @@ -1016,10 +1201,23 @@ impl IdentityManager { .await; } + + // [x] - May want to Auto VIP Authorizer here + Some(ChatBadge::VIP) + if (!authusrroles.contains(&UserRole::VIP(channel.clone()))) => + { + authusrroles.push(UserRole::VIP(channel.clone())); + + self.affirm_chatter_in_db(authorizer.clone()).await; + self.add_role(authorizer.clone(), UserRole::VIP(channel.clone())) + .await; + } + _ => (), } } + // [x] 2. Get Authorizer & Target Chatter Roles let trgusrroles = self @@ -1037,7 +1235,6 @@ impl IdentityManager { (authusrroles, trgusrroles) }; - // [x] 3. If the authorizer & Target Chatters are the same, and the Authorizer is not a Admin, return no change if trgchatter == authorizer && !authusrroles.contains(&UserRole::BotAdmin) { return ChangeResult::NoChange("Can't target yourself".to_string()); @@ -1056,20 +1253,59 @@ impl IdentityManager { } } - // [x] 4b. If target is Broadcaster, return NoChange + botlog::debug( + format!("VIP Evaluation : Channel = {:?} ; trg_role = {:?} ", + channel.clone(),trg_role + ).as_str(), + Some("identity.rs > promote()".to_string()), + None, + ); + + // [x] 4b. If Authorizer is a Mod,SupMod,Broadcaster & trg_role is Some(VIP(channel)), can Promote a Target Chatter > VIP + if let Some(trg_chnl) = channel.clone() { + if trg_role == Some(UserRole::VIP(trg_chnl.clone())) + && ( authusrroles.contains(&UserRole::Mod(trg_chnl.clone())) + || authusrroles.contains(&UserRole::SupMod(trg_chnl.clone())) + || authusrroles.contains(&UserRole::Broadcaster) + ) + { + if trgusrroles.contains(&UserRole::VIP(trg_chnl.clone())) { + return ChangeResult::NoChange("Already has the role".to_string()); + } + else { + self.affirm_chatter_in_db(trgchatter.clone()).await; + + self.add_role(trgchatter.clone(), UserRole::VIP(trg_chnl.clone())).await; + + return ChangeResult::Success("Promotion Successful".to_string()); + } + } else if trg_role == Some(UserRole::VIP(trg_chnl.clone())) + { + return ChangeResult::Failed(String::from("You're not permitted to do that")); + } + } + + + + + + // [x] 4c. If target is Broadcaster, return NoChange if trgusrroles.contains(&UserRole::Broadcaster) { return ChangeResult::NoChange("Can't target broadcaster".to_string()); } + /* - [ ] 4c. If Authorizer is a SupMod,Broadcaster,BotAdmin , can Promote Target Chatter > Mod + [x] 4d. If Authorizer is a SupMod,Broadcaster,BotAdmin , can Promote Target Chatter > Mod - NOTE : We do not validate trg_role here - app logic requires you to promote 1 to Mod and 1 more to SupMod - [ ] 4d. If Authorizer is a Broadcaster,BotAdmin , can Promote a Target Mod > SupMod + [x] 4e. If Authorizer is a Broadcaster,BotAdmin , can Promote a Target Mod > SupMod - NOTE : We do not validate trg_role here - app logic requires you to promote 1 to Mod and 1 more to SupMod */ if let Some(trg_chnl) = channel.clone() { + + // 1. Checks first if Target User's Roles do not Include Broadcaster,Mod,SupMod for the Channel if !trgusrroles.contains(&UserRole::Broadcaster) && !trgusrroles.contains(&UserRole::Mod(trg_chnl.clone())) && !trgusrroles.contains(&UserRole::SupMod(trg_chnl.clone())) @@ -1078,6 +1314,8 @@ impl IdentityManager { // target's Next Role would be Mod // Authorizer must be SupMod,Broadcaster,BotAdmin // > Promote target to Mod + + // 2. If Authorizer has Elevated Admin Roles for the Channel (SupMod,Broadcaster,BotAdmin) > set target to MOD if authusrroles.contains(&UserRole::SupMod(trg_chnl.clone())) || authusrroles.contains(&UserRole::Broadcaster) || authusrroles.contains(&UserRole::BotAdmin) @@ -1139,6 +1377,8 @@ impl IdentityManager { } }; + + botlog::warn( "Runtime reached undeveloped code", Some("identity.rs > promote()".to_string()), @@ -1153,6 +1393,7 @@ impl IdentityManager { authorizer_badge: &Option, trgchatter: String, channel: Option, + trg_role: Option, ) -> ChangeResult { botlog::trace(&format!("IN VARS for demote() : Authorizer : {:?} ; Target Chatter : {} ; Target Channel : {:?}", authorizer,trgchatter,channel), Some("identity.rs > demote()".to_string()), None); @@ -1166,7 +1407,7 @@ impl IdentityManager { Use the roles of the above to determine whether the authorizer can demote the target user or not */ - // [x] 1. If Authorizer's Badge is Mod, ensuring Sender is in DB as Mod(Channel) + // [x] 1. If Authorizer's Badge is Mod/VIP, ensuring Sender is in DB as Mod(Channel) let trgchatter = trgchatter.to_lowercase(); @@ -1189,6 +1430,17 @@ impl IdentityManager { self.add_role(authorizer.clone(), UserRole::Mod(channel.clone())) .await; } + // [x] - May want to Auto VIP Authorizer here + Some(ChatBadge::VIP) + if (!authusrroles.contains(&UserRole::VIP(channel.clone()))) => + { + authusrroles.push(UserRole::VIP(channel.clone())); + + self.affirm_chatter_in_db(authorizer.clone()).await; + self.add_role(authorizer.clone(), UserRole::VIP(channel.clone())) + .await; + } + _ => (), } } @@ -1204,7 +1456,30 @@ impl IdentityManager { return ChangeResult::NoChange("Can't target yourself".to_string()); } - // [x] 4a. Authorizers who are BotAdmin, Broadcaster or Supermod can demote a Mod + // [x] 4. If Authorizer is a Mod,SupMod,Broadcaster & trg_role is Some(VIP(channel)), can Promote a Target Chatter > VIP + + if ( authusrroles.contains(&UserRole::Mod(channel.clone())) + || authusrroles.contains(&UserRole::SupMod(channel.clone())) + || authusrroles.contains(&UserRole::Broadcaster) + ) + && trg_role == Some(UserRole::VIP(channel.clone())) { + if !trgusrroles.contains(&UserRole::VIP(channel.clone())) { + return ChangeResult::NoChange("Already does not have VIP role".to_string()); + } + else { + // self.affirm_chatter_in_db(trgchatter.clone()).await; + + self.remove_role(trgchatter.clone(), UserRole::VIP(channel.clone())).await; + + return ChangeResult::Success("Demotion Successful".to_string()); + } + } + + + // [x] 5. - Mod/SupMod Logic + + + // [x] 5a. Authorizers who are BotAdmin, Broadcaster or Supermod can demote a Mod if (authusrroles.contains(&UserRole::BotAdmin) || authusrroles.contains(&UserRole::Broadcaster) @@ -1215,7 +1490,7 @@ impl IdentityManager { .await; return ChangeResult::Success("Demoted successfully".to_string()); } - // [x] 4b. Authorizers who are BotAdmin, Broadcaster can demote a SupMod + // [x] 5b. Authorizers who are BotAdmin, Broadcaster can demote a SupMod else if (authusrroles.contains(&UserRole::BotAdmin) || authusrroles.contains(&UserRole::Broadcaster)) && trgusrroles.contains(&UserRole::SupMod(channel.clone())) @@ -1226,7 +1501,7 @@ impl IdentityManager { .await; return ChangeResult::Success("Demoted successfully".to_string()); } - // [x] 4c. When Target chatter isnt a Mod or SupMod to demote + // [x] 5c. When Target chatter isnt a Mod or SupMod to demote else if !trgusrroles.contains(&UserRole::Mod(channel.clone())) && !trgusrroles.contains(&UserRole::SupMod(channel.clone())) { @@ -1234,7 +1509,7 @@ impl IdentityManager { "Target chatter does not have a role that can be demoted".to_string(), ); } - // [x] 4d. When they're only a Mod + // [x] 5d. When they're only a Mod else if authusrroles.contains(&UserRole::Mod(channel.clone())) { return ChangeResult::Failed("You're not permitted to do that".to_string()); } @@ -1251,6 +1526,11 @@ impl IdentityManager { chattername: String, channel: Option, ) -> Vec { + /* + NOTE : Any NEW or CHANGES to UserRole type should have additional handling here + Specifically for Channel Elevated Roles + */ + /* Note : Ideally this be called for a given chatter name ? */ @@ -1275,7 +1555,8 @@ impl IdentityManager { Some(chnl) => { // In this block, Some input channel is given // We're comparing the channel name with chattername to determine if they're a broadcaster - if chattername == chnl.0 + // if chattername == chnl.0 + if chattername == chnl.0.to_lowercase() { evalsproles.push(UserRole::Broadcaster); } @@ -1320,6 +1601,9 @@ impl IdentityManager { if a.read().await.contains(&UserRole::SupMod(channel.clone())) { evalsproles.push(UserRole::SupMod(channel.clone())); } + if a.read().await.contains(&UserRole::VIP(channel.clone())) { + evalsproles.push(UserRole::VIP(channel.clone())); + } // else {}; } None => { @@ -1739,6 +2023,7 @@ mod core_identity { let authorizer = regmod.clone(); let authorizer_badge = &None; let trgchatter = supmod.clone(); + let trg_role = None; let rslt = test_id_mgr .demote( @@ -1746,6 +2031,7 @@ mod core_identity { authorizer_badge, trgchatter.clone(), channel.clone(), + trg_role.clone(), ) .await; @@ -1766,6 +2052,7 @@ mod core_identity { authorizer_badge, trgchatter.clone(), channel.clone(), + trg_role.clone(), ) .await; @@ -1780,6 +2067,7 @@ mod core_identity { authorizer_badge, trgchatter.clone(), channel.clone(), + trg_role.clone(), ) .await; @@ -1790,4 +2078,213 @@ mod core_identity { ) ); } + + + + #[tokio::test] + async fn vip_workflow_01() { + Log::set_file_ext(Extension::Log); + //Log::set_level(Level::Trace); + + // Channel Elevated User Promotes/Demotes VIP + + let test_id_mgr = IdentityManager::init(); + + + + // [x] 1. Requester has a Mod Role + + let channel = Some(Channel("somechannel".to_string())); + let authorizer_badge = &Some(ChatBadge::Mod); + let authorizer = "chatMod".to_string(); + let trgchatter = "regularChatter".to_string(); + let trg_role = Some(UserRole::VIP(channel.clone().unwrap())); + + let authorizer = authorizer.to_lowercase(); + let trgchatter = trgchatter.to_lowercase(); + + test_id_mgr.affirm_chatter_in_db(authorizer.clone()).await; + test_id_mgr.affirm_chatter_in_db(trgchatter.clone()).await; + + test_id_mgr + .add_role(authorizer.clone(), UserRole::Mod(channel.clone().unwrap())) + .await; + + let rslt = test_id_mgr + .getspecialuserroles(authorizer.clone(), channel.clone()) + .await; + + assert_eq!(rslt,vec![UserRole::Mod(channel.clone().unwrap())]); + + // [x] 2. assert getspecialuserroles for Target Chatter + + let rslt = test_id_mgr + .getspecialuserroles(trgchatter.clone(), channel.clone()) + .await; + + assert_eq!(rslt,vec![]); + + // [x] 3. Requester Promotes a Target Chatter to VIP + + let rslt = test_id_mgr + .promote( + authorizer.clone(), + authorizer_badge, + trgchatter.clone(), + channel.clone(), + trg_role.clone(), + ) + .await; + + assert_eq!( + rslt, + ChangeResult::Success("Promotion Successful".to_string()) + ); + + + // [x] 4. assert getspecialuserroles for Target Chatter + + let rslt = test_id_mgr + .getspecialuserroles(trgchatter.clone(), channel.clone()) + .await; + + assert!(rslt.contains(&UserRole::VIP(channel.clone().unwrap()))); + + // [x] 5. Requester Promotes a Target Chatter to VIP + + let rslt = test_id_mgr + .promote( + authorizer.clone(), + authorizer_badge, + trgchatter.clone(), + channel.clone(), + trg_role.clone(), + ) + .await; + + assert_eq!( + rslt, + ChangeResult::NoChange("Already has the role".to_string()) + ); + + + // [x] 6. assert getspecialuserroles for Target Chatter + + let rslt = test_id_mgr + .getspecialuserroles(trgchatter.clone(), channel.clone()) + .await; + + assert!(rslt.contains(&UserRole::VIP(channel.clone().unwrap()))); + + + // [x] 7. Requester Demotes a Target Chatter from VIP + + let rslt = test_id_mgr + .demote( + authorizer.clone(), + authorizer_badge, + trgchatter.clone(), + channel.clone(), + trg_role.clone(), + ) + .await; + + assert_eq!( + rslt, + ChangeResult::Success("Demotion Successful".to_string()) + ); + + // [x] 8. assert getspecialuserroles for Target Chatter + + let rslt = test_id_mgr + .getspecialuserroles(trgchatter.clone(), channel.clone()) + .await; + + // assert!(rslt.contains(&UserRole::VIP(channel.clone().unwrap()))); + assert_eq!(rslt,vec![]); + + + + // [x] 9. Requester Demotes a Target Chatter from VIP + + let rslt = test_id_mgr + .demote( + authorizer.clone(), + authorizer_badge, + trgchatter.clone(), + channel.clone(), + trg_role.clone(), + ) + .await; + + assert_eq!( + rslt, + ChangeResult::NoChange("Already does not have VIP role".to_string()) + ); + + // [x] 10. assert getspecialuserroles for Target Chatter + + let rslt = test_id_mgr + .getspecialuserroles(trgchatter.clone(), channel.clone()) + .await; + + assert_eq!(rslt,vec![]); + + + + + + } + + + #[tokio::test] + async fn auto_vip_workflow() { + Log::set_file_ext(Extension::Log); + + let mut test_id_mgr = IdentityManager::init(); + + + + // let channel = Some(Channel("somechannel".to_string())); + let channel = Channel("somechannel".to_string()); + let authorizer_badge = Some(ChatBadge::VIP); + let authorizer = "chatMod".to_string(); + + let authorizer = authorizer.to_lowercase(); + + + // [x] 1. assert getspecialuserroles for Target Chatter + + let rslt = test_id_mgr + .getspecialuserroles(authorizer.clone(), Some(channel.clone())) + .await; + + assert_eq!(rslt,vec![]); + + // [x] 2. Run canuserrun() for the Requester . (This is ran after BotCommands are ran) + + let rslt = test_id_mgr + .can_user_run( + authorizer.clone(), + channel.clone(), + authorizer_badge, + vec![ + UserRole::VIP(OF_CMD_CHANNEL), + ] + ).await; + + assert_eq!(rslt, + (Permissible::Allow,ChangeResult::Success("Auto Promoted VIP".to_string()))); + + // [x] 3. assert getspecialuserroles for Target Chatter + + let rslt = test_id_mgr + .getspecialuserroles(authorizer.clone(), Some(channel.clone())) + .await; + + assert_eq!(rslt,vec![UserRole::VIP(channel)]); + + + + } } diff --git a/src/custom/experimental/experiment001.rs b/src/custom/experimental/experiment001.rs index 58d0c59..dd3cba4 100644 --- a/src/custom/experimental/experiment001.rs +++ b/src/custom/experimental/experiment001.rs @@ -10,6 +10,10 @@ */ + +const OF_CMD_CHANNEL:Channel = Channel(String::new()); + + use rand::Rng; use std::sync::Arc; @@ -26,8 +30,6 @@ use tokio::time::{sleep, Duration}; pub async fn init(mgr: Arc) { - const OF_CMD_CHANNEL:Channel = Channel(String::new()); - // 1. Define the BotAction let botc1 = BotCommand { module: BotModule(String::from("experiments001")), diff --git a/src/custom/experimental/experiment002.rs b/src/custom/experimental/experiment002.rs index 3be88ac..a4ecb25 100644 --- a/src/custom/experimental/experiment002.rs +++ b/src/custom/experimental/experiment002.rs @@ -10,6 +10,10 @@ */ + +const OF_CMD_CHANNEL:Channel = Channel(String::new()); + + use std::sync::Arc; use chrono::{TimeZone,Local}; @@ -28,8 +32,6 @@ use crate::core::identity::UserRole::*; pub async fn init(mgr: Arc) { - const OF_CMD_CHANNEL:Channel = Channel(String::new()); - // 1. Define the BotAction let botc1 = BotCommand { @@ -42,7 +44,8 @@ pub async fn init(mgr: Arc) { help: String::from("Test Command tester"), required_roles: vec![ BotAdmin, - Mod(OF_CMD_CHANNEL), + // Mod(OF_CMD_CHANNEL), + VIP(OF_CMD_CHANNEL), ], };