feat: add notifications
This commit is contained in:
parent
b3885f80dd
commit
dfd0b52d50
5 changed files with 1129 additions and 20 deletions
1111
Cargo.lock
generated
1111
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -8,6 +8,7 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.71"
|
anyhow = "1.0.71"
|
||||||
clap = { version = "4.3.4", features = ["derive"] }
|
clap = { version = "4.3.4", features = ["derive"] }
|
||||||
|
notify-rust = "4.8.0"
|
||||||
serde = { version = "1.0.164", features = ["derive"] }
|
serde = { version = "1.0.164", features = ["derive"] }
|
||||||
serde_cbor = "0.11.2"
|
serde_cbor = "0.11.2"
|
||||||
thiserror = "1.0.44"
|
thiserror = "1.0.44"
|
||||||
|
|
19
src/cli.rs
19
src/cli.rs
|
@ -1,4 +1,4 @@
|
||||||
use crate::daemon::{Answer, Command as OtherCommand, AnswerErr};
|
use crate::daemon::{Answer, AnswerErr, Command as OtherCommand};
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use std::net::Shutdown;
|
use std::net::Shutdown;
|
||||||
|
@ -18,10 +18,18 @@ pub struct Cli {
|
||||||
|
|
||||||
#[derive(Debug, Subcommand)]
|
#[derive(Debug, Subcommand)]
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
Daemon,
|
Daemon {
|
||||||
Add { name: String, duration_seconds: u64 },
|
#[arg(short, long)]
|
||||||
|
notify: bool,
|
||||||
|
},
|
||||||
|
Add {
|
||||||
|
name: String,
|
||||||
|
duration_seconds: u64,
|
||||||
|
},
|
||||||
List,
|
List,
|
||||||
Remove { name: String },
|
Remove {
|
||||||
|
name: String,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_stream(socket_path: &String) -> Result<UnixStream> {
|
fn get_stream(socket_path: &String) -> Result<UnixStream> {
|
||||||
|
@ -35,7 +43,8 @@ pub fn send_command(socket_path: &String, command: OtherCommand) -> Result<()> {
|
||||||
stream
|
stream
|
||||||
.shutdown(Shutdown::Write)
|
.shutdown(Shutdown::Write)
|
||||||
.context("Could not shutdown write!")?;
|
.context("Could not shutdown write!")?;
|
||||||
let answer: Result<Answer, AnswerErr> = serde_cbor::from_reader(&stream).context("Could not read answer!")?;
|
let answer: Result<Answer, AnswerErr> =
|
||||||
|
serde_cbor::from_reader(&stream).context("Could not read answer!")?;
|
||||||
match answer {
|
match answer {
|
||||||
Ok(answer) => println!("{}", answer),
|
Ok(answer) => println!("{}", answer),
|
||||||
Err(err) => println!("Error: {}", err),
|
Err(err) => println!("Error: {}", err),
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
pub use crate::timer::Timer;
|
pub use crate::timer::Timer;
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
use notify_rust::Notification;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -50,10 +51,11 @@ pub enum AnswerErr {
|
||||||
pub struct Daemon {
|
pub struct Daemon {
|
||||||
listener: UnixListener,
|
listener: UnixListener,
|
||||||
timers: Vec<Timer>,
|
timers: Vec<Timer>,
|
||||||
|
notify: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Daemon {
|
impl Daemon {
|
||||||
pub fn new(socket_path: String) -> anyhow::Result<Self> {
|
pub fn new(socket_path: String, notify: bool) -> anyhow::Result<Self> {
|
||||||
let path = std::path::Path::new(&socket_path);
|
let path = std::path::Path::new(&socket_path);
|
||||||
if path.exists() {
|
if path.exists() {
|
||||||
std::fs::remove_file(path)
|
std::fs::remove_file(path)
|
||||||
|
@ -64,6 +66,7 @@ impl Daemon {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
listener,
|
listener,
|
||||||
timers: Vec::new(),
|
timers: Vec::new(),
|
||||||
|
notify,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,9 +108,18 @@ impl Daemon {
|
||||||
fn check_timers(&mut self) {
|
fn check_timers(&mut self) {
|
||||||
self.timers.retain(|timer| {
|
self.timers.retain(|timer| {
|
||||||
let expired = timer.is_expired();
|
let expired = timer.is_expired();
|
||||||
|
|
||||||
if expired {
|
if expired {
|
||||||
println!("Timer {} is expired!", timer.name);
|
let msg = format!("Timer {} has expired!", timer.name);
|
||||||
|
println!("{}", &msg);
|
||||||
|
if self.notify {
|
||||||
|
match Notification::new().summary(" Timers").body(&msg).show() {
|
||||||
|
Ok(_) => println!("Send notification sucessfully."),
|
||||||
|
Err(_) => println!("Failed to send notification."),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
!expired
|
!expired
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ use clap::Parser;
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let args = Cli::parse();
|
let args = Cli::parse();
|
||||||
let daemon_command = match args.command {
|
let daemon_command = match args.command {
|
||||||
CliCommand::Daemon => return Daemon::new(args.socket)?.run(),
|
CliCommand::Daemon { notify } => return Daemon::new(args.socket, notify)?.run(),
|
||||||
CliCommand::Add {
|
CliCommand::Add {
|
||||||
name,
|
name,
|
||||||
duration_seconds,
|
duration_seconds,
|
||||||
|
|
Loading…
Reference in a new issue