696 lines
19 KiB
Rust
696 lines
19 KiB
Rust
/*
|
|
Custom Modules -
|
|
|
|
Usage :
|
|
[ ] within the file's init(), define BotActions & Load them into the ModulesManager
|
|
[ ] Define Execution Bodies for these BotActions
|
|
[ ] Afterwards, add the following to parent modules.rs file
|
|
- mod <modulename>;
|
|
- within init(), <modulename>::init(mgr).await
|
|
|
|
*/
|
|
|
|
|
|
const OF_CMD_CHANNEL:Channel = Channel(String::new());
|
|
|
|
|
|
use casual_logger::Log;
|
|
use rand::Rng;
|
|
use rand::thread_rng;
|
|
use rand::rngs::StdRng;
|
|
use rand::seq::SliceRandom;
|
|
use tokio::sync::RwLock;
|
|
use std::borrow::Borrow;
|
|
use std::borrow::BorrowMut;
|
|
use std::sync::Arc;
|
|
|
|
use crate::core::bot_actions::ExecBodyParams;
|
|
use crate::core::botinstance::Channel;
|
|
use crate::core::botlog;
|
|
|
|
use crate::core::bot_actions::actions_util;
|
|
use crate::core::botmodules::{BotAction, BotActionTrait, BotCommand, BotModule, Listener, ModulesManager, Routine, RoutineAttr};
|
|
|
|
use crate::core::identity::UserRole::*;
|
|
|
|
use tokio::time::{sleep, Duration};
|
|
|
|
pub async fn init(mgr: Arc<ModulesManager>) {
|
|
|
|
// 1. Define the BotAction
|
|
let botc1 = BotCommand {
|
|
module: BotModule(String::from("experiments003")),
|
|
command: String::from("test3"), // command call name
|
|
alias: vec![], // String of alternative names
|
|
exec_body: actions_util::asyncbox(test3_body),
|
|
help: String::from("Test Command tester"),
|
|
required_roles: vec![
|
|
BotAdmin,
|
|
Mod(OF_CMD_CHANNEL),
|
|
],
|
|
};
|
|
|
|
// 2. Add the BotAction to ModulesManager
|
|
botc1.add_to_modmgr(Arc::clone(&mgr)).await;
|
|
|
|
|
|
// 1. Define the BotAction
|
|
let botc1 = BotCommand {
|
|
module: BotModule(String::from("experiments003")),
|
|
command: String::from("countdown"), // command call name
|
|
alias: vec![], // String of alternative names
|
|
exec_body: actions_util::asyncbox(countdown_chnl_v1),
|
|
help: String::from("Test Command tester"),
|
|
required_roles: vec![
|
|
BotAdmin,
|
|
Mod(OF_CMD_CHANNEL),
|
|
],
|
|
};
|
|
|
|
// 2. Add the BotAction to ModulesManager
|
|
botc1.add_to_modmgr(Arc::clone(&mgr)).await;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
async fn countdown_chnl_v1(params : ExecBodyParams) {
|
|
|
|
botlog::debug(
|
|
"[CHILDFN] countdown_chnl() triggered!",
|
|
Some("Experiments003 > countdown_chnl()".to_string()),
|
|
Some(¶ms.msg),
|
|
);
|
|
|
|
|
|
/*
|
|
create a fun countdown BotCommand that allows an Elevated Chatter to
|
|
-a add channels to target a routine message
|
|
-start to start the routine with an input String, that sends a number
|
|
of messages to the targeted channels with a countdown, until it
|
|
reaches 0 when it sends a cute or funny message
|
|
|
|
NOTE : At the moment, I don't have customizable persistence, so I would just use
|
|
counters from the Routine itself
|
|
*/
|
|
|
|
/*
|
|
Because of some bot core features are not available, v1.0 of this could be :
|
|
[x] 1. Create a Routine & start a routine
|
|
[x] 2. Have the routine go through each joined channel randomly and countdown
|
|
[x] 3. At the end, say "0, I love you uwu~" in the last chosen channel
|
|
*/
|
|
|
|
/*
|
|
Usage => 03.28 - skipping arguments as functinoality isn't enhanced
|
|
|
|
-a <channel> => 03.28 - Not sure if this is possible at the moment?
|
|
|
|
-start
|
|
|
|
-stop => 03.28 - Not sure if this is possible at the moment?
|
|
|
|
*/
|
|
|
|
/*
|
|
[ ] Functional Use Case
|
|
|
|
1. -a <channel> adds targetted channels
|
|
|
|
*/
|
|
|
|
// [-] 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)
|
|
// };
|
|
|
|
|
|
|
|
// [ ] 1. Create a Routine & start a routine
|
|
|
|
// let parentmodule = params.get_parent_module().await;
|
|
let module = params.get_module().await;
|
|
let channel = params.get_channel().await;
|
|
let routine_attr = vec![
|
|
// RoutineAttr::RunOnce
|
|
RoutineAttr::MaxIterations(5),
|
|
RoutineAttr::LoopDuration(Duration::from_secs(1))
|
|
];
|
|
// let exec_body = actions_util::asyncbox(rtestbody);
|
|
let exec_body = actions_util::asyncbox(innertester); // <-- 03.27 - when below is uncommented, this is throwing an issue
|
|
|
|
async fn innertester(params : ExecBodyParams) {
|
|
|
|
{
|
|
let curract_guard = params.curr_act.read().await;
|
|
|
|
|
|
// let logmsg_botact = match *params.curr_act.read().await {
|
|
|
|
let logmsg_botact = match *curract_guard {
|
|
BotAction::C(_) => "command",
|
|
BotAction::R(_) => "routine",
|
|
BotAction::L(_) => "listener",
|
|
} ;
|
|
|
|
|
|
botlog::trace(
|
|
format!("Params > Curr_act type : {:?}", logmsg_botact).as_str(),
|
|
Some("Experiments003 > countdown_chnl()".to_string()),
|
|
Some(¶ms.msg),
|
|
);
|
|
Log::flush();
|
|
}
|
|
|
|
{
|
|
let bot = Arc::clone(¶ms.bot);
|
|
let botlock = bot.read().await;
|
|
|
|
let curract_guard = params.curr_act.write().await;
|
|
|
|
// let routine_lock = arr.write().await;
|
|
|
|
if let BotAction::R(arr) = &*curract_guard {
|
|
// if let BotAction::R(arr) = &*params.curr_act.read().await {
|
|
|
|
botlog::trace(
|
|
"Before loading remaining iterations",
|
|
Some("Experiments003 > countdown_chnl()".to_string()),
|
|
None,
|
|
);
|
|
Log::flush();
|
|
|
|
|
|
// let iterleft = arr.read().await.remaining_iterations.unwrap_or(0);
|
|
|
|
// // let iterleft = if arr.read().await.remaining_iterations.is_none() { 0i64 }
|
|
// // else { arr.read().await.remaining_iterations.unwrap() };
|
|
// let iterleft = match arr.read().await.remaining_iterations {
|
|
// None => 0,
|
|
// Some(a) => a,
|
|
// };
|
|
|
|
// let routine_lock = arr.read().await;
|
|
// if let Some(a) = routine_lock.remaining_iterations.clone() {
|
|
// println!("Remaining iterations > {}",a)
|
|
// }
|
|
|
|
{
|
|
let routine_lock = arr.write().await;
|
|
let a = routine_lock.remaining_iterations;
|
|
println!("remaining iterations : {:?}", a);
|
|
}
|
|
|
|
botlog::trace(
|
|
"after loading remaining iterations",
|
|
Some("Experiments003 > countdown_chnl()".to_string()),
|
|
None,
|
|
);
|
|
Log::flush();
|
|
|
|
// [ ] get joined channels
|
|
let joinedchannels = botlock.bot_channels.clone();
|
|
|
|
|
|
fn pick_a_channel(chnlvec : Vec<Channel>) -> Channel {
|
|
|
|
|
|
botlog::trace(
|
|
"In Pick_a_Channel()",
|
|
Some("Experiments003 > countdown_chnl()".to_string()),
|
|
None,
|
|
);
|
|
Log::flush();
|
|
|
|
// More Information : https://docs.rs/rand/0.7.2/rand/seq/trait.SliceRandom.html#tymethod.choose
|
|
|
|
let mut rng = thread_rng();
|
|
|
|
// let joinedchannels = botlock.bot_channels.clone();
|
|
(*chnlvec.choose(&mut rng).unwrap()).clone()
|
|
}
|
|
|
|
|
|
let chosen_channel = pick_a_channel(joinedchannels);
|
|
|
|
botlog::trace(
|
|
format!("Picked a channel: {:?}", chosen_channel).as_str(),
|
|
Some("Experiments003 > countdown_chnl()".to_string()),
|
|
Some(¶ms.msg),
|
|
);
|
|
Log::flush();
|
|
|
|
// let outmsg = if iterleft == 1 {
|
|
// format!("{} I love you uwu~",iterleft)
|
|
// } else { format!("{}",iterleft) };
|
|
|
|
// botlock.botmgrs.chat
|
|
// .say(
|
|
// // joinedchannels.choose(&mut rng).unwrap().0.clone(),
|
|
// chosen_channel.0.clone(),
|
|
// outmsg,
|
|
// params.clone()
|
|
|
|
|
|
// ).await;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// [ ] setup the routine
|
|
if let Ok(newr) = Routine::from(
|
|
"Routine Test".to_string(),
|
|
module,
|
|
channel.unwrap(),
|
|
routine_attr,
|
|
exec_body,
|
|
params.clone()
|
|
).await {
|
|
let newr_ar = newr.clone();
|
|
// [ ] start the routine
|
|
if let Ok(_) = Routine::start(newr_ar.clone()).await {
|
|
|
|
|
|
botlog::debug(
|
|
"Successfully started",
|
|
Some("experiment003 > countdown_chnl()".to_string()),
|
|
Some(¶ms.msg),
|
|
);
|
|
|
|
|
|
Log::flush();
|
|
|
|
let bot = Arc::clone(¶ms.bot);
|
|
|
|
let botlock = bot.read().await;
|
|
|
|
// uses chat.say_in_reply_to() for the bot controls for messages
|
|
botlock
|
|
.botmgrs
|
|
.chat
|
|
.say_in_reply_to(
|
|
¶ms.msg,
|
|
"Started Routine!".to_string(),
|
|
params.clone()
|
|
).await;
|
|
|
|
// let jhandle = newr.clone().read().await.join_handle.clone().unwrap();
|
|
// let a = jhandle.write().await;
|
|
// a.
|
|
// sleep(Duration::from_secs(300)).await;
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// botlock
|
|
// .botmgrs
|
|
// .chat
|
|
// .say_in_reply_to(
|
|
// ¶ms.msg,
|
|
// format!("{:?}",),
|
|
// params.clone()
|
|
// ).await;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async fn test3_body(params : ExecBodyParams) {
|
|
// println!("testy triggered!"); // NOTE : This test function intends to print (e.g., to stdout) at fn call
|
|
botlog::debug(
|
|
"testy triggered!",
|
|
Some("Experiments003 > test3 command body".to_string()),
|
|
Some(¶ms.msg),
|
|
);
|
|
|
|
/*
|
|
Test Routine Start() by :
|
|
1. In this single exec body , create a Routine
|
|
2. Create a Routine Execution Body
|
|
3. Pass the Execution Body & Routine Attributes to create the Routine
|
|
4. Start the Routine
|
|
5. For RunOnce , we should see it only trigger once, and then complete in the logs
|
|
|
|
*/
|
|
|
|
// [x] Get the module from params
|
|
|
|
// let parentmodule = params.get_parent_module().await;
|
|
let module = params.get_module().await;
|
|
let channel = params.get_channel().await;
|
|
let routine_attr = vec![
|
|
RoutineAttr::RunOnce
|
|
];
|
|
// let exec_body = actions_util::asyncbox(rtestbody);
|
|
let exec_body = actions_util::asyncbox(rtestbody); // <-- 03.27 - when below is uncommented, this is throwing an issue
|
|
|
|
|
|
// let parent_params = params.clone();
|
|
// let params_clone = params.clone();
|
|
|
|
|
|
async fn rtestbody(params : ExecBodyParams) {
|
|
|
|
|
|
let guard1 = params.curr_act.read().await;
|
|
{
|
|
let logmsg_botact = match *guard1 {
|
|
BotAction::C(_) => "command",
|
|
BotAction::R(_) => "routine",
|
|
BotAction::L(_) => "listener",
|
|
} ;
|
|
|
|
botlog::trace(
|
|
format!("Params > Curr_act type : {:?}", logmsg_botact).as_str(),
|
|
Some("Experiments003 > test3 command body".to_string()),
|
|
Some(¶ms.msg),
|
|
);
|
|
Log::flush();
|
|
}
|
|
|
|
|
|
{
|
|
let logmsg_botact = match &*guard1 {
|
|
BotAction::C(_) => "command 2",
|
|
BotAction::R(_) => "routine 2",
|
|
BotAction::L(_) => "listener 2",
|
|
} ;
|
|
|
|
botlog::trace(
|
|
format!("Params > Curr_act type : {:?}", logmsg_botact).as_str(),
|
|
Some("Experiments003 > test3 command body".to_string()),
|
|
Some(¶ms.msg),
|
|
);
|
|
Log::flush();
|
|
}
|
|
|
|
// drop(guard1);
|
|
|
|
|
|
{
|
|
dbg!("Custom > within Child Custom fn - Before Critical area");
|
|
println!("Critical code area start"); // <= 03.29 - This is printed
|
|
|
|
// if let BotAction::R(c) = &*guard {
|
|
// println!("{:?}",c.read().await.channel);
|
|
// }
|
|
|
|
// let routine_channel = if let BotAction::R(c) = &*guard1 {
|
|
// dbg!("Custom > within Child Custom fn - During Critical area > Routine Guard ");
|
|
// let routineguard = c.read().await;
|
|
// Some(routineguard.channel.clone());
|
|
// } else {
|
|
// None
|
|
// };
|
|
|
|
|
|
// let chnl = match &*guard1 {
|
|
// BotAction::R(arr) => {
|
|
// dbg!("Custom > within Child Custom fn - During Critical area > Before Routine Guard ");
|
|
// let routineguard = arr.read().await;
|
|
// dbg!("Custom > within Child Custom fn - During Critical area > After Routine Guard ");
|
|
// Some(routineguard.channel.clone())
|
|
// },
|
|
// BotAction::C(_) | BotAction::L(_) => None ,
|
|
// } ;
|
|
|
|
let chnl = params.get_channel().await;
|
|
dbg!("Custom > within Child Custom fn - after GetChannel");
|
|
println!("{:?}",chnl);
|
|
|
|
|
|
println!("Critical code area end"); // <= 03.29 - ISSUE This is NOT printed
|
|
dbg!("Custom > within Child Custom fn - Before Critical area");
|
|
|
|
// if let BotAction::R(arr) = &*params.curr_act.read().await {
|
|
// for curriter in 0..5 {
|
|
// println!("tester - Routine - Completed Iterations : {}",
|
|
// arr.read().await.complete_iterations);
|
|
// println!("tester - Custom Loop - Completed Iterations : {}",
|
|
// curriter);
|
|
// sleep(Duration::from_secs_f64(0.5)).await;
|
|
// }
|
|
// }
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
botlog::debug(
|
|
format!("RTESTBODY : module - {:?} ; channel - {:?}",
|
|
module,channel
|
|
).as_str(),
|
|
Some("experiment003 > test3_body".to_string()),
|
|
Some(¶ms.msg),
|
|
);
|
|
|
|
|
|
|
|
let a = Routine::from(
|
|
"Routine Test".to_string(),
|
|
module,
|
|
channel.unwrap(),
|
|
routine_attr,
|
|
exec_body,
|
|
params.clone()
|
|
).await;
|
|
|
|
|
|
|
|
if let Ok(newr) = a {
|
|
|
|
// NOTE : The below is a "Playing aound" feature
|
|
// In the below, we're unnecessarily adjusting the ExecBodyParams of the parent
|
|
|
|
// To get the reference to the Routine or the BotAction there are now refernces to itself
|
|
|
|
// [ ] before execute , be sure to adjust curr_act
|
|
|
|
// let mut params_mut = params;
|
|
let newr_ar = newr.clone();
|
|
|
|
// params_mut.curr_act = Arc::new(RwLock::new(
|
|
// BotAction::R(newr_ar.clone())
|
|
// ));
|
|
|
|
|
|
// {
|
|
// newr_ar.write().await.parent_params = params_mut.clone();
|
|
// }
|
|
|
|
let rslt = Routine::start(newr_ar.clone()).await;
|
|
|
|
// let rslt = newr_ar.read().await.start().await;
|
|
|
|
let rsltstr = match rslt {
|
|
Ok(_) => "successful".to_string(),
|
|
Err(a) => a,
|
|
};
|
|
|
|
|
|
botlog::debug(
|
|
format!("TEST3_BODY RESULT : {:?}",
|
|
rsltstr
|
|
).as_str(),
|
|
Some("experiment003 > test3_body".to_string()),
|
|
Some(¶ms.msg),
|
|
);
|
|
|
|
Log::flush();
|
|
|
|
let bot = Arc::clone(¶ms.bot);
|
|
|
|
let botlock = bot.read().await;
|
|
|
|
// uses chat.say_in_reply_to() for the bot controls for messages
|
|
botlock
|
|
.botmgrs
|
|
.chat
|
|
.say_in_reply_to(
|
|
¶ms.msg,
|
|
format!("Routine Result : {:?}",rsltstr),
|
|
params.clone()
|
|
).await;
|
|
|
|
// [x] Will not be handling JoinHandles here . If immediate abort() handling is required, below is an example that works
|
|
/*
|
|
|
|
|
|
let a = newr.clone().read().await.join_handle.clone();
|
|
match a {
|
|
Some(b) => {
|
|
b.read().await.borrow().abort(); // [x] <-- This aborts if wanting to abort immediately
|
|
//()
|
|
},
|
|
None => (),
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
}
|
|
|
|
|
|
Log::flush();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async fn good_girl(params : ExecBodyParams) {
|
|
|
|
// [ ] 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 params.msg.sender.name.to_lowercase() == "ModulatingForce".to_lowercase()
|
|
|| params.msg.sender.name.to_lowercase() == "mzNToRi".to_lowercase()
|
|
{
|
|
botlog::debug(
|
|
"Good Girl Detected > Pausechamp",
|
|
Some("experiments > goodgirl()".to_string()),
|
|
Some(¶ms.msg),
|
|
);
|
|
|
|
let rollwin = rand::thread_rng().gen_ratio(1, 10);
|
|
|
|
if rollwin {
|
|
botlog::debug(
|
|
"Oh that's a good girl!",
|
|
Some("experiments > goodgirl()".to_string()),
|
|
Some(¶ms.msg),
|
|
);
|
|
|
|
let bot = Arc::clone(¶ms.bot);
|
|
|
|
|
|
let botlock = bot.read().await;
|
|
|
|
// uses chat.say_in_reply_to() for the bot controls for messages
|
|
botlock
|
|
.botmgrs
|
|
.chat
|
|
.say_in_reply_to(
|
|
¶ms.msg,
|
|
String::from("GoodGirl xdd "),
|
|
params.clone()
|
|
).await;
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
async fn testy(params : ExecBodyParams) {
|
|
println!("testy triggered!"); // NOTE : This test function intends to print (e.g., to stdout) at fn call
|
|
botlog::debug(
|
|
"testy triggered!",
|
|
Some("experiments > testy()".to_string()),
|
|
Some(¶ms.msg),
|
|
);
|
|
}
|
|
|
|
|
|
async fn babygirl(params : ExecBodyParams) {
|
|
|
|
|
|
println!("babygirl triggered!"); // NOTE : This test function intends to print (e.g., to stdout) at fn call
|
|
botlog::debug(
|
|
"babygirl triggered!",
|
|
Some("experiments > babygirl()".to_string()),
|
|
Some(¶ms.msg),
|
|
);
|
|
|
|
|
|
let bot = Arc::clone(¶ms.bot);
|
|
|
|
let botlock = bot.read().await;
|
|
|
|
|
|
botlock
|
|
.botmgrs
|
|
.chat
|
|
.say_in_reply_to(
|
|
¶ms.msg,
|
|
String::from("16:13 notohh: cafdk"),
|
|
params.clone()
|
|
).await;
|
|
|
|
|
|
sleep(Duration::from_secs_f64(0.5)).await;
|
|
|
|
botlock
|
|
.botmgrs
|
|
.chat
|
|
.say_in_reply_to(
|
|
¶ms.msg,
|
|
String::from("16:13 notohh: have fun eating princess"),
|
|
params.clone()
|
|
).await;
|
|
|
|
|
|
sleep(Duration::from_secs_f64(2.0)).await;
|
|
|
|
botlock
|
|
.botmgrs
|
|
.chat
|
|
.say_in_reply_to(
|
|
¶ms.msg,
|
|
String::from("16:13 notohh: baby girl"),
|
|
params.clone()
|
|
).await;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
async fn routinelike(params : ExecBodyParams) {
|
|
println!("routinelike triggered!"); // NOTE : This test function intends to print (e.g., to stdout) at fn call
|
|
botlog::debug(
|
|
"routinelike triggered!",
|
|
Some("experiments > routinelike()".to_string()),
|
|
Some(¶ms.msg),
|
|
);
|
|
|
|
// spawn an async block that runs independently from others
|
|
|
|
tokio::spawn( async {
|
|
for _ in 0..5 {
|
|
println!(">> Innterroutine triggered!");
|
|
sleep(Duration::from_secs_f64(5.0)).await;
|
|
}
|
|
}
|
|
);
|
|
|
|
// lines are executed after in conjunction to the spawn
|
|
|
|
}
|
|
|