From dc35f04f2ebe87917e97a4429ea2e6e6da6ff878 Mon Sep 17 00:00:00 2001 From: JMARyA Date: Thu, 6 Jun 2024 16:37:29 +0200 Subject: [PATCH] finalize --- Cargo.lock | 49 +++++++++++++++++++++++++++++++ Cargo.toml | 1 + README.md | 80 +++++++++++++++++++++++++++++++++++++++++++++++++- src/api/mod.rs | 1 + src/args.rs | 3 +- src/main.rs | 45 +++++++++++++++++++++------- 6 files changed, 166 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8fbb1b1..dd1ee8e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -262,6 +262,27 @@ dependencies = [ "winapi", ] +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "encoding_rs" version = "0.8.34" @@ -593,6 +614,16 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.5.0", + "libc", +] + [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -763,6 +794,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "parking_lot" version = "0.12.3" @@ -881,6 +918,17 @@ dependencies = [ "bitflags 2.5.0", ] +[[package]] +name = "redox_users" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + [[package]] name = "reqwest" version = "0.12.4" @@ -1413,6 +1461,7 @@ dependencies = [ "chrono", "clap", "crossterm", + "dirs", "moka", "reqwest", "serde", diff --git a/Cargo.toml b/Cargo.toml index 4b4ada8..542a1d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ authors = ["JMARyA "] chrono = "0.4.38" clap = { version = "4.5.4", features = ["cargo"] } crossterm = "0.27.0" +dirs = "5.0.1" moka = { version = "0.12.7", features = ["sync"] } reqwest = { version = "0.12.4", features = ["blocking", "json"] } serde = { version = "1.0.203", features = ["derive"] } diff --git a/README.md b/README.md index 609cdf2..3651afa 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,80 @@ # vk -`vk` is a command line todo tool for Vikunja. \ No newline at end of file +`vk` is a command line todo tool for Vikunja. + +## Setup +vk saves it's configuration at `$HOME/.config/vk.toml`. + +To log in to your Vikunja Instance you can either use a API Token which you have to create manually or sign in using: +```shell +vk login --username user --password somepass --totp code --host vikunja.example.com +``` + +## Usage + +**Show your current todos:** +```shell +# Just this +vk + +# See done tasks as well +vk -d +vk --done + +# Show favorites only +vk -f +vk --favorite + +# Show tasks from specific project +vk --from myproject + +# Show tasks which have a label +vk -l label +vk --label label +``` + +**Working with tasks:** +```shell +# Create a task +vk new mytask + +# Task Detail View +vk info 42 # Tasks are referenced by their ID + +# Remove a task +vk rm 42 + +# Mark as done +vk done 42 + +# Assign a user to a task +vk assign me 42 +vk assign -u me 42 # You can undo this +``` + +**Working with projects:** +```shell +# List your projects +vk prj ls + +# Create a new project +vk prj add MyPrj --description "My project" + +# Remove a project +vk prj rm MyPrj +``` + +**Working with labels:** +```shell +# Assign a label to a task +vk label mylabel 42 +vk label -u mylabel 42 # Undo as well + +# List your labels +vk labels ls + +# Create a new label +vk labels new mylabel + +# Remove a label +vk labels rm mylabel +``` diff --git a/src/api/mod.rs b/src/api/mod.rs index b352ef9..57a5327 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -270,6 +270,7 @@ impl VikunjaAPI { "title": title }); + // todo : // description // due_date // end_date diff --git a/src/args.rs b/src/args.rs index 8ff7159..b6f0ec9 100644 --- a/src/args.rs +++ b/src/args.rs @@ -57,13 +57,14 @@ pub fn get_args() -> clap::ArgMatches { .about("Get a JWT Token for authentication") .arg(arg!(-u --username "Username").required(true)) .arg(arg!(-p --password "Password").required(true)) + .arg(arg!(--host "Vikunja Host").required(true)) .arg(arg!(--totp "TOTP Code").required(false)), ) .subcommand( command!() .name("assign") .about("Assign a user to a task") - .arg(arg!(-u --undo "Remove label from task").required(false)) + .arg(arg!(-u --undo "Remove user from task").required(false)) .arg(arg!([user] "User").required(true)) .arg(arg!([task_id] "Task ID").required(true)), ) diff --git a/src/main.rs b/src/main.rs index 5114097..b5fec4a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,24 +6,47 @@ mod ui; use api::{ProjectID, VikunjaAPI}; fn main() { - let config: config::Config = - toml::from_str(&std::fs::read_to_string("config.toml").unwrap()).unwrap(); - let api = VikunjaAPI::new(&config.host, &config.token); let arg = args::get_args(); + let config_path = dirs::home_dir().unwrap().join(".config").join("vk.toml"); + + if let Some(("login", login_arg)) = arg.subcommand() { + let username: &String = login_arg.get_one("username").unwrap(); + let password: &String = login_arg.get_one("password").unwrap(); + let totp: Option<&String> = login_arg.get_one("totp"); + let host: &String = login_arg.get_one("host").unwrap(); + + let host = if host.starts_with("http") { + host.to_string() + } else { + format!("https://{host}") + }; + + let api = VikunjaAPI::new(&host, ""); + + let token = api.login(username, password, totp.map(|x| x.as_str())); + let config = format!("host = \"{host}\"\ntoken = \"{token}\""); + + std::fs::write(config_path, config).unwrap(); + std::process::exit(0); + } + + let content = &std::fs::read_to_string(config_path).unwrap_or_else(|e| { + ui::print_color( + crossterm::style::Color::Red, + &format!("Could not read config file: {e}"), + ); + println!("\nTo setup vk run `vk login --help`"); + std::process::exit(1); + }); + + let config: config::Config = toml::from_str(content).unwrap(); + let api = VikunjaAPI::new(&config.host, &config.token); match arg.subcommand() { Some(("info", task_info_arg)) => { let task_id: &String = task_info_arg.get_one("task_id").unwrap(); ui::task::print_task_info(task_id.parse().unwrap(), &api); } - Some(("login", login_arg)) => { - let username: &String = login_arg.get_one("username").unwrap(); - let password: &String = login_arg.get_one("password").unwrap(); - let totp: Option<&String> = login_arg.get_one("totp"); - - let token = api.login(username, password, totp.map(|x| x.as_str())); - println!("\"token\" = \"{token}\""); - } Some(("prj", prj_arg)) => match prj_arg.subcommand() { Some(("ls", _)) => { ui::project::list_projects(&api);