From f4d3d921460b606a9ff6686c9bb9a79bf546f264 Mon Sep 17 00:00:00 2001 From: FxQnLr Date: Thu, 2 Nov 2023 21:01:16 +0100 Subject: baseline ping --- src/main.rs | 48 ++++++++++++++++++++++++--------- src/requests/device.rs | 42 +++++++++++++++++------------ src/requests/start.rs | 73 +++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 120 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/main.rs b/src/main.rs index ab7e476..3e1388b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +use std::fmt::Display; + use clap::{Parser, Subcommand}; use config::SETTINGS; use error::CliError; @@ -21,7 +23,9 @@ struct Args { enum Commands { Start { /// id of the device - id: String + id: String, + #[arg(short, long)] + ping: Option }, Device { #[command(subcommand)] @@ -34,7 +38,8 @@ enum DeviceCmd { Add { id: String, mac: String, - broadcast_addr: String + broadcast_addr: String, + ip: String }, Get { id: String, @@ -42,27 +47,29 @@ enum DeviceCmd { Edit { id: String, mac: String, - broadcast_addr: String + broadcast_addr: String, + ip: String }, } -fn main() -> Result<(), CliError> { +#[tokio::main] +async fn main() -> Result<(), CliError> { let cli = Args::parse(); match cli.commands { - Commands::Start { id } => { - start(id)?; + Commands::Start { id, ping } => { + start(id, ping.unwrap_or(true)).await?; }, Commands::Device { devicecmd } => { match devicecmd { - DeviceCmd::Add { id, mac, broadcast_addr } => { - device::put(id, mac, broadcast_addr)?; + DeviceCmd::Add { id, mac, broadcast_addr, ip } => { + device::put(id, mac, broadcast_addr, ip).await?; }, DeviceCmd::Get { id } => { - device::get(id)?; + device::get(id).await?; }, - DeviceCmd::Edit { id, mac, broadcast_addr } => { - device::post(id, mac, broadcast_addr)?; + DeviceCmd::Edit { id, mac, broadcast_addr, ip } => { + device::post(id, mac, broadcast_addr, ip).await?; }, } } @@ -87,14 +94,29 @@ fn default_headers() -> Result { Ok(map) } -fn format_url(path: &str) -> Result { +fn format_url(path: &str, protocol: Protocols) -> Result { Ok(format!( - "{}/{}", + "{}://{}/{}", + protocol, SETTINGS.get_string("server").map_err(CliError::Config)?, path )) } +enum Protocols { + Http, + Websocket, +} + +impl Display for Protocols { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Http => f.write_str("http"), + Self::Websocket => f.write_str("ws") + } + } +} + #[derive(Debug, Deserialize)] struct ErrorResponse { error: String diff --git a/src/requests/device.rs b/src/requests/device.rs index 525745a..f7754a4 100644 --- a/src/requests/device.rs +++ b/src/requests/device.rs @@ -1,55 +1,63 @@ -use crate::{error::CliError, default_headers, format_url}; +use crate::{error::CliError, default_headers, format_url, Protocols}; -pub fn put(id: String, mac: String, broadcast_addr: String) -> Result<(), CliError> { - let res = reqwest::blocking::Client::new() - .put(format_url("device")?) +pub async fn put(id: String, mac: String, broadcast_addr: String, ip: String) -> Result<(), CliError> { + let res = reqwest::Client::new() + .put(format_url("device", Protocols::Http)?) .headers(default_headers()?) .body( format!( - r#"{{"id": "{}", "mac": "{}", "broadcast_addr": "{}"}}"#, + r#"{{"id": "{}", "mac": "{}", "broadcast_addr": "{}", "ip": "{}"}}"#, id, mac, - broadcast_addr + broadcast_addr, + ip ) ) .send() + .await .map_err(CliError::Reqwest)? - .text(); + .text() + .await; println!("{:?}", res); Ok(()) } -pub fn get(id: String) -> Result<(), CliError> { - let res = reqwest::blocking::Client::new() - .get(format_url("device")?) +pub async fn get(id: String) -> Result<(), CliError> { + let res = reqwest::Client::new() + .get(format_url("device", Protocols::Http)?) .headers(default_headers()?) .body( format!(r#"{{"id": "{}"}}"#, id) ) .send() + .await .map_err(CliError::Reqwest)? - .text(); + .text() + .await; println!("{:?}", res); Ok(()) } -pub fn post(id: String, mac: String, broadcast_addr: String) -> Result<(), CliError> { - let res = reqwest::blocking::Client::new() - .post(format_url("device")?) +pub async fn post(id: String, mac: String, broadcast_addr: String, ip: String) -> Result<(), CliError> { + let res = reqwest::Client::new() + .post(format_url("device", Protocols::Http)?) .headers(default_headers()?) .body( format!( - r#"{{"id": "{}", "mac": "{}", "broadcast_addr": "{}"}}"#, + r#"{{"id": "{}", "mac": "{}", "broadcast_addr": "{}", "ip": "{}"}}"#, id, mac, - broadcast_addr + broadcast_addr, + ip ) ) .send() + .await .map_err(CliError::Reqwest)? - .text(); + .text() + .await; println!("{:?}", res); Ok(()) diff --git a/src/requests/start.rs b/src/requests/start.rs index 30f65b9..d0c4411 100644 --- a/src/requests/start.rs +++ b/src/requests/start.rs @@ -1,37 +1,57 @@ +use std::time::Duration; + +use futures_util::{StreamExt, SinkExt}; +use indicatif::{ProgressBar, ProgressStyle}; use reqwest::StatusCode; use serde::Deserialize; +use tokio_tungstenite::{connect_async, tungstenite::Message}; -use crate::{config::SETTINGS, error::CliError, default_headers, ErrorResponse}; +use crate::{error::CliError, default_headers, ErrorResponse, format_url, Protocols}; -pub fn start(id: String) -> Result<(), CliError> { - let res = reqwest::blocking::Client::new() - .post( - format!( - "{}/start", - SETTINGS.get_string("server").map_err(CliError::Config)? - ) - ) +pub async fn start(id: String, ping: bool) -> Result<(), CliError> { + + let send_start = ProgressBar::new(1); + + // TODO: calculate average start-time on server + send_start.set_style( + ProgressStyle::with_template("{spinner:.green} ({elapsed}) {wide_msg}") + .unwrap() + .tick_chars("|/-\\\\") + ); + + let url = format_url("start", Protocols::Http)?; + + send_start.set_message(format!("connect to {}", url)); + send_start.enable_steady_tick(Duration::from_millis(125)); + + let res = reqwest::Client::new() + .post(url) .headers(default_headers()?) .body( - format!(r#"{{"id": "{}"}}"#, id) + format!(r#"{{"id": "{}", "ping": {}}}"#, id, ping) ) .send() + .await .map_err(CliError::Reqwest)?; match res.status() { StatusCode::OK => { let body = serde_json::from_str::( - &res.text().map_err(CliError::Reqwest)? + &res.text().await.map_err(CliError::Reqwest)? ) .map_err(CliError::Serde)?; if body.boot { - println!("successfully started {}", body.id); + send_start.println("connected, sent start packet"); + } + + if ping { + send_start.println(status_socket(body.uuid, &send_start).await?.to_string()); } }, _ => { let body = serde_json::from_str::( - &res.text().map_err(CliError::Reqwest)? + &res.text().await.map_err(CliError::Reqwest)? ) .map_err(CliError::Serde)?; @@ -42,8 +62,35 @@ pub fn start(id: String) -> Result<(), CliError> { Ok(()) } +async fn status_socket(uuid: String, pb: &ProgressBar) -> Result { + pb.set_message("setup websocket"); + + let (mut ws_stream, _response) = connect_async(format_url("status", Protocols::Websocket)?) + .await + .expect("Failed to connect"); + pb.println("connected to websocket"); + + pb.set_message("send uuid message"); + ws_stream.send(Message::Text(uuid)).await.unwrap(); + pb.println("sent uuid message"); + + pb.set_message("wait for message"); + let msg = ws_stream.next().await.unwrap(); + + pb.println(format!("msg: {:?}", msg)); + + ws_stream.close(None).await.unwrap(); + pb.println("connection closed"); + // TODO: Check for correct UUID and timeout + pb.set_message("verifying message"); + if msg.is_ok() { return Ok(true) } + + Ok(false) +} + #[derive(Debug, Deserialize)] struct StartResponse { boot: bool, id: String, + uuid: String, } -- cgit v1.2.3 From 344af3ff7c9493b4e2c6eee134b9b341eaabf736 Mon Sep 17 00:00:00 2001 From: FxQnLr Date: Tue, 7 Nov 2023 12:58:12 +0100 Subject: add ping support and readable output --- .gitignore | 1 + src/error.rs | 2 + src/main.rs | 28 +++++++++++- src/requests/device.rs | 4 +- src/requests/start.rs | 113 ++++++++++++++++++++++++++++++++++--------------- webol-cli.toml | 2 +- 6 files changed, 112 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/.gitignore b/.gitignore index 13a2081..f337b94 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target /postgres-data +webol-cli.toml diff --git a/src/error.rs b/src/error.rs index d35991b..27fc7a6 100644 --- a/src/error.rs +++ b/src/error.rs @@ -4,6 +4,7 @@ pub enum CliError { Reqwest(reqwest::Error), Config(config::ConfigError), Serde(serde_json::Error), + WsResponse, } impl Debug for CliError { @@ -12,6 +13,7 @@ impl Debug for CliError { Self::Reqwest(err) => { err.fmt(f) }, Self::Config(err) => { err.fmt(f) }, Self::Serde(err) => { err.fmt(f) }, + Self::WsResponse => { f.write_str("Error in Response") }, } } } diff --git a/src/main.rs b/src/main.rs index 3e1388b..d7c985f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,9 @@ -use std::fmt::Display; +use std::{fmt::Display, time::Duration}; use clap::{Parser, Subcommand}; use config::SETTINGS; use error::CliError; +use indicatif::{ProgressBar, ProgressStyle, MultiProgress}; use requests::{start::start, device}; use reqwest::header::{HeaderMap, HeaderValue}; use serde::Deserialize; @@ -11,7 +12,15 @@ mod config; mod error; mod requests; -/// webol http client +static OVERVIEW_STYLE: &str = "{spinner:.green} {wide_msg}({elapsed})"; +static OVERVIEW_ERROR: &str = "✗ {wide_msg}({elapsed})"; +static OVERVIEW_DONE: &str = "✓ {wide_msg}({elapsed})"; +static DEFAULT_STYLE: &str = " {spinner:.green} {wide_msg}"; +static DONE_STYLE: &str = " ✓ {wide_msg}"; +static ERROR_STYLE: &str = " ✗ {wide_msg}"; +static TICK_SPEED: u64 = 1000 / 16; + +/// webol client #[derive(Parser)] #[command(author, version, about, long_about = None)] struct Args { @@ -103,6 +112,21 @@ fn format_url(path: &str, protocol: Protocols) -> Result { )) } +fn add_pb(mp: &MultiProgress, template: &str, message: String) -> ProgressBar { + let pb = mp.add(ProgressBar::new(1)); + pb.set_style(ProgressStyle::with_template(template).unwrap()); + pb.enable_steady_tick(Duration::from_millis(TICK_SPEED)); + pb.set_message(message); + + pb +} + +fn finish_pb(pb: ProgressBar, message: String, template: &str) { + pb.set_style(ProgressStyle::with_template(template).unwrap()); + pb.finish_with_message(message); + +} + enum Protocols { Http, Websocket, diff --git a/src/requests/device.rs b/src/requests/device.rs index f7754a4..cbc838e 100644 --- a/src/requests/device.rs +++ b/src/requests/device.rs @@ -1,8 +1,10 @@ use crate::{error::CliError, default_headers, format_url, Protocols}; pub async fn put(id: String, mac: String, broadcast_addr: String, ip: String) -> Result<(), CliError> { + let url = format_url("device", Protocols::Http)?; + println!("{}", url); let res = reqwest::Client::new() - .put(format_url("device", Protocols::Http)?) + .put(url) .headers(default_headers()?) .body( format!( diff --git a/src/requests/start.rs b/src/requests/start.rs index d0c4411..882b154 100644 --- a/src/requests/start.rs +++ b/src/requests/start.rs @@ -1,29 +1,19 @@ -use std::time::Duration; - use futures_util::{StreamExt, SinkExt}; -use indicatif::{ProgressBar, ProgressStyle}; +use indicatif::MultiProgress; use reqwest::StatusCode; use serde::Deserialize; use tokio_tungstenite::{connect_async, tungstenite::Message}; -use crate::{error::CliError, default_headers, ErrorResponse, format_url, Protocols}; +use crate::{error::CliError, default_headers, ErrorResponse, format_url, Protocols, OVERVIEW_STYLE, DEFAULT_STYLE, DONE_STYLE, finish_pb, ERROR_STYLE, OVERVIEW_ERROR, OVERVIEW_DONE, add_pb}; pub async fn start(id: String, ping: bool) -> Result<(), CliError> { - let send_start = ProgressBar::new(1); + let send_start = MultiProgress::new(); + let overview = add_pb(&send_start, OVERVIEW_STYLE, format!("start {}", id)); // TODO: calculate average start-time on server - send_start.set_style( - ProgressStyle::with_template("{spinner:.green} ({elapsed}) {wide_msg}") - .unwrap() - .tick_chars("|/-\\\\") - ); - let url = format_url("start", Protocols::Http)?; - - send_start.set_message(format!("connect to {}", url)); - send_start.enable_steady_tick(Duration::from_millis(125)); - + let connect = add_pb(&send_start, DEFAULT_STYLE, format!("connect to {}", url)); let res = reqwest::Client::new() .post(url) .headers(default_headers()?) @@ -33,7 +23,9 @@ pub async fn start(id: String, ping: bool) -> Result<(), CliError> { .send() .await .map_err(CliError::Reqwest)?; + finish_pb(connect, "connected, got response".to_string(), DONE_STYLE); + let res_pb = add_pb(&send_start, DEFAULT_STYLE, "analyzing response".to_string()); match res.status() { StatusCode::OK => { let body = serde_json::from_str::( @@ -42,11 +34,16 @@ pub async fn start(id: String, ping: bool) -> Result<(), CliError> { .map_err(CliError::Serde)?; if body.boot { - send_start.println("connected, sent start packet"); + finish_pb(res_pb, "sent start packet".to_string(), DONE_STYLE); } if ping { - send_start.println(status_socket(body.uuid, &send_start).await?.to_string()); + let status = status_socket(body.uuid, &send_start).await?; + if status { + finish_pb(overview, format!("successfully started {}", body.id), OVERVIEW_DONE); + } else { + finish_pb(overview, format!("error while starting {}", body.id), OVERVIEW_ERROR); + } } }, _ => { @@ -55,37 +52,63 @@ pub async fn start(id: String, ping: bool) -> Result<(), CliError> { ) .map_err(CliError::Serde)?; - println!("got error: {}", body.error); + res_pb.finish_with_message(format!("✗ got error: {}", body.error)); } } Ok(()) } -async fn status_socket(uuid: String, pb: &ProgressBar) -> Result { - pb.set_message("setup websocket"); - +async fn status_socket(uuid: String, pb: &MultiProgress) -> Result { + // TODO: Remove unwraps + let ws_pb = add_pb(pb, DEFAULT_STYLE, "connect to websocket".to_string()); let (mut ws_stream, _response) = connect_async(format_url("status", Protocols::Websocket)?) .await .expect("Failed to connect"); - pb.println("connected to websocket"); - - pb.set_message("send uuid message"); - ws_stream.send(Message::Text(uuid)).await.unwrap(); - pb.println("sent uuid message"); + finish_pb(ws_pb, "connected to websocket".to_string(), DONE_STYLE); + + ws_stream.send(Message::Text(uuid.clone())).await.unwrap(); - pb.set_message("wait for message"); + let msg_pb = add_pb(pb, DEFAULT_STYLE, "await message".to_string()); let msg = ws_stream.next().await.unwrap(); + finish_pb(msg_pb, "received message".to_string(), DONE_STYLE); - pb.println(format!("msg: {:?}", msg)); - ws_stream.close(None).await.unwrap(); - pb.println("connection closed"); - // TODO: Check for correct UUID and timeout - pb.set_message("verifying message"); - if msg.is_ok() { return Ok(true) } - Ok(false) + let v_pb = add_pb(pb, DEFAULT_STYLE, "verify response".to_string()); + let res = verify_response(msg.unwrap().to_string(), uuid)?; + match res { + Verified::WrongUuid => { + finish_pb(v_pb, "returned wrong uuid".to_string(), ERROR_STYLE); + Ok(false) + }, + Verified::ResponseType(res_type) => { + match res_type { + ResponseType::Start => { + finish_pb(v_pb, "device started".to_string(), DONE_STYLE); + Ok(true) + }, + ResponseType::Timeout => { + finish_pb(v_pb, "ping timed out".to_string(), ERROR_STYLE); + Ok(false) + }, + ResponseType::NotFound => { + finish_pb(v_pb, "unknown uuid".to_string(), ERROR_STYLE); + Ok(false) + }, + } + } + } +} + +fn verify_response(res: String, org_uuid: String) -> Result { + let spl: Vec<&str> = res.split('_').collect(); + let res_type = spl[0]; + let uuid = spl[1]; + + if uuid != org_uuid { return Ok(Verified::WrongUuid) }; + + Ok(Verified::ResponseType(ResponseType::from(res_type)?)) } #[derive(Debug, Deserialize)] @@ -94,3 +117,25 @@ struct StartResponse { id: String, uuid: String, } + +enum Verified { + ResponseType(ResponseType), + WrongUuid +} + +enum ResponseType { + Start, + Timeout, + NotFound, +} + +impl ResponseType { + fn from(value: &str) -> Result { + match value { + "start" => Ok(ResponseType::Start), + "timeout" => Ok(ResponseType::Timeout), + "notfound" => Ok(ResponseType::NotFound), + _ => Err(CliError::WsResponse), + } + } +} diff --git a/webol-cli.toml b/webol-cli.toml index 7ffb99d..822af46 100644 --- a/webol-cli.toml +++ b/webol-cli.toml @@ -1,2 +1,2 @@ -server = "192.168.178.28:7229" +server = "localhost:7229" key = "aaa" -- cgit v1.2.3 From 9957da9b182ca209ff8caa8f670d3bd7eff154bb Mon Sep 17 00:00:00 2001 From: FxQnLr Date: Fri, 10 Nov 2023 12:23:31 +0100 Subject: add basic eta --- docker-compose.yml | 2 +- src/error.rs | 4 +++- src/main.rs | 6 +++--- src/requests/start.rs | 19 +++++++++++++++---- 4 files changed, 22 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/docker-compose.yml b/docker-compose.yml index 0a52d16..3a0ade5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ services: webol: - image: ghcr.io/fxqnlr/webol:dev-2 + image: ghcr.io/fxqnlr/webol:dev-6 container_name: webol restart: no depends_on: diff --git a/src/error.rs b/src/error.rs index 27fc7a6..f15c60a 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,9 +1,10 @@ -use std::fmt::Debug; +use std::{fmt::Debug, num::ParseIntError}; pub enum CliError { Reqwest(reqwest::Error), Config(config::ConfigError), Serde(serde_json::Error), + Parse(ParseIntError), WsResponse, } @@ -13,6 +14,7 @@ impl Debug for CliError { Self::Reqwest(err) => { err.fmt(f) }, Self::Config(err) => { err.fmt(f) }, Self::Serde(err) => { err.fmt(f) }, + Self::Parse(err) => { err.fmt(f) }, Self::WsResponse => { f.write_str("Error in Response") }, } } diff --git a/src/main.rs b/src/main.rs index d7c985f..204e671 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,9 +12,9 @@ mod config; mod error; mod requests; -static OVERVIEW_STYLE: &str = "{spinner:.green} {wide_msg}({elapsed})"; -static OVERVIEW_ERROR: &str = "✗ {wide_msg}({elapsed})"; -static OVERVIEW_DONE: &str = "✓ {wide_msg}({elapsed})"; +static OVERVIEW_STYLE: &str = "{spinner:.green} ({elapsed}{wide_msg}"; +static OVERVIEW_ERROR: &str = "✗ ({elapsed}) {wide_msg}"; +static OVERVIEW_DONE: &str = "✓ ({elapsed}) {wide_msg}"; static DEFAULT_STYLE: &str = " {spinner:.green} {wide_msg}"; static DONE_STYLE: &str = " ✓ {wide_msg}"; static ERROR_STYLE: &str = " ✗ {wide_msg}"; diff --git a/src/requests/start.rs b/src/requests/start.rs index 882b154..ca4ca44 100644 --- a/src/requests/start.rs +++ b/src/requests/start.rs @@ -1,5 +1,5 @@ use futures_util::{StreamExt, SinkExt}; -use indicatif::MultiProgress; +use indicatif::{MultiProgress, ProgressBar}; use reqwest::StatusCode; use serde::Deserialize; use tokio_tungstenite::{connect_async, tungstenite::Message}; @@ -9,7 +9,7 @@ use crate::{error::CliError, default_headers, ErrorResponse, format_url, Protoco pub async fn start(id: String, ping: bool) -> Result<(), CliError> { let send_start = MultiProgress::new(); - let overview = add_pb(&send_start, OVERVIEW_STYLE, format!("start {}", id)); + let overview = add_pb(&send_start, OVERVIEW_STYLE, format!(") start {}", id)); // TODO: calculate average start-time on server let url = format_url("start", Protocols::Http)?; @@ -38,7 +38,7 @@ pub async fn start(id: String, ping: bool) -> Result<(), CliError> { } if ping { - let status = status_socket(body.uuid, &send_start).await?; + let status = status_socket(body.uuid, &send_start, &overview, id).await?; if status { finish_pb(overview, format!("successfully started {}", body.id), OVERVIEW_DONE); } else { @@ -59,7 +59,7 @@ pub async fn start(id: String, ping: bool) -> Result<(), CliError> { Ok(()) } -async fn status_socket(uuid: String, pb: &MultiProgress) -> Result { +async fn status_socket(uuid: String, pb: &MultiProgress, overview: &ProgressBar, id: String) -> Result { // TODO: Remove unwraps let ws_pb = add_pb(pb, DEFAULT_STYLE, "connect to websocket".to_string()); let (mut ws_stream, _response) = connect_async(format_url("status", Protocols::Websocket)?) @@ -68,6 +68,11 @@ async fn status_socket(uuid: String, pb: &MultiProgress) -> Result Result Result { + let spl: Vec<&str> = msg.split('_').collect(); + if (spl[0] != "eta") || (spl[2] != uuid) { return Err(CliError::WsResponse); }; + Ok(u64::from_str_radix(spl[1], 10).map_err(CliError::Parse)?) +} + fn verify_response(res: String, org_uuid: String) -> Result { let spl: Vec<&str> = res.split('_').collect(); let res_type = spl[0]; -- cgit v1.2.3 From 93de8742961287cb9cfd08e68c8afa2347585a73 Mon Sep 17 00:00:00 2001 From: FxQnLr Date: Mon, 13 Nov 2023 15:21:25 +0100 Subject: add completion and cargo update --- Cargo.lock | 200 ++++++++++++++++++++++++++++++++---------------------------- Cargo.toml | 1 + src/main.rs | 17 +++++- 3 files changed, 122 insertions(+), 96 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 3337e1e..5620d60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" dependencies = [ "getrandom", "once_cell", @@ -116,9 +116,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.4" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" [[package]] name = "bitflags" @@ -161,9 +161,9 @@ checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cc" -version = "1.0.83" +version = "1.0.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "0f8e7c90afad890484a21653d08b6e209ae34770fb5ee298f9c699fcc1e5c856" dependencies = [ "libc", ] @@ -176,9 +176,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.4.6" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" +checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" dependencies = [ "clap_builder", "clap_derive", @@ -186,9 +186,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.6" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" +checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" dependencies = [ "anstream", "anstyle", @@ -196,11 +196,20 @@ dependencies = [ "strsim", ] +[[package]] +name = "clap_complete" +version = "4.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bffe91f06a11b4b9420f62103854e90867812cd5d01557f853c5ee8e791b12ae" +dependencies = [ + "clap", +] + [[package]] name = "clap_derive" -version = "4.4.2" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", @@ -210,9 +219,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "colorchoice" @@ -270,9 +279,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fbc60abd742b35f2492f808e1abbb83d45f72db402e14c55057edc9c7b1e9e4" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" dependencies = [ "libc", ] @@ -347,9 +356,9 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +checksum = "7c18ee0ed65a5f1f81cac6b1d213b69c35fa47d4252ad41f1486dbd8226fe36e" dependencies = [ "libc", "windows-sys 0.48.0", @@ -393,9 +402,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" dependencies = [ "futures-core", ] @@ -464,9 +473,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", "libc", @@ -521,9 +530,9 @@ checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "http" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "f95b9abcae896730d42b78e09c155ed4ddf82c07b4de772c64aee5b2d8b7c150" dependencies = [ "bytes", "fnv", @@ -634,9 +643,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "itoa" @@ -646,9 +655,9 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" dependencies = [ "wasm-bindgen", ] @@ -672,9 +681,20 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.149" +version = "0.2.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" + +[[package]] +name = "libredox" +version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.1", + "libc", + "redox_syscall", +] [[package]] name = "linked-hash-map" @@ -684,9 +704,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" [[package]] name = "log" @@ -723,9 +743,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" dependencies = [ "libc", "wasi", @@ -793,9 +813,9 @@ checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "openssl" -version = "0.10.57" +version = "0.10.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" +checksum = "7a257ad03cd8fb16ad4172fedf8094451e1af1c4b70097636ef2eac9a5f0cc33" dependencies = [ "bitflags 2.4.1", "cfg-if", @@ -825,9 +845,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.93" +version = "0.9.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" +checksum = "40a4130519a360279579c2053038317e40eff64d13fd3f004f9e1b72b8a6aaf9" dependencies = [ "cc", "libc", @@ -865,9 +885,9 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pest" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c022f1e7b65d6a24c0dbbd5fb344c66881bc01f3e5ae74a1c8100f2f985d98a4" +checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" dependencies = [ "memchr", "thiserror", @@ -876,9 +896,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35513f630d46400a977c4cb58f78e1bfbe01434316e60c37d27b9ad6139c66d8" +checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2" dependencies = [ "pest", "pest_generator", @@ -886,9 +906,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc9fc1b9e7057baba189b5c626e2d6f40681ae5b6eb064dc7c7834101ec8123a" +checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227" dependencies = [ "pest", "pest_meta", @@ -899,9 +919,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df74e9e7ec4053ceb980e7c0c8bd3594e977fde1af91daba9c928e8e8c6708d" +checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6" dependencies = [ "once_cell", "pest", @@ -988,30 +1008,21 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ "getrandom", - "redox_syscall 0.2.16", + "libredox", "thiserror", ] @@ -1021,7 +1032,7 @@ version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ - "base64 0.21.4", + "base64 0.21.5", "bytes", "encoding_rs", "futures-core", @@ -1082,9 +1093,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.20" +version = "0.38.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0" +checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" dependencies = [ "bitflags 2.4.1", "errno", @@ -1133,18 +1144,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.189" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" +checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.189" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" +checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" dependencies = [ "proc-macro2", "quote", @@ -1153,9 +1164,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa", "ryu", @@ -1233,9 +1244,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "2.0.38" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2", "quote", @@ -1265,13 +1276,13 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.3.5", + "redox_syscall", "rustix", "windows-sys 0.48.0", ] @@ -1313,9 +1324,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.33.0" +version = "1.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" dependencies = [ "backtrace", "bytes", @@ -1330,9 +1341,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", @@ -1363,9 +1374,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", @@ -1525,9 +1536,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1535,9 +1546,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" dependencies = [ "bumpalo", "log", @@ -1550,9 +1561,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02" dependencies = [ "cfg-if", "js-sys", @@ -1562,9 +1573,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1572,9 +1583,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" dependencies = [ "proc-macro2", "quote", @@ -1585,15 +1596,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" dependencies = [ "js-sys", "wasm-bindgen", @@ -1604,6 +1615,7 @@ name = "webol-cli" version = "0.1.0" dependencies = [ "clap", + "clap_complete", "config", "dirs", "futures-util", diff --git a/Cargo.toml b/Cargo.toml index 2ea0f27..ca76349 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ path = "src/main.rs" [dependencies] clap = { version = "4.4.6", features = ["derive"] } +clap_complete = "4.4.4" config = "0.13.3" dirs = "5.0.1" futures-util = "0.3.29" diff --git a/src/main.rs b/src/main.rs index 204e671..afe6fac 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ use std::{fmt::Display, time::Duration}; -use clap::{Parser, Subcommand}; +use clap::{Parser, Command, CommandFactory, Subcommand}; +use clap_complete::{generate, Shell, Generator}; use config::SETTINGS; use error::CliError; use indicatif::{ProgressBar, ProgressStyle, MultiProgress}; @@ -39,7 +40,10 @@ enum Commands { Device { #[command(subcommand)] devicecmd: DeviceCmd, - } + }, + CliGen { + id: Shell, + }, } #[derive(Subcommand)] @@ -81,12 +85,21 @@ async fn main() -> Result<(), CliError> { device::post(id, mac, broadcast_addr, ip).await?; }, } + }, + Commands::CliGen { id } => { + eprintln!("Generating completion file for {id:?}..."); + let mut cmd = Args::command(); + print_completions(id, &mut cmd) } } Ok(()) } +fn print_completions(gen: G, cmd: &mut Command) { + generate(gen, cmd, cmd.get_name().to_string(), &mut std::io::stdout()); +} + fn default_headers() -> Result { let mut map = HeaderMap::new(); map.append("Accept-Content", HeaderValue::from_str("application/json").unwrap()); -- cgit v1.2.3