This commit is contained in:
ModulatingForce 2024-02-25 10:40:54 -05:00
parent 66e82de28f
commit 0a7a4b539a
9 changed files with 2093 additions and 1874 deletions

View file

@ -1,7 +1,7 @@
pub mod botinstance;
pub mod ratelimiter;
pub mod botmodules;
pub mod identity;
pub mod ratelimiter;
// pub fn init() -> ()
// {

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
use core::{panic};
use core::panic;
use std::error::Error;
use std::collections::HashMap;
@ -15,34 +15,30 @@ use std::future::Future;
// Important to use tokios Mutex here since std Mutex doesn't work with async functions
use tokio::sync::Mutex;
use crate::core::botinstance::{self, botlog, BotInstance};
use std::rc::Rc;
// use tokio::sync::RwLock;
use async_trait::async_trait;
use casual_logger::{Level,Log};
use casual_logger::{Level, Log};
/*
ModulesManager is used to manage Modules and BotActions associated with those modules
ModulesManager is used to manage Modules and BotActions associated with those modules
pub struct ModulesManager {
statusdb: HashMap<ModType,Vec<ModStatusType>>,
botactions: HashMap<ModType,Vec<BotAction>>,
botactions: HashMap<ModType,Vec<BotAction>>,
}
- statusdb: HashMap<ModType,Vec<ModStatusType>> - Defines Modules and their ModStatusType (e.g., Enabled at an Instance level, Disabled at a Channel Level)
- botactions: HashMap<ModType,Vec<BotAction>> - Defines Modules and their BotActions (e.g., BotCommand , Listener, Routine)
- botactions: HashMap<ModType,Vec<BotAction>> - Defines Modules and their BotActions (e.g., BotCommand , Listener, Routine)
Example
{
ModulesManager {
statusdb: {BotModule("experiments 004"): [Enabled(Instance)]},
ModulesManager {
statusdb: {BotModule("experiments 004"): [Enabled(Instance)]},
botactions: {BotModule("experiments 004"): [C(BotCommand { module: BotModule("experiments 004"), command: "DUPCMD4", alias: ["DUPALIAS4A", "DUPALIAS4B"], help: "DUPCMD4 tester" })]} }
}
@ -52,7 +48,7 @@ Example
pub enum ModType {
BotModule(String),
}
pub use ModType::BotModule;
// #[derive(Debug, PartialEq, Eq, Hash, Clone)]
@ -62,13 +58,12 @@ pub use ModType::BotModule;
use botinstance::ChType;
pub use ChType::Channel;
use twitch_irc::message::PrivmsgMessage;
pub use ChType::Channel;
use self::bot_actions::actions_util;
use self::bot_actions::actions_util::BotAR;
#[derive(Debug)]
enum StatusLvl {
Instance,
@ -82,246 +77,223 @@ pub enum ModStatusType {
}
// #[derive(Clone)]
pub enum BotAction
{
C(BotCommand),
pub enum BotAction {
C(BotCommand),
L(Listener),
R(Routine),
R(Routine),
}
impl BotAction {
pub async fn execute(&self,m:BotAR,n:PrivmsgMessage) -> ()
{
pub async fn execute(&self, m: BotAR, n: PrivmsgMessage) -> () {
match self {
BotAction::L(a) => a.execute(m,n).await,
BotAction::C(a) => a.execute(m,n).await,
BotAction::L(a) => a.execute(m, n).await,
BotAction::C(a) => a.execute(m, n).await,
_ => (),
}
}
}
#[async_trait]
pub trait BotActionTrait
{
async fn add_to_bot(self, bot:BotInstance);
async fn add_to_modmgr(self,modmgr:Arc<ModulesManager>);
pub trait BotActionTrait {
async fn add_to_bot(self, bot: BotInstance);
async fn add_to_modmgr(self, modmgr: Arc<ModulesManager>);
}
// #[derive(Clone)]
pub struct BotCommand {
pub module : ModType,
pub command : String, // command call name
pub alias : Vec<String>, // String of alternative names
pub module: ModType,
pub command: String, // command call name
pub alias: Vec<String>, // String of alternative names
// bot_prefix : char, // although should be global?
pub exec_body : bot_actions::actions_util::ExecBody,
pub help : String,
pub required_roles : Vec<identity::UserRole>,
pub exec_body: bot_actions::actions_util::ExecBody,
pub help: String,
pub required_roles: Vec<identity::UserRole>,
}
impl BotCommand
{
pub async fn execute(&self,m:BotAR,n:PrivmsgMessage) -> () {
((*self).exec_body)(m,n).await;
impl BotCommand {
pub async fn execute(&self, m: BotAR, n: PrivmsgMessage) -> () {
((*self).exec_body)(m, n).await;
}
}
#[async_trait]
impl BotActionTrait for BotCommand
{
async fn add_to_bot(self, bot:BotInstance) {
impl BotActionTrait for BotCommand {
async fn add_to_bot(self, bot: BotInstance) {
self.add_to_modmgr(bot.botmodules).await;
}
// async fn add_to_modmgr(self, modmgr:Arc<Mutex<ModulesManager>>) {
async fn add_to_modmgr(self, modmgr:Arc<ModulesManager>) {
modmgr.add_botaction(self.module.clone(), BotAction::C(self)).await
async fn add_to_modmgr(self, modmgr: Arc<ModulesManager>) {
modmgr
.add_botaction(self.module.clone(), BotAction::C(self))
.await
}
}
pub mod bot_actions {
pub mod actions_util {
use std::future::Future;
use std::boxed::Box;
use std::future::Future;
use std::pin::Pin;
use std::rc::Rc;
use crate::core::botinstance::{BotInstance, BotManagers, Chat};
use twitch_irc::message::PrivmsgMessage;
use std::cell::RefCell;
use std::sync::{Arc};
use std::sync::Arc;
use twitch_irc::message::PrivmsgMessage;
// use futures::lock::Mutex;
// Important to use tokios Mutex here since std Mutex doesn't work with async functions
use tokio::sync::{Mutex,RwLock};
use tokio::sync::{Mutex, RwLock};
pub type BotAM = Arc<Mutex<BotInstance>>;
pub type BotAR = Arc<RwLock<BotInstance>>;
pub type ExecBody = Box<dyn Fn(BotAR,PrivmsgMessage) -> Pin<Box<dyn Future<Output=()> + Send>> + Send + Sync>;
pub type ExecBody = Box<
dyn Fn(BotAR, PrivmsgMessage) -> Pin<Box<dyn Future<Output = ()> + Send>> + Send + Sync,
>;
pub fn asyncbox<T>(f: fn(BotAR,PrivmsgMessage) -> T) -> ExecBody
pub fn asyncbox<T>(f: fn(BotAR, PrivmsgMessage) -> T) -> ExecBody
where
T: Future<Output=()> + Send + 'static
T: Future<Output = ()> + Send + 'static,
{
Box::new(move |a,b| Box::pin(f(a,b)))
Box::new(move |a, b| Box::pin(f(a, b)))
}
}
}
pub struct Listener
{
pub module : ModType,
pub name : String,
pub exec_body : bot_actions::actions_util::ExecBody,
pub help : String
pub struct Listener {
pub module: ModType,
pub name: String,
pub exec_body: bot_actions::actions_util::ExecBody,
pub help: String,
}
impl Listener
{
pub async fn execute(&self,m:BotAR,n:PrivmsgMessage) -> () {
((*self).exec_body)(m,n).await;
impl Listener {
pub async fn execute(&self, m: BotAR, n: PrivmsgMessage) -> () {
((*self).exec_body)(m, n).await;
}
}
#[async_trait]
impl BotActionTrait for Listener
{
async fn add_to_bot(self, bot:BotInstance) {
impl BotActionTrait for Listener {
async fn add_to_bot(self, bot: BotInstance) {
// println!("Adding action to bot");
// Log::trace("Adding action to bot");
botinstance::botlog::trace("Adding action to bot",
Some("BotModules > BotActionTrait > add_to_bot()".to_string()) ,
None);
botinstance::botlog::trace(
"Adding action to bot",
Some("BotModules > BotActionTrait > add_to_bot()".to_string()),
None,
);
self.add_to_modmgr(bot.botmodules).await;
}
async fn add_to_modmgr(self, modmgr:Arc<ModulesManager>) {
async fn add_to_modmgr(self, modmgr: Arc<ModulesManager>) {
// let modmgr = *modmgr.lock().await;
// println!("Adding action to module manager");
// Log::trace("Adding action to module manager");
botinstance::botlog::trace("Adding action to module manager",
Some("BotModules > BotActionTrait > add_to_bot()".to_string()) ,
None);
botinstance::botlog::trace(
"Adding action to module manager",
Some("BotModules > BotActionTrait > add_to_bot()".to_string()),
None,
);
modmgr.add_botaction(self.module.clone(), BotAction::L(self)).await;
modmgr
.add_botaction(self.module.clone(), BotAction::L(self))
.await;
}
}
#[derive(Debug)]
struct Routine {}
// #[derive(Clone)]
pub struct ModulesManager
{
statusdb: Arc<RwLock<HashMap<ModType,Vec<ModStatusType>>>>,
pub botactions: Arc<RwLock<HashMap<ModType,Vec<BotAction>>>>,
pub struct ModulesManager {
statusdb: Arc<RwLock<HashMap<ModType, Vec<ModStatusType>>>>,
pub botactions: Arc<RwLock<HashMap<ModType, Vec<BotAction>>>>,
}
/*
statusdb
<HashMap
<ModType, <-- e.g., BotModule(String::from("experiments001"))
<HashMap
<ModType, <-- e.g., BotModule(String::from("experiments001"))
Vec<ModStatusType> <-- shows Enabled/Disabled per Status level
botactions
botactions
HashMap<
ModType, <-- e.g., BotModule(String::from("experiments001"))
ModType, <-- e.g., BotModule(String::from("experiments001"))
Vec<BotAction>> BotCommand, Listener
*/
impl ModulesManager
{
pub async fn init() -> Arc<ModulesManager>
{
impl ModulesManager {
pub async fn init() -> Arc<ModulesManager> {
let m = HashMap::new();
let act = HashMap::new();
let mut mgr = ModulesManager {
statusdb : Arc::new(RwLock::new(m)),
botactions : Arc::new(RwLock::new(act)),
statusdb: Arc::new(RwLock::new(m)),
botactions: Arc::new(RwLock::new(act)),
};
// :: [x] initialize core modules
// println!("ModulesManager > init() > Adding modules");
botlog::debug("ModulesManager > init() > Adding modules",
botlog::debug(
"ModulesManager > init() > Adding modules",
Some("ModulesManager > init()".to_string()),
None
None,
);
let mgra = Arc::new(mgr);
crate::core::identity::init(Arc::clone(&mgra)).await;
crate::modules::init(Arc::clone(&mgra)).await;
// println!(">> Modules Manager : End of Init");
botlog::trace(">> Modules Manager : End of Init",
botlog::trace(
">> Modules Manager : End of Init",
Some("ModulesManager > init()".to_string()),
None
None,
);
mgra
}
}
pub fn modstatus(&self, _:ModType, _:ChType) -> ModStatusType {
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 ,
// )
// - 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 {
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>> {
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 async fn add_botaction(&self, in_module:ModType, in_action:BotAction ) {
pub async fn add_botaction(&self, in_module: ModType, in_action: BotAction) {
// println!("Add botaction called");
botlog::trace("Add botaction called",
Some("ModulesManager > init()".to_string()),
None
botlog::trace(
"Add botaction called",
Some("ModulesManager > init()".to_string()),
None,
);
/*
adds a BotAction to the Modules Manager - This will require a BotModule passed as well
This will including the logic of a valid add
@ -331,7 +303,7 @@ impl ModulesManager
-- 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
both would be called separately, even if they both have the same or different logic
*/
// let newlistener = Listener {
@ -341,20 +313,15 @@ impl ModulesManager
// 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
// [x] Before Adding, validate the following :
// - If BotAction to Add is a BotCommand , In Module Manager DB (botactions),
// [x] Before Adding, validate the following :
// - If BotAction to Add is a BotCommand , In Module Manager DB (botactions),
// Check All Other BotAction Command Names & Aliases to ensure they don't conflict
async fn find_conflict_module(mgr:& ModulesManager, act:& BotAction) -> Option<ModType>
{
async fn find_conflict_module(mgr: &ModulesManager, act: &BotAction) -> Option<ModType> {
// Some(BotModule(String::from("GambaCore")))
// match act {
// BotAction::C(c) => {
// Some(BotModule(String::from("GambaCore")))
@ -364,15 +331,12 @@ impl ModulesManager
// }
if let BotAction::C(incmd) = act {
// let n = & mgr.botactions;
let d = mgr.botactions.read().await;
let d = &(*d);
for (module,moduleactions) in d {
for (module, moduleactions) in d {
for modact in moduleactions.iter() {
if let BotAction::C(dbcmd) = &modact {
// At this point, there is an command incmd and looked up dbcmd
@ -385,54 +349,43 @@ impl ModulesManager
// return Some(incmd); // for some reason I keep getting issues
//return Some(BotModule(String::from("GambaCore"))); // works
return Some(module.clone()); // works
// return Some(dbcmd.clone());
}
// return Some(dbcmd.clone());
}
for a in &dbcmd.alias {
if incmd.command.to_lowercase() == a.to_lowercase() {
// Returning State - with the identified module
// return Some((module.clone(),BotAction::C(dbcmd)));
return Some(module.clone()); // works
}
}
}
}
// [x] Then do the same check except for each c.alias
for inalias in &incmd.alias {
if inalias.to_lowercase() == dbcmd.command.to_lowercase() {
// Returning State - with the identified module
// return Some((module.clone(),BotAction::C(dbcmd)));
return Some(module.clone()); // works
}
}
for a in &dbcmd.alias {
if inalias.to_lowercase() == a.to_lowercase() {
// Returning State - with the identified module
// return Some((module.clone(),BotAction::C(dbcmd)));
return Some(module.clone()); // works
}
}
}
}
}
}
}
}
// return Some(BotModule(String::from("GambaCore")))
}
// for all other scenarios (e.g., Listener, Routine), find no conflicts
None
}
// if let probmod = find_conflict_module(&self, &in_action) {
@ -441,7 +394,10 @@ impl ModulesManager
// }
match find_conflict_module(&self, &in_action).await {
// Some(c) => panic!("ERROR: Could not add {:?} ; there was a conflict with existing module {:?}", in_action , c ),
Some(c) => panic!("ERROR: Could not add module; there was a conflict with existing module {:?}", c ),
Some(c) => panic!(
"ERROR: Could not add module; there was a conflict with existing module {:?}",
c
),
None => (),
}
@ -456,30 +412,28 @@ impl ModulesManager
let mut a = self.botactions.write().await;
let modactions = a
//.entry( BotModule(String::from("experiments")))
.entry( in_module.clone())
.entry(in_module.clone())
.or_insert(Vec::new());
// modactions.push(BotAction::L(newlistener));
modactions.push(in_action);
// println!(">> Modules Manager : Called Add bot Action");
botlog::trace(">> Modules Manager : Called Add bot Action",
Some("ModulesManager > init()".to_string()),
None
botlog::trace(
">> Modules Manager : Called Add bot Action",
Some("ModulesManager > init()".to_string()),
None,
);
// println!("add_botaction - botactions size : {}",modactions.len());
botlog::trace(&format!("add_botaction - botactions size : {}",modactions.len()),
Some("ModulesManager > init()".to_string()),
None
botlog::trace(
&format!("add_botaction - botactions size : {}", modactions.len()),
Some("ModulesManager > init()".to_string()),
None,
);
}
fn statuscleanup(&self,_:Option<ChType>) -> () {
// internal cleans up statusdb . For example :
fn statuscleanup(&self, _: Option<ChType>) -> () {
// 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
@ -487,7 +441,4 @@ impl ModulesManager
// Passing None to chnl may be a heavy operation, as this will review and look at the whole table
()
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,8 @@
use std::time::Instant;
const TIME_THRESHOLD_S: u64 = 30;
const MSG_THRESHOLD: u32 = 20;
#[derive(Debug, Clone)]
pub struct RateLimiter {
timer: Instant,
@ -13,10 +11,9 @@ pub struct RateLimiter {
pub enum LimiterResp {
Allow, // when it's evaluated to be within limits
Skip, // as outside of rate limits
Skip, // as outside of rate limits
}
impl RateLimiter {
pub fn new() -> Self {
Self {
@ -25,24 +22,23 @@ impl RateLimiter {
}
}
pub fn check_limiter(&mut self) -> LimiterResp {
if self.timer.elapsed().as_secs() >= TIME_THRESHOLD_S {
// # [x] elapsed >= TIME_THRESHOLD_S
self.timer = Instant::now();
self.msgcounter = 0;
LimiterResp::Allow
} else if self.msgcounter < MSG_THRESHOLD {
// # [x] elapsed < TIME_THRESHOLD_S && msgcounter < MSG_THRESHOLD
LimiterResp::Allow
// } else if self.msgcounter >= MSG_THRESHOLD {
} else {
// # [x] elapsed < TIME_THRESHOLD_S && msgcounter >= MSG_THRESHOLD
LimiterResp::Skip
pub fn check_limiter(&mut self) -> LimiterResp {
if self.timer.elapsed().as_secs() >= TIME_THRESHOLD_S {
// # [x] elapsed >= TIME_THRESHOLD_S
self.timer = Instant::now();
self.msgcounter = 0;
LimiterResp::Allow
} else if self.msgcounter < MSG_THRESHOLD {
// # [x] elapsed < TIME_THRESHOLD_S && msgcounter < MSG_THRESHOLD
LimiterResp::Allow
// } else if self.msgcounter >= MSG_THRESHOLD {
} else {
// # [x] elapsed < TIME_THRESHOLD_S && msgcounter >= MSG_THRESHOLD
LimiterResp::Skip
}
}
}
pub fn increment_counter(&mut self) -> () {
self.msgcounter += 1;
self.msgcounter += 1;
}
}
}

View file

@ -1,3 +1,2 @@
pub mod core;
pub mod modules;

View file

@ -1,5 +1,3 @@
// pub mod core;
// pub mod modules;
//use myLib;
@ -9,22 +7,21 @@ use std::process::Output;
// use crate::core::botinstance::ArcBox;
use botLib::core::botinstance::ArcBox;
use botLib::core::botinstance::{self,BotInstance};
use botLib::core::botinstance::{self, BotInstance};
// use core::botinstance::{self,BotInstance};
use casual_logger::Extension;
use tokio::sync::RwLock;
use std::sync::Arc;
use tokio::sync::RwLock;
pub type BotAR = Arc<RwLock<BotInstance>>;
use casual_logger::{Level,Log};
use casual_logger::{Level, Log};
#[tokio::main]
pub async fn main() {
Log::set_file_ext(Extension::Log);
Log::set_level(Level::Trace);
// Log::set_level(Level::Notice);
// Log::set_level(Level::Notice);
let bot = BotInstance::init().await;
@ -34,28 +31,39 @@ pub async fn main() {
let a = a.read().await;
// let a = *a;
for (_,acts) in &*a {
for (_, acts) in &*a {
for act in acts {
match act {
botLib::core::botmodules::BotAction::C(b) => {
// println!("bot actiions: {}",b.command)
// Log::info(&format!("bot actions: {}",b.command));
botinstance::botlog::info(&format!("bot actions: {}",b.command), Some("main()".to_string()), None);
},
botinstance::botlog::info(
&format!("bot actions: {}", b.command),
Some("main()".to_string()),
None,
);
}
botLib::core::botmodules::BotAction::L(l) => {
// println!("bot actiions: {}",l.name)
// Log::info(&format!("bot actions: {}",l.name));
botinstance::botlog::info(&format!("bot actions: {}",l.name), Some("main()".to_string()), None);
},
botinstance::botlog::info(
&format!("bot actions: {}", l.name),
Some("main()".to_string()),
None,
);
}
_ => {
// println!("Not a valid match??")
// Log::info("Not a valid match??");
botinstance::botlog::info("Not a valid match??", Some("main()".to_string()), None);
},
botinstance::botlog::info(
"Not a valid match??",
Some("main()".to_string()),
None,
);
}
}
}
};
}
// println!("Starting runner..");
// Log::notice("Starting Bot Runner");
@ -70,6 +78,5 @@ pub async fn main() {
// let msg = Log::fatal("ERROR : EXIT Game loop");
// panic!("{}",Log::fatal("ERROR : EXIT Game loop"));
let a = botinstance::botlog::fatal("ERROR : EXIT Game loop", Some("main()".to_string()), None);
panic!("{}",a);
}
panic!("{}", a);
}

View file

@ -10,22 +10,20 @@ pub use crate::core::botmodules::ModulesManager;
// use crate::core::botinstance;
pub use crate::core::botinstance::BotInstance;
use std::sync::Arc;
use futures::lock::Mutex;
use std::sync::Arc;
// [ ] Load submodules
mod experiments;
// [ ] init() function that accepts bot instance - this is passed to init() on submodules
pub async fn init(mgr:Arc<ModulesManager>)
{
pub async fn init(mgr: Arc<ModulesManager>) {
// Modules initializer loads modules into the bot
// this is achieved by calling submodules that also have fn init() defined
experiments::init(mgr).await
experiments::init(mgr).await
//();
}
}

View file

@ -1,9 +1,8 @@
/*
Submodules -
- should have definitions of BotAction that will be added to a bit
- therefore, will be defined in modules.rs file
- therefore, will be defined in modules.rs file
- will define one init(&BotInstance) take within the module that will contain :
- BotAction definitions that each call &BotInstance module manager to add itself
@ -14,28 +13,23 @@
use std::future::Future;
use crate::core::botmodules::{ModulesManager,Listener,BotModule,BotActionTrait, BotCommand};
use crate::core::botmodules::bot_actions::actions_util::{self, BotAR};
use crate::core::botmodules::{BotActionTrait, BotCommand, BotModule, Listener, ModulesManager};
use crate::core::botinstance::{self,BotInstance,ChType};
use crate::core::botinstance::{self, BotInstance, ChType};
use futures::lock::Mutex;
use twitch_irc::message::PrivmsgMessage;
use crate::core::identity;
use rand::Rng;
use std::rc::Rc;
use std::sync::{Arc, RwLock};
// pub fn init(mgr:&mut ModulesManager)
pub async fn init(mgr:Arc<ModulesManager>)
{
pub async fn init(mgr: Arc<ModulesManager>) {
// BotCommand {
// module : BotModule(String::from("experiments 004")),
// command : String::from("test1"), // command call name
@ -48,81 +42,78 @@ pub async fn init(mgr:Arc<ModulesManager>)
// ],
// }.add_to_modmgr(mgr);
let botc1 = BotCommand {
module : BotModule(String::from("experiments001")),
command : String::from("test1"), // command call name
alias : vec![String::from("tester1"),String::from("testy1")], // String of alternative names
exec_body : actions_util::asyncbox(testy) ,
help : String::from("Test Command tester"),
required_roles : vec![
identity::UserRole::BotAdmin
],
module: BotModule(String::from("experiments001")),
command: String::from("test1"), // command call name
alias: vec![String::from("tester1"), String::from("testy1")], // String of alternative names
exec_body: actions_util::asyncbox(testy),
help: String::from("Test Command tester"),
required_roles: vec![identity::UserRole::BotAdmin],
};
botc1.add_to_modmgr(Arc::clone(&mgr)).await;
let list1 = Listener {
module : BotModule(String::from("experiments001")),
name : String::from("GoodGirl Listener"),
exec_body : actions_util::asyncbox(good_girl) ,
help : String::from("")
module: BotModule(String::from("experiments001")),
name: String::from("GoodGirl Listener"),
exec_body: actions_util::asyncbox(good_girl),
help: String::from(""),
};
list1.add_to_modmgr(Arc::clone(&mgr)).await;
}
async fn good_girl(mut bot:BotAR,msg:PrivmsgMessage)
{
async fn good_girl(mut bot: BotAR, msg: PrivmsgMessage) {
// println!("In GoodGirl() Listener");
// Change below from debug to trace if required later
botinstance::botlog::debug("In GoodGirl() Listener",
Some("experiments > goodgirl()".to_string()) ,
Some(&msg));
botinstance::botlog::debug(
"In GoodGirl() Listener",
Some("experiments > goodgirl()".to_string()),
Some(&msg),
);
//println!("(#{}) {}: {}", msg.channel_login, msg.sender.name, msg.message_text);
// [ ] Uses gen_ratio() to output bool based on a ratio probability .
// [ ] Uses gen_ratio() to output bool based on a ratio probability .
// - For example gen_ratio(2,3) is 2 out of 3 or 0.67% (numerator,denomitator)
// - More Info : https://rust-random.github.io/rand/rand/trait.Rng.html#method.gen_ratio
if msg.sender.name.to_lowercase() == "ModulatingForce".to_lowercase() || msg.sender.name.to_lowercase() == "mzNToRi".to_lowercase() // && msg.message_text.contains("GoodGirl")
if msg.sender.name.to_lowercase() == "ModulatingForce".to_lowercase()
|| msg.sender.name.to_lowercase() == "mzNToRi".to_lowercase()
// && msg.message_text.contains("GoodGirl")
{
// chat.say_in_reply_to(&msg,String::from("GoodGirl")).await;
//if rng.gen_ratio(1,5) {
// println!("In GoodGirl() > Pausechamp");
botinstance::botlog::debug("In GoodGirl() > Pausechamp",
Some("experiments > goodgirl()".to_string()) ,
Some(&msg));
let rollwin = rand::thread_rng().gen_ratio(1,8);
botinstance::botlog::debug(
"In GoodGirl() > Pausechamp",
Some("experiments > goodgirl()".to_string()),
Some(&msg),
);
let rollwin = rand::thread_rng().gen_ratio(1, 8);
if rollwin {
// println!("In GoodGirl() > Win");
botinstance::botlog::debug("In GoodGirl() > Win",
Some("experiments > goodgirl()".to_string()) ,
Some(&msg));
let a = Arc::clone(&bot);
let botlock = a.read().await;
botlock.botmgrs.chat.say_in_reply_to(&msg, String::from("GoodGirl xdd ")).await;
botinstance::botlog::debug(
"In GoodGirl() > Win",
Some("experiments > goodgirl()".to_string()),
Some(&msg),
);
let a = Arc::clone(&bot);
let botlock = a.read().await;
botlock
.botmgrs
.chat
.say_in_reply_to(&msg, String::from("GoodGirl xdd "))
.await;
}
}
}
async fn testy(mut _chat:BotAR,msg:PrivmsgMessage)
{
async fn testy(mut _chat: BotAR, msg: PrivmsgMessage) {
println!("testy triggered!"); // NOTE : This test function intends to print (e.g., to stdout) at fn call
botinstance::botlog::debug("testy triggered!",
Some("experiments > testy()".to_string()) ,
Some(&msg));
}
botinstance::botlog::debug(
"testy triggered!",
Some("experiments > testy()".to_string()),
Some(&msg),
);
}