use std::thread;
use std::time::Duration;
use clap::{arg, ArgMatches, Command};
use rand::{rng, RngExt};
use windows_troll::modules::mouse_teleporter;
use crate::cli::CliModule;
pub struct MouseTeleporterCli;
impl CliModule for MouseTeleporterCli {
fn name(&self) -> &'static str {
"mouse-teleporter"
}
fn about(&self) -> &'static str {
"Move the mouse to chosen or random positions"
}
fn command(&self) -> Command {
Command::new(self.name())
.about(self.about())
.subcommand_required(true)
.arg_required_else_help(true)
.subcommand(
Command::new("teleport")
.about("Move the mouse to a specific position")
.arg(arg!(<X> "Horizontal screen coordinate").value_parser(clap::value_parser!(i32)))
.arg(arg!(<Y> "Vertical screen coordinate").value_parser(clap::value_parser!(i32))),
)
.subcommand(Command::new("random").about("Move the mouse to a random position"))
.subcommand(
Command::new("resolution").about("Print the primary display resolution"),
)
.subcommand(
Command::new("loop")
.about("Continuously move the mouse to random positions")
.arg(
arg!(-m --min <SECONDS> "Minimum wait time in seconds")
.default_value("10")
.value_parser(clap::value_parser!(u64)),
)
.arg(
arg!(-M --max <SECONDS> "Maximum wait time in seconds")
.default_value("60")
.value_parser(clap::value_parser!(u64)),
),
)
}
fn run(&self, matches: &ArgMatches) -> Result<(), Box<dyn std::error::Error>> {
match matches.subcommand() {
Some(("teleport", m)) => run_teleport(m),
Some(("random", _)) => run_random(),
Some(("resolution", _)) => run_resolution(),
Some(("loop", m)) => run_loop(m),
_ => unreachable!("exhausted subcommands"),
}
}
}
fn run_teleport(m: &ArgMatches) -> Result<(), Box<dyn std::error::Error>> {
let x = *m.get_one::<i32>("X").expect("required argument");
let y = *m.get_one::<i32>("Y").expect("required argument");
if mouse_teleporter::teleport_mouse(x, y) {
println!("Teleported mouse to ({x}, {y})");
} else {
println!("Failed to teleport mouse to ({x}, {y})");
}
Ok(())
}
fn run_random() -> Result<(), Box<dyn std::error::Error>> {
let (x, y) = mouse_teleporter::teleport_random();
println!("Teleported mouse to random position ({x}, {y})");
Ok(())
}
fn run_resolution() -> Result<(), Box<dyn std::error::Error>> {
let res = mouse_teleporter::get_resolution();
println!("{}x{}", res.width, res.height);
Ok(())
}
fn run_loop(m: &ArgMatches) -> Result<(), Box<dyn std::error::Error>> {
let mut min = *m.get_one::<u64>("min").expect("has default");
let mut max = *m.get_one::<u64>("max").expect("has default");
if min > max {
std::mem::swap(&mut min, &mut max);
}
println!("mouse-teleporter loop started. Press Ctrl+C to exit.");
println!("wait range: {min}..={max} seconds");
let mut rng = rng();
loop {
let wait = rng.random_range(min..=max);
println!("waiting {wait}s...");
thread::sleep(Duration::from_secs(wait));
let (x, y) = mouse_teleporter::teleport_random();
println!("teleported mouse to ({x}, {y})");
}
}