forcebot_rs/src/core/identity.rs

1859 lines
63 KiB
Rust
Raw Normal View History

2024-01-29 06:18:27 -05:00
use std::collections::HashMap;
2024-03-02 12:21:18 -05:00
use std::sync::Arc;
2024-01-29 11:09:33 -05:00
2024-03-02 12:21:18 -05:00
use tokio::sync::RwLock;
2024-01-29 11:09:33 -05:00
2024-03-01 23:36:37 -05:00
use twitch_irc::message::PrivmsgMessage;
2024-01-29 11:09:33 -05:00
2024-03-01 23:36:37 -05:00
use casual_logger::Log;
2024-02-04 14:28:37 -05:00
2024-03-02 12:21:18 -05:00
use crate::core::bot_actions::actions_util::{self, BotAR};
2024-03-21 00:05:52 -04:00
use crate::core::botinstance::{ChType,ChangeResult};
2024-03-02 12:21:18 -05:00
use crate::core::botlog;
use crate::core::botmodules::{BotActionTrait, BotCommand, BotModule, ModulesManager};
2024-02-12 01:25:12 -05:00
2024-03-20 19:08:01 -04:00
use dotenv::dotenv;
use std::env;
2024-01-29 06:18:27 -05:00
fn adminvector() -> Vec<String> {
vec![String::from("ModulatingForce")]
//vec![]
2024-01-29 06:18:27 -05:00
}
2024-03-20 19:08:01 -04:00
pub fn otherbots_vector() -> Vec<String> {
// vec![String::from("ModulatingForce")]
// //vec![]
dotenv().ok();
let mut other_bots = Vec::new();
if let Ok(value) = env::var("OtherBots") {
for bot in value.split(',') {
other_bots.push(String::from(bot).to_lowercase())
}
}
botlog::debug(
&format!(
"OtherBots : {:?}",other_bots,
),
Some("identity.rs > otherbots_vector()".to_string()),
None,
);
other_bots
}
2024-02-25 10:40:54 -05:00
pub async fn init(mgr: Arc<ModulesManager>) {
2024-03-02 10:06:26 -05:00
botlog::trace(
2024-03-02 12:21:18 -05:00
"Went into Identity Module init",
2024-02-25 10:40:54 -05:00
Some("identity.rs > init()".to_string()),
None,
);
2024-02-12 01:25:12 -05:00
2024-02-12 02:34:32 -05:00
let tempb = BotCommand {
2024-02-25 10:40:54 -05:00
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"),
required_roles: vec![
UserRole::Mod(ChType::Channel(String::new())),
UserRole::SupMod(ChType::Channel(String::new())),
UserRole::Broadcaster,
UserRole::BotAdmin,
2024-02-25 10:40:54 -05:00
],
2024-02-12 02:34:32 -05:00
};
2024-02-25 10:40:54 -05:00
2024-03-20 23:26:05 -04:00
// tempb.add_to_modmgr(Arc::clone(&mgr)).await;
tempb.add_core_to_modmgr(Arc::clone(&mgr)).await;
2024-01-29 11:09:33 -05:00
2024-03-01 23:36:37 -05:00
async fn cmd_promote(bot: BotAR, msg: PrivmsgMessage) {
2024-03-02 10:06:26 -05:00
botlog::trace(
2024-02-25 10:40:54 -05:00
"Called cmd promote",
Some("identity.rs > cmd_prommote()".to_string()),
Some(&msg),
);
2024-01-29 12:41:26 -05:00
2024-01-31 21:30:08 -05:00
// -- 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
2024-01-30 15:07:40 -05:00
/*
- `promote` / `demote`
- [ ] `SupMod` & `Broadcaster` & `BotAdmin` can run
2024-02-25 10:40:54 -05:00
- [ ] `UserRole`s that can run, can
2024-01-30 15:07:40 -05:00
- [ ] run `promote` on a regular `Chatter` to make them a `Mod`
- [ ] run `demote` on a `Mod` to make them a `Chatter`
2024-02-25 10:40:54 -05:00
- [ ] Only `BotAdmin` can :
2024-01-30 15:07:40 -05:00
- [ ] target themselves to `promote` / `demote` , in the case that they want to make themselves either a `Mod` or `SupMod` for the channel temporarily
2024-02-25 10:40:54 -05:00
- [ ] `promote admin <Chatter>` to assign them `BotAdmin` role
2024-02-14 01:09:55 -05:00
- `[ ] Broadcaster` & `BotAdmin` can `demote` a `SupMod` to make them a `Mod` or `promote` the other way
2024-01-30 15:07:40 -05:00
*/
2024-01-31 21:30:08 -05:00
/*
2024-02-25 10:40:54 -05:00
Usage :
2024-01-31 21:30:08 -05:00
2024-02-14 01:09:55 -05:00
promote <user>
2024-01-31 21:30:08 -05:00
2024-02-25 10:40:54 -05:00
demote <user>
2024-01-31 21:30:08 -05:00
2024-02-14 01:09:55 -05:00
promote -admin <user>
2024-01-31 21:30:08 -05:00
2024-02-25 10:40:54 -05:00
*/
2024-02-04 14:28:37 -05:00
2024-02-13 10:11:49 -05:00
// println!("{}",msg.message_text);
2024-03-02 10:06:26 -05:00
botlog::trace(
2024-03-02 12:21:18 -05:00
format!("Twich Message > {}", msg.message_text).as_str(),
2024-02-25 10:40:54 -05:00
Some("identity.rs > cmd_promote()".to_string()),
None,
);
2024-02-13 10:11:49 -05:00
let sendername = msg.clone().sender.name;
2024-03-01 23:36:37 -05:00
let mut argv = msg.message_text.split(' ');
2024-02-01 08:40:09 -05:00
2024-02-25 10:40:54 -05:00
argv.next(); // Skip the command name
2024-02-01 08:40:09 -05:00
2024-02-25 10:40:54 -05:00
let arg1 = argv.next();
2024-02-01 08:40:09 -05:00
2024-02-25 10:40:54 -05:00
let arg2 = argv.next();
2024-02-01 08:40:09 -05:00
2024-02-25 10:40:54 -05:00
let mut sender_badge: Option<ChatBadge> = None;
2024-02-25 10:40:54 -05:00
for b in &msg.badges {
if b.name == "moderator" {
sender_badge = Some(ChatBadge::Mod);
} else if b.name == "broadcaster" {
sender_badge = Some(ChatBadge::Broadcaster);
}
}
let targetchnl = msg.channel_login.to_lowercase();
2024-02-25 10:40:54 -05:00
/*
2024-02-25 10:40:54 -05:00
[x] 1. Get trgusr (regardless of -admin flag)
[x] 2. promote trguser
[x] 3. Output resulting change
2024-02-25 10:40:54 -05:00
*/
// [x] 1. Get trgusr (regardless of -admin flag)
2024-02-25 10:40:54 -05:00
let targetusr = if arg1 == Some("-admin") { arg2 } else { arg1 };
2024-02-01 08:40:09 -05:00
// [x] 2. promote trguser
// [x] Get a required lock first
let botlock = bot.read().await;
let id = botlock.get_identity();
let idlock = id.read().await;
let rslt = match targetusr {
Some(targetusr) => {
2024-03-02 10:06:26 -05:00
botlog::debug(
2024-03-01 23:36:37 -05:00
"running promote()",
2024-02-25 10:40:54 -05:00
Some("identity.rs > cmd_promote()".to_string()),
None,
);
Log::flush();
2024-02-25 10:40:54 -05:00
let target_bot_admin_role = if arg1 == Some("-admin") {
Some(UserRole::BotAdmin)
} else {
None
};
2024-02-25 10:40:54 -05:00
idlock
.promote(
sendername.clone(),
&sender_badge,
targetusr.to_string(),
Some(ChType::Channel(targetchnl.clone())),
target_bot_admin_role,
)
.await
}
None => {
2024-03-02 10:06:26 -05:00
botlog::debug(
2024-03-01 23:36:37 -05:00
// &format!("No Targer User argument"),
"No Targer User argument",
2024-02-25 10:40:54 -05:00
Some("identity.rs > cmd_demote()".to_string()),
None,
);
Log::flush();
ChangeResult::NoChange("No Targer User".to_string())
}
};
2024-02-25 10:40:54 -05:00
// [x] 3. Output resulting change
2024-03-02 12:21:18 -05:00
let outmsg = match rslt {
ChangeResult::Success(a) => {
2024-03-02 12:21:18 -05:00
format!("o7 Successfully promoted : {a}")
2024-02-25 10:40:54 -05:00
}
ChangeResult::Failed(a) => {
2024-03-02 12:21:18 -05:00
format!("PoroSad failed to promote : {a}")
2024-02-25 10:40:54 -05:00
}
ChangeResult::NoChange(a) => {
2024-03-02 12:21:18 -05:00
format!("uuh No Promotion Change : {a}")
2024-02-25 10:40:54 -05:00
}
2024-03-02 12:21:18 -05:00
};
2024-02-14 01:09:55 -05:00
2024-03-02 12:21:18 -05:00
botlog::debug(
outmsg.as_str(),
Some("identity.rs > cmd_prommote()".to_string()),
Some(&msg),
);
2024-02-14 01:09:55 -05:00
2024-03-02 12:21:18 -05:00
botlock
.botmgrs
.chat
.say_in_reply_to(&msg, outmsg.to_string())
.await;
2024-02-14 01:09:55 -05:00
2024-03-02 10:06:26 -05:00
botlog::trace(
2024-03-01 23:36:37 -05:00
// &format!("End of cmd_promote()"),
"End of cmd_promote()",
2024-02-25 10:40:54 -05:00
Some("identity.rs > cmd_prommote()".to_string()),
None,
);
2024-01-29 11:09:33 -05:00
}
2024-02-12 02:34:32 -05:00
let tempb = BotCommand {
2024-02-25 10:40:54 -05:00
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"),
required_roles: vec![
UserRole::Mod(ChType::Channel(String::new())),
UserRole::SupMod(ChType::Channel(String::new())),
UserRole::Broadcaster,
UserRole::BotAdmin,
2024-02-25 10:40:54 -05:00
],
2024-02-12 02:34:32 -05:00
};
2024-02-25 10:40:54 -05:00
2024-03-20 23:26:05 -04:00
// tempb.add_to_modmgr(Arc::clone(&mgr)).await;
// add_core_to_modmgr
tempb.add_core_to_modmgr(Arc::clone(&mgr)).await;
2024-01-29 11:09:33 -05:00
2024-03-01 23:36:37 -05:00
async fn cmd_demote(bot: BotAR, msg: PrivmsgMessage) {
2024-03-02 10:06:26 -05:00
botlog::debug(
2024-02-25 10:40:54 -05:00
"Called cmd demote",
Some("identity.rs > cmd_demote()".to_string()),
Some(&msg),
);
2024-02-14 01:09:55 -05:00
Log::flush();
2024-02-25 10:40:54 -05:00
2024-02-14 01:09:55 -05:00
// -- 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
2024-02-25 10:40:54 -05:00
- [ ] `UserRole`s that can run, can
2024-02-14 01:09:55 -05:00
- [ ] run `promote` on a regular `Chatter` to make them a `Mod`
- [ ] run `demote` on a `Mod` to make them a `Chatter`
2024-02-25 10:40:54 -05:00
- [ ] Only `BotAdmin` can :
2024-02-14 01:09:55 -05:00
- [ ] target themselves to `promote` / `demote` , in the case that they want to make themselves either a `Mod` or `SupMod` for the channel temporarily
2024-02-25 10:40:54 -05:00
- [ ] `promote admin <Chatter>` to assign them `BotAdmin` role
2024-02-14 01:09:55 -05:00
- `[ ] Broadcaster` & `BotAdmin` can `demote` a `SupMod` to make them a `Mod` or `promote` the other way
*/
2024-01-29 11:09:33 -05:00
2024-02-14 01:09:55 -05:00
/*
2024-02-25 10:40:54 -05:00
Usage :
2024-02-14 01:09:55 -05:00
promote <user>
2024-02-25 10:40:54 -05:00
demote <user>
2024-02-14 01:09:55 -05:00
promote -admin <user>
2024-02-25 10:40:54 -05:00
2024-02-14 01:09:55 -05:00
*/
2024-01-31 21:30:08 -05:00
// [x] Unwraps arguments from message
2024-03-01 23:36:37 -05:00
let (arg1, _arg2) = {
let mut argv = msg.message_text.split(' ');
2024-02-25 10:40:54 -05:00
argv.next(); // Skip the command name
2024-02-25 10:40:54 -05:00
let arg1 = argv.next();
let arg2 = argv.next();
2024-02-25 10:40:54 -05:00
(arg1, arg2)
};
// ---
/*
2024-03-02 12:21:18 -05:00
- [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)
2024-02-25 10:40:54 -05:00
2024-03-02 12:21:18 -05:00
- [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
2024-03-02 12:21:18 -05:00
- [x] 3. Take ChangeResult and output response
2024-02-25 10:40:54 -05:00
*/
/*
2024-02-25 10:40:54 -05:00
- [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)
2024-02-25 10:40:54 -05:00
*/
let sendername = msg.clone().sender.name;
2024-02-25 10:40:54 -05:00
let mut sender_badge_mut: Option<ChatBadge> = None;
for b in &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 = msg.channel_login.to_lowercase();
/*
2024-02-25 10:40:54 -05:00
- [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
2024-02-25 10:40:54 -05:00
*/
2024-02-25 10:40:54 -05:00
// [x] Get a required lock first
2024-02-25 10:40:54 -05:00
let botlock = bot.read().await;
let id = botlock.get_identity();
let idlock = id.read().await;
let rslt = match targetusr {
Some(targetusr) => {
2024-03-02 10:06:26 -05:00
botlog::debug(
2024-03-01 23:36:37 -05:00
// &format!("running demote()"),
"running demote()",
2024-02-25 10:40:54 -05:00
Some("identity.rs > cmd_demote()".to_string()),
None,
);
Log::flush();
2024-02-25 10:40:54 -05:00
idlock
.demote(
sendername.clone(),
&sender_badge,
targetusr.to_string(),
Some(ChType::Channel(targetchnl.clone())),
)
.await
}
None => {
2024-03-02 10:06:26 -05:00
botlog::debug(
2024-03-01 23:36:37 -05:00
// &format!("No Targer User argument"),
"No Targer User argument",
2024-02-25 10:40:54 -05:00
Some("identity.rs > cmd_demote()".to_string()),
None,
);
Log::flush();
ChangeResult::NoChange("No Targer User".to_string())
}
};
/*
2024-02-25 10:40:54 -05:00
- [x] 3. Take ChangeResult and output response
2024-02-25 10:40:54 -05:00
*/
2024-03-02 12:21:18 -05:00
let outmsg = match rslt {
ChangeResult::Success(a) => {
2024-03-02 12:21:18 -05:00
format!("o7 Successfully demoted : {a}")
2024-02-25 10:40:54 -05:00
}
ChangeResult::Failed(a) => {
2024-03-02 12:21:18 -05:00
format!("PoroSad failed to demote : {a}")
2024-02-25 10:40:54 -05:00
}
ChangeResult::NoChange(a) => {
2024-03-02 12:21:18 -05:00
format!("uuh No Demotion Change : {a}")
2024-02-25 10:40:54 -05:00
}
2024-03-02 12:21:18 -05:00
};
2024-03-02 12:21:18 -05:00
botlog::debug(
outmsg.as_str(),
Some("identity.rs > cmd_demote()".to_string()),
Some(&msg),
);
botlock
.botmgrs
.chat
.say_in_reply_to(&msg, outmsg.to_string())
.await;
2024-02-14 09:21:50 -05:00
}
2024-02-25 10:40:54 -05:00
let tempcomm = 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![
2024-01-31 21:30:08 -05:00
UserRole::Mod(ChType::Channel(String::new())),
UserRole::SupMod(ChType::Channel(String::new())),
UserRole::Broadcaster,
UserRole::BotAdmin,
2024-02-25 10:40:54 -05:00
],
2024-02-12 02:34:32 -05:00
};
2024-01-31 21:30:08 -05:00
2024-03-20 23:26:05 -04:00
// tempcomm.add_to_modmgr(Arc::clone(&mgr)).await;
// add_core_to_modmgr
tempcomm.add_core_to_modmgr(Arc::clone(&mgr)).await;
2024-01-31 21:30:08 -05:00
2024-02-25 10:40:54 -05:00
async fn getroles(bot: BotAR, msg: PrivmsgMessage) {
2024-03-02 10:06:26 -05:00
botlog::debug(
2024-02-25 10:40:54 -05:00
"Called cmd getroles",
Some("identity.rs > cmd_getroles()".to_string()),
Some(&msg),
);
2024-01-31 21:30:08 -05:00
/*
Usage
getroles <user> <Channel>
2024-02-25 10:40:54 -05:00
- If channel is provided, provide roles for that channel specifically
2024-01-31 21:30:08 -05:00
*/
2024-03-01 23:36:37 -05:00
let mut argv = msg.message_text.split(' ');
2024-01-31 21:30:08 -05:00
2024-02-01 08:40:09 -05:00
argv.next(); // Skip the command name
2024-01-31 21:30:08 -05:00
let arg1 = argv.next();
let targetuser = match arg1 {
2024-02-25 10:40:54 -05:00
None => return, // exit if no arguments
2024-01-31 21:30:08 -05:00
Some(arg) => arg,
};
let arg2 = argv.next();
2024-02-25 10:40:54 -05:00
let targetchnl = arg2;
2024-01-31 21:30:08 -05:00
2024-02-12 01:25:12 -05:00
let botlock = bot.read().await;
2024-03-02 12:21:18 -05:00
let id = botlock.get_identity();
let idlock = id.read().await;
2024-02-04 14:28:37 -05:00
let sproles = match targetchnl {
2024-01-31 21:30:08 -05:00
None => {
2024-02-13 19:49:36 -05:00
// [ ] If targetchnl is not provided, default to pulling the current channel
2024-02-25 10:40:54 -05:00
idlock
.getspecialuserroles(
String::from(targetuser),
Some(ChType::Channel(msg.channel_login.to_lowercase())),
)
.await
}
2024-01-31 21:30:08 -05:00
Some(targetchnl) => {
2024-03-02 12:21:18 -05:00
// [x] gets special roles for caller
2024-02-25 10:40:54 -05:00
let callersproles = idlock
.getspecialuserroles(
msg.sender.name.to_lowercase(),
Some(ChType::Channel(targetchnl.to_lowercase().to_string())),
)
.await;
2024-03-02 12:21:18 -05:00
2024-02-25 10:40:54 -05:00
if callersproles.contains(&UserRole::Mod(ChType::Channel(
targetchnl.to_lowercase().to_string(),
))) || callersproles.contains(&UserRole::SupMod(ChType::Channel(
targetchnl.to_lowercase().to_string(),
2024-03-01 23:36:37 -05:00
))) || callersproles.contains(&UserRole::Broadcaster)
2024-02-25 10:40:54 -05:00
{
idlock
.getspecialuserroles(
String::from(targetuser),
Some(ChType::Channel(targetchnl.to_lowercase())),
)
.await
2024-02-13 19:49:36 -05:00
} else {
// Otherwise, don't get the target channel, return the current channel instead
2024-02-25 10:40:54 -05:00
idlock
.getspecialuserroles(
String::from(targetuser),
Some(ChType::Channel(msg.channel_login.to_lowercase())),
)
.await
2024-02-13 19:49:36 -05:00
}
2024-02-25 10:40:54 -05:00
}
2024-02-04 14:28:37 -05:00
};
2024-01-31 21:30:08 -05:00
2024-03-02 10:06:26 -05:00
botlog::debug(
2024-02-25 10:40:54 -05:00
&format!("User roles of Target Chatter >> {:?}", sproles),
Some("identity.rs > init > getroles()".to_string()),
Some(&msg),
);
2024-03-02 12:21:18 -05:00
botlog::trace(
2024-03-01 23:36:37 -05:00
// &format!("Evaluating special roles"),
"Evaluating special roles",
2024-02-25 10:40:54 -05:00
Some("identity.rs > init > getroles()".to_string()),
Some(&msg),
);
2024-02-13 19:49:36 -05:00
2024-02-25 10:40:54 -05:00
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
2024-03-02 12:21:18 -05:00
2024-03-01 23:36:37 -05:00
let mut outmsg = "FeelsWowMan they're the broadcaster. ".to_string();
2024-03-02 12:21:18 -05:00
2024-02-25 10:40:54 -05:00
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)
{
2024-03-02 12:21:18 -05:00
outmsg += format!("Target chatter's user roles are : {:?}", sproles).as_str();
2024-02-13 19:49:36 -05:00
}
2024-02-25 10:40:54 -05:00
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)
{
format!("Target chatter's user roles are : {:?}", sproles)
} else {
2024-03-01 23:36:37 -05:00
"Target chatter has no special roles LULE ".to_string()
2024-02-25 10:40:54 -05:00
};
2024-02-13 19:49:36 -05:00
2024-03-02 10:06:26 -05:00
botlog::debug(
2024-03-02 12:21:18 -05:00
format!("Chat Say Reply message : {}", outmsg).as_str(),
2024-02-25 10:40:54 -05:00
Some("identity.rs > init > getroles()".to_string()),
Some(&msg),
);
2024-03-02 12:21:18 -05:00
2024-02-13 19:49:36 -05:00
botlock.botmgrs.chat.say_in_reply_to(&msg, outmsg).await;
2024-02-25 10:40:54 -05:00
// [ ] 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
2024-01-31 21:30:08 -05:00
}
2024-03-02 10:06:26 -05:00
botlog::trace(
2024-02-25 10:40:54 -05:00
"End of Init MOdule add",
Some("identity.rs > init ".to_string()),
None,
);
2024-01-31 21:30:08 -05:00
2024-02-13 19:49:36 -05:00
Log::flush();
2024-01-29 11:09:33 -05:00
}
2024-02-25 10:40:54 -05:00
#[derive(Debug, PartialEq, Eq, Clone)]
2024-01-29 11:09:33 -05:00
pub enum UserRole {
2024-02-25 10:40:54 -05:00
Chatter,
Mod(ChType), // String specifies Channel
SupMod(ChType), // String specifies Channel
Broadcaster,
BotAdmin,
2024-01-29 06:18:27 -05:00
}
2024-03-20 19:26:04 -04:00
#[derive(Debug, PartialEq, Eq)]
2024-01-29 22:57:07 -05:00
pub enum Permissible {
2024-02-25 10:40:54 -05:00
Allow,
Block,
2024-01-29 12:41:26 -05:00
}
2024-03-01 23:36:37 -05:00
type UserRolesDB = HashMap<String, Arc<RwLock<Vec<UserRole>>>>;
2024-01-31 18:36:23 -05:00
#[derive(Clone)]
2024-01-29 06:18:27 -05:00
pub struct IdentityManager {
2024-03-01 23:36:37 -05:00
special_roles_users: Arc<RwLock<UserRolesDB>>,
2024-02-25 10:40:54 -05:00
}
/*
HashMap<
String, <-- Chatter / Username
Vec<UserRole> -- <-- Vectors are basically arrays
>
*/
2024-01-29 06:18:27 -05:00
#[derive(Debug)]
2024-01-29 22:57:07 -05:00
pub enum ChatBadge {
2024-01-29 12:41:26 -05:00
Broadcaster,
Mod,
}
2024-03-21 00:05:52 -04:00
// #[derive(Debug, PartialEq, Eq)]
// pub enum ChangeResult {
// Success(String),
// Failed(String),
// NoChange(String),
// }
2024-01-31 21:30:08 -05:00
2024-01-29 06:18:27 -05:00
impl IdentityManager {
pub fn init() -> IdentityManager {
let mut a = HashMap::new();
for admn in adminvector() {
2024-02-25 10:40:54 -05:00
a.insert(
admn.to_lowercase(),
Arc::new(RwLock::new(vec![UserRole::BotAdmin])),
);
}
2024-01-29 06:18:27 -05:00
IdentityManager {
2024-02-25 10:40:54 -05:00
special_roles_users: Arc::new(RwLock::new(a)),
2024-01-29 06:18:27 -05:00
}
}
2024-01-29 12:41:26 -05:00
2024-02-25 10:40:54 -05:00
async fn add_role(&self, trgchatter: String, trg_role: UserRole) {
2024-02-18 19:23:50 -05:00
let mut srulock = self.special_roles_users.write().await;
let mut usrrolelock = srulock
.get_mut(&trgchatter)
.expect("Error retrieving roles")
2024-02-25 10:40:54 -05:00
.write()
.await;
usrrolelock.push(trg_role);
2024-02-18 19:23:50 -05:00
}
2024-02-25 10:40:54 -05:00
async fn remove_role(&self, trgchatter: String, trg_role: UserRole) {
2024-02-18 19:23:50 -05:00
let mut srulock = self.special_roles_users.write().await;
let mut usrrolelock = srulock
.get_mut(&trgchatter)
.expect("Error retrieving roles")
2024-02-25 10:40:54 -05:00
.write()
.await;
if let Some(indx) = usrrolelock.iter().position(|value| *value == trg_role) {
2024-02-18 19:23:50 -05:00
usrrolelock.swap_remove(indx);
}
}
2024-02-25 10:40:54 -05:00
async fn affirm_chatter_in_db(&self, trgchatter: String) {
2024-02-18 19:23:50 -05:00
let mut srulock = self.special_roles_users.write().await;
2024-02-25 10:40:54 -05:00
srulock
.entry(trgchatter.clone())
.or_insert(Arc::new(RwLock::new(vec![])));
2024-03-02 10:06:26 -05:00
botlog::trace(
2024-02-25 10:40:54 -05:00
&format!(
"Ensuring User in Roles {:?}",
srulock.entry(trgchatter.clone())
),
Some("IdentityManager > affirm_chatter_in_db()".to_string()),
None,
);
2024-02-18 19:23:50 -05:00
Log::flush();
}
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
2024-02-25 10:40:54 -05:00
2024-03-01 23:36:37 -05:00
pub async fn can_user_run_prvmsg(
2024-02-25 10:40:54 -05:00
&mut self,
msg: &PrivmsgMessage,
cmdreqroles: Vec<UserRole>,
) -> (Permissible, ChangeResult) {
2024-01-29 22:57:07 -05:00
// [ ] Check what Badges in PrivmsgMessage
2024-03-02 12:21:18 -05:00
botlog::trace(
2024-02-25 10:40:54 -05:00
"Checking within PRVMSG",
Some("identity.rs > can_user_run_PRVMSG()".to_string()),
2024-03-01 23:36:37 -05:00
// Some(&msg),
Some(msg),
2024-02-25 10:40:54 -05:00
);
2024-01-29 22:57:07 -05:00
2024-02-25 10:40:54 -05:00
let mut sender_badge: Option<ChatBadge> = None;
2024-01-29 22:57:07 -05:00
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{}) {
// }
2024-02-13 19:49:36 -05:00
// if let Some(sender_badge) = sender_badge {
// match sender_badge {
// Some(sender_badge) => {
2024-02-25 10:40:54 -05:00
// return &self.can_user_run(msg.sender.name.to_owned(),
// ChType::Channel(msg.channel_login.to_owned()),
// sender_badge,
// cmdreqroles
// return self.can_user_run(msg.sender.name.to_owned(),
// let a = Arc::new(Mutex::new(self));
// let mut a = a.lock().await;
// let a = **a;
// let a = a.can_user_run(msg.sender.name.to_owned(),
// ChType::Channel(msg.channel_login.to_owned()),
// sender_badge,
// cmdreqroles
// ) ;
// let a = *self;
// let a = Arc::new(Mutex::new(a));
// let a = a.lock().await.can_user_run(msg.sender.name.to_owned(),
// ChType::Channel(msg.channel_login.to_owned()),
// sender_badge,
// cmdreqroles
// ) ;
// return a;
// return self.can_user_run(msg.sender.name.to_owned(),
// ChType::Channel(msg.channel_login.to_owned()),
// sender_badge,
// cmdreqroles
// ).await
// * NOTE : We're preferring to pass the ChangeResult up , where we have access to Chat via BotInstance
// that have more strained chatting rules
// let evalpermissible = self.can_user_run(msg.sender.name.to_owned(),
// ChType::Channel(msg.channel_login.to_owned()),
// sender_badge,
// cmdreqroles
// ).await ;
// evalpermissible
// // }
// None => {
// }
2024-02-13 19:49:36 -05:00
// here , sender_badge is likely None
// This could be a regular chatter, BotAdmin,SupserMod
2024-01-29 22:57:07 -05:00
// [ ] Call can_user_run()
2024-02-12 01:25:12 -05:00
// (self,Permissible::Block)
2024-02-13 19:49:36 -05:00
// (Permissible::Block,ChangeResult::NoChange("".to_string()))
2024-02-25 10:40:54 -05:00
self.can_user_run(
msg.sender.name.to_owned(),
ChType::Channel(msg.channel_login.to_owned()),
sender_badge,
cmdreqroles,
)
.await
2024-01-29 22:57:07 -05:00
}
2024-02-25 10:40:54 -05:00
pub async fn can_user_run(
&mut self,
usr: String,
channelname: ChType,
chat_badge: Option<ChatBadge>,
cmdreqroles: Vec<UserRole>, // ) -> Result<Permissible,Box<dyn Error>> {
) -> (Permissible, ChangeResult) {
// println!{"Checking within can_user_run()"};
2024-03-02 10:06:26 -05:00
botlog::debug(
2024-02-25 10:40:54 -05:00
&format!(
"Checking within can_user_run() :
usr : {} ; channel : {:?} ; badge : {:?} ; cmdreqroles : {:?}",
2024-02-25 10:40:54 -05:00
usr, channelname, chat_badge, cmdreqroles
),
Some("identity.rs > can_user_run()".to_string()),
None,
);
/*
canUserRun -
2024-01-29 12:41:26 -05:00
2024-02-25 10:40:54 -05:00
Input :
usr:String,
channelname:ChType,
chat_badge:ChatBadge,
cmdreqroles:Vec<UserRole>
2024-01-29 12:41:26 -05:00
2024-02-25 10:40:54 -05:00
Output : Result<Permissible,Box<dyn Error>>
Some Possible outcomes : Ok(Permissible::Allow) , Ok(Permissible::Block)
2024-01-29 12:41:26 -05:00
2024-02-25 10:40:54 -05:00
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
2024-01-29 12:41:26 -05:00
2024-02-25 10:40:54 -05:00
Inputs and business logic determine if the user can run the command based on the command's required roles
*/
2024-01-29 12:41:26 -05:00
2024-02-25 10:40:54 -05:00
// Requirements
/*
[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)
*/
// [x] If cmdreqroles is empty vector , automatically assume Ok(Permissible::Allow)
2024-01-29 12:41:26 -05:00
2024-02-25 10:40:54 -05:00
// let idar = Arc::new(RwLock::new(self));
2024-01-29 12:41:26 -05:00
2024-02-25 10:40:54 -05:00
let usr = usr.to_lowercase();
2024-01-29 12:41:26 -05:00
2024-03-20 19:08:01 -04:00
let bot_vector = otherbots_vector() ; // result of pulling from Cargo.toml
botlog::trace(
&format!(
"Checking user is part of known bots: bot_vector.contains(&usr) : {:?}",bot_vector.contains(&usr)
),
Some("identity.rs > can_user_run()".to_string()),
None,
);
if bot_vector.contains(&usr) {
return (
Permissible::Block,
ChangeResult::NoChange("Other Bots Cannot Run Commands".to_string()),
);
}
2024-03-01 23:36:37 -05:00
// if cmdreqroles.len() == 0 {
if cmdreqroles.is_empty() {
2024-02-25 10:40:54 -05:00
// return Ok(Permissible::Allow)
return (
Permissible::Allow,
ChangeResult::NoChange("Command has no required cmdreqroles".to_string()),
);
}
2024-02-12 05:25:38 -05:00
2024-02-25 10:40:54 -05:00
let mut modrolechange = ChangeResult::NoChange("".to_string());
2024-02-25 10:40:54 -05:00
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)
Some(ChatBadge::Broadcaster) => {
if cmdreqroles.contains(&UserRole::Broadcaster)
|| cmdreqroles.contains(&UserRole::Mod(ChType::Channel(String::new())))
|| cmdreqroles.contains(&UserRole::SupMod(ChType::Channel(String::new())))
{
2024-01-29 22:57:07 -05:00
// return Ok(Permissible::Allow)
2024-02-25 10:40:54 -05:00
return (
Permissible::Allow,
ChangeResult::NoChange("Broadcaster Role".to_string()),
);
2024-01-29 22:57:07 -05:00
}
2024-02-25 10:40:54 -05:00
}
2024-01-29 22:57:07 -05:00
2024-02-25 10:40:54 -05:00
// [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)
Some(ChatBadge::Mod) => {
2024-03-02 10:06:26 -05:00
botlog::info(
2024-02-25 10:40:54 -05:00
"Mod Chatbadge detected",
Some("identity.rs > can_user_run()".to_string()),
None,
);
2024-03-02 12:21:18 -05:00
let rolesdb = Arc::clone(&self.special_roles_users);
2024-02-25 10:40:54 -05:00
self.affirm_chatter_in_db(usr.clone()).await;
2024-03-02 12:21:18 -05:00
let rolesdb_lock = rolesdb.write().await;
match (*rolesdb_lock).get(&usr.to_lowercase()) {
2024-02-25 10:40:54 -05:00
Some(usrroles)
if usrroles
.read()
.await
.contains(&UserRole::Mod(channelname.clone()))
|| usrroles
.read()
.await
.contains(&UserRole::SupMod(channelname.clone())) =>
{
// Do nothing when theh have a mod badge and have either a supmod or mod badge for the channel
2024-03-02 10:06:26 -05:00
botlog::trace(
2024-02-25 10:40:54 -05:00
"Already a mod in roles",
Some("identity.rs > can_user_run()".to_string()),
None,
);
}
2024-03-02 12:21:18 -05:00
2024-02-25 10:40:54 -05:00
_ => {
// In the event they have a mod badge , are running a bot command, but don't have a channel mod role yet...
2024-03-02 12:21:18 -05:00
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;
2024-02-25 10:40:54 -05:00
2024-03-02 12:21:18 -05:00
usrroles_lock.push(UserRole::Mod(channelname.clone()));
2024-02-25 10:40:54 -05:00
modrolechange = ChangeResult::Success("Auto Promoted Mod".to_string());
2024-03-02 12:21:18 -05:00
}
2024-01-29 22:57:07 -05:00
}
2024-02-25 10:40:54 -05:00
}
_ => (), // Don't handle other roles here
}
2024-01-29 22:57:07 -05:00
2024-02-25 10:40:54 -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)
2024-01-29 22:57:07 -05:00
2024-03-02 10:06:26 -05:00
botlog::trace(
2024-02-25 10:40:54 -05:00
&format!("cmd required roles : {:?}", cmdreqroles),
Some("identity.rs > can_user_run()".to_string()),
None,
);
2024-01-29 22:57:07 -05:00
2024-02-25 10:40:54 -05:00
if cmdreqroles.contains(&UserRole::Mod(ChType::Channel(String::new()))) {
2024-03-02 10:06:26 -05:00
botlog::trace(
2024-02-25 10:40:54 -05:00
"Command requires Mod Role",
Some("identity.rs > can_user_run()".to_string()),
None,
);
2024-03-01 23:36:37 -05:00
if let Some(a) = self
2024-02-25 10:40:54 -05:00
.special_roles_users
.read()
.await
.get(&usr.to_lowercase())
{
2024-03-02 10:06:26 -05:00
botlog::trace(
2024-02-25 10:40:54 -05:00
"Special roles found for user",
Some("identity.rs > can_user_run()".to_string()),
None,
);
if a.read().await.contains(&UserRole::Mod(channelname.clone()))
|| a.read()
.await
.contains(&UserRole::SupMod(channelname.clone()))
{
2024-03-02 10:06:26 -05:00
botlog::trace(
2024-02-25 10:40:54 -05:00
"> Special Role Identified : Mod ",
Some("identity.rs > can_user_run()".to_string()),
None,
);
return (Permissible::Allow, modrolechange);
2024-01-29 22:57:07 -05:00
}
2024-02-25 10:40:54 -05:00
}
}
2024-01-29 22:57:07 -05:00
2024-02-25 10:40:54 -05:00
// [x] If cmdreqroles includes UserRole::SupMod("") , checks if chatter has UserRole::SupMod(channelname::ChType) to determine if Ok(Permissible::Allow)
2024-01-29 22:57:07 -05:00
2024-02-25 10:40:54 -05:00
if cmdreqroles.contains(&UserRole::SupMod(ChType::Channel(String::new()))) {
2024-03-01 23:36:37 -05:00
if let Some(a) = self
2024-02-25 10:40:54 -05:00
.special_roles_users
.read()
.await
.get(&usr.to_lowercase())
{
if a.read()
.await
.contains(&UserRole::SupMod(channelname.clone()))
{
return (Permissible::Allow, modrolechange);
2024-01-29 22:57:07 -05:00
}
2024-02-25 10:40:54 -05:00
}
}
2024-01-29 22:57:07 -05:00
2024-02-25 10:40:54 -05:00
// [x] If cmdreqroles includes UserRole::BotAdmin and chatter has UserRole::BotAdmin , Ok(Permissible::Allow)
2024-03-02 10:06:26 -05:00
botlog::trace(
2024-02-25 10:40:54 -05:00
&format!(
"Eval cmdreqroles with botadmin : {}",
cmdreqroles.contains(&UserRole::BotAdmin)
),
Some("identity.rs > can_user_run()".to_string()),
None,
);
if cmdreqroles.contains(&UserRole::BotAdmin) {
2024-03-02 10:06:26 -05:00
botlog::trace(
2024-03-02 12:21:18 -05:00
format!(
2024-02-25 10:40:54 -05:00
"special roles get : {:?}",
2024-03-01 23:36:37 -05:00
self.special_roles_users
2024-02-25 10:40:54 -05:00
.read()
.await
.get(&usr.to_lowercase())
2024-03-02 12:21:18 -05:00
)
.as_str(),
2024-02-25 10:40:54 -05:00
Some("identity.rs > can_user_run()".to_string()),
None,
);
2024-03-01 23:36:37 -05:00
if let Some(a) = (self)
2024-02-25 10:40:54 -05:00
.special_roles_users
.read()
.await
.get(&usr.to_lowercase())
{
2024-03-02 10:06:26 -05:00
botlog::trace(
2024-03-02 12:21:18 -05:00
format!(
2024-02-25 10:40:54 -05:00
"special roles contains BotAdmin: {}",
a.read().await.contains(&UserRole::BotAdmin)
2024-03-02 12:21:18 -05:00
)
.as_str(),
2024-02-25 10:40:54 -05:00
Some("identity.rs > can_user_run()".to_string()),
None,
);
if a.read().await.contains(&UserRole::BotAdmin) {
return (Permissible::Allow, modrolechange);
2024-01-29 22:57:07 -05:00
}
2024-02-25 10:40:54 -05:00
}
2024-01-29 12:41:26 -05:00
}
2024-01-31 21:30:08 -05:00
2024-02-25 10:40:54 -05:00
(
Permissible::Block,
ChangeResult::NoChange("Not any permissiable condition".to_string()),
)
}
2024-02-01 08:40:09 -05:00
2024-02-25 10:40:54 -05:00
pub async fn promote(
&self,
authorizer: String,
authorizer_badge: &Option<ChatBadge>,
trgchatter: String,
channel: Option<ChType>,
trg_role: Option<UserRole>,
) -> ChangeResult {
2024-03-02 10:06:26 -05:00
botlog::trace(
2024-02-25 10:40:54 -05:00
&format!(
"IN VARS for promote() : auth : {} ; authbadge : {:?} ; trg : {} ; Channel {:?} ; {:?}",
2024-02-25 10:40:54 -05:00
authorizer,authorizer_badge,trgchatter,channel,trg_role),
Some("identity.rs > promote()".to_string()),
None,
);
2024-02-14 01:09:55 -05:00
Log::flush();
2024-02-01 08:40:09 -05:00
/*
[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
- 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
- NOTE : We do not validate trg_role here - app logic requires you to promote 1 to Mod and 1 more to SupMod
2024-02-25 10:40:54 -05:00
*/
// [x] 1. Check if Authorizer Mod Badge then Auto Promote to Mod if not Mod
2024-02-18 16:01:28 -05:00
let trgchatter = trgchatter.to_lowercase();
2024-02-25 10:40:54 -05:00
let (authusrroles, trgusrroles) = if let Some(channel) = channel.clone() {
let mut authusrroles = self
.getspecialuserroles(authorizer.to_lowercase().clone(), Some(channel.clone()))
.await;
2024-02-01 08:40:09 -05:00
2024-02-25 10:40:54 -05:00
{
match *authorizer_badge {
2024-02-25 10:40:54 -05:00
Some(ChatBadge::Mod)
if (!authusrroles.contains(&UserRole::Mod(channel.clone()))
&& !authusrroles.contains(&UserRole::SupMod(channel.clone()))) =>
{
authusrroles.push(UserRole::Mod(channel.clone()));
2024-02-19 21:04:01 -05:00
self.affirm_chatter_in_db(authorizer.clone()).await;
2024-02-25 10:40:54 -05:00
self.add_role(authorizer.clone(), UserRole::Mod(channel.clone()))
.await;
}
2024-02-25 10:40:54 -05:00
_ => (),
}
2024-03-02 12:21:18 -05:00
}
2024-02-25 10:40:54 -05:00
// [x] 2. Get Authorizer & Target Chatter Roles
2024-02-25 10:40:54 -05:00
let trgusrroles = self
.getspecialuserroles(trgchatter.to_lowercase().clone(), Some(channel.clone()))
.await;
2024-02-25 10:40:54 -05:00
(authusrroles, trgusrroles)
} else {
2024-03-01 23:36:37 -05:00
let authusrroles = self
2024-02-25 10:40:54 -05:00
.getspecialuserroles(authorizer.to_lowercase().clone(), None)
.await;
let trgusrroles = self
.getspecialuserroles(trgchatter.to_lowercase().clone(), None)
.await;
2024-03-02 12:21:18 -05:00
2024-02-25 10:40:54 -05:00
(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());
}
// [x] 4a. If Authorizer is BotAdmin & trg_role is Some(BotAdmin) , set Target as BotAdmin and return
if authusrroles.contains(&UserRole::BotAdmin) && trg_role == Some(UserRole::BotAdmin) {
if trgusrroles.contains(&UserRole::BotAdmin) {
return ChangeResult::NoChange("Already has the role".to_string());
} else {
2024-02-18 19:23:50 -05:00
self.affirm_chatter_in_db(trgchatter.clone()).await;
2024-02-18 19:23:50 -05:00
self.add_role(trgchatter.clone(), UserRole::BotAdmin).await;
return ChangeResult::Success("Promotion Successful".to_string());
}
}
// [x] 4b. If target is Broadcaster, return NoChange
if trgusrroles.contains(&UserRole::Broadcaster) {
return ChangeResult::NoChange("Can't target broadcaster".to_string());
}
/*
2024-02-25 10:40:54 -05:00
[ ] 4c. 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
- 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() {
2024-02-25 10:40:54 -05:00
if !trgusrroles.contains(&UserRole::Broadcaster)
&& !trgusrroles.contains(&UserRole::Mod(trg_chnl.clone()))
&& !trgusrroles.contains(&UserRole::SupMod(trg_chnl.clone()))
{
// target user is neither Mod nor SupMod && not broadcaster
// target's Next Role would be Mod
2024-02-25 10:40:54 -05:00
// Authorizer must be SupMod,Broadcaster,BotAdmin
// > Promote target to Mod
2024-02-25 10:40:54 -05:00
if authusrroles.contains(&UserRole::SupMod(trg_chnl.clone()))
|| authusrroles.contains(&UserRole::Broadcaster)
|| authusrroles.contains(&UserRole::BotAdmin)
{
2024-02-18 19:23:50 -05:00
self.affirm_chatter_in_db(trgchatter.clone()).await;
2024-02-25 10:40:54 -05:00
self.add_role(trgchatter.clone(), UserRole::Mod(trg_chnl.clone()))
.await;
2024-02-25 10:40:54 -05:00
return ChangeResult::Success(String::from("Promotion Successful"));
2024-03-01 23:36:37 -05:00
} else {
// Other else conditions would be mostly spcecial responses like ChangeResult::NoChange or ChangeResult::Fail
// related to authusrroles
return ChangeResult::Failed(String::from("You're not permitted to do that"));
}
2024-02-25 10:40:54 -05:00
} else if !trgusrroles.contains(&UserRole::Broadcaster)
&& trgusrroles.contains(&UserRole::Mod(trg_chnl.clone()))
&& !trgusrroles.contains(&UserRole::SupMod(trg_chnl.clone()))
{
// target user is a Mod && not broadcaster
// target's Next Role would be SupMod
// [ ] #todo Check first if target have SupMod - Optional but could be done to cleanup first
2024-02-25 10:40:54 -05:00
// Authorizer must be Broadcaster,BotAdmin
// > Promote target to SupMod
2024-02-25 10:40:54 -05:00
if authusrroles.contains(&UserRole::Broadcaster)
|| authusrroles.contains(&UserRole::BotAdmin)
{
2024-02-18 19:23:50 -05:00
self.affirm_chatter_in_db(trgchatter.clone()).await;
2024-02-25 10:40:54 -05:00
self.add_role(trgchatter.clone(), UserRole::SupMod(trg_chnl.clone()))
.await;
2024-02-18 19:23:50 -05:00
2024-02-25 10:40:54 -05:00
self.remove_role(trgchatter, UserRole::Mod(trg_chnl.clone()))
.await;
2024-02-12 05:25:38 -05:00
2024-02-25 10:40:54 -05:00
return ChangeResult::Success(String::from("Promotion Successful"));
} else {
return ChangeResult::Failed(String::from("You're not permitted to do that"));
}
2024-02-25 10:40:54 -05:00
} else if !trgusrroles.contains(&UserRole::Broadcaster)
&& trgusrroles.contains(&UserRole::SupMod(trg_chnl.clone()))
{
// target user is a SuMod && not broadcaster
// No Change
return ChangeResult::Failed(String::from("Already highest available role"));
2024-02-25 10:40:54 -05:00
} else {
// since handling for channel is already done, will be handling other trguserroles situations here
2024-02-25 10:40:54 -05:00
// At the moment, without any new roles, this should not be reached
2024-03-02 10:06:26 -05:00
botlog::warn(
2024-03-01 23:36:37 -05:00
"Code Warning : add handing for other trgusrroles",
2024-02-25 10:40:54 -05:00
Some("identity.rs > promote()".to_string()),
None,
);
2024-03-02 12:21:18 -05:00
2024-02-25 10:40:54 -05:00
return ChangeResult::Failed(String::from("Code Warning"));
}
};
2024-03-02 10:06:26 -05:00
botlog::warn(
2024-03-01 23:36:37 -05:00
"Runtime reached undeveloped code",
2024-02-25 10:40:54 -05:00
Some("identity.rs > promote()".to_string()),
None,
);
ChangeResult::Failed(String::from("ERROR"))
2024-02-25 10:40:54 -05:00
}
2024-01-31 21:30:08 -05:00
2024-02-25 10:40:54 -05:00
pub async fn demote(
&self,
authorizer: String,
authorizer_badge: &Option<ChatBadge>,
trgchatter: String,
channel: Option<ChType>,
) -> ChangeResult {
2024-03-02 10:06:26 -05:00
botlog::trace(&format!("IN VARS for demote() : Authorizer : {:?} ; Target Chatter : {} ; Target Channel : {:?}",
2024-02-25 10:40:54 -05:00
authorizer,trgchatter,channel), Some("identity.rs > demote()".to_string()), None);
2024-02-14 09:21:50 -05:00
Log::flush();
/*
2024-02-25 10:40:54 -05:00
Check authorizer roles (if any) for the target channel
Check Targer User's roles (if any) for the target channel
Target Channel may be NONE in the case of Non-Channel related roles (FUTURE ENH)
2024-02-14 09:21:50 -05:00
2024-02-25 10:40:54 -05:00
Use the roles of the above to determine whether the authorizer can demote the target user or not
*/
2024-02-14 09:21:50 -05:00
// [x] 1. If Authorizer's Badge is Mod, ensuring Sender is in DB as Mod(Channel)
2024-02-18 16:01:28 -05:00
let trgchatter = trgchatter.to_lowercase();
2024-02-14 09:21:50 -05:00
if let Some(channel) = channel {
2024-02-25 10:40:54 -05:00
let mut authusrroles = self
.getspecialuserroles(authorizer.to_lowercase().clone(), Some(channel.clone()))
2024-02-14 09:21:50 -05:00
.await;
// let authusrroles = authusrroles;
{
// let authusrroles_mut = &mut authusrroles;
// [x] Add Mod(channel) to authusrroles
// [x] #TODO also add to DB if possible?
match *authorizer_badge {
2024-02-25 10:40:54 -05:00
Some(ChatBadge::Mod)
if (!authusrroles.contains(&UserRole::Mod(channel.clone()))
&& !authusrroles.contains(&UserRole::SupMod(channel.clone()))) =>
{
authusrroles.push(UserRole::Mod(channel.clone()));
2024-02-25 10:40:54 -05:00
self.add_role(authorizer.clone(), UserRole::Mod(channel.clone()))
.await;
}
_ => (),
}
}
// [x] 2. Targer User's Vec<UserRole>
2024-02-14 09:21:50 -05:00
2024-02-25 10:40:54 -05:00
let trgusrroles = self
.getspecialuserroles(trgchatter.to_lowercase().clone(), Some(channel.clone()))
2024-02-14 09:21:50 -05:00
.await;
// [x] 3. Return if Authorizer & Target are same chatter and Authorizer is not a BotAdmin
if trgchatter == authorizer && !authusrroles.contains(&UserRole::BotAdmin) {
2024-02-25 10:40:54 -05:00
return ChangeResult::NoChange("Can't target yourself".to_string());
}
// [x] 4a. Authorizers who are BotAdmin, Broadcaster or Supermod can demote a Mod
2024-02-25 10:40:54 -05:00
if (authusrroles.contains(&UserRole::BotAdmin)
|| authusrroles.contains(&UserRole::Broadcaster)
|| authusrroles.contains(&UserRole::SupMod(channel.clone())))
&& trgusrroles.contains(&UserRole::Mod(channel.clone()))
{
self.remove_role(trgchatter.clone(), UserRole::Mod(channel.clone()))
.await;
return ChangeResult::Success("Demoted successfully".to_string());
}
// [x] 4b. Authorizers who are BotAdmin, Broadcaster can demote a SupMod
2024-02-25 10:40:54 -05:00
else if (authusrroles.contains(&UserRole::BotAdmin)
|| authusrroles.contains(&UserRole::Broadcaster))
&& trgusrroles.contains(&UserRole::SupMod(channel.clone()))
{
self.add_role(trgchatter.clone(), UserRole::Mod(channel.clone()))
.await;
self.remove_role(trgchatter.clone(), UserRole::SupMod(channel.clone()))
.await;
return ChangeResult::Success("Demoted successfully".to_string());
}
// [x] 4c. When Target chatter isnt a Mod or SupMod to demote
2024-02-25 10:40:54 -05:00
else if !trgusrroles.contains(&UserRole::Mod(channel.clone()))
&& !trgusrroles.contains(&UserRole::SupMod(channel.clone()))
{
return ChangeResult::Failed(
"Target chatter does not have a role that can be demoted".to_string(),
);
}
2024-02-18 16:01:28 -05:00
// [x] 4d. When they're only a Mod
else if authusrroles.contains(&UserRole::Mod(channel.clone())) {
2024-02-25 10:40:54 -05:00
return ChangeResult::Failed("You're not permitted to do that".to_string());
}
2024-02-14 09:21:50 -05:00
}
2024-03-02 10:06:26 -05:00
botlog::warn("Potential Unhandled Demotion Condition : Consider explicitely adding in for better handling",
2024-03-01 23:36:37 -05:00
Some("identity.rs > demote()".to_string()), None);
Log::flush();
2024-02-14 09:21:50 -05:00
ChangeResult::Failed(String::from("Did not meet criteria to demote succesfully"))
2024-01-31 21:30:08 -05:00
}
pub async fn getspecialuserroles(
2024-02-25 10:40:54 -05:00
&self,
chattername: String,
channel: Option<ChType>,
) -> Vec<UserRole> {
2024-02-12 05:25:38 -05:00
/*
2024-02-25 10:40:54 -05:00
Note : Ideally this be called for a given chatter name ?
*/
2024-02-13 19:49:36 -05:00
// [ ] !!! TODO: I don't think below is evaluating by given channel
2024-03-02 10:06:26 -05:00
botlog::debug(
2024-02-25 10:40:54 -05:00
&format!(
"IN VARS > chattername {} ; channel {:?}",
chattername, channel
),
Some("IdentityManager > getspecialuserroles()".to_string()),
None,
);
2024-02-13 19:49:36 -05:00
// resulting vector
let mut evalsproles = vec![];
2024-01-31 21:30:08 -05:00
2024-02-12 05:25:38 -05:00
let chattername = chattername.to_lowercase();
2024-01-31 21:30:08 -05:00
2024-02-13 19:49:36 -05:00
// Checks if broadcaster
let channel_out = match channel {
Some(channel_tmp) => {
match channel_tmp {
ChType::Channel(channel_tmp) => {
// 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 == channel_tmp.to_lowercase() {
evalsproles.push(UserRole::Broadcaster);
}
Some(ChType::Channel(channel_tmp))
2024-02-25 10:40:54 -05:00
} // _ => ()
2024-02-13 19:49:36 -05:00
}
}
None => None,
};
2024-03-02 12:21:18 -05:00
let rolesdb = Arc::clone(&self.special_roles_users);
let rolesdb_lock = rolesdb.read().await;
2024-02-12 05:25:38 -05:00
2024-03-02 12:21:18 -05:00
let vecroles = &(*rolesdb_lock).get(&chattername);
2024-02-13 19:49:36 -05:00
match vecroles {
Some(a) => {
// [ ] This needs to take the user roles for the user, then yield only the one for the channel if channel is explicitely provided
// Some(Arc::clone(a))
match channel_out {
Some(channel) => {
2024-03-02 10:06:26 -05:00
botlog::debug(
2024-02-25 10:40:54 -05:00
&format!("INTERNAL > All Roles found {:?}", &a),
Some("IdentityManager > getspecialuserroles()".to_string()),
None,
);
2024-02-13 19:49:36 -05:00
2024-03-02 12:21:18 -05:00
botlog::debug(
2024-02-25 10:40:54 -05:00
&format!(
"INTERNAL > eval special roles contains botadmin : {:?}",
a.read().await.contains(&UserRole::BotAdmin)
),
Some("IdentityManager > getspecialuserroles()".to_string()),
None,
);
2024-02-13 19:49:36 -05:00
if a.read().await.contains(&UserRole::BotAdmin) {
evalsproles.push(UserRole::BotAdmin);
2024-02-25 10:40:54 -05:00
}
2024-02-13 19:49:36 -05:00
if a.read().await.contains(&UserRole::Mod(channel.clone())) {
evalsproles.push(UserRole::Mod(channel.clone()));
}
if a.read().await.contains(&UserRole::SupMod(channel.clone())) {
evalsproles.push(UserRole::SupMod(channel.clone()));
2024-02-25 10:40:54 -05:00
}
2024-02-13 19:49:36 -05:00
// else {};
2024-02-25 10:40:54 -05:00
}
2024-02-13 19:49:36 -05:00
None => {
2024-02-25 10:40:54 -05:00
if a.read().await.contains(&UserRole::BotAdmin) {
2024-02-13 19:49:36 -05:00
evalsproles.push(UserRole::BotAdmin);
2024-02-25 10:40:54 -05:00
}
2024-02-13 19:49:36 -05:00
}
}
2024-02-25 10:40:54 -05:00
}
2024-02-13 19:49:36 -05:00
None => {
// here, the user has no special listed roles. Note though Broadcaster is not stored in special roles
// Do nothing in this case
// There may be an issue if the chattername does not exist at the moment in special_roles_users
2024-02-25 10:40:54 -05:00
// In this case, evalsproles would only contain Broadcaster flags if any
}
2024-02-12 05:25:38 -05:00
}
2024-02-04 14:28:37 -05:00
2024-03-02 10:06:26 -05:00
botlog::debug(
2024-02-25 10:40:54 -05:00
&format!("OUT > evalsproles {:?}", &evalsproles),
Some("IdentityManager > getspecialuserroles()".to_string()),
None,
);
2024-02-13 19:49:36 -05:00
2024-03-01 23:36:37 -05:00
// return evalsproles;
evalsproles
2024-01-31 21:30:08 -05:00
}
2024-01-29 06:18:27 -05:00
}
2024-02-19 21:04:01 -05:00
2024-03-02 12:21:18 -05:00
// =====================
// =====================
// =====================
// =====================
// =====================
2024-02-19 21:04:01 -05:00
#[cfg(test)]
mod core_identity {
use casual_logger::Extension;
use super::*;
#[test]
fn user_role_identity() {
Log::set_file_ext(Extension::Log);
2024-02-25 10:40:54 -05:00
assert_eq!(
UserRole::SupMod(ChType::Channel("strong".to_string())),
UserRole::SupMod(ChType::Channel("Strong".to_lowercase()))
);
}
2024-02-19 21:04:01 -05:00
2024-03-20 19:26:04 -04:00
#[tokio::test]
async fn otherbots_checks() {
Log::set_file_ext(Extension::Log);
let mut test_id_mgr = IdentityManager::init();
for bot in otherbots_vector() {
let (usr, channelname, chat_badge, cmdreqroles) = (
bot,
ChType::Channel("twitchchanneltest".to_string()),
None,
vec![]
);
let rslt = test_id_mgr.can_user_run(usr, channelname, chat_badge, cmdreqroles).await;
assert_eq!(
(Permissible::Block,
ChangeResult::NoChange("Other Bots Cannot Run Commands".to_string())),
rslt
);
}
}
2024-02-19 21:04:01 -05:00
#[tokio::test]
async fn promote_workflow_01() {
Log::set_file_ext(Extension::Log);
// Log::set_level(Level::Trace);
2024-02-25 10:40:54 -05:00
2024-02-19 21:04:01 -05:00
let test_id_mgr = IdentityManager::init();
// [x] Mod Attempts to Promote User
let channel = Some(ChType::Channel("twitchchanneltest".to_string()));
let trgchatter = "regularChatter".to_string();
let authorizer_badge = &Some(ChatBadge::Mod);
let authorizer = "chatMod".to_string();
let trg_role = None;
2024-02-25 10:40:54 -05:00
let rslt = test_id_mgr
.promote(
authorizer,
authorizer_badge,
trgchatter.clone(),
channel.clone(),
trg_role,
)
.await;
assert_eq!(
rslt,
ChangeResult::Failed(String::from("You're not permitted to do that"))
);
}
2024-02-19 21:04:01 -05:00
#[tokio::test]
async fn promote_workflow_02() {
Log::set_file_ext(Extension::Log);
// Log::set_level(Level::Trace);
2024-02-25 10:40:54 -05:00
2024-02-19 21:04:01 -05:00
let test_id_mgr = IdentityManager::init();
// [x] Broadcaster Promotes Chatter to SupMod
let channel = Some(ChType::Channel("broadcasterer".to_string()));
let trgchatter = "regularChatter".to_string();
let authorizer_badge = &Some(ChatBadge::Broadcaster);
let authorizer = "broadcasterer".to_string();
let trg_role = None;
2024-02-25 10:40:54 -05:00
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())
);
let rslt = test_id_mgr
.getspecialuserroles(trgchatter.clone(), channel.clone())
.await;
2024-02-19 21:04:01 -05:00
assert!(rslt.contains(&UserRole::Mod(ChType::Channel("broadcasterer".to_string()))));
2024-02-25 10:40:54 -05:00
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())
);
let rslt = test_id_mgr
.getspecialuserroles(trgchatter.clone(), channel.clone())
.await;
assert!(rslt.contains(&UserRole::SupMod(ChType::Channel(
"broadcasterer".to_string()
))));
let rslt = test_id_mgr
.promote(
authorizer.clone(),
authorizer_badge,
trgchatter.clone(),
channel.clone(),
trg_role.clone(),
)
.await;
assert_eq!(
rslt,
ChangeResult::Failed(String::from("Already highest available role"))
);
2024-02-19 21:04:01 -05:00
}
#[tokio::test]
async fn promote_workflow_03() {
Log::set_file_ext(Extension::Log);
// Log::set_level(Level::Trace);
2024-02-25 10:40:54 -05:00
2024-02-19 21:04:01 -05:00
let test_id_mgr = IdentityManager::init();
// [x] SupMod Promotes Chatter to SupMod
// [x] Broadcaster first promotes a SupMod
2024-02-25 10:40:54 -05:00
2024-02-19 21:04:01 -05:00
let broadcaster = "broadcasterer".to_string();
let broadcaster_badge = &Some(ChatBadge::Broadcaster);
2024-03-02 12:21:18 -05:00
// let channel = Some(ChType::Channel(broadcaster.clone()));
let channel = ChType::Channel(broadcaster.clone());
2024-02-19 21:04:01 -05:00
let supchatter = "superModerator".to_string();
let trg_role = None;
2024-02-25 10:40:54 -05:00
let rslt = test_id_mgr
.promote(
broadcaster.clone(),
broadcaster_badge,
supchatter.clone(),
2024-03-02 12:21:18 -05:00
Some(channel.clone()),
2024-02-25 10:40:54 -05:00
trg_role.clone(),
)
.await;
assert_eq!(
rslt,
ChangeResult::Success("Promotion Successful".to_string())
);
let rslt = test_id_mgr
.promote(
broadcaster.clone(),
broadcaster_badge,
supchatter.clone(),
2024-03-02 12:21:18 -05:00
Some(channel.clone()),
2024-02-25 10:40:54 -05:00
trg_role.clone(),
)
.await;
assert_eq!(
rslt,
ChangeResult::Success("Promotion Successful".to_string())
);
let rslt = test_id_mgr
2024-03-02 12:21:18 -05:00
.getspecialuserroles(supchatter.clone(), Some(channel.clone()))
2024-02-25 10:40:54 -05:00
.await;
2024-02-19 21:04:01 -05:00
2024-03-02 12:21:18 -05:00
assert!(rslt.contains(&UserRole::SupMod(channel)));
2024-02-19 21:04:01 -05:00
// [x] SupMod Attempts to Promote Chatter to SupMod
// let broadcaster = "broadcasterer".to_string();
let authorizer = supchatter;
let authorizer_badge = &Some(ChatBadge::Broadcaster);
let channel = Some(ChType::Channel(broadcaster.clone()));
let trgchatter = "regularChatter".to_string();
let trg_role = None;
2024-02-25 10:40:54 -05:00
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())
);
let rslt = test_id_mgr
.getspecialuserroles(trgchatter.clone(), channel.clone())
.await;
2024-02-19 21:04:01 -05:00
assert!(rslt.contains(&UserRole::Mod(channel.clone().unwrap())));
2024-02-25 10:40:54 -05:00
let rslt = test_id_mgr
.promote(
authorizer.clone(),
authorizer_badge,
trgchatter.clone(),
channel.clone(),
trg_role.clone(),
)
.await;
2024-02-19 21:04:01 -05:00
2024-02-25 10:40:54 -05:00
assert_eq!(
rslt,
ChangeResult::Failed("You're not permitted to do that".to_string())
);
}
2024-02-19 21:04:01 -05:00
#[tokio::test]
async fn promote_workflow_04() {
Log::set_file_ext(Extension::Log);
// Log::set_level(Level::Trace);
2024-02-25 10:40:54 -05:00
2024-02-19 21:04:01 -05:00
let test_id_mgr = IdentityManager::init();
// [x] BotAdmin Promotes Chatter to SupMod
// [x] Create BotAdmin first
let botadmin = "botadministrator".to_string();
let botadmin_badge = &None;
test_id_mgr.affirm_chatter_in_db(botadmin.clone()).await;
2024-02-25 10:40:54 -05:00
test_id_mgr
.add_role(botadmin.clone(), UserRole::BotAdmin)
.await;
2024-02-19 21:04:01 -05:00
2024-02-25 10:40:54 -05:00
let rslt = test_id_mgr
.getspecialuserroles(botadmin.clone(), None)
.await;
2024-02-19 21:04:01 -05:00
2024-02-25 10:40:54 -05:00
assert!(rslt.contains(&UserRole::BotAdmin));
2024-02-19 21:04:01 -05:00
// [x] SupMod Attempts to Promote Chatter to SupMod
// let broadcaster = "broadcasterer".to_string();
let authorizer = botadmin;
let authorizer_badge = botadmin_badge;
let channel = Some(ChType::Channel("somechannel".to_string()));
let trgchatter = "regularChatter".to_string();
let trg_role = None;
2024-02-25 10:40:54 -05:00
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())
);
let rslt = test_id_mgr
.getspecialuserroles(trgchatter.clone(), channel.clone())
.await;
2024-02-19 21:04:01 -05:00
assert!(rslt.contains(&UserRole::Mod(channel.clone().unwrap())));
2024-02-25 10:40:54 -05:00
let rslt = test_id_mgr
.promote(
authorizer.clone(),
authorizer_badge,
trgchatter.clone(),
channel.clone(),
trg_role.clone(),
)
.await;
2024-02-19 21:04:01 -05:00
2024-02-25 10:40:54 -05:00
assert_eq!(
rslt,
ChangeResult::Success("Promotion Successful".to_string())
);
2024-02-19 21:04:01 -05:00
2024-02-25 10:40:54 -05:00
let rslt = test_id_mgr
.getspecialuserroles(trgchatter.clone(), channel.clone())
.await;
2024-02-19 21:04:01 -05:00
assert!(rslt.contains(&UserRole::SupMod(channel.clone().unwrap())));
2024-02-25 10:40:54 -05:00
let rslt = test_id_mgr
.promote(
authorizer.clone(),
authorizer_badge,
trgchatter.clone(),
channel.clone(),
trg_role.clone(),
)
.await;
assert_eq!(
rslt,
ChangeResult::Failed(String::from("Already highest available role"))
);
}
2024-02-19 21:04:01 -05:00
#[tokio::test]
async fn demote_workflow_01() {
Log::set_file_ext(Extension::Log);
// Log::set_level(Level::Trace);
// [x] SupMod demotes a mod
// [x] create a SupMod first
2024-02-25 10:40:54 -05:00
2024-02-19 21:04:01 -05:00
let test_id_mgr = IdentityManager::init();
let supmod = "supmoder".to_string();
2024-03-02 12:21:18 -05:00
2024-02-19 21:04:01 -05:00
let channel = Some(ChType::Channel("somechannel".to_string()));
test_id_mgr.affirm_chatter_in_db(supmod.clone()).await;
2024-02-25 10:40:54 -05:00
test_id_mgr
.add_role(supmod.clone(), UserRole::SupMod(channel.clone().unwrap()))
.await;
2024-02-19 21:04:01 -05:00
2024-02-25 10:40:54 -05:00
let rslt = test_id_mgr
.getspecialuserroles(supmod.clone(), channel.clone())
.await;
2024-02-19 21:04:01 -05:00
assert!(rslt.contains(&UserRole::SupMod(channel.clone().unwrap())));
// [x] Create regular mod
let regmod = "moder".to_string();
test_id_mgr.affirm_chatter_in_db(regmod.clone()).await;
2024-02-25 10:40:54 -05:00
test_id_mgr
.add_role(regmod.clone(), UserRole::Mod(channel.clone().unwrap()))
.await;
2024-02-19 21:04:01 -05:00
2024-02-25 10:40:54 -05:00
let rslt = test_id_mgr
.getspecialuserroles(regmod.clone(), channel.clone())
.await;
2024-02-19 21:04:01 -05:00
assert!(rslt.contains(&UserRole::Mod(channel.clone().unwrap())));
// [x] Regular mod attempts to demote a supmod
let authorizer = regmod.clone();
let authorizer_badge = &None;
let trgchatter = supmod.clone();
2024-02-25 10:40:54 -05:00
let rslt = test_id_mgr
.demote(
authorizer.clone(),
authorizer_badge,
trgchatter.clone(),
channel.clone(),
)
.await;
2024-02-19 21:04:01 -05:00
2024-02-25 10:40:54 -05:00
assert_eq!(
rslt,
ChangeResult::Failed("You're not permitted to do that".to_string())
);
2024-02-19 21:04:01 -05:00
// [x] SupMod demotes regular mod
let authorizer = supmod;
let authorizer_badge = &None;
let trgchatter = regmod;
2024-02-25 10:40:54 -05:00
let rslt = test_id_mgr
.demote(
authorizer.clone(),
authorizer_badge,
trgchatter.clone(),
channel.clone(),
)
.await;
assert_eq!(
rslt,
ChangeResult::Success("Demoted successfully".to_string())
);
let rslt = test_id_mgr
.demote(
authorizer.clone(),
authorizer_badge,
trgchatter.clone(),
channel.clone(),
)
.await;
assert_eq!(
rslt,
ChangeResult::Failed(
"Target chatter does not have a role that can be demoted".to_string()
)
);
2024-02-19 21:04:01 -05:00
}
}