diff options
-rw-r--r-- | Cargo.lock | 281 | ||||
-rw-r--r-- | Cargo.toml | 27 | ||||
-rw-r--r-- | docker-compose.yml | 10 | ||||
-rw-r--r-- | src/config.rs | 39 | ||||
-rw-r--r-- | src/error.rs | 56 | ||||
-rw-r--r-- | src/main.rs | 111 | ||||
-rw-r--r-- | src/requests.rs (renamed from src/requests/mod.rs) | 0 | ||||
-rw-r--r-- | src/requests/device.rs | 86 | ||||
-rw-r--r-- | src/requests/start.rs | 189 |
9 files changed, 494 insertions, 305 deletions
@@ -18,21 +18,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" | 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" |
19 | 19 | ||
20 | [[package]] | 20 | [[package]] |
21 | name = "ahash" | ||
22 | version = "0.7.7" | ||
23 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
24 | checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" | ||
25 | dependencies = [ | ||
26 | "getrandom", | ||
27 | "once_cell", | ||
28 | "version_check", | ||
29 | ] | ||
30 | |||
31 | [[package]] | ||
32 | name = "anstream" | 21 | name = "anstream" |
33 | version = "0.6.4" | 22 | version = "0.6.12" |
34 | source = "registry+https://github.com/rust-lang/crates.io-index" | 23 | source = "registry+https://github.com/rust-lang/crates.io-index" |
35 | checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" | 24 | checksum = "96b09b5178381e0874812a9b157f7fe84982617e48f71f4e3235482775e5b540" |
36 | dependencies = [ | 25 | dependencies = [ |
37 | "anstyle", | 26 | "anstyle", |
38 | "anstyle-parse", | 27 | "anstyle-parse", |
@@ -77,6 +66,12 @@ dependencies = [ | |||
77 | ] | 66 | ] |
78 | 67 | ||
79 | [[package]] | 68 | [[package]] |
69 | name = "anyhow" | ||
70 | version = "1.0.80" | ||
71 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
72 | checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" | ||
73 | |||
74 | [[package]] | ||
80 | name = "async-trait" | 75 | name = "async-trait" |
81 | version = "0.1.74" | 76 | version = "0.1.74" |
82 | source = "registry+https://github.com/rust-lang/crates.io-index" | 77 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -110,12 +105,6 @@ dependencies = [ | |||
110 | 105 | ||
111 | [[package]] | 106 | [[package]] |
112 | name = "base64" | 107 | name = "base64" |
113 | version = "0.13.1" | ||
114 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
115 | checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" | ||
116 | |||
117 | [[package]] | ||
118 | name = "base64" | ||
119 | version = "0.21.5" | 108 | version = "0.21.5" |
120 | source = "registry+https://github.com/rust-lang/crates.io-index" | 109 | source = "registry+https://github.com/rust-lang/crates.io-index" |
121 | checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" | 110 | checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" |
@@ -131,6 +120,9 @@ name = "bitflags" | |||
131 | version = "2.4.1" | 120 | version = "2.4.1" |
132 | source = "registry+https://github.com/rust-lang/crates.io-index" | 121 | source = "registry+https://github.com/rust-lang/crates.io-index" |
133 | checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" | 122 | checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" |
123 | dependencies = [ | ||
124 | "serde", | ||
125 | ] | ||
134 | 126 | ||
135 | [[package]] | 127 | [[package]] |
136 | name = "block-buffer" | 128 | name = "block-buffer" |
@@ -176,9 +168,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | |||
176 | 168 | ||
177 | [[package]] | 169 | [[package]] |
178 | name = "clap" | 170 | name = "clap" |
179 | version = "4.4.8" | 171 | version = "4.5.1" |
180 | source = "registry+https://github.com/rust-lang/crates.io-index" | 172 | source = "registry+https://github.com/rust-lang/crates.io-index" |
181 | checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" | 173 | checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" |
182 | dependencies = [ | 174 | dependencies = [ |
183 | "clap_builder", | 175 | "clap_builder", |
184 | "clap_derive", | 176 | "clap_derive", |
@@ -186,9 +178,9 @@ dependencies = [ | |||
186 | 178 | ||
187 | [[package]] | 179 | [[package]] |
188 | name = "clap_builder" | 180 | name = "clap_builder" |
189 | version = "4.4.8" | 181 | version = "4.5.1" |
190 | source = "registry+https://github.com/rust-lang/crates.io-index" | 182 | source = "registry+https://github.com/rust-lang/crates.io-index" |
191 | checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" | 183 | checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" |
192 | dependencies = [ | 184 | dependencies = [ |
193 | "anstream", | 185 | "anstream", |
194 | "anstyle", | 186 | "anstyle", |
@@ -198,18 +190,18 @@ dependencies = [ | |||
198 | 190 | ||
199 | [[package]] | 191 | [[package]] |
200 | name = "clap_complete" | 192 | name = "clap_complete" |
201 | version = "4.4.4" | 193 | version = "4.5.1" |
202 | source = "registry+https://github.com/rust-lang/crates.io-index" | 194 | source = "registry+https://github.com/rust-lang/crates.io-index" |
203 | checksum = "bffe91f06a11b4b9420f62103854e90867812cd5d01557f853c5ee8e791b12ae" | 195 | checksum = "885e4d7d5af40bfb99ae6f9433e292feac98d452dcb3ec3d25dfe7552b77da8c" |
204 | dependencies = [ | 196 | dependencies = [ |
205 | "clap", | 197 | "clap", |
206 | ] | 198 | ] |
207 | 199 | ||
208 | [[package]] | 200 | [[package]] |
209 | name = "clap_derive" | 201 | name = "clap_derive" |
210 | version = "4.4.7" | 202 | version = "4.5.0" |
211 | source = "registry+https://github.com/rust-lang/crates.io-index" | 203 | source = "registry+https://github.com/rust-lang/crates.io-index" |
212 | checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" | 204 | checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" |
213 | dependencies = [ | 205 | dependencies = [ |
214 | "heck", | 206 | "heck", |
215 | "proc-macro2", | 207 | "proc-macro2", |
@@ -219,9 +211,9 @@ dependencies = [ | |||
219 | 211 | ||
220 | [[package]] | 212 | [[package]] |
221 | name = "clap_lex" | 213 | name = "clap_lex" |
222 | version = "0.6.0" | 214 | version = "0.7.0" |
223 | source = "registry+https://github.com/rust-lang/crates.io-index" | 215 | source = "registry+https://github.com/rust-lang/crates.io-index" |
224 | checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" | 216 | checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" |
225 | 217 | ||
226 | [[package]] | 218 | [[package]] |
227 | name = "colorchoice" | 219 | name = "colorchoice" |
@@ -231,11 +223,12 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" | |||
231 | 223 | ||
232 | [[package]] | 224 | [[package]] |
233 | name = "config" | 225 | name = "config" |
234 | version = "0.13.3" | 226 | version = "0.14.0" |
235 | source = "registry+https://github.com/rust-lang/crates.io-index" | 227 | source = "registry+https://github.com/rust-lang/crates.io-index" |
236 | checksum = "d379af7f68bfc21714c6c7dea883544201741d2ce8274bb12fa54f89507f52a7" | 228 | checksum = "7328b20597b53c2454f0b1919720c25c7339051c02b72b7e05409e00b14132be" |
237 | dependencies = [ | 229 | dependencies = [ |
238 | "async-trait", | 230 | "async-trait", |
231 | "convert_case", | ||
239 | "json5", | 232 | "json5", |
240 | "lazy_static", | 233 | "lazy_static", |
241 | "nom", | 234 | "nom", |
@@ -262,6 +255,35 @@ dependencies = [ | |||
262 | ] | 255 | ] |
263 | 256 | ||
264 | [[package]] | 257 | [[package]] |
258 | name = "const-random" | ||
259 | version = "0.1.17" | ||
260 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
261 | checksum = "5aaf16c9c2c612020bcfd042e170f6e32de9b9d75adb5277cdbbd2e2c8c8299a" | ||
262 | dependencies = [ | ||
263 | "const-random-macro", | ||
264 | ] | ||
265 | |||
266 | [[package]] | ||
267 | name = "const-random-macro" | ||
268 | version = "0.1.16" | ||
269 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
270 | checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" | ||
271 | dependencies = [ | ||
272 | "getrandom", | ||
273 | "once_cell", | ||
274 | "tiny-keccak", | ||
275 | ] | ||
276 | |||
277 | [[package]] | ||
278 | name = "convert_case" | ||
279 | version = "0.6.0" | ||
280 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
281 | checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" | ||
282 | dependencies = [ | ||
283 | "unicode-segmentation", | ||
284 | ] | ||
285 | |||
286 | [[package]] | ||
265 | name = "core-foundation" | 287 | name = "core-foundation" |
266 | version = "0.9.3" | 288 | version = "0.9.3" |
267 | source = "registry+https://github.com/rust-lang/crates.io-index" | 289 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -287,6 +309,12 @@ dependencies = [ | |||
287 | ] | 309 | ] |
288 | 310 | ||
289 | [[package]] | 311 | [[package]] |
312 | name = "crunchy" | ||
313 | version = "0.2.2" | ||
314 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
315 | checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" | ||
316 | |||
317 | [[package]] | ||
290 | name = "crypto-common" | 318 | name = "crypto-common" |
291 | version = "0.1.6" | 319 | version = "0.1.6" |
292 | source = "registry+https://github.com/rust-lang/crates.io-index" | 320 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -335,9 +363,12 @@ dependencies = [ | |||
335 | 363 | ||
336 | [[package]] | 364 | [[package]] |
337 | name = "dlv-list" | 365 | name = "dlv-list" |
338 | version = "0.3.0" | 366 | version = "0.5.2" |
339 | source = "registry+https://github.com/rust-lang/crates.io-index" | 367 | source = "registry+https://github.com/rust-lang/crates.io-index" |
340 | checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" | 368 | checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" |
369 | dependencies = [ | ||
370 | "const-random", | ||
371 | ] | ||
341 | 372 | ||
342 | [[package]] | 373 | [[package]] |
343 | name = "encode_unicode" | 374 | name = "encode_unicode" |
@@ -355,6 +386,12 @@ dependencies = [ | |||
355 | ] | 386 | ] |
356 | 387 | ||
357 | [[package]] | 388 | [[package]] |
389 | name = "equivalent" | ||
390 | version = "1.0.1" | ||
391 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
392 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" | ||
393 | |||
394 | [[package]] | ||
358 | name = "errno" | 395 | name = "errno" |
359 | version = "0.3.6" | 396 | version = "0.3.6" |
360 | source = "registry+https://github.com/rust-lang/crates.io-index" | 397 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -499,8 +536,8 @@ dependencies = [ | |||
499 | "futures-core", | 536 | "futures-core", |
500 | "futures-sink", | 537 | "futures-sink", |
501 | "futures-util", | 538 | "futures-util", |
502 | "http", | 539 | "http 0.2.10", |
503 | "indexmap", | 540 | "indexmap 1.9.3", |
504 | "slab", | 541 | "slab", |
505 | "tokio", | 542 | "tokio", |
506 | "tokio-util", | 543 | "tokio-util", |
@@ -512,9 +549,18 @@ name = "hashbrown" | |||
512 | version = "0.12.3" | 549 | version = "0.12.3" |
513 | source = "registry+https://github.com/rust-lang/crates.io-index" | 550 | source = "registry+https://github.com/rust-lang/crates.io-index" |
514 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" | 551 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" |
515 | dependencies = [ | 552 | |
516 | "ahash", | 553 | [[package]] |
517 | ] | 554 | name = "hashbrown" |
555 | version = "0.13.2" | ||
556 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
557 | checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" | ||
558 | |||
559 | [[package]] | ||
560 | name = "hashbrown" | ||
561 | version = "0.14.3" | ||
562 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
563 | checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" | ||
518 | 564 | ||
519 | [[package]] | 565 | [[package]] |
520 | name = "heck" | 566 | name = "heck" |
@@ -540,13 +586,24 @@ dependencies = [ | |||
540 | ] | 586 | ] |
541 | 587 | ||
542 | [[package]] | 588 | [[package]] |
589 | name = "http" | ||
590 | version = "1.0.0" | ||
591 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
592 | checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" | ||
593 | dependencies = [ | ||
594 | "bytes", | ||
595 | "fnv", | ||
596 | "itoa", | ||
597 | ] | ||
598 | |||
599 | [[package]] | ||
543 | name = "http-body" | 600 | name = "http-body" |
544 | version = "0.4.5" | 601 | version = "0.4.5" |
545 | source = "registry+https://github.com/rust-lang/crates.io-index" | 602 | source = "registry+https://github.com/rust-lang/crates.io-index" |
546 | checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" | 603 | checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" |
547 | dependencies = [ | 604 | dependencies = [ |
548 | "bytes", | 605 | "bytes", |
549 | "http", | 606 | "http 0.2.10", |
550 | "pin-project-lite", | 607 | "pin-project-lite", |
551 | ] | 608 | ] |
552 | 609 | ||
@@ -573,7 +630,7 @@ dependencies = [ | |||
573 | "futures-core", | 630 | "futures-core", |
574 | "futures-util", | 631 | "futures-util", |
575 | "h2", | 632 | "h2", |
576 | "http", | 633 | "http 0.2.10", |
577 | "http-body", | 634 | "http-body", |
578 | "httparse", | 635 | "httparse", |
579 | "httpdate", | 636 | "httpdate", |
@@ -616,7 +673,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
616 | checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" | 673 | checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" |
617 | dependencies = [ | 674 | dependencies = [ |
618 | "autocfg", | 675 | "autocfg", |
619 | "hashbrown", | 676 | "hashbrown 0.12.3", |
677 | ] | ||
678 | |||
679 | [[package]] | ||
680 | name = "indexmap" | ||
681 | version = "2.2.3" | ||
682 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
683 | checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" | ||
684 | dependencies = [ | ||
685 | "equivalent", | ||
686 | "hashbrown 0.14.3", | ||
620 | ] | 687 | ] |
621 | 688 | ||
622 | [[package]] | 689 | [[package]] |
@@ -807,9 +874,9 @@ dependencies = [ | |||
807 | 874 | ||
808 | [[package]] | 875 | [[package]] |
809 | name = "once_cell" | 876 | name = "once_cell" |
810 | version = "1.18.0" | 877 | version = "1.19.0" |
811 | source = "registry+https://github.com/rust-lang/crates.io-index" | 878 | source = "registry+https://github.com/rust-lang/crates.io-index" |
812 | checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" | 879 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" |
813 | 880 | ||
814 | [[package]] | 881 | [[package]] |
815 | name = "openssl" | 882 | name = "openssl" |
@@ -863,12 +930,12 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" | |||
863 | 930 | ||
864 | [[package]] | 931 | [[package]] |
865 | name = "ordered-multimap" | 932 | name = "ordered-multimap" |
866 | version = "0.4.3" | 933 | version = "0.6.0" |
867 | source = "registry+https://github.com/rust-lang/crates.io-index" | 934 | source = "registry+https://github.com/rust-lang/crates.io-index" |
868 | checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a" | 935 | checksum = "4ed8acf08e98e744e5384c8bc63ceb0364e68a6854187221c18df61c4797690e" |
869 | dependencies = [ | 936 | dependencies = [ |
870 | "dlv-list", | 937 | "dlv-list", |
871 | "hashbrown", | 938 | "hashbrown 0.13.2", |
872 | ] | 939 | ] |
873 | 940 | ||
874 | [[package]] | 941 | [[package]] |
@@ -960,18 +1027,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" | |||
960 | 1027 | ||
961 | [[package]] | 1028 | [[package]] |
962 | name = "proc-macro2" | 1029 | name = "proc-macro2" |
963 | version = "1.0.69" | 1030 | version = "1.0.78" |
964 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1031 | source = "registry+https://github.com/rust-lang/crates.io-index" |
965 | checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" | 1032 | checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" |
966 | dependencies = [ | 1033 | dependencies = [ |
967 | "unicode-ident", | 1034 | "unicode-ident", |
968 | ] | 1035 | ] |
969 | 1036 | ||
970 | [[package]] | 1037 | [[package]] |
971 | name = "quote" | 1038 | name = "quote" |
972 | version = "1.0.33" | 1039 | version = "1.0.35" |
973 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1040 | source = "registry+https://github.com/rust-lang/crates.io-index" |
974 | checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" | 1041 | checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" |
975 | dependencies = [ | 1042 | dependencies = [ |
976 | "proc-macro2", | 1043 | "proc-macro2", |
977 | ] | 1044 | ] |
@@ -1032,13 +1099,13 @@ version = "0.11.22" | |||
1032 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1099 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1033 | checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" | 1100 | checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" |
1034 | dependencies = [ | 1101 | dependencies = [ |
1035 | "base64 0.21.5", | 1102 | "base64", |
1036 | "bytes", | 1103 | "bytes", |
1037 | "encoding_rs", | 1104 | "encoding_rs", |
1038 | "futures-core", | 1105 | "futures-core", |
1039 | "futures-util", | 1106 | "futures-util", |
1040 | "h2", | 1107 | "h2", |
1041 | "http", | 1108 | "http 0.2.10", |
1042 | "http-body", | 1109 | "http-body", |
1043 | "hyper", | 1110 | "hyper", |
1044 | "hyper-tls", | 1111 | "hyper-tls", |
@@ -1066,20 +1133,21 @@ dependencies = [ | |||
1066 | 1133 | ||
1067 | [[package]] | 1134 | [[package]] |
1068 | name = "ron" | 1135 | name = "ron" |
1069 | version = "0.7.1" | 1136 | version = "0.8.1" |
1070 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1137 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1071 | checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a" | 1138 | checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" |
1072 | dependencies = [ | 1139 | dependencies = [ |
1073 | "base64 0.13.1", | 1140 | "base64", |
1074 | "bitflags 1.3.2", | 1141 | "bitflags 2.4.1", |
1075 | "serde", | 1142 | "serde", |
1143 | "serde_derive", | ||
1076 | ] | 1144 | ] |
1077 | 1145 | ||
1078 | [[package]] | 1146 | [[package]] |
1079 | name = "rust-ini" | 1147 | name = "rust-ini" |
1080 | version = "0.18.0" | 1148 | version = "0.19.0" |
1081 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1149 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1082 | checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df" | 1150 | checksum = "7e2a3bcec1f113553ef1c88aae6c020a369d03d55b58de9869a0908930385091" |
1083 | dependencies = [ | 1151 | dependencies = [ |
1084 | "cfg-if", | 1152 | "cfg-if", |
1085 | "ordered-multimap", | 1153 | "ordered-multimap", |
@@ -1174,6 +1242,15 @@ dependencies = [ | |||
1174 | ] | 1242 | ] |
1175 | 1243 | ||
1176 | [[package]] | 1244 | [[package]] |
1245 | name = "serde_spanned" | ||
1246 | version = "0.6.5" | ||
1247 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1248 | checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" | ||
1249 | dependencies = [ | ||
1250 | "serde", | ||
1251 | ] | ||
1252 | |||
1253 | [[package]] | ||
1177 | name = "serde_urlencoded" | 1254 | name = "serde_urlencoded" |
1178 | version = "0.7.1" | 1255 | version = "0.7.1" |
1179 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1256 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1238,15 +1315,15 @@ dependencies = [ | |||
1238 | 1315 | ||
1239 | [[package]] | 1316 | [[package]] |
1240 | name = "strsim" | 1317 | name = "strsim" |
1241 | version = "0.10.0" | 1318 | version = "0.11.0" |
1242 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1319 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1243 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" | 1320 | checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" |
1244 | 1321 | ||
1245 | [[package]] | 1322 | [[package]] |
1246 | name = "syn" | 1323 | name = "syn" |
1247 | version = "2.0.39" | 1324 | version = "2.0.50" |
1248 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1325 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1249 | checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" | 1326 | checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" |
1250 | dependencies = [ | 1327 | dependencies = [ |
1251 | "proc-macro2", | 1328 | "proc-macro2", |
1252 | "quote", | 1329 | "quote", |
@@ -1289,18 +1366,18 @@ dependencies = [ | |||
1289 | 1366 | ||
1290 | [[package]] | 1367 | [[package]] |
1291 | name = "thiserror" | 1368 | name = "thiserror" |
1292 | version = "1.0.50" | 1369 | version = "1.0.57" |
1293 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1370 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1294 | checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" | 1371 | checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" |
1295 | dependencies = [ | 1372 | dependencies = [ |
1296 | "thiserror-impl", | 1373 | "thiserror-impl", |
1297 | ] | 1374 | ] |
1298 | 1375 | ||
1299 | [[package]] | 1376 | [[package]] |
1300 | name = "thiserror-impl" | 1377 | name = "thiserror-impl" |
1301 | version = "1.0.50" | 1378 | version = "1.0.57" |
1302 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1379 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1303 | checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" | 1380 | checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" |
1304 | dependencies = [ | 1381 | dependencies = [ |
1305 | "proc-macro2", | 1382 | "proc-macro2", |
1306 | "quote", | 1383 | "quote", |
@@ -1308,6 +1385,15 @@ dependencies = [ | |||
1308 | ] | 1385 | ] |
1309 | 1386 | ||
1310 | [[package]] | 1387 | [[package]] |
1388 | name = "tiny-keccak" | ||
1389 | version = "2.0.2" | ||
1390 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1391 | checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" | ||
1392 | dependencies = [ | ||
1393 | "crunchy", | ||
1394 | ] | ||
1395 | |||
1396 | [[package]] | ||
1311 | name = "tinyvec" | 1397 | name = "tinyvec" |
1312 | version = "1.6.0" | 1398 | version = "1.6.0" |
1313 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1399 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1324,9 +1410,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" | |||
1324 | 1410 | ||
1325 | [[package]] | 1411 | [[package]] |
1326 | name = "tokio" | 1412 | name = "tokio" |
1327 | version = "1.34.0" | 1413 | version = "1.36.0" |
1328 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1414 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1329 | checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" | 1415 | checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" |
1330 | dependencies = [ | 1416 | dependencies = [ |
1331 | "backtrace", | 1417 | "backtrace", |
1332 | "bytes", | 1418 | "bytes", |
@@ -1362,9 +1448,9 @@ dependencies = [ | |||
1362 | 1448 | ||
1363 | [[package]] | 1449 | [[package]] |
1364 | name = "tokio-tungstenite" | 1450 | name = "tokio-tungstenite" |
1365 | version = "0.20.1" | 1451 | version = "0.21.0" |
1366 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1452 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1367 | checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" | 1453 | checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" |
1368 | dependencies = [ | 1454 | dependencies = [ |
1369 | "futures-util", | 1455 | "futures-util", |
1370 | "log", | 1456 | "log", |
@@ -1388,11 +1474,36 @@ dependencies = [ | |||
1388 | 1474 | ||
1389 | [[package]] | 1475 | [[package]] |
1390 | name = "toml" | 1476 | name = "toml" |
1391 | version = "0.5.11" | 1477 | version = "0.8.10" |
1478 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1479 | checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" | ||
1480 | dependencies = [ | ||
1481 | "serde", | ||
1482 | "serde_spanned", | ||
1483 | "toml_datetime", | ||
1484 | "toml_edit", | ||
1485 | ] | ||
1486 | |||
1487 | [[package]] | ||
1488 | name = "toml_datetime" | ||
1489 | version = "0.6.5" | ||
1490 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1491 | checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" | ||
1492 | dependencies = [ | ||
1493 | "serde", | ||
1494 | ] | ||
1495 | |||
1496 | [[package]] | ||
1497 | name = "toml_edit" | ||
1498 | version = "0.22.6" | ||
1392 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1499 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1393 | checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" | 1500 | checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6" |
1394 | dependencies = [ | 1501 | dependencies = [ |
1502 | "indexmap 2.2.3", | ||
1395 | "serde", | 1503 | "serde", |
1504 | "serde_spanned", | ||
1505 | "toml_datetime", | ||
1506 | "winnow", | ||
1396 | ] | 1507 | ] |
1397 | 1508 | ||
1398 | [[package]] | 1509 | [[package]] |
@@ -1428,14 +1539,14 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" | |||
1428 | 1539 | ||
1429 | [[package]] | 1540 | [[package]] |
1430 | name = "tungstenite" | 1541 | name = "tungstenite" |
1431 | version = "0.20.1" | 1542 | version = "0.21.0" |
1432 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1543 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1433 | checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" | 1544 | checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" |
1434 | dependencies = [ | 1545 | dependencies = [ |
1435 | "byteorder", | 1546 | "byteorder", |
1436 | "bytes", | 1547 | "bytes", |
1437 | "data-encoding", | 1548 | "data-encoding", |
1438 | "http", | 1549 | "http 1.0.0", |
1439 | "httparse", | 1550 | "httparse", |
1440 | "log", | 1551 | "log", |
1441 | "rand", | 1552 | "rand", |
@@ -1479,6 +1590,12 @@ dependencies = [ | |||
1479 | ] | 1590 | ] |
1480 | 1591 | ||
1481 | [[package]] | 1592 | [[package]] |
1593 | name = "unicode-segmentation" | ||
1594 | version = "1.11.0" | ||
1595 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1596 | checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" | ||
1597 | |||
1598 | [[package]] | ||
1482 | name = "unicode-width" | 1599 | name = "unicode-width" |
1483 | version = "0.1.11" | 1600 | version = "0.1.11" |
1484 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1601 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1612,18 +1729,19 @@ dependencies = [ | |||
1612 | 1729 | ||
1613 | [[package]] | 1730 | [[package]] |
1614 | name = "webol-cli" | 1731 | name = "webol-cli" |
1615 | version = "0.1.0" | 1732 | version = "0.2.0" |
1616 | dependencies = [ | 1733 | dependencies = [ |
1734 | "anyhow", | ||
1617 | "clap", | 1735 | "clap", |
1618 | "clap_complete", | 1736 | "clap_complete", |
1619 | "config", | 1737 | "config", |
1620 | "dirs", | 1738 | "dirs", |
1621 | "futures-util", | 1739 | "futures-util", |
1622 | "indicatif", | 1740 | "indicatif", |
1623 | "once_cell", | ||
1624 | "reqwest", | 1741 | "reqwest", |
1625 | "serde", | 1742 | "serde", |
1626 | "serde_json", | 1743 | "serde_json", |
1744 | "thiserror", | ||
1627 | "tokio", | 1745 | "tokio", |
1628 | "tokio-tungstenite", | 1746 | "tokio-tungstenite", |
1629 | ] | 1747 | ] |
@@ -1783,6 +1901,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
1783 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" | 1901 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" |
1784 | 1902 | ||
1785 | [[package]] | 1903 | [[package]] |
1904 | name = "winnow" | ||
1905 | version = "0.6.2" | ||
1906 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1907 | checksum = "7a4191c47f15cc3ec71fcb4913cb83d58def65dd3787610213c649283b5ce178" | ||
1908 | dependencies = [ | ||
1909 | "memchr", | ||
1910 | ] | ||
1911 | |||
1912 | [[package]] | ||
1786 | name = "winreg" | 1913 | name = "winreg" |
1787 | version = "0.50.0" | 1914 | version = "0.50.0" |
1788 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1915 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1,6 +1,6 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "webol-cli" | 2 | name = "webol-cli" |
3 | version = "0.1.0" | 3 | version = "0.2.0" |
4 | edition = "2021" | 4 | edition = "2021" |
5 | 5 | ||
6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html |
@@ -10,15 +10,16 @@ name = "webol" | |||
10 | path = "src/main.rs" | 10 | path = "src/main.rs" |
11 | 11 | ||
12 | [dependencies] | 12 | [dependencies] |
13 | clap = { version = "4.4.6", features = ["derive"] } | 13 | anyhow = "1.0" |
14 | clap_complete = "4.4.4" | 14 | clap = { version = "4.5", features = ["derive"] } |
15 | config = "0.13.3" | 15 | clap_complete = "4.5" |
16 | dirs = "5.0.1" | 16 | config = "0.14" |
17 | futures-util = "0.3.29" | 17 | dirs = "5.0" |
18 | indicatif = "0.17.7" | 18 | futures-util = "0.3" |
19 | once_cell = "1.18.0" | 19 | indicatif = "0.17" |
20 | reqwest = { version = "0.11.22", features = ["blocking"] } | 20 | reqwest = { version = "0.11", features = ["blocking"] } |
21 | serde = "1.0.189" | 21 | serde = "1.0" |
22 | serde_json = "1.0.107" | 22 | serde_json = "1.0" |
23 | tokio = { version = "1.33.0", features = ["macros", "rt-multi-thread", "io-std"] } | 23 | thiserror = "1.0" |
24 | tokio-tungstenite = "0.20.1" | 24 | tokio = { version = "1.36", features = ["macros", "rt-multi-thread", "io-std"] } |
25 | tokio-tungstenite = "0.21" | ||
diff --git a/docker-compose.yml b/docker-compose.yml index 3a0ade5..ea10db2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml | |||
@@ -1,20 +1,20 @@ | |||
1 | services: | 1 | services: |
2 | webol: | 2 | webol: |
3 | image: ghcr.io/fxqnlr/webol:dev-6 | 3 | image: ghcr.io/fxqnlr/webol:dev-9 |
4 | container_name: webol | 4 | container_name: webol-cli-server |
5 | restart: no | 5 | restart: no |
6 | depends_on: | 6 | depends_on: |
7 | - db | 7 | - db |
8 | environment: | 8 | environment: |
9 | - RUST_LOG=info,webol=trace | 9 | - RUST_LOG=info,webol=trace |
10 | - WEBOL_DATABASE_URL=postgres://postgres:postgres@localhost:5432/webol | 10 | - WEBOL_DATABASE_URL=postgres://postgres:postgres@localhost:5432/webol |
11 | - WEBOL_APIKEY=aaa | 11 | - WEBOL_APIKEY=dev |
12 | - WEBOL_SERVERADDR=127.0.0.1:7229 | 12 | - WEBOL_SERVERADDR=0.0.0.0:7229 |
13 | network_mode: host | 13 | network_mode: host |
14 | 14 | ||
15 | db: | 15 | db: |
16 | image: postgres | 16 | image: postgres |
17 | container_name: webol-db | 17 | container_name: webol-cli-db |
18 | restart: no | 18 | restart: no |
19 | environment: | 19 | environment: |
20 | POSTGRES_PASSWORD: postgres | 20 | POSTGRES_PASSWORD: postgres |
diff --git a/src/config.rs b/src/config.rs index 9a9e44b..769269c 100644 --- a/src/config.rs +++ b/src/config.rs | |||
@@ -1,19 +1,30 @@ | |||
1 | use config::Config; | 1 | use serde::Deserialize; |
2 | use once_cell::sync::Lazy; | ||
3 | 2 | ||
4 | pub static SETTINGS: Lazy<Config> = Lazy::new(setup); | 3 | #[derive(Deserialize)] |
4 | pub struct Config { | ||
5 | pub apikey: String, | ||
6 | pub server: String, | ||
7 | } | ||
8 | |||
9 | impl Config { | ||
10 | pub fn load() -> Result<Config, config::ConfigError> { | ||
11 | let config_dir = dirs::config_dir(); | ||
12 | |||
13 | let builder = config::Config::builder(); | ||
5 | 14 | ||
6 | fn setup() -> Config { | 15 | let builder = if let Some(conf) = config_dir { |
7 | #[cfg(not(debug_assertions))] | 16 | let dir = conf.to_string_lossy(); |
8 | let builder = Config::builder().add_source(config::File::with_name( | 17 | builder.add_source(config::File::with_name(format!("{dir}/webol-cli").as_str()).required(false)) |
9 | format!("{}/webol-cli.toml", dirs::config_dir().unwrap().to_string_lossy()).as_str(), | 18 | } else { |
10 | )); | 19 | println!("!No config dir found"); |
20 | builder | ||
21 | }; | ||
11 | 22 | ||
12 | #[cfg(debug_assertions)] | 23 | let build = builder |
13 | let builder = Config::builder().add_source(config::File::with_name("webol-cli.toml")); | 24 | .add_source(config::File::with_name("webol-cli").required(false)) |
25 | .add_source(config::Environment::with_prefix("WEBOL_CLI").separator("_")) | ||
26 | .build()?; | ||
14 | 27 | ||
15 | builder | 28 | build.try_deserialize() |
16 | .add_source(config::Environment::with_prefix("WEBOL_CLI_").separator("_")) | 29 | } |
17 | .build() | ||
18 | .unwrap() | ||
19 | } | 30 | } |
diff --git a/src/error.rs b/src/error.rs index f15c60a..1e6eac1 100644 --- a/src/error.rs +++ b/src/error.rs | |||
@@ -1,21 +1,43 @@ | |||
1 | use std::{fmt::Debug, num::ParseIntError}; | 1 | use std::{fmt::Debug, num::ParseIntError}; |
2 | 2 | ||
3 | pub enum CliError { | 3 | use reqwest::header::InvalidHeaderValue; |
4 | Reqwest(reqwest::Error), | ||
5 | Config(config::ConfigError), | ||
6 | Serde(serde_json::Error), | ||
7 | Parse(ParseIntError), | ||
8 | WsResponse, | ||
9 | } | ||
10 | 4 | ||
11 | impl Debug for CliError { | 5 | #[derive(Debug, thiserror::Error)] |
12 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | 6 | pub enum Error { |
13 | match self { | 7 | #[error("request: {source}")] |
14 | Self::Reqwest(err) => { err.fmt(f) }, | 8 | Reqwest { |
15 | Self::Config(err) => { err.fmt(f) }, | 9 | #[from] |
16 | Self::Serde(err) => { err.fmt(f) }, | 10 | source: reqwest::Error, |
17 | Self::Parse(err) => { err.fmt(f) }, | 11 | }, |
18 | Self::WsResponse => { f.write_str("Error in Response") }, | 12 | #[error("config: {source}")] |
19 | } | 13 | Config { |
20 | } | 14 | #[from] |
15 | source: config::ConfigError, | ||
16 | }, | ||
17 | #[error("serde: {source}")] | ||
18 | Serde { | ||
19 | #[from] | ||
20 | source: serde_json::Error, | ||
21 | }, | ||
22 | #[error("parse int: {source}")] | ||
23 | Parse { | ||
24 | #[from] | ||
25 | source: ParseIntError, | ||
26 | }, | ||
27 | #[error("parse header: {source}")] | ||
28 | InvalidHeaderValue { | ||
29 | #[from] | ||
30 | source: InvalidHeaderValue, | ||
31 | }, | ||
32 | #[error("tungstenite: {source}")] | ||
33 | Tungstenite { | ||
34 | #[from] | ||
35 | source: tokio_tungstenite::tungstenite::Error, | ||
36 | }, | ||
37 | #[error("faulty websocket response")] | ||
38 | WsResponse, | ||
39 | #[error("authorization failed")] | ||
40 | Authorization, | ||
41 | #[error("Http error status: {0}")] | ||
42 | HttpStatus(u16), | ||
21 | } | 43 | } |
diff --git a/src/main.rs b/src/main.rs index afe6fac..5a0931d 100644 --- a/src/main.rs +++ b/src/main.rs | |||
@@ -1,21 +1,24 @@ | |||
1 | use std::{fmt::Display, time::Duration}; | 1 | use std::{fmt::Display, time::Duration}; |
2 | 2 | ||
3 | use clap::{Parser, Command, CommandFactory, Subcommand}; | 3 | use crate::config::Config; |
4 | use clap_complete::{generate, Shell, Generator}; | 4 | use clap::{Command, CommandFactory, Parser, Subcommand}; |
5 | use config::SETTINGS; | 5 | use clap_complete::{generate, Generator, Shell}; |
6 | use error::CliError; | 6 | use error::Error; |
7 | use indicatif::{ProgressBar, ProgressStyle, MultiProgress}; | 7 | use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; |
8 | use requests::{start::start, device}; | 8 | use requests::{device, start::start}; |
9 | use reqwest::header::{HeaderMap, HeaderValue}; | 9 | use reqwest::{ |
10 | header::{HeaderMap, HeaderValue}, | ||
11 | Response, | ||
12 | }; | ||
10 | use serde::Deserialize; | 13 | use serde::Deserialize; |
11 | 14 | ||
12 | mod config; | 15 | mod config; |
13 | mod error; | 16 | mod error; |
14 | mod requests; | 17 | mod requests; |
15 | 18 | ||
16 | static OVERVIEW_STYLE: &str = "{spinner:.green} ({elapsed}{wide_msg}"; | 19 | static OVERVIEW_STYLE: &str = "{spinner:.green} ({elapsed_precise}{wide_msg}"; |
17 | static OVERVIEW_ERROR: &str = "✗ ({elapsed}) {wide_msg}"; | 20 | static OVERVIEW_ERROR: &str = "✗ ({elapsed_precise}) {wide_msg}"; |
18 | static OVERVIEW_DONE: &str = "✓ ({elapsed}) {wide_msg}"; | 21 | static OVERVIEW_DONE: &str = "✓ ({elapsed_precise}) {wide_msg}"; |
19 | static DEFAULT_STYLE: &str = " {spinner:.green} {wide_msg}"; | 22 | static DEFAULT_STYLE: &str = " {spinner:.green} {wide_msg}"; |
20 | static DONE_STYLE: &str = " ✓ {wide_msg}"; | 23 | static DONE_STYLE: &str = " ✓ {wide_msg}"; |
21 | static ERROR_STYLE: &str = " ✗ {wide_msg}"; | 24 | static ERROR_STYLE: &str = " ✗ {wide_msg}"; |
@@ -35,7 +38,7 @@ enum Commands { | |||
35 | /// id of the device | 38 | /// id of the device |
36 | id: String, | 39 | id: String, |
37 | #[arg(short, long)] | 40 | #[arg(short, long)] |
38 | ping: Option<bool> | 41 | ping: Option<bool>, |
39 | }, | 42 | }, |
40 | Device { | 43 | Device { |
41 | #[command(subcommand)] | 44 | #[command(subcommand)] |
@@ -52,7 +55,7 @@ enum DeviceCmd { | |||
52 | id: String, | 55 | id: String, |
53 | mac: String, | 56 | mac: String, |
54 | broadcast_addr: String, | 57 | broadcast_addr: String, |
55 | ip: String | 58 | ip: String, |
56 | }, | 59 | }, |
57 | Get { | 60 | Get { |
58 | id: String, | 61 | id: String, |
@@ -61,35 +64,45 @@ enum DeviceCmd { | |||
61 | id: String, | 64 | id: String, |
62 | mac: String, | 65 | mac: String, |
63 | broadcast_addr: String, | 66 | broadcast_addr: String, |
64 | ip: String | 67 | ip: String, |
65 | }, | 68 | }, |
66 | } | 69 | } |
67 | 70 | ||
68 | #[tokio::main] | 71 | #[tokio::main] |
69 | async fn main() -> Result<(), CliError> { | 72 | async fn main() -> Result<(), anyhow::Error> { |
73 | let config = Config::load()?; | ||
74 | |||
70 | let cli = Args::parse(); | 75 | let cli = Args::parse(); |
71 | 76 | ||
72 | match cli.commands { | 77 | match cli.commands { |
73 | Commands::Start { id, ping } => { | 78 | Commands::Start { id, ping } => { |
74 | start(id, ping.unwrap_or(true)).await?; | 79 | start(&config, id, ping.unwrap_or(true)).await?; |
75 | }, | 80 | } |
76 | Commands::Device { devicecmd } => { | 81 | Commands::Device { devicecmd } => match devicecmd { |
77 | match devicecmd { | 82 | DeviceCmd::Add { |
78 | DeviceCmd::Add { id, mac, broadcast_addr, ip } => { | 83 | id, |
79 | device::put(id, mac, broadcast_addr, ip).await?; | 84 | mac, |
80 | }, | 85 | broadcast_addr, |
81 | DeviceCmd::Get { id } => { | 86 | ip, |
82 | device::get(id).await?; | 87 | } => { |
83 | }, | 88 | device::put(&config, id, mac, broadcast_addr, ip).await?; |
84 | DeviceCmd::Edit { id, mac, broadcast_addr, ip } => { | 89 | } |
85 | device::post(id, mac, broadcast_addr, ip).await?; | 90 | DeviceCmd::Get { id } => { |
86 | }, | 91 | device::get(&config, id).await?; |
92 | } | ||
93 | DeviceCmd::Edit { | ||
94 | id, | ||
95 | mac, | ||
96 | broadcast_addr, | ||
97 | ip, | ||
98 | } => { | ||
99 | device::post(&config, id, mac, broadcast_addr, ip).await?; | ||
87 | } | 100 | } |
88 | }, | 101 | }, |
89 | Commands::CliGen { id } => { | 102 | Commands::CliGen { id } => { |
90 | eprintln!("Generating completion file for {id:?}..."); | 103 | eprintln!("Generating completion file for {id:?}..."); |
91 | let mut cmd = Args::command(); | 104 | let mut cmd = Args::command(); |
92 | print_completions(id, &mut cmd) | 105 | print_completions(id, &mut cmd); |
93 | } | 106 | } |
94 | } | 107 | } |
95 | 108 | ||
@@ -100,29 +113,28 @@ fn print_completions<G: Generator>(gen: G, cmd: &mut Command) { | |||
100 | generate(gen, cmd, cmd.get_name().to_string(), &mut std::io::stdout()); | 113 | generate(gen, cmd, cmd.get_name().to_string(), &mut std::io::stdout()); |
101 | } | 114 | } |
102 | 115 | ||
103 | fn default_headers() -> Result<HeaderMap, CliError> { | 116 | fn default_headers(config: &Config) -> Result<HeaderMap, Error> { |
104 | let mut map = HeaderMap::new(); | 117 | let mut map = HeaderMap::new(); |
105 | map.append("Accept-Content", HeaderValue::from_str("application/json").unwrap()); | 118 | map.append("Accept-Content", HeaderValue::from_str("application/json")?); |
106 | map.append("Content-Type", HeaderValue::from_str("application/json").unwrap()); | 119 | map.append("Content-Type", HeaderValue::from_str("application/json")?); |
107 | map.append( | 120 | map.append("Authorization", HeaderValue::from_str(&config.apikey)?); |
108 | "Authorization", | ||
109 | HeaderValue::from_str( | ||
110 | SETTINGS.get_string("key") | ||
111 | .map_err(CliError::Config)? | ||
112 | .as_str() | ||
113 | ).unwrap() | ||
114 | ); | ||
115 | 121 | ||
116 | Ok(map) | 122 | Ok(map) |
117 | } | 123 | } |
118 | 124 | ||
119 | fn format_url(path: &str, protocol: Protocols) -> Result<String, CliError> { | 125 | fn format_url(config: &Config, path: &str, protocol: &Protocols) -> String { |
120 | Ok(format!( | 126 | format!("{}://{}/{}", protocol, config.server, path) |
121 | "{}://{}/{}", | 127 | } |
122 | protocol, | 128 | |
123 | SETTINGS.get_string("server").map_err(CliError::Config)?, | 129 | async fn check_success(res: Response) -> Result<String, Error> { |
124 | path | 130 | let status = res.status(); |
125 | )) | 131 | if status.is_success() { |
132 | Ok(res.text().await?) | ||
133 | } else if status.as_u16() == 401 { | ||
134 | Err(Error::Authorization) | ||
135 | } else { | ||
136 | Err(Error::HttpStatus(status.as_u16())) | ||
137 | } | ||
126 | } | 138 | } |
127 | 139 | ||
128 | fn add_pb(mp: &MultiProgress, template: &str, message: String) -> ProgressBar { | 140 | fn add_pb(mp: &MultiProgress, template: &str, message: String) -> ProgressBar { |
@@ -134,10 +146,9 @@ fn add_pb(mp: &MultiProgress, template: &str, message: String) -> ProgressBar { | |||
134 | pb | 146 | pb |
135 | } | 147 | } |
136 | 148 | ||
137 | fn finish_pb(pb: ProgressBar, message: String, template: &str) { | 149 | fn finish_pb(pb: &ProgressBar, message: String, template: &str) { |
138 | pb.set_style(ProgressStyle::with_template(template).unwrap()); | 150 | pb.set_style(ProgressStyle::with_template(template).unwrap()); |
139 | pb.finish_with_message(message); | 151 | pb.finish_with_message(message); |
140 | |||
141 | } | 152 | } |
142 | 153 | ||
143 | enum Protocols { | 154 | enum Protocols { |
@@ -149,12 +160,12 @@ impl Display for Protocols { | |||
149 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | 160 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
150 | match self { | 161 | match self { |
151 | Self::Http => f.write_str("http"), | 162 | Self::Http => f.write_str("http"), |
152 | Self::Websocket => f.write_str("ws") | 163 | Self::Websocket => f.write_str("ws"), |
153 | } | 164 | } |
154 | } | 165 | } |
155 | } | 166 | } |
156 | 167 | ||
157 | #[derive(Debug, Deserialize)] | 168 | #[derive(Debug, Deserialize)] |
158 | struct ErrorResponse { | 169 | struct ErrorResponse { |
159 | error: String | 170 | error: String, |
160 | } | 171 | } |
diff --git a/src/requests/mod.rs b/src/requests.rs index 6855db1..6855db1 100644 --- a/src/requests/mod.rs +++ b/src/requests.rs | |||
diff --git a/src/requests/device.rs b/src/requests/device.rs index cbc838e..7583406 100644 --- a/src/requests/device.rs +++ b/src/requests/device.rs | |||
@@ -1,66 +1,58 @@ | |||
1 | use crate::{error::CliError, default_headers, format_url, Protocols}; | 1 | use crate::{check_success, config::Config, default_headers, error::Error, format_url, Protocols}; |
2 | 2 | ||
3 | pub async fn put(id: String, mac: String, broadcast_addr: String, ip: String) -> Result<(), CliError> { | 3 | pub async fn put( |
4 | let url = format_url("device", Protocols::Http)?; | 4 | config: &Config, |
5 | println!("{}", url); | 5 | id: String, |
6 | mac: String, | ||
7 | broadcast_addr: String, | ||
8 | ip: String, | ||
9 | ) -> Result<(), Error> { | ||
10 | let url = format_url(config, "device", &Protocols::Http); | ||
11 | println!("{url}"); | ||
6 | let res = reqwest::Client::new() | 12 | let res = reqwest::Client::new() |
7 | .put(url) | 13 | .put(url) |
8 | .headers(default_headers()?) | 14 | .headers(default_headers(config)?) |
9 | .body( | 15 | .body(format!( |
10 | format!( | 16 | r#"{{"id": "{id}", "mac": "{mac}", "broadcast_addr": "{broadcast_addr}", "ip": "{ip}"}}"#, |
11 | r#"{{"id": "{}", "mac": "{}", "broadcast_addr": "{}", "ip": "{}"}}"#, | 17 | )) |
12 | id, | ||
13 | mac, | ||
14 | broadcast_addr, | ||
15 | ip | ||
16 | ) | ||
17 | ) | ||
18 | .send() | 18 | .send() |
19 | .await | 19 | .await?; |
20 | .map_err(CliError::Reqwest)? | ||
21 | .text() | ||
22 | .await; | ||
23 | 20 | ||
24 | println!("{:?}", res); | 21 | let body = check_success(res).await?; |
22 | println!("{body}"); | ||
25 | Ok(()) | 23 | Ok(()) |
26 | } | 24 | } |
27 | 25 | ||
28 | pub async fn get(id: String) -> Result<(), CliError> { | 26 | pub async fn get(config: &Config, id: String) -> Result<(), Error> { |
29 | let res = reqwest::Client::new() | 27 | let res = reqwest::Client::new() |
30 | .get(format_url("device", Protocols::Http)?) | 28 | .get(format_url(config, "device", &Protocols::Http)) |
31 | .headers(default_headers()?) | 29 | .headers(default_headers(config)?) |
32 | .body( | 30 | .body(format!(r#"{{"id": "{id}"}}"#)) |
33 | format!(r#"{{"id": "{}"}}"#, id) | ||
34 | ) | ||
35 | .send() | 31 | .send() |
36 | .await | 32 | .await?; |
37 | .map_err(CliError::Reqwest)? | ||
38 | .text() | ||
39 | .await; | ||
40 | 33 | ||
41 | println!("{:?}", res); | 34 | let body = check_success(res).await?; |
35 | println!("{body}"); | ||
42 | Ok(()) | 36 | Ok(()) |
43 | } | 37 | } |
44 | 38 | ||
45 | pub async fn post(id: String, mac: String, broadcast_addr: String, ip: String) -> Result<(), CliError> { | 39 | pub async fn post( |
40 | config: &Config, | ||
41 | id: String, | ||
42 | mac: String, | ||
43 | broadcast_addr: String, | ||
44 | ip: String, | ||
45 | ) -> Result<(), Error> { | ||
46 | let res = reqwest::Client::new() | 46 | let res = reqwest::Client::new() |
47 | .post(format_url("device", Protocols::Http)?) | 47 | .post(format_url(config, "device", &Protocols::Http)) |
48 | .headers(default_headers()?) | 48 | .headers(default_headers(config)?) |
49 | .body( | 49 | .body(format!( |
50 | format!( | 50 | r#"{{"id": "{id}", "mac": "{mac}", "broadcast_addr": "{broadcast_addr}", "ip": "{ip}"}}"#, |
51 | r#"{{"id": "{}", "mac": "{}", "broadcast_addr": "{}", "ip": "{}"}}"#, | 51 | )) |
52 | id, | ||
53 | mac, | ||
54 | broadcast_addr, | ||
55 | ip | ||
56 | ) | ||
57 | ) | ||
58 | .send() | 52 | .send() |
59 | .await | 53 | .await?; |
60 | .map_err(CliError::Reqwest)? | ||
61 | .text() | ||
62 | .await; | ||
63 | 54 | ||
64 | println!("{:?}", res); | 55 | let body = check_success(res).await?; |
56 | println!("{body}"); | ||
65 | Ok(()) | 57 | Ok(()) |
66 | } | 58 | } |
diff --git a/src/requests/start.rs b/src/requests/start.rs index ca4ca44..3afbe3a 100644 --- a/src/requests/start.rs +++ b/src/requests/start.rs | |||
@@ -1,124 +1,149 @@ | |||
1 | use futures_util::{StreamExt, SinkExt}; | 1 | use futures_util::{SinkExt, StreamExt}; |
2 | use indicatif::{MultiProgress, ProgressBar}; | 2 | use indicatif::{MultiProgress, ProgressBar}; |
3 | use reqwest::StatusCode; | 3 | use reqwest::StatusCode; |
4 | use serde::Deserialize; | 4 | use serde::Deserialize; |
5 | use tokio_tungstenite::{connect_async, tungstenite::Message}; | 5 | use tokio_tungstenite::{ |
6 | 6 | connect_async, | |
7 | 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}; | 7 | tungstenite::{http::Request, Message}, |
8 | 8 | }; | |
9 | pub async fn start(id: String, ping: bool) -> Result<(), CliError> { | 9 | |
10 | 10 | use crate::{ | |
11 | add_pb, config::Config, default_headers, error::Error, finish_pb, format_url, ErrorResponse, | ||
12 | Protocols, DEFAULT_STYLE, DONE_STYLE, ERROR_STYLE, OVERVIEW_DONE, OVERVIEW_ERROR, | ||
13 | OVERVIEW_STYLE, | ||
14 | }; | ||
15 | |||
16 | pub async fn start(config: &Config, id: String, ping: bool) -> Result<(), Error> { | ||
11 | let send_start = MultiProgress::new(); | 17 | let send_start = MultiProgress::new(); |
12 | let overview = add_pb(&send_start, OVERVIEW_STYLE, format!(") start {}", id)); | 18 | let overview = add_pb(&send_start, OVERVIEW_STYLE, format!(") start {id}")); |
13 | 19 | ||
14 | // TODO: calculate average start-time on server | 20 | let url = format_url(config, "start", &Protocols::Http); |
15 | let url = format_url("start", Protocols::Http)?; | 21 | let connect = add_pb(&send_start, DEFAULT_STYLE, format!("connect to {url}")); |
16 | let connect = add_pb(&send_start, DEFAULT_STYLE, format!("connect to {}", url)); | ||
17 | let res = reqwest::Client::new() | 22 | let res = reqwest::Client::new() |
18 | .post(url) | 23 | .post(url) |
19 | .headers(default_headers()?) | 24 | .headers(default_headers(config)?) |
20 | .body( | 25 | .body(format!(r#"{{"id": "{id}", "ping": {ping}}}"#)) |
21 | format!(r#"{{"id": "{}", "ping": {}}}"#, id, ping) | ||
22 | ) | ||
23 | .send() | 26 | .send() |
24 | .await | 27 | .await?; |
25 | .map_err(CliError::Reqwest)?; | 28 | finish_pb(&connect, "connected, got response".to_string(), DONE_STYLE); |
26 | finish_pb(connect, "connected, got response".to_string(), DONE_STYLE); | ||
27 | 29 | ||
28 | let res_pb = add_pb(&send_start, DEFAULT_STYLE, "analyzing response".to_string()); | 30 | let res_pb = add_pb(&send_start, DEFAULT_STYLE, "analyzing response".to_string()); |
29 | match res.status() { | ||
30 | StatusCode::OK => { | ||
31 | let body = serde_json::from_str::<StartResponse>( | ||
32 | &res.text().await.map_err(CliError::Reqwest)? | ||
33 | ) | ||
34 | .map_err(CliError::Serde)?; | ||
35 | |||
36 | if body.boot { | ||
37 | finish_pb(res_pb, "sent start packet".to_string(), DONE_STYLE); | ||
38 | } | ||
39 | 31 | ||
40 | if ping { | 32 | if res.status() == StatusCode::OK { |
41 | let status = status_socket(body.uuid, &send_start, &overview, id).await?; | 33 | let body = serde_json::from_str::<StartResponse>(&res.text().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 | } | ||
47 | } | ||
48 | }, | ||
49 | _ => { | ||
50 | let body = serde_json::from_str::<ErrorResponse>( | ||
51 | &res.text().await.map_err(CliError::Reqwest)? | ||
52 | ) | ||
53 | .map_err(CliError::Serde)?; | ||
54 | 34 | ||
55 | res_pb.finish_with_message(format!("✗ got error: {}", body.error)); | 35 | if body.boot { |
36 | finish_pb(&res_pb, "sent start packet".to_string(), DONE_STYLE); | ||
56 | } | 37 | } |
38 | |||
39 | if ping { | ||
40 | let status = status_socket(config, body.uuid, &send_start, &overview, id).await?; | ||
41 | if status { | ||
42 | finish_pb( | ||
43 | &overview, | ||
44 | format!("successfully started {}", body.id), | ||
45 | OVERVIEW_DONE, | ||
46 | ); | ||
47 | } else { | ||
48 | finish_pb( | ||
49 | &overview, | ||
50 | format!("error while starting {}", body.id), | ||
51 | OVERVIEW_ERROR, | ||
52 | ); | ||
53 | } | ||
54 | } | ||
55 | } else { | ||
56 | let body = serde_json::from_str::<ErrorResponse>(&res.text().await?)?; | ||
57 | |||
58 | res_pb.finish_with_message(format!("✗ got error: {}", body.error)); | ||
57 | } | 59 | } |
58 | 60 | ||
59 | Ok(()) | 61 | Ok(()) |
60 | } | 62 | } |
61 | 63 | ||
62 | async fn status_socket(uuid: String, pb: &MultiProgress, overview: &ProgressBar, id: String) -> Result<bool, CliError> { | 64 | async fn status_socket( |
63 | // TODO: Remove unwraps | 65 | config: &Config, |
66 | uuid: String, | ||
67 | pb: &MultiProgress, | ||
68 | overview: &ProgressBar, | ||
69 | id: String, | ||
70 | ) -> Result<bool, Error> { | ||
64 | let ws_pb = add_pb(pb, DEFAULT_STYLE, "connect to websocket".to_string()); | 71 | let ws_pb = add_pb(pb, DEFAULT_STYLE, "connect to websocket".to_string()); |
65 | let (mut ws_stream, _response) = connect_async(format_url("status", Protocols::Websocket)?) | 72 | |
66 | .await | 73 | let request = Request::builder() |
67 | .expect("Failed to connect"); | 74 | .uri(format_url(config, "status", &Protocols::Websocket)) |
68 | finish_pb(ws_pb, "connected to websocket".to_string(), DONE_STYLE); | 75 | .header("Authorization", &config.apikey) |
69 | 76 | .header("sec-websocket-key", "") | |
77 | .header("host", &config.server) | ||
78 | .header("upgrade", "websocket") | ||
79 | .header("connection", "upgrade") | ||
80 | .header("sec-websocket-version", 13) | ||
81 | .body(()) | ||
82 | .unwrap(); | ||
83 | |||
84 | let (mut ws_stream, _response) = connect_async(request).await?; | ||
85 | finish_pb(&ws_pb, "connected to websocket".to_string(), DONE_STYLE); | ||
86 | |||
70 | ws_stream.send(Message::Text(uuid.clone())).await.unwrap(); | 87 | ws_stream.send(Message::Text(uuid.clone())).await.unwrap(); |
71 | 88 | ||
72 | // Get ETA | 89 | // Get ETA |
73 | let eta_msg = ws_stream.next().await.unwrap().unwrap(); | 90 | let eta_msg = ws_stream.next().await.unwrap().unwrap(); |
74 | let eta = get_eta(eta_msg.into_text().unwrap(), uuid.clone())? + overview.elapsed().as_secs(); | 91 | let eta = get_eta(&eta_msg.into_text().unwrap(), &uuid)?; |
75 | overview.set_message(format!("/{}) start {}", eta, id)); | 92 | overview.set_message(format!("/{eta}) start {id}")); |
76 | 93 | ||
77 | let msg_pb = add_pb(pb, DEFAULT_STYLE, "await message".to_string()); | 94 | let msg_pb = add_pb(pb, DEFAULT_STYLE, "await message".to_string()); |
78 | let msg = ws_stream.next().await.unwrap(); | 95 | let msg = ws_stream.next().await.unwrap(); |
79 | finish_pb(msg_pb, "received message".to_string(), DONE_STYLE); | 96 | finish_pb(&msg_pb, "received message".to_string(), DONE_STYLE); |
80 | 97 | ||
81 | ws_stream.close(None).await.unwrap(); | 98 | ws_stream.close(None).await.unwrap(); |
82 | 99 | ||
83 | let v_pb = add_pb(pb, DEFAULT_STYLE, "verify response".to_string()); | 100 | let v_pb = add_pb(pb, DEFAULT_STYLE, "verify response".to_string()); |
84 | let res = verify_response(msg.unwrap().to_string(), uuid)?; | 101 | let res = verify_response(&msg.unwrap().to_string(), &uuid)?; |
85 | match res { | 102 | match res { |
86 | Verified::WrongUuid => { | 103 | Verified::WrongUuid => { |
87 | finish_pb(v_pb, "returned wrong uuid".to_string(), ERROR_STYLE); | 104 | finish_pb(&v_pb, "returned wrong uuid".to_string(), ERROR_STYLE); |
88 | Ok(false) | 105 | Ok(false) |
89 | }, | ||
90 | Verified::ResponseType(res_type) => { | ||
91 | match res_type { | ||
92 | ResponseType::Start => { | ||
93 | finish_pb(v_pb, "device started".to_string(), DONE_STYLE); | ||
94 | Ok(true) | ||
95 | }, | ||
96 | ResponseType::Timeout => { | ||
97 | finish_pb(v_pb, "ping timed out".to_string(), ERROR_STYLE); | ||
98 | Ok(false) | ||
99 | }, | ||
100 | ResponseType::NotFound => { | ||
101 | finish_pb(v_pb, "unknown uuid".to_string(), ERROR_STYLE); | ||
102 | Ok(false) | ||
103 | }, | ||
104 | } | ||
105 | } | 106 | } |
107 | Verified::ResponseType(res_type) => match res_type { | ||
108 | ResponseType::Start => { | ||
109 | finish_pb(&v_pb, "device started".to_string(), DONE_STYLE); | ||
110 | Ok(true) | ||
111 | } | ||
112 | ResponseType::Timeout => { | ||
113 | finish_pb(&v_pb, "ping timed out".to_string(), ERROR_STYLE); | ||
114 | Ok(false) | ||
115 | } | ||
116 | ResponseType::NotFound => { | ||
117 | finish_pb(&v_pb, "unknown uuid".to_string(), ERROR_STYLE); | ||
118 | Ok(false) | ||
119 | } | ||
120 | }, | ||
106 | } | 121 | } |
107 | } | 122 | } |
108 | 123 | ||
109 | fn get_eta(msg: String, uuid: String) -> Result<u64, CliError> { | 124 | fn get_eta(msg: &str, uuid: &str) -> Result<String, Error> { |
110 | let spl: Vec<&str> = msg.split('_').collect(); | 125 | let spl: Vec<&str> = msg.split('_').collect(); |
111 | if (spl[0] != "eta") || (spl[2] != uuid) { return Err(CliError::WsResponse); }; | 126 | if (spl[0] != "eta") || (spl[2] != uuid) { |
112 | Ok(u64::from_str_radix(spl[1], 10).map_err(CliError::Parse)?) | 127 | return Err(Error::WsResponse); |
128 | }; | ||
129 | let input: u64 = spl[1].parse()?; | ||
130 | |||
131 | let sec = input % 60; | ||
132 | let min = (input / 60) % 60; | ||
133 | let hou = (input / (60 * 60)) % 60; | ||
134 | |||
135 | Ok(format!("{hou:0>2}:{min:0>2}:{sec:0>2}")) | ||
113 | } | 136 | } |
114 | 137 | ||
115 | fn verify_response(res: String, org_uuid: String) -> Result<Verified, CliError> { | 138 | fn verify_response(res: &str, org_uuid: &str) -> Result<Verified, Error> { |
116 | let spl: Vec<&str> = res.split('_').collect(); | 139 | let spl: Vec<&str> = res.split('_').collect(); |
117 | let res_type = spl[0]; | 140 | let res_type = spl[0]; |
118 | let uuid = spl[1]; | 141 | let uuid = spl[1]; |
119 | 142 | ||
120 | if uuid != org_uuid { return Ok(Verified::WrongUuid) }; | 143 | if uuid != org_uuid { |
121 | 144 | return Ok(Verified::WrongUuid); | |
145 | }; | ||
146 | |||
122 | Ok(Verified::ResponseType(ResponseType::from(res_type)?)) | 147 | Ok(Verified::ResponseType(ResponseType::from(res_type)?)) |
123 | } | 148 | } |
124 | 149 | ||
@@ -131,7 +156,7 @@ struct StartResponse { | |||
131 | 156 | ||
132 | enum Verified { | 157 | enum Verified { |
133 | ResponseType(ResponseType), | 158 | ResponseType(ResponseType), |
134 | WrongUuid | 159 | WrongUuid, |
135 | } | 160 | } |
136 | 161 | ||
137 | enum ResponseType { | 162 | enum ResponseType { |
@@ -141,12 +166,12 @@ enum ResponseType { | |||
141 | } | 166 | } |
142 | 167 | ||
143 | impl ResponseType { | 168 | impl ResponseType { |
144 | fn from(value: &str) -> Result<Self, CliError> { | 169 | fn from(value: &str) -> Result<Self, Error> { |
145 | match value { | 170 | match value { |
146 | "start" => Ok(ResponseType::Start), | 171 | "start" => Ok(ResponseType::Start), |
147 | "timeout" => Ok(ResponseType::Timeout), | 172 | "timeout" => Ok(ResponseType::Timeout), |
148 | "notfound" => Ok(ResponseType::NotFound), | 173 | "notfound" => Ok(ResponseType::NotFound), |
149 | _ => Err(CliError::WsResponse), | 174 | _ => Err(Error::WsResponse), |
150 | } | 175 | } |
151 | } | 176 | } |
152 | } | 177 | } |