Initial commit
This commit is contained in:
commit
22ecf89c69
8 changed files with 1753 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/target
|
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"cmake.configureOnOpen": false
|
||||||
|
}
|
1563
Cargo.lock
generated
Normal file
1563
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
26
Cargo.toml
Normal file
26
Cargo.toml
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
[package]
|
||||||
|
name = "notipriv"
|
||||||
|
version = "1.0.0"
|
||||||
|
edition = "2021"
|
||||||
|
build = "build.rs"
|
||||||
|
authors = ["Rémi BERTHO <remi.bertho@dalan.fr>"]
|
||||||
|
description = "UnifiedPush message sender"
|
||||||
|
readme = "README.md"
|
||||||
|
license = "MIT"
|
||||||
|
homepage = "https://dalan.fr"
|
||||||
|
repository = "https://git.berthor.eu/dalan/notipriv"
|
||||||
|
keywords = ["UnifiedPush", "notification"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow = "1"
|
||||||
|
clap = {version ="4", features=["derive"]}
|
||||||
|
human-panic = "1"
|
||||||
|
shadow-rs = "0.23"
|
||||||
|
confy = "0.5"
|
||||||
|
serde = {version ="1", features = ["derive"]}
|
||||||
|
reqwest = { version = "0.11", default_features = false, features = ["blocking", "rustls-tls"] }
|
||||||
|
url = {version ="2", features=["serde"]}
|
||||||
|
opener = "0.6"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
shadow-rs = "0.23"
|
26
LICENSE.md
Normal file
26
LICENSE.md
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Copyright © `2023` `Rémi BERTHO <remi.bertho@dalan.fr>`
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person
|
||||||
|
obtaining a copy of this software and associated documentation
|
||||||
|
files (the “Software”), to deal in the Software without
|
||||||
|
restriction, including without limitation the rights to use,
|
||||||
|
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following
|
||||||
|
conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
22
README.md
Normal file
22
README.md
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
# notipriv
|
||||||
|
UnifiedPush message sender.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
1. `cargo install notipriv` to install notipriv
|
||||||
|
2. `notipriv config` to configure the endpoint
|
||||||
|
3. Add alias in `~/.bashrc` or `~/.zshrc`
|
||||||
|
```sh
|
||||||
|
alias nr="notipriv run --"
|
||||||
|
alias ns="notipriv send"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
To send a notification:
|
||||||
|
```sh
|
||||||
|
ns "message
|
||||||
|
```
|
||||||
|
|
||||||
|
To run a command and send a notification at the end:
|
||||||
|
```sh
|
||||||
|
nr command
|
||||||
|
```
|
3
build.rs
Normal file
3
build.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
fn main() -> shadow_rs::SdResult<()> {
|
||||||
|
shadow_rs::new()
|
||||||
|
}
|
109
src/main.rs
Normal file
109
src/main.rs
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
use anyhow::{Result, bail};
|
||||||
|
use clap::{Parser, Subcommand};
|
||||||
|
use reqwest::Url;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use shadow_rs::{formatcp, shadow};
|
||||||
|
use std::{
|
||||||
|
ffi::{OsStr, OsString},
|
||||||
|
process::Command,
|
||||||
|
};
|
||||||
|
|
||||||
|
shadow!(build);
|
||||||
|
|
||||||
|
const VERSION_INFO: &str = formatcp!(
|
||||||
|
r#"{}
|
||||||
|
branch: {}
|
||||||
|
commit_hash: {}
|
||||||
|
build_env: {},{}"#,
|
||||||
|
build::PKG_VERSION,
|
||||||
|
build::BRANCH,
|
||||||
|
build::COMMIT_HASH,
|
||||||
|
build::RUST_VERSION,
|
||||||
|
build::RUST_CHANNEL
|
||||||
|
);
|
||||||
|
|
||||||
|
#[derive(Parser)]
|
||||||
|
#[clap(author, version = VERSION_INFO, about, long_about = None)]
|
||||||
|
#[command(propagate_version = true)]
|
||||||
|
struct Cli {
|
||||||
|
#[clap(subcommand)]
|
||||||
|
command: Commands,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subcommand)]
|
||||||
|
enum Commands {
|
||||||
|
/// Send a notification
|
||||||
|
Send {
|
||||||
|
/// The message to send
|
||||||
|
#[clap(action)]
|
||||||
|
msg: String,
|
||||||
|
},
|
||||||
|
/// Run a command and send notification result at the end
|
||||||
|
Run {
|
||||||
|
/// The command to execute
|
||||||
|
#[clap(action)]
|
||||||
|
cmd: Vec<OsString>,
|
||||||
|
},
|
||||||
|
/// Open configuration file
|
||||||
|
Config
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
struct Config {
|
||||||
|
endpoint: Url,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Config {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
endpoint: Url::parse("https://example.net").unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
human_panic::setup_panic!();
|
||||||
|
|
||||||
|
let cfg: Config = confy::load("notipriv", None)?;
|
||||||
|
|
||||||
|
let cli = Cli::parse();
|
||||||
|
|
||||||
|
match cli.command {
|
||||||
|
Commands::Send { msg } => send_notif(cfg.endpoint, msg)?,
|
||||||
|
Commands::Run { cmd } => run(cfg.endpoint, &cmd)?,
|
||||||
|
Commands::Config => opener::open(confy::get_configuration_file_path("notipriv", None)?)?
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_notif(endpoint: Url, msg: String) -> Result<()> {
|
||||||
|
let client = reqwest::blocking::Client::new();
|
||||||
|
let status = client.post(endpoint).body(msg).send()?.status();
|
||||||
|
if !status.is_success() {
|
||||||
|
println!("Error with status {}", status);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(endpoint: Url, cmd: &[impl AsRef<OsStr>]) -> Result<()> {
|
||||||
|
if cmd.is_empty() {
|
||||||
|
bail!("Empty command");
|
||||||
|
}
|
||||||
|
|
||||||
|
let cmd_name = cmd[0].as_ref().to_string_lossy();
|
||||||
|
let status = Command::new(cmd[0].as_ref())
|
||||||
|
.args(cmd[1..].as_ref())
|
||||||
|
.status()?;
|
||||||
|
if status.success() {
|
||||||
|
send_notif(endpoint, format!("✅ {} succes", cmd_name))?;
|
||||||
|
} else {
|
||||||
|
let msg = if let Some(code) = status.code() {
|
||||||
|
format!("❌ {} failed with code {}", cmd_name, code)
|
||||||
|
} else {
|
||||||
|
format!("❌ {} failed", cmd_name)
|
||||||
|
};
|
||||||
|
send_notif(endpoint, msg)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in a new issue