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)] 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 { 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 { statusdb: HashMap>, botactions: HashMap>, } 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"), // }; // // 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()); // statusvector.push(ModStatusType::Enabled(StatusLvl::Instance)); // let modactions = act // .entry( BotModule(String::from("experiments"))) // .or_insert(Vec::new()); // modactions.push(BotAction::L(newlistener)); let mgr = ModulesManager { statusdb : m, botactions : act, }; 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> { // 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)); (); } fn statuscleanup(&self,_:Option) -> () { // 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 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 () } }