blah-rs/src/files.rs

60 lines
1.8 KiB
Rust

use anyhow::{anyhow, Result};
use futures_util::StreamExt;
use indicatif::{ProgressBar, ProgressStyle};
use reqwest::Client;
use std::{cmp::min, fs::File, io::Write};
pub async fn open_or_download(url: &str, path: &str) -> Result<Vec<u8>> {
// Download file if it doesn't exist
if !tokio::fs::try_exists(path).await? {
download_file(url, path).await?;
} else {
println!("{} found", path);
}
Ok(tokio::fs::read(path).await?)
}
async fn download_file(url: &str, path: &str) -> Result<()> {
// Reqwest setup
let res = Client::new().get(url).send().await?;
let total_size = res.content_length().unwrap();
// Indicatif setup
let pb = ProgressBar::new(total_size);
pb.set_style(ProgressStyle::default_bar()
.template("{msg}\n{spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({bytes_per_sec}, {eta})")?
.progress_chars("#>-"));
pb.set_message(format!("Downloading {}", url));
let mut file = File::create(path)?;
let mut downloaded: u64 = 0;
let mut stream = res.bytes_stream();
while let Some(item) = stream.next().await {
let chunk = item?;
file.write_all(&chunk)?;
let new = min(downloaded + (chunk.len() as u64), total_size);
downloaded = new;
pb.set_position(new);
}
pb.finish_with_message(format!("Downloaded {} to {}", url, path));
Ok(())
}
pub async fn save_decklist(filepath: &str, decklist: Vec<String>) -> Result<()> {
let mut file =
File::create(filepath).or(Err(anyhow!("Failed to create file '{}'", filepath)))?;
let contents = decklist
.iter()
.map(|line| format!("1 {}\n", line))
.collect::<Vec<_>>()
.join("");
file.write_all(contents.as_bytes())?;
println!("Decklist saved to {}", filepath);
Ok(())
}