1#![doc = include_str!("../README.md")]
2
3use std::{thread::{spawn, sleep}, time::Duration, sync::mpsc::Receiver};
4use mouse_rs::{Mouse, types::Point};
5mod wiggler;
6
7pub struct Meth {
27 terminate: std::sync::mpsc::Sender<()>
29}
30
31impl Drop for Meth {
32 fn drop(&mut self) {
33 let _ = self.terminate.send(());
36 }
37}
38
39impl Meth {
40 const SLEEP_PERIOD: Duration = Duration::from_secs(30);
42
43 pub fn new() -> Self {
45 let (terminate, rx) = std::sync::mpsc::channel();
46
47 spawn(move || {
48 loop {
49 if let Ok(_) = rx.try_recv() { break }
51
52 if Self::keep_awake(&rx).is_ok() { break }
54 sleep(Self::SLEEP_PERIOD)
55 }
56 });
57
58 Meth { terminate }
59 }
60
61 fn identical(a: &Point, b: &Point) -> bool {
63 a.x == b.x &&
64 a.y == b.y
65 }
66
67 fn keep_awake(rx: &Receiver<()>) -> Result<(), Box<dyn std::error::Error>> {
70 let mouse = Mouse::new();
71 let mut position = mouse.get_position().unwrap();
72 let mut wiggler = wiggler::Wiggler::default();
73
74 loop {
75 if let Ok(_) = rx.try_recv() { break }
77
78 {
79 let mut p = mouse.get_position()?;
80
81 if Self::identical(&p, &position) {
83 wiggler.transform(&mut p);
85 mouse.move_to(p.x as i32, p.y as i32)?;
86 }
87
88 position = p;
89 };
90
91 sleep(Meth::SLEEP_PERIOD);
93 }
94
95 Ok(())
96 }
97}
98
99
100#[cfg(test)]
101mod test {
102 use std::time::Duration;
103 use crate::Meth;
104
105 #[test]
106 fn test_move() {
107 {
108 println!("Wiggling soon!");
109 let _meth = Meth::new();
110 std::thread::sleep(Duration::from_secs(60));
111 }
112
113 println!("No more wiggles!");
114 std::thread::sleep(Duration::from_secs(90));
115 }
116
117 #[test]
118 fn two() {
119 {
120 println!("Wiggling soon!");
121 let _meth_a = Meth::new();
122 let _meth_b = Meth::new();
123 std::thread::sleep(Duration::from_secs(60));
124 }
125
126 println!("No more wiggles!");
127 std::thread::sleep(Duration::from_secs(90));
128 }
129}