summaryrefslogtreecommitdiff
path: root/src/requests/start.rs
diff options
context:
space:
mode:
authorFxQnLr <[email protected]>2023-11-07 12:58:12 +0100
committerFxQnLr <[email protected]>2023-11-07 12:58:12 +0100
commit344af3ff7c9493b4e2c6eee134b9b341eaabf736 (patch)
treea6b0af984ac4e0d799ae6991635ca1980872f1ce /src/requests/start.rs
parentf4d3d921460b606a9ff6686c9bb9a79bf546f264 (diff)
downloadwebol-cli-344af3ff7c9493b4e2c6eee134b9b341eaabf736.tar
webol-cli-344af3ff7c9493b4e2c6eee134b9b341eaabf736.tar.gz
webol-cli-344af3ff7c9493b4e2c6eee134b9b341eaabf736.zip
add ping support and readable output
Diffstat (limited to 'src/requests/start.rs')
-rw-r--r--src/requests/start.rs113
1 files changed, 79 insertions, 34 deletions
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 @@
1use std::time::Duration;
2
3use futures_util::{StreamExt, SinkExt}; 1use futures_util::{StreamExt, SinkExt};
4use indicatif::{ProgressBar, ProgressStyle}; 2use indicatif::MultiProgress;
5use reqwest::StatusCode; 3use reqwest::StatusCode;
6use serde::Deserialize; 4use serde::Deserialize;
7use tokio_tungstenite::{connect_async, tungstenite::Message}; 5use tokio_tungstenite::{connect_async, tungstenite::Message};
8 6
9use crate::{error::CliError, default_headers, ErrorResponse, format_url, Protocols}; 7use 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};
10 8
11pub async fn start(id: String, ping: bool) -> Result<(), CliError> { 9pub async fn start(id: String, ping: bool) -> Result<(), CliError> {
12 10
13 let send_start = ProgressBar::new(1); 11 let send_start = MultiProgress::new();
12 let overview = add_pb(&send_start, OVERVIEW_STYLE, format!("start {}", id));
14 13
15 // TODO: calculate average start-time on server 14 // TODO: calculate average start-time on server
16 send_start.set_style(
17 ProgressStyle::with_template("{spinner:.green} ({elapsed}) {wide_msg}")
18 .unwrap()
19 .tick_chars("|/-\\\\")
20 );
21
22 let url = format_url("start", Protocols::Http)?; 15 let url = format_url("start", Protocols::Http)?;
23 16 let connect = add_pb(&send_start, DEFAULT_STYLE, format!("connect to {}", url));
24 send_start.set_message(format!("connect to {}", url));
25 send_start.enable_steady_tick(Duration::from_millis(125));
26
27 let res = reqwest::Client::new() 17 let res = reqwest::Client::new()
28 .post(url) 18 .post(url)
29 .headers(default_headers()?) 19 .headers(default_headers()?)
@@ -33,7 +23,9 @@ pub async fn start(id: String, ping: bool) -> Result<(), CliError> {
33 .send() 23 .send()
34 .await 24 .await
35 .map_err(CliError::Reqwest)?; 25 .map_err(CliError::Reqwest)?;
26 finish_pb(connect, "connected, got response".to_string(), DONE_STYLE);
36 27
28 let res_pb = add_pb(&send_start, DEFAULT_STYLE, "analyzing response".to_string());
37 match res.status() { 29 match res.status() {
38 StatusCode::OK => { 30 StatusCode::OK => {
39 let body = serde_json::from_str::<StartResponse>( 31 let body = serde_json::from_str::<StartResponse>(
@@ -42,11 +34,16 @@ pub async fn start(id: String, ping: bool) -> Result<(), CliError> {
42 .map_err(CliError::Serde)?; 34 .map_err(CliError::Serde)?;
43 35
44 if body.boot { 36 if body.boot {
45 send_start.println("connected, sent start packet"); 37 finish_pb(res_pb, "sent start packet".to_string(), DONE_STYLE);
46 } 38 }
47 39
48 if ping { 40 if ping {
49 send_start.println(status_socket(body.uuid, &send_start).await?.to_string()); 41 let status = status_socket(body.uuid, &send_start).await?;
42 if status {
43 finish_pb(overview, format!("successfully started {}", body.id), OVERVIEW_DONE);
44 } else {
45 finish_pb(overview, format!("error while starting {}", body.id), OVERVIEW_ERROR);
46 }
50 } 47 }
51 }, 48 },
52 _ => { 49 _ => {
@@ -55,37 +52,63 @@ pub async fn start(id: String, ping: bool) -> Result<(), CliError> {
55 ) 52 )
56 .map_err(CliError::Serde)?; 53 .map_err(CliError::Serde)?;
57 54
58 println!("got error: {}", body.error); 55 res_pb.finish_with_message(format!("got error: {}", body.error));
59 } 56 }
60 } 57 }
61 58
62 Ok(()) 59 Ok(())
63} 60}
64 61
65async fn status_socket(uuid: String, pb: &ProgressBar) -> Result<bool, CliError> { 62async fn status_socket(uuid: String, pb: &MultiProgress) -> Result<bool, CliError> {
66 pb.set_message("setup websocket"); 63 // TODO: Remove unwraps
67 64 let ws_pb = add_pb(pb, DEFAULT_STYLE, "connect to websocket".to_string());
68 let (mut ws_stream, _response) = connect_async(format_url("status", Protocols::Websocket)?) 65 let (mut ws_stream, _response) = connect_async(format_url("status", Protocols::Websocket)?)
69 .await 66 .await
70 .expect("Failed to connect"); 67 .expect("Failed to connect");
71 pb.println("connected to websocket"); 68 finish_pb(ws_pb, "connected to websocket".to_string(), DONE_STYLE);
72 69
73 pb.set_message("send uuid message"); 70 ws_stream.send(Message::Text(uuid.clone())).await.unwrap();
74 ws_stream.send(Message::Text(uuid)).await.unwrap();
75 pb.println("sent uuid message");
76 71
77 pb.set_message("wait for message"); 72 let msg_pb = add_pb(pb, DEFAULT_STYLE, "await message".to_string());
78 let msg = ws_stream.next().await.unwrap(); 73 let msg = ws_stream.next().await.unwrap();
74 finish_pb(msg_pb, "received message".to_string(), DONE_STYLE);
79 75
80 pb.println(format!("msg: {:?}", msg));
81
82 ws_stream.close(None).await.unwrap(); 76 ws_stream.close(None).await.unwrap();
83 pb.println("connection closed");
84 // TODO: Check for correct UUID and timeout
85 pb.set_message("verifying message");
86 if msg.is_ok() { return Ok(true) }
87 77
88 Ok(false) 78 let v_pb = add_pb(pb, DEFAULT_STYLE, "verify response".to_string());
79 let res = verify_response(msg.unwrap().to_string(), uuid)?;
80 match res {
81 Verified::WrongUuid => {
82 finish_pb(v_pb, "returned wrong uuid".to_string(), ERROR_STYLE);
83 Ok(false)
84 },
85 Verified::ResponseType(res_type) => {
86 match res_type {
87 ResponseType::Start => {
88 finish_pb(v_pb, "device started".to_string(), DONE_STYLE);
89 Ok(true)
90 },
91 ResponseType::Timeout => {
92 finish_pb(v_pb, "ping timed out".to_string(), ERROR_STYLE);
93 Ok(false)
94 },
95 ResponseType::NotFound => {
96 finish_pb(v_pb, "unknown uuid".to_string(), ERROR_STYLE);
97 Ok(false)
98 },
99 }
100 }
101 }
102}
103
104fn verify_response(res: String, org_uuid: String) -> Result<Verified, CliError> {
105 let spl: Vec<&str> = res.split('_').collect();
106 let res_type = spl[0];
107 let uuid = spl[1];
108
109 if uuid != org_uuid { return Ok(Verified::WrongUuid) };
110
111 Ok(Verified::ResponseType(ResponseType::from(res_type)?))
89} 112}
90 113
91#[derive(Debug, Deserialize)] 114#[derive(Debug, Deserialize)]
@@ -94,3 +117,25 @@ struct StartResponse {
94 id: String, 117 id: String,
95 uuid: String, 118 uuid: String,
96} 119}
120
121enum Verified {
122 ResponseType(ResponseType),
123 WrongUuid
124}
125
126enum ResponseType {
127 Start,
128 Timeout,
129 NotFound,
130}
131
132impl ResponseType {
133 fn from(value: &str) -> Result<Self, CliError> {
134 match value {
135 "start" => Ok(ResponseType::Start),
136 "timeout" => Ok(ResponseType::Timeout),
137 "notfound" => Ok(ResponseType::NotFound),
138 _ => Err(CliError::WsResponse),
139 }
140 }
141}