forcebot_rs/src/core/botmodules.rs

199 lines
5.9 KiB
Rust
Raw Normal View History

2023-12-21 00:48:09 -05:00
use std::error::Error;
use std::collections::HashMap;
/*
ModulesManager is made of modulesdb , a HashMap of BotModules with a Vector representing their enabled/disabled status based on channel and instance
Example
{
BotModule("Experiments") , [Enabled(Channel("modulatingforce")) , Disabled(Channel("modulatingforce")), Enabled(Instance)]
}
*/
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
2023-12-21 00:48:09 -05:00
pub enum ModType {
BotModule(String),
}
pub use ModType::BotModule;
#[derive(Debug, PartialEq, Eq, Hash)]
pub enum ChType {
Channel(String),
}
pub use ChType::Channel;
#[derive(Debug)]
enum StatusLvl {
Instance,
Ch(ChType),
}
#[derive(Debug)]
pub enum ModStatusType {
Enabled(StatusLvl),
Disabled(StatusLvl),
}
// pub use EnType::Enabled;
#[derive(Debug)]
pub enum BotAction {
2023-12-21 00:48:09 -05:00
C(BotCommand),
L(Listener),
R(Routine),
}
#[derive(Debug)]
struct BotCommand {}
#[derive(Debug)]
struct Listener {
module : ModType,
name : String,
// exec_body : fn,
help : String
}
#[derive(Debug)]
struct Routine {}
#[derive(Debug)]
pub struct ModulesManager {
2023-12-21 12:10:50 -05:00
statusdb: HashMap<ModType,Vec<ModStatusType>>,
2023-12-21 00:48:09 -05:00
botactions: HashMap<ModType,Vec<BotAction>>,
}
impl ModulesManager {
pub fn init() -> ModulesManager {
// initializes the modulers manager
// Ideally, this should have added known modules based on
// directory structure and API user recommendations
let mut m = HashMap::new();
let mut act = HashMap::new();
// -- some processing including adding into the hashmap
// let newmodule = BotModule(String::from("GambaCore"));
// let newlistener = Listener {
// module : BotModule(String::from("experiments").to_owned()),
// name : String::from("socklistener"),
// help : String::from("This will listen and react to sock randomly"),
// };
2023-12-21 00:48:09 -05:00
// // As a Demonstration, the listener's Module is added and Enabled at Instance level
// let statusvector = m
// .entry(BotModule(String::from("experiments")))
// .or_insert(Vec::new());
2023-12-21 00:48:09 -05:00
// statusvector.push(ModStatusType::Enabled(StatusLvl::Instance));
2023-12-21 00:48:09 -05:00
// let modactions = act
// .entry( BotModule(String::from("experiments")))
// .or_insert(Vec::new());
2023-12-21 00:48:09 -05:00
// modactions.push(BotAction::L(newlistener));
2023-12-21 00:48:09 -05:00
let mgr = ModulesManager {
2023-12-21 12:10:50 -05:00
statusdb : m,
2023-12-21 00:48:09 -05:00
botactions : act,
};
2023-12-21 00:48:09 -05:00
println!(">> Modules Manager : {:?}",mgr);
mgr
}
pub fn modstatus(&self, _:ModType, _:ChType) -> ModStatusType {
// Example usage : botmanager.modstatus(
// BotModule("GambaCore"),
// Channel("modulatingforce")
// )
// - The ModStatusType checks in the context of the given channel ,
// but also validates based on wheher the module is disabled at a bot instance
// level as well
ModStatusType::Enabled(StatusLvl::Instance)
}
pub fn togglestatus(&self, _:ModType, _:ChType) -> ModStatusType {
// enables or disables based on current status
ModStatusType::Enabled(StatusLvl::Instance)
}
pub fn setstatus(&self, _:ModType, _:ModStatusType) -> Result<&str,Box<dyn Error>> {
// sets the status based given ModSatusType
// e.g., b.setstatus(BodModule("GambaCore"), Enabled(Channel("modulatingforce"))).expect("ERROR")
Ok("")
}
pub fn add_botaction(&mut self, in_module:ModType, _:BotAction ) -> () {
// adds a BotAction to the Modules Manager - This will require a BotModule passed as well
// This will including the logic of a valid add
// If it fails to add, either a PANIC or some default coded business rules that handles the botaction add
// For example, this Should PANIC (ideally Panic?) if it does not successfully add a bot module
// -- Being unable to indicates a Programming/Developer code logic issue : They cannot add botactions that already exists (?)
// -- In particular to BotCommands, which must have Unique command call names and aliases that to not conflict with any other
// already BotCommand added name or alias
// Other types might be fine? For example, if 2 modules have their own listeners but each have the name "targetchatter" ,
// both would be called separately, even if they both have the same or different logic
let newlistener = Listener {
// module : BotModule(String::from("experiments").to_owned()),
module : in_module.clone(),
name : String::from("socklistener"),
help : String::from("This will listen and react to sock randomly"),
};
// As a Demonstration, the listener's Module is added and Enabled at Instance level
let statusvector = self.statusdb
// .entry(BotModule(String::from("experiments")))
.entry(in_module.clone())
.or_insert(Vec::new());
statusvector.push(ModStatusType::Enabled(StatusLvl::Instance));
let modactions = self.botactions
//.entry( BotModule(String::from("experiments")))
.entry( in_module.clone())
.or_insert(Vec::new());
modactions.push(BotAction::L(newlistener));
();
}
2023-12-21 00:48:09 -05:00
fn statuscleanup(&self,_:Option<ChType>) -> () {
2023-12-21 12:10:50 -05:00
// internal cleans up statusdb . For example :
// - remove redudancies . If we see several Enabled("m"), only keep 1x
// - Clarify Conflict. If we see Enabled("m") and Disabled("m") , we remove Enabled("m") and keep Disabled("m")
// the IDEAL is that this is ran before every read/update operation to ensure quality
// Option<ChType> can pass Some(Channel("m")) (as an example) so statuscleanup only works on the given channel
// Passing None to chnl may be a heavy operation, as this will review and look at the whole table
()
}
2023-12-21 00:48:09 -05:00
}