forcebot_rs/src/core/identity.rs

2843 lines
91 KiB
Rust
Raw Normal View History

2024-03-25 17:46:57 -04:00
const OF_CMD_CHANNEL:Channel = Channel(String::new());
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-24 14:09:08 -04:00
use crate::core::bot_actions::actions_util;
2024-03-24 14:38:09 -04:00
use crate::core::bot_actions::ExecBodyParams;
use crate::core::botinstance::{Channel,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-03-23 14:00:20 -04:00
module: BotModule(String::from("identity")),
2024-02-25 10:40:54 -05:00
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![
2024-03-25 17:46:57 -04:00
UserRole::Mod(OF_CMD_CHANNEL),
UserRole::SupMod(OF_CMD_CHANNEL),
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_core_to_modmgr(Arc::clone(&mgr)).await;
2024-03-25 19:36:45 -04:00
/*
2024-03-24 14:38:09 -04:00
async fn cmd_promote(params : ExecBodyParams) {
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()),
2024-03-24 14:38:09 -04:00
Some(&params.msg),
2024-02-25 10:40:54 -05:00
);
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-03-25 19:33:24 -04:00
promote -m <user>
promote -mod <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-03-25 19:33:24 -04:00
promote -v <user>
promote -vip <user>
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-03-24 14:38:09 -04:00
// println!("{}",params.msg.message_text);
2024-03-02 10:06:26 -05:00
botlog::trace(
2024-03-24 14:38:09 -04:00
format!("Twich Message > {}", params.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
2024-03-24 14:38:09 -04:00
let sendername = params.msg.clone().sender.name;
2024-03-24 14:38:09 -04:00
let mut argv = params.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-03-24 14:38:09 -04:00
for b in &params.msg.badges {
2024-02-25 10:40:54 -05:00
if b.name == "moderator" {
sender_badge = Some(ChatBadge::Mod);
} else if b.name == "broadcaster" {
sender_badge = Some(ChatBadge::Broadcaster);
2024-03-25 17:01:27 -04:00
} else if b.name == "vip" {
sender_badge = Some(ChatBadge::VIP);
2024-02-25 10:40:54 -05:00
}
2024-03-25 17:01:27 -04:00
};
2024-02-25 10:40:54 -05:00
2024-03-24 14:38:09 -04:00
let targetchnl = params.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-03-25 19:33:24 -04:00
// 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 { arg1 };
2024-02-01 08:40:09 -05:00
// [x] 2. promote trguser
// [x] Get a required lock first
2024-03-24 14:38:09 -04:00
let botlock = params.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,
);
2024-03-25 19:33:24 -04:00
Log::flush();
2024-03-25 19:33:24 -04:00
// // Believe this is just using this as a Constaint depending on input
// let target_bot_admin_role =
// if arg1 == Some("-admin") {
// Some(UserRole::BotAdmin)
// } else {
// None
// };
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
};
// let target_bot_admin_role =
// if arg1 == Some("-admin") {
// Some(UserRole::BotAdmin)
// } else if arg1 == Some("-v") {
// Some(UserRole::VIP)
// } else {
// None
// };
2024-02-25 10:40:54 -05:00
idlock
.promote(
sendername.clone(),
&sender_badge,
targetusr.to_string(),
2024-03-23 14:00:20 -04:00
Some(Channel(targetchnl.clone())),
2024-03-25 19:33:24 -04:00
target_role,
2024-02-25 10:40:54 -05:00
)
.await
}
None => {
2024-03-02 10:06:26 -05:00
botlog::debug(
2024-03-01 23:36:37 -05:00
"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()),
2024-03-24 14:38:09 -04:00
Some(&params.msg),
2024-03-02 12:21:18 -05:00
);
2024-02-14 01:09:55 -05:00
2024-03-25 14:11:21 -04:00
// We should call a notification around here
2024-03-24 16:59:50 -04:00
2024-03-25 14:11:21 -04:00
botlock.botmgrs.chat.send_botmsg(super::chat::BotMsgType::Notif(
outmsg.to_string()
),
params.clone(),
).await;
2024-03-24 16:59:50 -04:00
2024-03-02 10:06:26 -05:00
botlog::trace(
2024-03-01 23:36:37 -05:00
"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-03-25 19:36:45 -04:00
*/
2024-02-12 02:34:32 -05:00
let tempb = BotCommand {
2024-03-23 14:00:20 -04:00
module: BotModule(String::from("identity")),
2024-02-25 10:40:54 -05:00
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![
2024-03-25 17:46:57 -04:00
UserRole::Mod(OF_CMD_CHANNEL),
UserRole::SupMod(OF_CMD_CHANNEL),
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_core_to_modmgr(Arc::clone(&mgr)).await;
2024-03-25 19:36:45 -04:00
/*
2024-03-24 14:38:09 -04:00
async fn cmd_demote(params : ExecBodyParams) {
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()),
2024-03-24 14:38:09 -04:00
Some(&params.msg),
2024-02-25 10:40:54 -05:00
);
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
2024-03-25 19:33:24 -04:00
demote -m <user>
demote -mod <user>
demote -v <user>
demote -vip <user>
// 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-25 19:33:24 -04:00
let (arg1, arg2) = {
2024-03-24 14:38:09 -04:00
let mut argv = params.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
*/
2024-03-24 14:38:09 -04:00
let sendername = params.msg.clone().sender.name;
2024-02-25 10:40:54 -05:00
let mut sender_badge_mut: Option<ChatBadge> = None;
2024-03-24 14:38:09 -04:00
for b in &params.msg.badges {
if b.name == "moderator" {
sender_badge_mut = Some(ChatBadge::Mod);
} else if b.name == "broadcaster" {
sender_badge_mut = Some(ChatBadge::Broadcaster);
2024-03-25 17:01:27 -04:00
} else if b.name == "vip" {
sender_badge_mut = Some(ChatBadge::VIP);
}
2024-03-25 17:01:27 -04:00
};
let sender_badge = sender_badge_mut;
2024-03-25 19:33:24 -04:00
2024-03-24 14:38:09 -04:00
let targetchnl = params.msg.channel_login.to_lowercase();
2024-03-25 19:33:24 -04:00
// let targetusr = arg1;
let targetusr = if
arg1 == Some("-v")
|| arg1 == Some("-vip")
|| arg1 == Some("-m")
|| arg1 == Some("-mod")
{ arg2 }
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
};
/*
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-03-24 14:38:09 -04:00
let botlock = params.bot.read().await;
2024-02-25 10:40:54 -05:00
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 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(),
2024-03-23 14:00:20 -04:00
Some(Channel(targetchnl.clone())),
2024-03-25 19:33:24 -04:00
target_role,
2024-02-25 10:40:54 -05:00
)
.await
}
None => {
2024-03-02 10:06:26 -05:00
botlog::debug(
2024-03-01 23:36:37 -05:00
"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()),
2024-03-24 14:38:09 -04:00
Some(&params.msg),
2024-03-02 12:21:18 -05:00
);
2024-03-25 14:11:21 -04:00
botlock.botmgrs.chat.send_botmsg(super::chat::BotMsgType::Notif(
outmsg.to_string()
),
params.clone(),
).await;
2024-03-24 16:59:50 -04:00
2024-02-14 09:21:50 -05:00
}
2024-03-25 19:36:45 -04:00
*/
2024-02-25 10:40:54 -05:00
let tempcomm = BotCommand {
2024-03-23 14:00:20 -04:00
module: BotModule(String::from("identity")),
2024-02-25 10:40:54 -05:00
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-03-25 17:46:57 -04:00
UserRole::Mod(OF_CMD_CHANNEL),
UserRole::SupMod(OF_CMD_CHANNEL),
2024-01-31 21:30:08 -05:00
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_core_to_modmgr(Arc::clone(&mgr)).await;
2024-03-25 19:36:45 -04:00
/*
2024-03-24 14:38:09 -04:00
async fn getroles(params : ExecBodyParams) {
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()),
2024-03-24 14:38:09 -04:00
Some(&params.msg),
2024-02-25 10:40:54 -05:00
);
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-24 16:59:50 -04:00
2024-03-24 14:38:09 -04:00
let mut argv = params.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-03-24 14:38:09 -04:00
let botlock = params.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),
2024-03-24 14:38:09 -04:00
Some(Channel(params.msg.channel_login.to_lowercase())),
2024-02-25 10:40:54 -05:00
)
.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(
2024-03-24 14:38:09 -04:00
params.msg.sender.name.to_lowercase(),
2024-03-23 14:00:20 -04:00
Some(Channel(targetchnl.to_lowercase().to_string())),
2024-02-25 10:40:54 -05:00
)
.await;
2024-03-02 12:21:18 -05:00
2024-03-25 17:46:57 -04:00
// Below appears to be validating if getroles() should run based on caller's specific roles
// - No Need to add VIP here
2024-03-23 14:00:20 -04:00
if callersproles.contains(&UserRole::Mod(Channel(
2024-02-25 10:40:54 -05:00
targetchnl.to_lowercase().to_string(),
2024-03-23 14:00:20 -04:00
))) || callersproles.contains(&UserRole::SupMod(Channel(
2024-02-25 10:40:54 -05:00
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),
2024-03-23 14:00:20 -04:00
Some(Channel(targetchnl.to_lowercase())),
2024-02-25 10:40:54 -05:00
)
.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),
2024-03-24 14:38:09 -04:00
Some(Channel(params.msg.channel_login.to_lowercase())),
2024-02-25 10:40:54 -05:00
)
.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()),
2024-03-24 14:38:09 -04:00
Some(&params.msg),
2024-02-25 10:40:54 -05:00
);
2024-03-02 12:21:18 -05:00
botlog::trace(
2024-03-01 23:36:37 -05:00
"Evaluating special roles",
2024-02-25 10:40:54 -05:00
Some("identity.rs > init > getroles()".to_string()),
2024-03-24 14:38:09 -04:00
Some(&params.msg),
2024-02-25 10:40:54 -05:00
);
2024-02-13 19:49:36 -05:00
2024-03-24 14:38:09 -04:00
let outmsg = if ((targetuser.to_lowercase() == params.msg.channel_login.to_lowercase())
2024-02-25 10:40:54 -05:00
&& 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-03-25 17:46:57 -04:00
// Below appears to be validating if getroles() should run based on caller's specific roles
// - No Need to add VIP here
2024-03-23 14:00:20 -04:00
if sproles.contains(&UserRole::Mod(Channel(
2024-03-24 14:38:09 -04:00
params.msg.channel_login.to_lowercase(),
2024-03-23 14:00:20 -04:00
))) || sproles.contains(&UserRole::SupMod(Channel(
2024-03-24 14:38:09 -04:00
params.msg.channel_login.to_lowercase(),
2024-02-25 10:40:54 -05:00
))) || 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
2024-03-23 14:00:20 -04:00
} else if sproles.contains(&UserRole::Mod(Channel(
2024-03-24 14:38:09 -04:00
params.msg.channel_login.to_lowercase(),
2024-03-23 14:00:20 -04:00
))) || sproles.contains(&UserRole::SupMod(Channel(
2024-03-24 14:38:09 -04:00
params.msg.channel_login.to_lowercase(),
2024-02-25 10:40:54 -05:00
))) || 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()),
2024-03-24 14:38:09 -04:00
Some(&params.msg),
2024-02-25 10:40:54 -05:00
);
2024-03-02 12:21:18 -05:00
botlock.botmgrs.chat.send_botmsg(super::chat::BotMsgType::Notif(
outmsg.to_string()
),
params.clone(),
).await;
2024-03-24 16:59:50 -04:00
2024-02-13 19:49:36 -05:00
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-25 19:36:45 -04: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-03-25 19:36:45 -04:00
async fn cmd_promote(params : ExecBodyParams) {
botlog::trace(
"Called cmd promote",
Some("identity.rs > cmd_prommote()".to_string()),
Some(&params.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 <Chatter>` to assign them `BotAdmin` role
- `[ ] Broadcaster` & `BotAdmin` can `demote` a `SupMod` to make them a `Mod` or `promote` the other way
*/
/*
Usage :
promote <user>
promote -m <user>
promote -mod <user>
demote <user>
promote -v <user>
promote -vip <user>
promote -admin <user>
*/
// 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<ChatBadge> = None;
for b in &params.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
*/
2024-03-25 20:24:05 -04:00
let botlock = params.bot.read().await;
let id = botlock.get_identity();
let idlock = id.read().await;
2024-03-25 19:36:45 -04:00
// [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 }
2024-03-25 20:24:05 -04:00
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 }
}
2024-03-25 19:36:45 -04:00
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_bot_admin_role =
// if arg1 == Some("-admin") {
// Some(UserRole::BotAdmin)
// } else {
// None
// };
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
};
// let target_bot_admin_role =
// if arg1 == Some("-admin") {
// Some(UserRole::BotAdmin)
// } else if arg1 == Some("-v") {
// Some(UserRole::VIP)
// } else {
// None
// };
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(&params.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(&params.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 <Chatter>` to assign them `BotAdmin` role
- `[ ] Broadcaster` & `BotAdmin` can `demote` a `SupMod` to make them a `Mod` or `promote` the other way
*/
/*
Usage :
promote <user>
demote <user>
demote -m <user>
demote -mod <user>
demote -v <user>
demote -vip <user>
// promote -admin <user>
*/
// [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)
*/
2024-03-25 20:24:05 -04:00
// [x] Get a required lock first
let botlock = params.bot.read().await;
let id = botlock.get_identity();
let idlock = id.read().await;
2024-03-25 19:36:45 -04:00
let sendername = params.msg.clone().sender.name;
let mut sender_badge_mut: Option<ChatBadge> = None;
for b in &params.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 }
2024-03-25 20:24:05 -04:00
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 }
}
2024-03-25 19:36:45 -04:00
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(&params.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(&params.msg),
);
/*
Usage
getroles <user> <Channel>
- 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(&params.msg),
);
botlog::trace(
"Evaluating special roles",
Some("identity.rs > init > getroles()".to_string()),
Some(&params.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(&params.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
}
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,
2024-03-25 17:46:57 -04:00
Mod(Channel),
SupMod(Channel),
VIP(Channel),
2024-02-25 10:40:54 -05:00
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
2024-03-21 21:20:16 -04:00
#[derive(Debug, Clone)]
2024-01-29 22:57:07 -05:00
pub enum ChatBadge {
2024-01-29 12:41:26 -05:00
Broadcaster,
Mod,
2024-03-25 17:01:27 -04:00
VIP,
2024-01-29 12:41:26 -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-03-22 17:06:09 -04:00
// => 03.22 - Force - Made public because botmodules unit tests
pub 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-03-22 17:06:09 -04:00
// => 03.22 - Force - Made public because botmodules unit tests
pub 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),
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);
2024-03-25 17:01:27 -04:00
} else if b.name == "vip" {
sender_badge = Some(ChatBadge::VIP);
2024-01-29 22:57:07 -05:00
}
2024-03-25 17:01:27 -04:00
};
2024-01-29 22:57:07 -05:00
2024-02-25 10:40:54 -05:00
self.can_user_run(
msg.sender.name.to_owned(),
2024-03-23 14:00:20 -04:00
Channel(msg.channel_login.to_owned()),
2024-02-25 10:40:54 -05:00
sender_badge,
cmdreqroles,
)
.await
2024-03-22 21:06:15 -04:00
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: Channel,
2024-02-25 10:40:54 -05:00
chat_badge: Option<ChatBadge>,
cmdreqroles: Vec<UserRole>, // ) -> Result<Permissible,Box<dyn Error>> {
) -> (Permissible, ChangeResult) {
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 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.is_empty() {
2024-02-25 10:40:54 -05:00
return (
Permissible::Allow,
ChangeResult::NoChange("Command has no required cmdreqroles".to_string()),
);
}
2024-02-12 05:25:38 -05:00
2024-03-25 17:46:57 -04:00
let mut rolechange = ChangeResult::NoChange("".to_string());
2024-02-25 10:40:54 -05:00
match chat_badge {
2024-03-25 19:33:24 -04:00
// If ChatBadge::Broadcaster is observed,
// Check if cmdreqroles contains Channel Level Roles . Broadcaster should have Permissible::Allow for any of these
2024-02-25 10:40:54 -05:00
Some(ChatBadge::Broadcaster) => {
if cmdreqroles.contains(&UserRole::Broadcaster)
2024-03-25 19:33:24 -04:00
|| cmdreqroles.contains(&UserRole::Mod(OF_CMD_CHANNEL))
|| cmdreqroles.contains(&UserRole::SupMod(OF_CMD_CHANNEL))
|| cmdreqroles.contains(&UserRole::VIP(OF_CMD_CHANNEL))
2024-02-25 10:40:54 -05:00
{
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
2024-03-25 17:46:57 -04:00
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());
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-03-25 17:46:57 -04:00
if cmdreqroles.contains(&UserRole::Mod(OF_CMD_CHANNEL)) {
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,
);
2024-03-25 17:46:57 -04:00
return (Permissible::Allow, rolechange);
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-03-25 17:46:57 -04:00
if cmdreqroles.contains(&UserRole::SupMod(OF_CMD_CHANNEL)) {
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()))
{
2024-03-25 17:46:57 -04:00
return (Permissible::Allow, rolechange);
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) {
2024-03-25 17:46:57 -04:00
return (Permissible::Allow, rolechange);
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-03-25 17:46:57 -04:00
// [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);
}
}
}
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<Channel>,
2024-02-25 10:40:54 -05:00
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
/*
2024-03-25 19:33:24 -04:00
// [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
2024-03-25 19:33:24 -04:00
[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
2024-03-25 19:33:24 -04:00
[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
2024-02-25 10:40:54 -05:00
2024-03-25 19:33:24 -04:00
*/
2024-03-25 19:33:24 -04:00
// [x] 1. Check if Authorizer Mod or VIP Badge then Auto Promote to matching UserRole if not already assigned
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-03-25 19:33:24 -04:00
// [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;
}
2024-02-25 10:40:54 -05:00
_ => (),
}
2024-03-02 12:21:18 -05:00
}
2024-03-25 19:33:24 -04: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());
}
}
2024-03-25 20:11:50 -04:00
botlog::debug(
format!("VIP Evaluation : Channel = {:?} ; trg_role = {:?} ",
channel.clone(),trg_role
).as_str(),
Some("identity.rs > promote()".to_string()),
None,
);
2024-03-25 19:33:24 -04:00
// [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() {
2024-03-25 20:11:50 -04:00
if trg_role == Some(UserRole::VIP(trg_chnl.clone()))
&& ( authusrroles.contains(&UserRole::Mod(trg_chnl.clone()))
2024-03-25 19:33:24 -04:00
|| authusrroles.contains(&UserRole::SupMod(trg_chnl.clone()))
|| authusrroles.contains(&UserRole::Broadcaster)
)
2024-03-25 20:11:50 -04:00
{
2024-03-25 19:33:24 -04:00
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());
}
2024-03-25 20:11:50 -04:00
} else if trg_role == Some(UserRole::VIP(trg_chnl.clone()))
{
return ChangeResult::Failed(String::from("You're not permitted to do that"));
2024-03-25 19:33:24 -04:00
}
}
// [x] 4c. If target is Broadcaster, return NoChange
if trgusrroles.contains(&UserRole::Broadcaster) {
return ChangeResult::NoChange("Can't target broadcaster".to_string());
}
2024-03-25 19:33:24 -04:00
/*
2024-03-25 19:33:24 -04:00
[x] 4d. If Authorizer is a SupMod,Broadcaster,BotAdmin , can Promote Target Chatter > Mod
2024-02-25 10:40:54 -05:00
- NOTE : We do not validate trg_role here - app logic requires you to promote 1 to Mod and 1 more to SupMod
2024-03-25 19:33:24 -04:00
[x] 4e. If Authorizer is a Broadcaster,BotAdmin , can Promote a Target Mod > SupMod
2024-02-25 10:40:54 -05:00
- 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-03-25 19:33:24 -04:00
// 1. Checks first if Target User's Roles do not Include Broadcaster,Mod,SupMod for the Channel
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-03-25 19:33:24 -04:00
// 2. If Authorizer has Elevated Admin Roles for the Channel (SupMod,Broadcaster,BotAdmin) > set 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-25 19:33:24 -04:00
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<Channel>,
2024-03-25 19:33:24 -04:00
trg_role: Option<UserRole>,
2024-02-25 10:40:54 -05:00
) -> 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
2024-03-25 19:33:24 -04:00
// [x] 1. If Authorizer's Badge is Mod/VIP, 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;
}
2024-03-25 19:33:24 -04:00
// [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. 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());
}
2024-03-25 19:33:24 -04:00
// [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())) {
2024-03-25 20:11:50 -04:00
if !trgusrroles.contains(&UserRole::VIP(channel.clone())) {
2024-03-25 21:26:32 -04:00
return ChangeResult::NoChange("Already does not have VIP role".to_string());
2024-03-25 19:33:24 -04:00
}
else {
2024-03-25 20:11:50 -04:00
// self.affirm_chatter_in_db(trgchatter.clone()).await;
2024-03-25 19:33:24 -04:00
2024-03-25 20:11:50 -04:00
self.remove_role(trgchatter.clone(), UserRole::VIP(channel.clone())).await;
2024-03-25 19:33:24 -04:00
2024-03-25 20:11:50 -04:00
return ChangeResult::Success("Demotion Successful".to_string());
2024-03-25 19:33:24 -04:00
}
}
// [x] 5. - Mod/SupMod Logic
// [x] 5a. 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());
}
2024-03-25 19:33:24 -04:00
// [x] 5b. 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());
}
2024-03-25 19:33:24 -04:00
// [x] 5c. 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-03-25 19:33:24 -04:00
// [x] 5d. 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<Channel>,
2024-02-25 10:40:54 -05:00
) -> Vec<UserRole> {
2024-03-25 20:11:50 -04:00
/*
NOTE : Any NEW or CHANGES to UserRole type should have additional handling here
Specifically for Channel Elevated Roles
*/
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 {
2024-03-23 14:00:02 -04:00
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
2024-03-25 21:26:32 -04:00
// if chattername == chnl.0
if chattername == chnl.0.to_lowercase()
2024-03-23 14:00:02 -04:00
{
evalsproles.push(UserRole::Broadcaster);
2024-02-13 19:49:36 -05:00
}
2024-03-23 14:00:02 -04:00
Some(chnl)
},
2024-02-13 19:49:36 -05:00
None => None,
};
2024-03-23 14:00:02 -04:00
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-03-25 20:11:50 -04:00
if a.read().await.contains(&UserRole::VIP(channel.clone())) {
evalsproles.push(UserRole::VIP(channel.clone()));
}
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 {
2024-03-25 21:26:32 -04:00
use casual_logger::{Extension, Level};
2024-02-19 21:04:01 -05:00
use super::*;
#[test]
fn user_role_identity() {
Log::set_file_ext(Extension::Log);
2024-02-25 10:40:54 -05:00
assert_eq!(
2024-03-23 14:00:20 -04:00
UserRole::SupMod(Channel("strong".to_string())),
UserRole::SupMod(Channel("Strong".to_lowercase()))
2024-02-25 10:40:54 -05:00
);
}
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,
2024-03-23 14:00:20 -04:00
// Channel::construct("twitchchanneltest".to_string()),
Channel("twitchchanneltest".to_string()),
2024-03-20 19:26:04 -04:00
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
2024-03-23 14:00:20 -04:00
// let channel = Some(Channel::construct("twitchchanneltest".to_string()));
let channel = Some(Channel("twitchchanneltest".to_string()));
2024-02-19 21:04:01 -05:00
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
2024-03-23 14:00:20 -04:00
let channel = Some(Channel("broadcasterer".to_string()));
2024-02-19 21:04:01 -05:00
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
2024-03-23 14:00:20 -04:00
assert!(rslt.contains(&UserRole::Mod(Channel("broadcasterer".to_string()))));
2024-02-19 21:04:01 -05:00
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-03-23 14:00:20 -04:00
assert!(rslt.contains(&UserRole::SupMod(Channel(
2024-02-25 10:40:54 -05:00
"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-23 14:00:20 -04:00
let channel = 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 authorizer = supchatter;
let authorizer_badge = &Some(ChatBadge::Broadcaster);
2024-03-23 14:00:20 -04:00
let channel = Some(Channel(broadcaster.clone()));
2024-02-19 21:04:01 -05:00
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 authorizer = botadmin;
let authorizer_badge = botadmin_badge;
2024-03-23 14:00:20 -04:00
let channel = Some(Channel("somechannel".to_string()));
2024-02-19 21:04:01 -05:00
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-03-23 14:00:20 -04:00
let channel = Some(Channel("somechannel".to_string()));
2024-02-19 21:04:01 -05:00
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-03-25 19:33:24 -04:00
let trg_role = None;
2024-02-19 21:04:01 -05:00
2024-02-25 10:40:54 -05:00
let rslt = test_id_mgr
.demote(
authorizer.clone(),
authorizer_badge,
trgchatter.clone(),
channel.clone(),
2024-03-25 19:33:24 -04:00
trg_role.clone(),
2024-02-25 10:40:54 -05:00
)
.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(),
2024-03-25 19:33:24 -04:00
trg_role.clone(),
2024-02-25 10:40:54 -05:00
)
.await;
assert_eq!(
rslt,
ChangeResult::Success("Demoted successfully".to_string())
);
let rslt = test_id_mgr
.demote(
authorizer.clone(),
authorizer_badge,
trgchatter.clone(),
channel.clone(),
2024-03-25 19:33:24 -04:00
trg_role.clone(),
2024-02-25 10:40:54 -05:00
)
.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
}
2024-03-25 21:26:32 -04:00
#[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 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(), 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().unwrap(),
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(), channel.clone())
.await;
assert_eq!(rslt,vec![UserRole::VIP(channel.unwrap())]);
}
2024-02-19 21:04:01 -05:00
}