648 lines
23 KiB
Rust
648 lines
23 KiB
Rust
|
|
use std::collections::HashMap;
|
|
use std::error::Error;
|
|
|
|
use crate::core::botmodules::{ModulesManager,Listener,BotModule,BotActionTrait, BotCommand};
|
|
use crate::core::botmodules::bot_actions::actions_util;
|
|
|
|
use crate::core::botinstance::{self};
|
|
use twitch_irc::message::{Badge, PrivmsgMessage};
|
|
|
|
use crate::core::botmodules::ChType;
|
|
|
|
fn adminvector() -> Vec<String> {
|
|
vec![String::from("ModulatingForce")]
|
|
}
|
|
|
|
|
|
pub fn init(mgr:&mut ModulesManager)
|
|
{
|
|
|
|
BotCommand {
|
|
module : BotModule(String::from("identity")),
|
|
command : String::from("promote"), // command call name
|
|
alias : vec![], // String of alternative names
|
|
exec_body : actions_util::asyncbox(cmd_promote) ,
|
|
help : String::from("promote"),
|
|
required_roles : vec![
|
|
UserRole::Mod(ChType::Channel(String::new())),
|
|
UserRole::SupMod(ChType::Channel(String::new())),
|
|
UserRole::Broadcaster,
|
|
UserRole::BotAdmin,
|
|
],
|
|
}.add_to_modmgr(mgr);
|
|
|
|
async fn cmd_promote(bot:botinstance::BotManagers,msg:PrivmsgMessage) {
|
|
//println!("(#{}) {}: {}", msg.channel_login, msg.sender.name, msg.message_text);
|
|
println!("Called cmd promote");
|
|
|
|
// -- 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`
|
|
*/
|
|
|
|
|
|
/*
|
|
Usage :
|
|
|
|
promote <user> <channel>
|
|
|
|
demote <user> <channel>
|
|
|
|
promote admin <user>
|
|
|
|
*/
|
|
|
|
println!("{}",msg.message_text);
|
|
let mut argv = 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 &msg.badges {
|
|
if b.name == "moderator" {
|
|
sender_badge = Some(ChatBadge::Mod);
|
|
} else if b.name == "broadcaster" {
|
|
sender_badge = Some(ChatBadge::Broadcaster);
|
|
}
|
|
}
|
|
|
|
|
|
match arg1 {
|
|
Some(a) if a == String::from("admin") => {
|
|
// - BotAdmins can promote admin to give BotAdmin UserRole
|
|
let a = bot.identity.getspecialuserroles(msg.sender.name.to_lowercase(), Some(ChType::Channel(msg.channel_login.to_lowercase())));
|
|
|
|
if let Some(a) = a {
|
|
if a.contains(&UserRole::BotAdmin) {
|
|
println!("BotAdmin allowed to promote admin");
|
|
match bot.identity.promote(msg.sender.name.to_lowercase(), None, Some(UserRole::BotAdmin)) {
|
|
// Success(_) => {
|
|
// ;
|
|
// },
|
|
ChangeResult::Success(a) => println!("Succesfully promoted : {a} ;"),
|
|
ChangeResult::Failed(a) => println!("Failed to promote : {a} ; "),
|
|
ChangeResult::NoChange(a) => println!("No Changes Made : {a} ; "),
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
},
|
|
Some(_) => {
|
|
// -
|
|
|
|
},
|
|
_ => (),
|
|
}
|
|
|
|
|
|
|
|
// match String::from(arg1) {
|
|
// a if a == String::from("admin") => (),
|
|
// _ => (),
|
|
// }
|
|
|
|
|
|
// match argv[1] {
|
|
// String::from("admin") => (),
|
|
|
|
// }
|
|
|
|
let arg2 = argv.next();
|
|
|
|
let targetchnl = arg2;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
BotCommand {
|
|
module : BotModule(String::from("identity")),
|
|
command : String::from("demote"), // command call name
|
|
alias : vec![], // String of alternative names
|
|
exec_body : actions_util::asyncbox(cmd_demote) ,
|
|
help : String::from("demote"),
|
|
required_roles : vec![
|
|
UserRole::Mod(ChType::Channel(String::new())),
|
|
UserRole::SupMod(ChType::Channel(String::new())),
|
|
UserRole::Broadcaster,
|
|
UserRole::BotAdmin,
|
|
],
|
|
}.add_to_modmgr(mgr);
|
|
|
|
|
|
async fn cmd_demote(mut _chat:botinstance::BotManagers,_msg:PrivmsgMessage) {
|
|
println!("Called cmd demote");
|
|
}
|
|
|
|
|
|
|
|
BotCommand {
|
|
module : BotModule(String::from("identity")),
|
|
command : String::from("getroles"), // command call name
|
|
alias : vec![], // String of alternative names
|
|
exec_body : actions_util::asyncbox(getroles) ,
|
|
help : String::from("getroles"),
|
|
required_roles : vec![
|
|
UserRole::Mod(ChType::Channel(String::new())),
|
|
UserRole::SupMod(ChType::Channel(String::new())),
|
|
UserRole::Broadcaster,
|
|
UserRole::BotAdmin,
|
|
],
|
|
}.add_to_modmgr(mgr);
|
|
|
|
|
|
async fn getroles(bot:botinstance::BotManagers,msg:PrivmsgMessage) {
|
|
println!("Called cmd getroles");
|
|
|
|
/*
|
|
Usage
|
|
|
|
getroles <user> <Channel>
|
|
- If channel is provided, provide roles for that channel specifically
|
|
|
|
*/
|
|
|
|
// IN other code areas , I see this
|
|
// ServerMessage::Privmsg(msg) => {
|
|
// println!("(#{}) {}: {}", msg.channel_login, msg.sender.name, msg.message_text);
|
|
|
|
// println!("{}",msg.message_text);
|
|
let mut argv = msg.message_text.split(" ");
|
|
|
|
// for v in argv {
|
|
// println!("args : {v}");
|
|
// }
|
|
|
|
|
|
argv.next(); // Skip the command name
|
|
|
|
let arg1 = argv.next();
|
|
|
|
// if arg == None {
|
|
// return ; // Do nothing if no arguments
|
|
// }
|
|
|
|
|
|
let targetuser = match arg1 {
|
|
None => return , // exit if no arguments
|
|
Some(arg) => arg,
|
|
};
|
|
|
|
// match String::from(arg1) {
|
|
// a if a == String::from("admin") => (),
|
|
// _ => (),
|
|
// }
|
|
|
|
|
|
// match argv[1] {
|
|
// String::from("admin") => (),
|
|
|
|
// }
|
|
|
|
let arg2 = argv.next();
|
|
|
|
let targetchnl = arg2;
|
|
|
|
match targetchnl {
|
|
None => {
|
|
let a = bot.identity.getspecialuserroles(String::from(targetuser),None);
|
|
println!("Retrieved User Roles >> {:?}",a);
|
|
},
|
|
Some(targetchnl) => {
|
|
let a = bot.identity.getspecialuserroles(String::from(targetuser), Some(ChType::Channel(String::from(targetchnl))));
|
|
println!("Retrieved User Roles >> {:?}",a);
|
|
},
|
|
}
|
|
|
|
|
|
// let a = bot.identity.getuserroles(String::from("ModulatingForce"), Some(ChType::Channel(String::from("ModulatingForcebot"))));
|
|
// println!("{:?}",a);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
// #[derive(Debug, PartialEq, Eq, Hash, Clone)]
|
|
// pub enum ChType {
|
|
// Channel(String),
|
|
// }
|
|
|
|
#[derive(Debug, PartialEq, Eq , Clone)]
|
|
pub enum UserRole {
|
|
Chatter,
|
|
Mod(ChType), // String specifies Channel
|
|
SupMod(ChType), // String specifies Channel
|
|
Broadcaster,
|
|
BotAdmin,
|
|
|
|
}
|
|
|
|
|
|
pub enum Permissible {
|
|
Allow,
|
|
Block
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct IdentityManager {
|
|
special_roles_users : HashMap<String,Vec<UserRole>>, // # <-- (!) This must be String instead of ChType because we're checking a User not a Channel
|
|
// parent_mgr : Box<crate::core::botinstance::BotManagers>,
|
|
//parent_mgr : Option<Box<crate::core::botinstance::BotManagers>>,
|
|
}
|
|
|
|
pub enum ChatBadge {
|
|
Broadcaster,
|
|
Mod,
|
|
}
|
|
|
|
|
|
enum ChangeResult {
|
|
Success(String),
|
|
Failed(String),
|
|
NoChange(String),
|
|
}
|
|
|
|
|
|
impl IdentityManager {
|
|
|
|
pub fn init() -> IdentityManager {
|
|
let mut a = HashMap::new();
|
|
for admn in adminvector() {
|
|
a.insert(admn.to_lowercase(),vec![UserRole::BotAdmin]);
|
|
};
|
|
|
|
IdentityManager {
|
|
special_roles_users : a,
|
|
//parent_mgr : None,
|
|
}
|
|
}
|
|
|
|
// [ ] Maybe I should create a can_user_run version that simply takes PrvMsg, but then calls can_user_run directly
|
|
|
|
// pub fn can_user_run_PRVMSG(self,msg:&PrivmsgMessage,cmdreqroles:Vec<UserRole>) -> Result<Permissible,Box<dyn Error>>
|
|
pub fn can_user_run_PRVMSG(self,msg:&PrivmsgMessage,cmdreqroles:Vec<UserRole>) -> Permissible
|
|
{
|
|
// println!("(#{}) {}: {}", msg.channel_login, msg.sender.name, msg.message_text);
|
|
|
|
// [ ] Check what Badges in PrivmsgMessage
|
|
|
|
let mut sender_badge:Option<ChatBadge> = None;
|
|
|
|
for b in &msg.badges {
|
|
if b.name == "moderator" {
|
|
sender_badge = Some(ChatBadge::Mod);
|
|
} else if b.name == "broadcaster" {
|
|
sender_badge = Some(ChatBadge::Broadcaster);
|
|
}
|
|
}
|
|
|
|
// if &msg.badges.contains(Badge{}) {
|
|
|
|
// }
|
|
|
|
if let Some(sender_badge) = sender_badge {
|
|
// return &self.can_user_run(msg.sender.name.to_owned(),
|
|
// ChType::Channel(msg.channel_login.to_owned()),
|
|
// sender_badge,
|
|
// cmdreqroles
|
|
return self.can_user_run(msg.sender.name.to_owned(),
|
|
ChType::Channel(msg.channel_login.to_owned()),
|
|
sender_badge,
|
|
cmdreqroles
|
|
) ;
|
|
}
|
|
|
|
|
|
|
|
// [ ] Call can_user_run()
|
|
Permissible::Block
|
|
}
|
|
|
|
pub fn can_user_run(mut self,
|
|
usr:String,
|
|
channelname:ChType,
|
|
chat_badge:ChatBadge,
|
|
cmdreqroles:Vec<UserRole>
|
|
// ) -> Result<Permissible,Box<dyn Error>> {
|
|
) -> Permissible {
|
|
/*
|
|
canUserRun -
|
|
|
|
Input :
|
|
usr:String,
|
|
channelname:ChType,
|
|
chat_badge:ChatBadge,
|
|
cmdreqroles:Vec<UserRole>
|
|
|
|
Output : Result<Permissible,Box<dyn Error>>
|
|
Some Possible outcomes : Ok(Permissible::Allow) , Ok(Permissible::Block)
|
|
|
|
|
|
Description
|
|
For a Given Chatter (with any special ChatBadge) who ran the Command at a Given Channel , check if that user can
|
|
run the command based on the given cmdreqroles required by the command
|
|
|
|
Inputs and business logic determine if the user can run the command based on the command's required roles
|
|
*/
|
|
|
|
|
|
// 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)
|
|
|
|
if cmdreqroles.len() == 0 {
|
|
// return Ok(Permissible::Allow)
|
|
return Permissible::Allow
|
|
}
|
|
|
|
|
|
|
|
match chat_badge {
|
|
|
|
// [x] If chatBadge::Broadcaster ...
|
|
// [x] and cmdreqroles includes UserRole::Broadcaster , Ok(Permissible::Allow)
|
|
// [x] and cmdreqroles includes UserRole::Mod("") OR UserRole::SupMod("") , Ok(Permissible::Allow)
|
|
|
|
ChatBadge::Broadcaster => {
|
|
if cmdreqroles.contains(&UserRole::Broadcaster) ||
|
|
cmdreqroles.contains(&UserRole::Mod(ChType::Channel(String::new()))) ||
|
|
cmdreqroles.contains(&UserRole::SupMod(ChType::Channel(String::new()))) {
|
|
// return Ok(Permissible::Allow)
|
|
return Permissible::Allow
|
|
}
|
|
},
|
|
|
|
// [x] If chatBadge::Mod ...
|
|
// [x] Check if they have either UserRole::Mod(channelname::ChType) or UserRole::SupMod(channelname::ChType)
|
|
// [x] If not, assign them UserRole::Mod(channelname::ChType)
|
|
|
|
ChatBadge::Mod => {
|
|
|
|
// println!("Mod Chatbadge detected");
|
|
|
|
// println!("debug special roles : {:?}",self.special_roles_users);
|
|
// println!("debug usr : {}",&usr.to_lowercase());
|
|
|
|
// let Some((k,v)) = self.special_roles_users.get_key_value(usr);
|
|
// match self.special_roles_users.get_mut(&usr.to_lowercase()) {
|
|
match self.special_roles_users.get(&usr.to_lowercase()) {
|
|
Some(usrroles) => {
|
|
// println!("contains mod : {}", usrroles.contains(&UserRole::Mod(channelname.clone())));
|
|
// println!("contains supmod : {}", usrroles.contains(&UserRole::SupMod(channelname.clone())));
|
|
if usrroles.contains(&UserRole::Mod(channelname.clone())) ||
|
|
usrroles.contains(&UserRole::SupMod(channelname.clone())) {
|
|
// Do nothing - this is expected
|
|
} else {
|
|
// in this case, they have a ChatBadge::Mod but should have this for the channel
|
|
// let mut a = usrroles;
|
|
// usrroles.push(UserRole::Mod(channelname.clone()));
|
|
// a.push(UserRole::Mod(channelname.clone()));
|
|
self.special_roles_users
|
|
.get_mut(&usr.to_lowercase())
|
|
.expect("ERROR")
|
|
.push(UserRole::Mod(channelname.clone()));
|
|
// println!("debug special roles : {:?}",self.special_roles_users);
|
|
}
|
|
},
|
|
_ => ()
|
|
}
|
|
|
|
},
|
|
// _ => (),
|
|
}
|
|
|
|
// [x] If cmdreqroles includes UserRole::Mod("") , checks if chatter has UserRole::Mod(channelname::ChType) or UserRole::SupMod(channelname::ChType) to determine if Ok(Permissible::Allow)
|
|
|
|
println!("cmd required roles : {:?}",cmdreqroles);
|
|
|
|
if cmdreqroles.contains(&UserRole::Mod(ChType::Channel(String::new()))) {
|
|
// match self.special_roles_users.get(&channelname) {
|
|
// Some(usrroles) => {},
|
|
// None => (),
|
|
|
|
// }
|
|
|
|
println!("Mod Role required");
|
|
|
|
if let Some(a) = self.special_roles_users.get(&usr.to_lowercase()) {
|
|
if a.contains(&UserRole::Mod(channelname.clone())) || a.contains(&UserRole::SupMod(channelname.clone())){
|
|
// return Ok(Permissible::Allow);
|
|
return Permissible::Allow
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// [x] If cmdreqroles includes UserRole::SupMod("") , checks if chatter has UserRole::SupMod(channelname::ChType) to determine if Ok(Permissible::Allow)
|
|
|
|
|
|
if cmdreqroles.contains(&UserRole::SupMod(ChType::Channel(String::new()))) {
|
|
if let Some(a) = self.special_roles_users.get(&usr.to_lowercase()) {
|
|
if a.contains(&UserRole::SupMod(channelname.clone())) {
|
|
// return Ok(Permissible::Allow);
|
|
return Permissible::Allow
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// [x] If cmdreqroles includes UserRole::BotAdmin and chatter has UserRole::BotAdmin , Ok(Permissible::Allow)
|
|
|
|
println!("Eval cmdreqroles with botadmin : {}",cmdreqroles.contains(&UserRole::BotAdmin));
|
|
|
|
if cmdreqroles.contains(&UserRole::BotAdmin) {
|
|
println!("special roles get : {:?}",self.special_roles_users.get(&usr.to_lowercase()));
|
|
if let Some(a) = self.special_roles_users.get(&usr.to_lowercase()) {
|
|
println!("special roles contains BotAdmin: {}",a.contains(&UserRole::BotAdmin));
|
|
if a.contains(&UserRole::BotAdmin) {
|
|
// return Ok(Permissible::Allow);
|
|
return Permissible::Allow
|
|
}
|
|
}
|
|
}
|
|
|
|
Permissible::Block
|
|
}
|
|
|
|
pub fn promote(mut self,trgchatter:String,channel:Option<ChType>,trg_role:Option<UserRole>) -> ChangeResult {
|
|
|
|
// Note : If channel is none, getspecialuserroles() returns all roles for the user
|
|
|
|
// let chatterroles = self.getspecialuserroles(trgchatter, channel);
|
|
|
|
let chatterroles = self.getspecialuserroles(trgchatter.clone(), channel.clone());
|
|
|
|
let emptyvec = vec![];
|
|
|
|
let chatterroles = match chatterroles {
|
|
Some(a) => a,
|
|
_ => &(emptyvec),
|
|
};
|
|
|
|
|
|
match trg_role {
|
|
Some(UserRole::Mod(a)) => {
|
|
if let Some(trg_chnl) = channel {
|
|
if chatterroles.contains(&UserRole::Mod(trg_chnl.clone())) {
|
|
return ChangeResult::NoChange(String::from("Target User already has Target Role"));
|
|
}
|
|
// # otherwise, trg_role for the given chnl is not assigned to the trgchatter
|
|
// chatterroles.push(UserRole::Mod(trg_chnl.clone()));
|
|
self.special_roles_users
|
|
.get_mut(&trgchatter)
|
|
.expect("Error getting roles")
|
|
.push(UserRole::Mod(trg_chnl));
|
|
|
|
return ChangeResult::Success(String::from("Promotion Successful"));
|
|
}
|
|
|
|
|
|
},
|
|
Some(UserRole::SupMod(a)) => (),
|
|
Some(UserRole::BotAdmin) => (),
|
|
Some(_) => (),
|
|
None => (),
|
|
}
|
|
|
|
|
|
// match chatterroles {
|
|
// Some(chatterroles) => {
|
|
|
|
// // [x] chatter already has the target role
|
|
// if chatterroles.contains(&trg_role) {
|
|
// return ChangeResult::NoChange(String::from("Target User already has Target Role"));
|
|
// }
|
|
|
|
// // By this point, chatteroles does not contain target role
|
|
// // match trgRole {
|
|
// // Some(trgRole) => {
|
|
// // match trgRole {
|
|
// // UserRole::Mod(a) => {
|
|
|
|
// // },
|
|
// // UserRole::SupMod(a) => (),
|
|
// // UserRole::BotAdmin => (),
|
|
// // _ => (), // <-- do nothing with al other options
|
|
// // }
|
|
// // },
|
|
// // None => {
|
|
// // /*
|
|
// // - If trgRole is None , then promote by implicit rules . For example,
|
|
// // - For UserRoles without Mod or SupMod & Caller is SupMod | Broadcaster | BotAdmin > To Mod
|
|
// // - For Mod & Caller is SupMod | Broadcaster | BotAdmin > To SupMod
|
|
// // - For UserRoles without BotAdmin & Caller is BotAdmin > To BotAdmin
|
|
// // */
|
|
// // },
|
|
|
|
// // }
|
|
|
|
// // let trgRole = match trgRole {
|
|
// // Some(UserRole::Mod(a)) => a,
|
|
// // Some(UserRole::SupMod(a)) => a,
|
|
// // Some(UserRole::BotAdmin) => UserRole::BotAdmin,
|
|
// // None => {
|
|
// // /*
|
|
// // - If trgRole is None , then promote by implicit rules . For example,
|
|
// // - For UserRoles without Mod or SupMod & Caller is SupMod | Broadcaster | BotAdmin > To Mod
|
|
// // - For Mod & Caller is SupMod | Broadcaster | BotAdmin > To SupMod
|
|
// // - For UserRoles without BotAdmin & Caller is BotAdmin > To BotAdmin
|
|
// // */
|
|
// // },
|
|
|
|
// // };
|
|
|
|
|
|
|
|
// // if let Some(trgRole) = trgRole {
|
|
|
|
// // // [x] chatter already has the target role
|
|
// // if chatterroles.contains(&trgRole) {
|
|
// // return ChangeResult::NoChange(String::from("Target User already has Target Role"));
|
|
// // }
|
|
|
|
// // // [ ] trgRole should be assigned based on the input channel
|
|
// // let roletoassign = UserRole::
|
|
// // }
|
|
|
|
// },
|
|
// _ => (),
|
|
// }
|
|
|
|
ChangeResult::Success(String::from("TEST > Promotion Successful"))
|
|
}
|
|
|
|
pub fn demote(self,trgchatter:String,channel:Option<ChType>,trgRole:Option<UserRole>) -> ChangeResult {
|
|
|
|
ChangeResult::Success(String::from("TEST > Promotion Successful"))
|
|
}
|
|
|
|
pub fn getspecialuserroles(&self,chattername:String,channel:Option<ChType>) -> Option<&Vec<UserRole>> {
|
|
|
|
// let a = chattername.to_lowercase();
|
|
|
|
// self.special_roles_users.get(&a)
|
|
|
|
|
|
|
|
// for k in self.special_roles_users.keys() {
|
|
// println!("Special Roles Keys {k}");
|
|
// for v in
|
|
// }
|
|
|
|
// for (k,v) in &self.special_roles_users {
|
|
// println!("User {k}");
|
|
// println!("> Roles : {:?}",v);
|
|
// }
|
|
|
|
let a = chattername.to_lowercase();
|
|
|
|
// println!("{a}");
|
|
|
|
self.special_roles_users.get(&a)
|
|
|
|
|
|
|
|
// Some(vec![UserRole::Mod(ChType::Channel(String::from("modulatingforcebot")))])
|
|
}
|
|
|
|
|
|
}
|