feat: vanilla server downloading + lots of ux improvements
This commit is contained in:
parent
505bfbbb5d
commit
0a12b87a2a
6 changed files with 241 additions and 22 deletions
126
Cargo.lock
generated
126
Cargo.lock
generated
|
|
@ -93,6 +93,15 @@ version = "2.13.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
|
checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-buffer"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa"
|
||||||
|
dependencies = [
|
||||||
|
"hybrid-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.20.3"
|
version = "3.20.3"
|
||||||
|
|
@ -217,6 +226,12 @@ dependencies = [
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "const-oid"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation"
|
name = "core-foundation"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
|
|
@ -252,6 +267,15 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-common"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453"
|
||||||
|
dependencies = [
|
||||||
|
"hybrid-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dialoguer"
|
name = "dialoguer"
|
||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
|
|
@ -265,6 +289,17 @@ dependencies = [
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "digest"
|
||||||
|
version = "0.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer",
|
||||||
|
"const-oid",
|
||||||
|
"crypto-common",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "displaydoc"
|
name = "displaydoc"
|
||||||
version = "0.2.7"
|
version = "0.2.7"
|
||||||
|
|
@ -361,6 +396,23 @@ version = "0.3.34"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e"
|
checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-io"
|
||||||
|
version = "0.3.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-macro"
|
||||||
|
version = "0.3.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 3.0.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-sink"
|
name = "futures-sink"
|
||||||
version = "0.3.34"
|
version = "0.3.34"
|
||||||
|
|
@ -380,7 +432,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc"
|
checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
|
"futures-macro",
|
||||||
|
"futures-sink",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
|
"memchr",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"slab",
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
@ -491,6 +547,15 @@ version = "1.10.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
|
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hybrid-array"
|
||||||
|
version = "0.4.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "1.11.1"
|
version = "1.11.1"
|
||||||
|
|
@ -666,6 +731,19 @@ dependencies = [
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indicatif"
|
||||||
|
version = "0.18.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9433806cd6b4ec1aba79c021c7e4c58fb4c3b9977c085062e611ac929998fb0c"
|
||||||
|
dependencies = [
|
||||||
|
"console",
|
||||||
|
"portable-atomic",
|
||||||
|
"unicode-width",
|
||||||
|
"unit-prefix",
|
||||||
|
"web-time",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipnet"
|
name = "ipnet"
|
||||||
version = "2.12.1"
|
version = "2.12.1"
|
||||||
|
|
@ -799,8 +877,11 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"dialoguer",
|
"dialoguer",
|
||||||
|
"futures-util",
|
||||||
|
"indicatif",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
|
"sha1",
|
||||||
"tokio",
|
"tokio",
|
||||||
"toml",
|
"toml",
|
||||||
]
|
]
|
||||||
|
|
@ -887,6 +968,12 @@ version = "0.3.34"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548"
|
checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "portable-atomic"
|
||||||
|
version = "1.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "potential_utf"
|
name = "potential_utf"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
|
|
@ -1022,6 +1109,7 @@ dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
"futures-util",
|
||||||
"h2",
|
"h2",
|
||||||
"http",
|
"http",
|
||||||
"http-body",
|
"http-body",
|
||||||
|
|
@ -1043,12 +1131,14 @@ dependencies = [
|
||||||
"sync_wrapper",
|
"sync_wrapper",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
|
"tokio-util",
|
||||||
"tower",
|
"tower",
|
||||||
"tower-http",
|
"tower-http",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"url",
|
"url",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
|
"wasm-streams",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1280,6 +1370,17 @@ dependencies = [
|
||||||
"serde_core",
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shell-words"
|
name = "shell-words"
|
||||||
version = "1.1.1"
|
version = "1.1.1"
|
||||||
|
|
@ -1649,6 +1750,12 @@ version = "0.2.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typenum"
|
||||||
|
version = "1.20.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.24"
|
version = "1.0.24"
|
||||||
|
|
@ -1661,6 +1768,12 @@ version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
|
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unit-prefix"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "untrusted"
|
name = "untrusted"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
|
|
@ -1771,6 +1884,19 @@ dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-streams"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb"
|
||||||
|
dependencies = [
|
||||||
|
"futures-util",
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"wasm-bindgen-futures",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "web-sys"
|
name = "web-sys"
|
||||||
version = "0.3.104"
|
version = "0.3.104"
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,10 @@ edition = "2024"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "4.6.6", features = ["derive"] }
|
clap = { version = "4.6.6", features = ["derive"] }
|
||||||
dialoguer = { version = "0.12.0", features = ["fuzzy-select"] }
|
dialoguer = { version = "0.12.0", features = ["fuzzy-select"] }
|
||||||
reqwest = { version = "0.13.4", features = ["json"] }
|
futures-util = "0.3.34"
|
||||||
|
indicatif = "0.18.6"
|
||||||
|
reqwest = { version = "0.13.4", features = ["json", "stream"] }
|
||||||
serde = { version = "1.0.229", features = ["derive"] }
|
serde = { version = "1.0.229", features = ["derive"] }
|
||||||
|
sha1 = "0.11.0"
|
||||||
tokio = { version = "1.53.1", features = ["full"] }
|
tokio = { version = "1.53.1", features = ["full"] }
|
||||||
toml = "1.1.4"
|
toml = "1.1.4"
|
||||||
|
|
|
||||||
BIN
new/server.jar
Normal file
BIN
new/server.jar
Normal file
Binary file not shown.
90
src/main.rs
90
src/main.rs
|
|
@ -1,10 +1,17 @@
|
||||||
mod models;
|
mod models;
|
||||||
|
mod utils;
|
||||||
|
|
||||||
use std::{error::Error, fs};
|
use crate::{models::vanilla::{VanillaVersionDetail, VanillaVersionType, VanillaVersions}, utils::with_spinner};
|
||||||
use clap::{Parser, Subcommand, builder::styling::{self}};
|
use clap::{
|
||||||
|
Parser, Subcommand,
|
||||||
|
builder::styling::{self},
|
||||||
|
};
|
||||||
use dialoguer::{FuzzySelect, Select, theme::ColorfulTheme};
|
use dialoguer::{FuzzySelect, Select, theme::ColorfulTheme};
|
||||||
use crate::models::vanilla::{VanillaVersionType, VanillaVersions};
|
use futures_util::StreamExt;
|
||||||
|
use indicatif::{ProgressBar, ProgressStyle};
|
||||||
|
use sha1::{Digest, Sha1};
|
||||||
|
use std::error::Error;
|
||||||
|
use tokio::io::AsyncWriteExt;
|
||||||
|
|
||||||
fn styles() -> styling::Styles {
|
fn styles() -> styling::Styles {
|
||||||
styling::Styles::styled()
|
styling::Styles::styled()
|
||||||
|
|
@ -22,17 +29,17 @@ struct Mcsm {
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
enum Commands {
|
enum Commands {
|
||||||
Init {
|
Init { name: String },
|
||||||
name: String
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn Error>> {
|
async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let mcsm = Mcsm::parse();
|
let mcsm = Mcsm::parse();
|
||||||
|
|
||||||
match mcsm.command {
|
match mcsm.command {
|
||||||
Commands::Init { name } => {
|
Commands::Init { name: project_name } => {
|
||||||
fs::create_dir(name)?;
|
tokio::fs::create_dir(&project_name).await?;
|
||||||
|
std::env::set_current_dir(&project_name)?;
|
||||||
|
|
||||||
let loaders = vec!["Vanilla", "Fabric"];
|
let loaders = vec!["Vanilla", "Fabric"];
|
||||||
let loader_index = Select::with_theme(&ColorfulTheme::default())
|
let loader_index = Select::with_theme(&ColorfulTheme::default())
|
||||||
|
|
@ -40,31 +47,74 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
.items(&loaders)
|
.items(&loaders)
|
||||||
.default(0)
|
.default(0)
|
||||||
.interact()?;
|
.interact()?;
|
||||||
|
|
||||||
match loader_index {
|
match loader_index {
|
||||||
0 => {
|
0 => {
|
||||||
const URL: &str = "https://launchermeta.mojang.com/mc/game/version_manifest.json";
|
const URL: &str =
|
||||||
let res: VanillaVersions = reqwest::get(URL).await?.json().await?;
|
"https://launchermeta.mojang.com/mc/game/version_manifest.json";
|
||||||
let release_versions = res.versions
|
let res = with_spinner("", "", || async {
|
||||||
|
let res: VanillaVersions = reqwest::get(URL).await?.json().await?;
|
||||||
|
Ok(res)
|
||||||
|
}).await?;
|
||||||
|
|
||||||
|
let release_versions = res
|
||||||
|
.versions
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|version| version.version_type == VanillaVersionType::Release)
|
.filter(|version| version.version_type == VanillaVersionType::Release)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let release_version_names = release_versions
|
||||||
|
.iter()
|
||||||
.map(|version| version.id.clone())
|
.map(|version| version.id.clone())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let version_index = FuzzySelect::with_theme(&ColorfulTheme::default())
|
let version_index = FuzzySelect::with_theme(&ColorfulTheme::default())
|
||||||
.with_prompt("Select Version")
|
.with_prompt("Select Version")
|
||||||
.items(&release_versions)
|
.items(&release_version_names)
|
||||||
.default(0)
|
.default(0)
|
||||||
.interact()?;
|
.interact()?;
|
||||||
|
|
||||||
println!("you selected {} with version {}", loaders[loader_index], release_versions[version_index]);
|
let version_detail: VanillaVersionDetail =
|
||||||
|
reqwest::get(release_versions[version_index].url.clone())
|
||||||
|
.await?
|
||||||
|
.json()
|
||||||
|
.await?;
|
||||||
|
|
||||||
},
|
println!(
|
||||||
1 => {
|
"downloading server.jar for {} {}",
|
||||||
|
loaders[loader_index], release_version_names[version_index]
|
||||||
|
);
|
||||||
|
let pb = ProgressBar::new(version_detail.downloads.server.size);
|
||||||
|
pb.set_style(ProgressStyle::default_bar().template(
|
||||||
|
"{bar:40.green/white} {bytes}/{total_bytes} ({bytes_per_sec})",
|
||||||
|
)?);
|
||||||
|
|
||||||
|
let server_bytes = reqwest::get(version_detail.downloads.server.url).await?;
|
||||||
|
let mut file = tokio::fs::File::create("server.jar").await?;
|
||||||
|
let mut stream = server_bytes.bytes_stream();
|
||||||
|
|
||||||
|
while let Some(chunk) = stream.next().await {
|
||||||
|
let chunk = chunk?;
|
||||||
|
file.write_all(&chunk).await?;
|
||||||
|
pb.inc(chunk.len() as u64);
|
||||||
|
}
|
||||||
|
pb.finish_with_message("download finished");
|
||||||
|
|
||||||
|
with_spinner("verifying sha1 hash", "sha1 hash verified", || async {
|
||||||
|
let data = tokio::fs::read("server.jar").await?;
|
||||||
|
let mut hasher = Sha1::new();
|
||||||
|
hasher.update(&data);
|
||||||
|
let hash = hasher.finalize();
|
||||||
|
let hex: String = hash.iter().map(|b| format!("{:02x}", b)).collect();
|
||||||
|
|
||||||
|
if hex != version_detail.downloads.server.sha1 {
|
||||||
|
tokio::fs::remove_file("server.jar").await?;
|
||||||
|
return Err("sha1 verifaction failed for downloaded file".into());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}).await?;
|
||||||
}
|
}
|
||||||
_ => return Err("Invalid selection".into())
|
1 => {}
|
||||||
|
_ => return Err("Invalid selection".into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct VanillaVersions {
|
pub struct VanillaVersions {
|
||||||
pub latest: VanillaLatestVersion,
|
pub latest: VanillaLatestVersion,
|
||||||
pub versions: Vec<VanillaVersion>,
|
pub versions: Vec<VanillaVersion>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -29,3 +29,20 @@ pub struct VanillaVersion {
|
||||||
pub url: String,
|
pub url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct VanillaVersionDetail {
|
||||||
|
pub downloads: VanillaVersionDownloads,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct VanillaVersionDownloads {
|
||||||
|
pub client: VanillaVersionDownloadItem,
|
||||||
|
pub server: VanillaVersionDownloadItem,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct VanillaVersionDownloadItem {
|
||||||
|
pub sha1: String,
|
||||||
|
pub size: u64,
|
||||||
|
pub url: String,
|
||||||
|
}
|
||||||
|
|
|
||||||
23
src/utils.rs
Normal file
23
src/utils.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
use std::{error::Error, future::Future};
|
||||||
|
use indicatif::ProgressBar;
|
||||||
|
|
||||||
|
pub async fn with_spinner<F, Fut, T>(
|
||||||
|
start_msg: &str,
|
||||||
|
finish_msg: &str,
|
||||||
|
f: F,
|
||||||
|
) -> Result<T, Box<dyn Error>>
|
||||||
|
where
|
||||||
|
F: FnOnce() -> Fut,
|
||||||
|
Fut: Future<Output = Result<T, Box<dyn Error>>>,
|
||||||
|
{
|
||||||
|
let pb = ProgressBar::new_spinner();
|
||||||
|
pb.set_message(start_msg.to_string());
|
||||||
|
pb.enable_steady_tick(std::time::Duration::from_millis(100));
|
||||||
|
|
||||||
|
let result = f().await;
|
||||||
|
|
||||||
|
pb.finish_and_clear();
|
||||||
|
println!("{} {}", dialoguer::console::style("✔").green(), finish_msg);
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue