diff --git a/src/core/identity.rs b/src/core/identity.rs index d745684..1ae9e60 100644 --- a/src/core/identity.rs +++ b/src/core/identity.rs @@ -6,7 +6,7 @@ use std::error::Error; use crate::core::botmodules::{ModulesManager,Listener,BotModule,BotActionTrait, BotCommand}; use crate::core::botmodules::bot_actions::actions_util; -use crate::core::botinstance::{self,BotInstance}; +use crate::core::botinstance::{self, botlog, BotInstance}; use futures::lock::Mutex; use twitch_irc::message::{Badge, PrivmsgMessage}; @@ -77,25 +77,25 @@ pub async fn init(mgr:Arc) - [ ] 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` + - `[ ] Broadcaster` & `BotAdmin` can `demote` a `SupMod` to make them a `Mod` or `promote` the other way */ /* Usage : - promote + promote - demote + demote - promote admin + promote -admin */ // println!("{}",msg.message_text); - botinstance::botlog::trace(&format!("{}",msg.message_text), - Some("identity.rs > cmd_prommote()".to_string()), None); + botinstance::botlog::trace(&format!("Twich Message > {}",msg.message_text), + Some("identity.rs > cmd_promote()".to_string()), None); let mut argv = msg.message_text.split(" "); @@ -118,14 +118,16 @@ pub async fn init(mgr:Arc) match arg1 { Some(a1) if a1 == String::from("-admin") => { - // - [ ] BotAdmins can promote admin to give BotAdmin UserRole + // - [x] BotAdmins can promote admin to give BotAdmin UserRole let botlock = bot.read().await; let idlock = botlock.get_identity(); let id = idlock.read().await; // let ta = ta.getspecialuserroles(String::from("Hello"), Some(ChType::Channel(msg.channel_login.to_lowercase()))); // let ta = ta.getspecialuserroles(arg2.unwrap().to_string(), Some(ChType::Channel(msg.channel_login.to_lowercase()))); - let rolesfut = id.getspecialuserroles(msg.sender.name.to_lowercase(), Some(ChType::Channel(msg.channel_login.to_lowercase()))); + let rolesfut = id.getspecialuserroles( + msg.sender.name.to_lowercase(), + Some(ChType::Channel(msg.channel_login.to_lowercase()))); let usrroles = rolesfut.await; // let ta = ta.unwrap(); // let a = ta.read().await; @@ -150,33 +152,210 @@ pub async fn init(mgr:Arc) match ta { ChangeResult::Success(a) => { // println!("Succesfully promoted : {a} ;"); - botinstance::botlog::debug(&format!("BotAdmin Successful Promotion : {a}"), - Some("identity.rs > cmd_prommote()".to_string()), Some(&msg)); - let outmsg = "o7 Successfully promoted : ".to_string(); - botlock.botmgrs.chat.say_in_reply_to(&msg, outmsg).await; + let outmsg = &format!("o7 Successfully promoted : {a}"); + botinstance::botlog::debug(outmsg, + Some("identity.rs > cmd_prommote()".to_string()), Some(&msg)); + // let outmsg = "o7 Successfully promoted : ".to_string(); + botlock.botmgrs.chat.say_in_reply_to(&msg, outmsg.to_string()).await; }, ChangeResult::Failed(a) => { // println!("Failed to promote : {a} ; "); - botinstance::botlog::debug(&format!("BotAdmin Failed Promotion : {a}"), + let outmsg = &format!("PoroSad failed to promote : {a}"); + botinstance::botlog::debug(outmsg, Some("identity.rs > cmd_prommote()".to_string()), Some(&msg)); - let outmsg = "PoroSad failed to promote : ".to_string(); - botlock.botmgrs.chat.say_in_reply_to(&msg, outmsg).await; + // let outmsg = "PoroSad failed to promote : ".to_string(); + botlock.botmgrs.chat.say_in_reply_to(&msg, outmsg.to_string()).await; }, ChangeResult::NoChange(a) => { // println!("No Changes Made : {a} ; "); - botinstance::botlog::debug(&format!("BotAdmin No Change in Promotion : {a}"), + let outmsg = &format!("uuh No Promotion Change : {a}"); + botinstance::botlog::debug(outmsg, Some("identity.rs > cmd_prommote()".to_string()), Some(&msg)); - let outmsg = "uuh No Promotion Change : ".to_string(); - botlock.botmgrs.chat.say_in_reply_to(&msg, outmsg).await; + // let outmsg = "uuh No Promotion Change : ".to_string(); + botlock.botmgrs.chat.say_in_reply_to(&msg, outmsg.to_string()).await; }, } } - } + } // if usrroles.contains(&UserRole::BotAdmin) } // }, Some(arg1) => { + // In the case of promoting another chatter + // Check caller's roles + // Check targer chatter's roles + // - Also check if target chatter alread has target roles + // if caller's role is Broadcaster, SupMod, BotAdmin , they can Promote target Chatters to become Mod (i.e., the target user is not a Mod,SupMod,BotAdmin) + // if caller is BotAdmin, they can promote BotAdmins to Mod + // if caller's role is Broadcaster, BotAdmin, they can Promote target Mod to SupMod + botinstance::botlog::debug(&format!("Evaluating arg1: {arg1}"), + Some("identity.rs > cmd_prommote()".to_string()), Some(&msg)); + Log::flush(); + + let idlock = Arc::clone(&bot.read().await.get_identity()); + let idlock = idlock.read().await; + // let ta = idlock.promote(msg.sender.name.to_lowercase(), None, Some(UserRole::BotAdmin)).await; + + let senderroles = idlock.getspecialuserroles( + msg.sender.name.to_lowercase(), + Some(ChType::Channel(msg.channel_login.to_lowercase()))).await; + + let trgusrroles = idlock.getspecialuserroles( + arg1.to_lowercase(), + Some(ChType::Channel(msg.channel_login.to_lowercase()))).await; + + botinstance::botlog::debug(&format!("Ready to evaluate sender and targer user roles"), + Some("identity.rs > cmd_prommote()".to_string()), Some(&msg)); + Log::flush(); + + botinstance::botlog::trace(&format!("Related Vars : sender roles : {:?} ; targer usr roles : {:?}" , + senderroles,trgusrroles), + Some("identity.rs > cmd_prommote()".to_string()), Some(&msg)); + Log::flush(); + + if ( senderroles.contains(&UserRole::Broadcaster) || + senderroles.contains(&UserRole::SupMod(ChType::Channel(msg.channel_login.to_lowercase()))) || + senderroles.contains(&UserRole::BotAdmin) ) && + ( !trgusrroles.contains(&UserRole::Broadcaster) && + // !trgusrroles.contains(&UserRole::BotAdmin) && // target users that are BotAdmins can promote themselves to Mod or SupMod + !trgusrroles.contains(&UserRole::SupMod(ChType::Channel(msg.channel_login.to_lowercase()))) && + !trgusrroles.contains(&UserRole::Mod(ChType::Channel(msg.channel_login.to_lowercase()))) + ) + { + // if caller's role is Broadcaster, SupMod, BotAdmin , they can Promote target Chatters to become Mod (i.e., the target user is not a Mod,SupMod,BotAdmin) + botinstance::botlog::trace(&format!("Attempting promote..."), + Some("identity.rs > cmd_prommote()".to_string()), Some(&msg)); + Log::flush(); + let ta = idlock.promote(arg1.to_string().to_lowercase(), + Some(ChType::Channel(msg.channel_login.to_lowercase())), + Some(UserRole::Mod(ChType::Channel(msg.channel_login.to_lowercase())))).await; + + match ta { + ChangeResult::Success(a) => { + // println!("Succesfully promoted : {a} ;"); + let outmsg = &format!("Successful Promotion : {a}"); + botinstance::botlog::debug(&format!("Successful Promotion : {a}"), + Some("identity.rs > cmd_prommote()".to_string()), Some(&msg)); + Log::flush(); + // let outmsg = "o7 Successfully promoted : ".to_string(); + bot.read().await.botmgrs.chat.say_in_reply_to(&msg, outmsg.to_string()).await; + }, + ChangeResult::Failed(a) => { + // println!("Failed to promote : {a} ; "); + let outmsg = &format!("PoroSad failed to promote : {a}"); + botinstance::botlog::debug(outmsg, + Some("identity.rs > cmd_prommote()".to_string()), Some(&msg)); + // Log::flush(); + // let outmsg = "PoroSad failed to promote : ".to_string(); + bot.read().await.botmgrs.chat.say_in_reply_to(&msg, outmsg.to_string()).await; + }, + ChangeResult::NoChange(a) => { + // println!("No Changes Made : {a} ; "); + let outmsg = &format!("uuh No Change in Promotion : {a}"); + botinstance::botlog::debug(outmsg, + Some("identity.rs > cmd_prommote()".to_string()), Some(&msg)); + Log::flush(); + // let outmsg = "uuh No Promotion Change : ".to_string(); + bot.read().await.botmgrs.chat.say_in_reply_to(&msg, outmsg.to_string()).await; + }, + + } + + } else if trgusrroles.contains(&UserRole::Mod(ChType::Channel(msg.channel_login.to_lowercase()))) && + ( senderroles.contains(&UserRole::Broadcaster) || + senderroles.contains(&UserRole::BotAdmin) ) + { + botinstance::botlog::trace(&format!("Attempting promote..."), + Some("identity.rs > cmd_prommote()".to_string()), Some(&msg)); + Log::flush(); + + // broadcaster & botadmins can make mods into superadmins + let ta = idlock.promote(arg1.to_string().to_lowercase(), + Some(ChType::Channel(msg.channel_login.to_lowercase())), + Some(UserRole::Mod(ChType::Channel(msg.channel_login.to_lowercase())))).await; + + match ta { + ChangeResult::Success(a) => { + // println!("Succesfully promoted : {a} ;"); + let outmsg = &format!("Successful Promotion : {a}"); + botinstance::botlog::debug(&format!("Successful Promotion : {a}"), + Some("identity.rs > cmd_prommote()".to_string()), Some(&msg)); + Log::flush(); + // let outmsg = "o7 Successfully promoted : ".to_string(); + bot.read().await.botmgrs.chat.say_in_reply_to(&msg, outmsg.to_string()).await; + }, + ChangeResult::Failed(a) => { + // println!("Failed to promote : {a} ; "); + let outmsg = &format!("PoroSad failed to promote : {a}"); + botinstance::botlog::debug(outmsg, + Some("identity.rs > cmd_prommote()".to_string()), Some(&msg)); + // Log::flush(); + // let outmsg = "PoroSad failed to promote : ".to_string(); + bot.read().await.botmgrs.chat.say_in_reply_to(&msg, outmsg.to_string()).await; + }, + ChangeResult::NoChange(a) => { + // println!("No Changes Made : {a} ; "); + let outmsg = &format!("uuh No Change in Promotion : {a}"); + botinstance::botlog::debug(outmsg, + Some("identity.rs > cmd_prommote()".to_string()), Some(&msg)); + Log::flush(); + // let outmsg = "uuh No Promotion Change : ".to_string(); + bot.read().await.botmgrs.chat.say_in_reply_to(&msg, outmsg.to_string()).await; + }, + + } + + } else if trgusrroles.contains(&UserRole::Broadcaster) // This should always be NoChange + { + botinstance::botlog::trace(&format!("Attempting promote..."), + Some("identity.rs > cmd_prommote()".to_string()), Some(&msg)); + Log::flush(); + + // broadcaster & botadmins can make mods into superadmins + let ta = idlock.promote(arg1.to_string().to_lowercase(), + Some(ChType::Channel(msg.channel_login.to_lowercase())), + Some(UserRole::Mod(ChType::Channel(msg.channel_login.to_lowercase())))).await; + + match ta { + ChangeResult::Success(a) => { + // println!("Succesfully promoted : {a} ;"); + let outmsg = &format!("Successful Promotion : {a}"); + botinstance::botlog::debug(&format!("Successful Promotion : {a}"), + Some("identity.rs > cmd_prommote()".to_string()), Some(&msg)); + Log::flush(); + // let outmsg = "o7 Successfully promoted : ".to_string(); + bot.read().await.botmgrs.chat.say_in_reply_to(&msg, outmsg.to_string()).await; + }, + ChangeResult::Failed(a) => { + // println!("Failed to promote : {a} ; "); + let outmsg = &format!("PoroSad failed to promote : {a}"); + botinstance::botlog::debug(outmsg, + Some("identity.rs > cmd_prommote()".to_string()), Some(&msg)); + // Log::flush(); + // let outmsg = "PoroSad failed to promote : ".to_string(); + bot.read().await.botmgrs.chat.say_in_reply_to(&msg, outmsg.to_string()).await; + }, + ChangeResult::NoChange(a) => { + // println!("No Changes Made : {a} ; "); + let outmsg = &format!("uuh No Change in Promotion : {a}"); + botinstance::botlog::debug(outmsg, + Some("identity.rs > cmd_prommote()".to_string()), Some(&msg)); + Log::flush(); + // let outmsg = "uuh No Promotion Change : ".to_string(); + bot.read().await.botmgrs.chat.say_in_reply_to(&msg, outmsg.to_string()).await; + }, + + } + } + + else { + let s = botlog::fatal("Reached unreachable else", + Some("identity > cmd_promote()".to_string()), Some(&msg)); + panic!("{}",s); + }; + + Log::flush(); } _ => (), @@ -189,6 +368,11 @@ pub async fn init(mgr:Arc) let targetchnl = arg2; + + botinstance::botlog::trace(&format!("End of cmd_promote()"), + Some("identity.rs > cmd_prommote()".to_string()), None); + + } // BotCommand { @@ -226,23 +410,35 @@ pub async fn init(mgr:Arc) // println!("Called cmd demote"); botinstance::botlog::debug("Called cmd demote", Some("identity.rs > cmd_demote()".to_string()), Some(&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 + + */ - // BotCommand { - // module : BotModule(String::from("identity")), - // command : String::from("getroles"), // command call name - // alias : vec![], // String of alternative names - // exec_body : actions_util::asyncbox(getroles) , - // help : String::from("getroles"), - // required_roles : vec![ - // UserRole::Mod(ChType::Channel(String::new())), - // UserRole::SupMod(ChType::Channel(String::new())), - // UserRole::Broadcaster, - // UserRole::BotAdmin, - // ], - // }.add_to_modmgr(Arc::clone(&mgr)); let tempcomm = BotCommand { module : BotModule(String::from("identity")), @@ -442,9 +638,16 @@ pub async fn init(mgr:Arc) let outmsg = if ((targetuser.to_lowercase() == msg.channel_login.to_lowercase()) && arg2.is_none()) || (arg2.is_some() && arg2.unwrap() == targetuser.to_lowercase()) { - // First evaluates if they're broadcaster - format!("FeelsWowMan they're the broadcaster ") + // First evaluates if they're broadcaster + let mut outmsg = format!("FeelsWowMan they're the broadcaster. "); + if sproles.contains(&UserRole::Mod(ChType::Channel(msg.channel_login.to_lowercase()))) || + sproles.contains(&UserRole::SupMod(ChType::Channel(msg.channel_login.to_lowercase()))) || + sproles.contains(&UserRole::BotAdmin) { + outmsg = outmsg + &format!("Target chatter's user roles are : {:?}",sproles) ; + } + outmsg } + else if sproles.contains(&UserRole::Mod(ChType::Channel(msg.channel_login.to_lowercase()))) || sproles.contains(&UserRole::SupMod(ChType::Channel(msg.channel_login.to_lowercase()))) || sproles.contains(&UserRole::BotAdmin) { @@ -885,6 +1088,10 @@ impl IdentityManager { // pub async fn promote(&mut self,trgchatter:String,channel:Option,trg_role:Option) -> ChangeResult { pub async fn promote(&self,trgchatter:String,channel:Option,trg_role:Option) -> ChangeResult { + botinstance::botlog::trace(&format!("IN VARS for promote() : Target Chatter : {} ; Target Channel : {:?} ; Targer Role {:?}", + trgchatter,channel,trg_role), + Some("identity.rs > promote()".to_string()), None); + Log::flush(); // Note : If channel is none, getspecialuserroles() returns all roles for the user // let chatterroles = self.getspecialuserroles(trgchatter, channel); @@ -917,7 +1124,7 @@ impl IdentityManager { match trg_role { - Some(UserRole::Mod(a)) => { + Some(UserRole::Mod(_)) => { if let Some(trg_chnl) = channel.clone() { let chatterroles = self.getspecialuserroles(trgchatter.clone(), channel.clone()).await; @@ -925,7 +1132,10 @@ impl IdentityManager { // let rolemap = rolemap.unwrap(); if rolemap.contains(&UserRole::Mod(trg_chnl.clone())) { return ChangeResult::NoChange(String::from("Target User already has Target Role")); + } else if rolemap.contains(&UserRole::Broadcaster) { + return ChangeResult::NoChange(String::from("No need to do that for broadcaster")); } + // # otherwise, trg_role for the given chnl is not assigned to the trgchatter // chatterroles.push(UserRole::Mod(trg_chnl.clone())); // let a = self.special_roles_users; @@ -960,7 +1170,72 @@ impl IdentityManager { }, - Some(UserRole::SupMod(a)) => (), + Some(UserRole::SupMod(_)) => + { + if let Some(trg_chnl) = channel.clone() { + + let chatterroles = self.getspecialuserroles(trgchatter.clone(), channel.clone()).await; + let rolemap = chatterroles; + // let rolemap = rolemap.unwrap(); + if rolemap.contains(&UserRole::SupMod(trg_chnl.clone())) { + return ChangeResult::NoChange(String::from("Target User already has Target Role")); + } else if rolemap.contains(&UserRole::Broadcaster) { + return ChangeResult::NoChange(String::from("No need to do that for broadcaster")); + } + // # otherwise, trg_role for the given chnl is not assigned to the trgchatter + // chatterroles.push(UserRole::Mod(trg_chnl.clone())); + // let a = self.special_roles_users; + // let b = a.write().await; + // // let c = b.get_mut(&trgchatter); + // let c = (*b).; + + // [x] (!!) AROUND HERE - check if the user exists first, and at least add the user as we're promoting anyway + + { + let mut srulock = self.special_roles_users.write().await; + srulock.entry(trgchatter.clone()).or_insert(Arc::new(RwLock::new(vec![]))); + botinstance::botlog::trace(&format!("SRLOCK - 1st write > {:?}",srulock.entry(trgchatter.clone())), + Some("identity.rs > promote()".to_string()), None); + Log::flush(); + } + { + let mut srulock = self.special_roles_users.write().await; + srulock + .get_mut(&trgchatter) + .expect("Error getting roles") + // !! [ ] Unsure what happens if promoting a chatter that doesn't exist at + .write().await + .push(UserRole::SupMod(trg_chnl.clone())); + botinstance::botlog::trace(&format!("SRLOCK - 2st write > {:?}",srulock.entry(trgchatter.clone())), + Some("identity.rs > promote()".to_string()), None); + Log::flush(); + } + { + let mut srulock = self.special_roles_users.write().await; + // srulock + // .get_mut(&trgchatter) + // .expect("Error getting roles") + // // !! [ ] Unsure what happens if promoting a chatter that doesn't exist at + // .write().await + // .(UserRole::Mod(trg_chnl)); + // let indx = srulock.iter().position() + let mut uroleslock = srulock + .get_mut(&trgchatter) + .expect("Error getting roles") + // !! [ ] Unsure what happens if promoting a chatter that doesn't exist at + .write().await; + if let Some(indx) = uroleslock.iter().position(|value| *value == UserRole::Mod(trg_chnl.clone())){ + uroleslock.swap_remove(indx); + } + + botinstance::botlog::trace(&format!("SRLOCK - 2st write > {:?}",uroleslock), + Some("identity.rs > promote()".to_string()), None); + Log::flush(); + } + + return ChangeResult::Success(String::from("Promotion Successful")); + } + } , Some(UserRole::BotAdmin) => { let chatterroles = self.getspecialuserroles(trgchatter.clone(), channel.clone()).await;