mirror of
https://github.com/pcvolkmer/checkbar.git
synced 2025-04-19 11:06:50 +00:00
Add commands to be executed on mouse click
This commit is contained in:
parent
fb312d2102
commit
fbc5237a8e
1040
Cargo.lock
generated
Normal file
1040
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -2,13 +2,13 @@
|
||||
name = "checkbar"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
author = "Paul-Christian Volkmer <code@pcvolkmer.de>"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
dirs = "4"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "*"
|
||||
chrono = { version = "*", features = ["serde"] }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
toml = "*"
|
||||
|
16
README.adoc
16
README.adoc
@ -32,3 +32,19 @@ You can optionally specify `check_type`:
|
||||
|
||||
* `Html`: Default value, checks if a request is succeessful and returns HTTP OK - 200.
|
||||
* `Actuator`: Like `Html`, but checks if _Actuator_ shows that the application is up and running.
|
||||
|
||||
=== Execute commands
|
||||
|
||||
_This feature is experimental and starts further commands only after previous commands have been finished._
|
||||
|
||||
You can also specify a command to be executed when a mouse click occurs on a checked host.
|
||||
Use `click_cmd` to specifiy the command to be executed, e.g.
|
||||
|
||||
----
|
||||
...
|
||||
[[checks]]
|
||||
name = "Host 1"
|
||||
url = "http://host1.example.com"
|
||||
click_cmd = "xterm -e ssh admin@host1.example.com"
|
||||
...
|
||||
----
|
||||
|
108
src/main.rs
108
src/main.rs
@ -13,6 +13,7 @@ struct CheckConfig {
|
||||
name: String,
|
||||
url: String,
|
||||
check_type: Option<CheckType>,
|
||||
click_cmd: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@ -26,6 +27,11 @@ struct ActuatorResponse {
|
||||
status: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ClickEvent {
|
||||
name: String,
|
||||
}
|
||||
|
||||
struct CheckResult {
|
||||
name: String,
|
||||
state: CheckState,
|
||||
@ -40,8 +46,8 @@ impl Display for CheckResult {
|
||||
};
|
||||
write!(
|
||||
f,
|
||||
"{{\"full_text\":\"{}\",\"separator_block_width\":16,\"color\":\"{}\"}}",
|
||||
self.name, color
|
||||
"{{\"full_text\":\"{}\",\"name\":\"{}\",\"separator_block_width\":16,\"color\":\"{}\"}}",
|
||||
self.name, self.name, color
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -96,30 +102,86 @@ async fn print_states(check_configs: &[CheckConfig]) {
|
||||
println!("{}],", entries.join(","));
|
||||
}
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() {
|
||||
println!("{{\"version\":1,\"click_events\":false}}");
|
||||
println!("[");
|
||||
loop {
|
||||
let home_dir = dirs::home_dir().unwrap();
|
||||
let config = match std::fs::read_to_string(format!(
|
||||
"{}/.checkbar.toml",
|
||||
home_dir.to_str().unwrap_or("")
|
||||
)) {
|
||||
Ok(config) => match toml::from_str(config.as_str()) {
|
||||
Ok(config) => config,
|
||||
Err(_e) => Config {
|
||||
interval: None,
|
||||
checks: vec![],
|
||||
},
|
||||
},
|
||||
async fn get_config() -> Config {
|
||||
let home_dir = dirs::home_dir().unwrap();
|
||||
match std::fs::read_to_string(format!(
|
||||
"{}/.checkbar.toml",
|
||||
home_dir.to_str().unwrap_or("")
|
||||
)) {
|
||||
Ok(config) => match toml::from_str(config.as_str()) {
|
||||
Ok(config) => config,
|
||||
Err(_e) => Config {
|
||||
interval: None,
|
||||
checks: vec![],
|
||||
},
|
||||
};
|
||||
|
||||
print_states(&config.checks).await;
|
||||
std::thread::sleep(Duration::from_secs(config.interval.unwrap_or(60)));
|
||||
},
|
||||
Err(_e) => Config {
|
||||
interval: None,
|
||||
checks: vec![],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_click_cmd(name: String) -> Option<String> {
|
||||
for check in get_config().await.checks {
|
||||
if check.name == name {
|
||||
return check.click_cmd;
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
async fn run_click_cmd(cmd: String) {
|
||||
let _r = match std::process::Command::new("sh")
|
||||
.stdin(std::process::Stdio::piped())
|
||||
.stderr(std::process::Stdio::piped())
|
||||
.spawn()
|
||||
{
|
||||
Ok(mut child) => {
|
||||
use std::io::Write;
|
||||
let _r = child.stdin.as_mut().unwrap().write_all(cmd.as_bytes());
|
||||
child.wait()
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
};
|
||||
}
|
||||
|
||||
#[tokio::main(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn main() {
|
||||
println!("{{\"version\":1,\"click_events\":true}}");
|
||||
println!("[");
|
||||
|
||||
let inputs = tokio::task::spawn(async {
|
||||
let stdin = std::io::stdin();
|
||||
loop {
|
||||
let mut input = String::new();
|
||||
|
||||
if stdin.read_line(&mut input).is_err() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if input.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Remove leading comma
|
||||
let input = input.replace(",{", "{");
|
||||
|
||||
if let Ok(click_event) = serde_json::from_str::<ClickEvent>(input.as_str()) {
|
||||
if let Some(click_cmd) = get_click_cmd(click_event.name).await {
|
||||
run_click_cmd(click_cmd).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let checks = tokio::task::spawn(async {
|
||||
loop {
|
||||
let config = get_config().await;
|
||||
print_states(&config.checks).await;
|
||||
std::thread::sleep(Duration::from_secs(config.interval.unwrap_or(60)));
|
||||
}
|
||||
});
|
||||
|
||||
let _r = tokio::join!(inputs, checks);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user