working prototype

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
Sean Cross 2021-05-11 12:24:27 +08:00
parent 9b1630d71c
commit 4608977088
3 changed files with 85 additions and 31 deletions

12
Cargo.lock generated
View File

@ -113,11 +113,12 @@ dependencies = [
]
[[package]]
name = "lark-killer"
name = "larkinator"
version = "0.1.0"
dependencies = [
"chrono",
"sysinfo",
"winreg",
"winrt-notification",
]
@ -411,6 +412,15 @@ dependencies = [
"syn",
]
[[package]]
name = "winreg"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d107f8c6e916235c4c01cabb3e8acf7bea8ef6a63ca2e7fa0527c049badfc48c"
dependencies = [
"winapi",
]
[[package]]
name = "winrt-notification"
version = "0.3.1"

View File

@ -1,13 +1,12 @@
[package]
authors = ["Sean Cross <sean@xobs.io>"]
description = "Terminate Lark when it's not office hours"
description = "Terminator for Lark when it's not office hours"
edition = "2018"
name = "lark-killer"
name = "larkinator"
version = "0.1.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
chrono = "0.4"
sysinfo = "0.17"
winreg = "0.8"
winrt-notification = "0.3"

View File

@ -1,7 +1,12 @@
fn make_holidays() -> std::collections::BTreeMap<chrono::Date<chrono::Local>, &'static str> {
use chrono::offset::TimeZone;
use chrono::Local;
let mut holidays = std::collections::BTreeMap::new();
use chrono::{Date, Local, TimeZone};
use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
use sysinfo::{ProcessExt, SystemExt};
use winreg::{RegValue, types::FromRegValue};
use winrt_notification::{Duration, Sound, Toast};
fn make_holidays() -> BTreeMap<Date<Local>, &'static str> {
let mut holidays = BTreeMap::new();
holidays.insert(Local.ymd(2021, 1, 1), "New Year's Day");
holidays.insert(Local.ymd(2021, 2, 12), "Chinese New Year");
@ -30,7 +35,6 @@ fn make_holidays() -> std::collections::BTreeMap<chrono::Date<chrono::Local>, &'
}
fn process_is_running(name: &str) -> bool {
use sysinfo::{ProcessExt, SystemExt};
// First we update all information of our system struct.
let mut system = sysinfo::System::new_all();
system.refresh_all();
@ -44,7 +48,6 @@ fn process_is_running(name: &str) -> bool {
fn try_terminating(name: &str) -> Option<std::path::PathBuf> {
let mut process_path = None;
use sysinfo::{ProcessExt, SystemExt};
// First we update all information of our system struct.
let mut system = sysinfo::System::new_all();
@ -79,18 +82,60 @@ fn is_working_hours<T: chrono::Datelike + chrono::Timelike>(date_time: &T) -> bo
date_time.hour() >= 9 && date_time.hour() <= 18
}
fn get_lark_path() -> Option<PathBuf> {
use winreg::enums::*;
use winreg::RegKey;
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
let lark_cfg = match hkcu.open_subkey("SOFTWARE\\Ion\\Larkinator") {
Ok(v) => Some(v),
Err(_) => None,
}?;
let v: std::io::Result<RegValue> = lark_cfg.get_raw_value("Lark Path");
let mut buf = v.unwrap();
// Strip off NULL termination
buf.bytes.pop();
buf.bytes.pop();
let osstr = std::ffi::OsString::from_reg_value(&buf).unwrap();
Some(Path::new(&osstr).to_owned())
// match v {
// Ok(v) => {
// print!("Values: ");
// use std::os::windows::ffi::OsStrExt;
// for (_idx, c) in v.encode_wide().enumerate() {
// print!(" {:04x}", c);
// }
// println!();
// let converted: PathBuf = v.into();
// Some(converted.to_owned())
// }
// Err(_) => None,
// }
// None
}
fn set_lark_path(new_path: &Path) -> std::io::Result<()> {
use winreg::enums::*;
use winreg::RegKey;
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
let (key, _disp) = hkcu.create_subkey("SOFTWARE\\Ion\\Larkinator")?;
key.set_value("Lark Path", &new_path.as_os_str())?;
Ok(())
}
fn main() {
use chrono::Local;
use winrt_notification::{Duration, Sound, Toast};
let mut process_path: Option<std::path::PathBuf> = None;
let process_name = "Lark.exe";
loop {
let local = Local::now(); // e.g. `2014-11-28T21:45:59.324310806+09:00`
let should_be_running = is_working_hours(&local);
if let Some(p) = &process_path {
if should_be_running && !process_is_running(process_name) {
println!("Running Lark!");
let is_running = process_is_running(process_name);
// println!("Should? {} Running? {}", should_be_running, is_running);
if should_be_running && !is_running {
println!("Running Lark!");
if let Some(p) = get_lark_path() {
println!("Lark path: {}", p.display());
std::process::Command::new(p)
.spawn()
.expect("Couldn't run Lark!");
@ -102,22 +147,22 @@ fn main() {
.duration(Duration::Short)
.show()
.expect("unable to toast");
} else {
println!("Would run Lark, but no path found");
}
} else {
if !should_be_running && process_is_running(process_name) {
println!("Terminating Lark, since it should't be running");
process_path = try_terminating(process_name);
if process_path.is_some() {
Toast::new(Toast::POWERSHELL_APP_ID)
.title("Terminated Lark")
.text1("Lark was terminated because it is outside working hours")
.sound(Some(Sound::SMS))
.duration(Duration::Short)
.show()
.expect("unable to toast");
}
} else if !should_be_running && is_running {
println!("Terminating Lark, since it should't be running");
if let Some(p) = try_terminating(process_name) {
set_lark_path(&p).ok();
Toast::new(Toast::POWERSHELL_APP_ID)
.title("Terminated Lark")
.text1("Lark was terminated because it is outside working hours")
.sound(Some(Sound::SMS))
.duration(Duration::Short)
.show()
.expect("unable to toast");
}
}
std::thread::sleep(std::time::Duration::from_secs(100));
std::thread::sleep(std::time::Duration::from_secs(3));
}
}