mirror of
https://github.com/Dangoware/confetti-box.git
synced 2025-04-19 15:22:57 -05:00
Added download function and default download directory to the config
This commit is contained in:
parent
8514c52e93
commit
cb2520be03
1 changed files with 130 additions and 10 deletions
|
@ -7,7 +7,7 @@ use owo_colors::OwoColorize as _;
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::{fs::File, io::AsyncReadExt, task::JoinSet};
|
use tokio::{fs::{create_dir, File}, io::{AsyncReadExt, AsyncWriteExt}, task::JoinSet};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use clap::{arg, builder::{styling::RgbColor, Styles}, Parser, Subcommand};
|
use clap::{arg, builder::{styling::RgbColor, Styles}, Parser, Subcommand};
|
||||||
use anyhow::{anyhow, bail, Context as _, Result};
|
use anyhow::{anyhow, bail, Context as _, Result};
|
||||||
|
@ -20,6 +20,7 @@ const CLAP_STYLE: Styles = Styles::styled()
|
||||||
.error(RgbColor::on_default(RgbColor(181,66,127)).underline());
|
.error(RgbColor::on_default(RgbColor(181,66,127)).underline());
|
||||||
|
|
||||||
const DEBUG_CONFIG: &str = "test/config.toml";
|
const DEBUG_CONFIG: &str = "test/config.toml";
|
||||||
|
const DEBUG_DOWNLOAD_DIR: &str = "test/downloads/";
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[command(name = "confetti_cli")]
|
#[command(name = "confetti_cli")]
|
||||||
|
@ -55,15 +56,22 @@ enum Commands {
|
||||||
/// Set the URL of the server to connect to
|
/// Set the URL of the server to connect to
|
||||||
#[arg(long, required = false)]
|
#[arg(long, required = false)]
|
||||||
url: Option<String>,
|
url: Option<String>,
|
||||||
|
/// Set the directory to download into by default
|
||||||
|
#[arg(value_name="directory", short_alias='d', long, required = false)]
|
||||||
|
dl_dir: Option<String>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Get server information manually
|
/// Get server information manually
|
||||||
Info,
|
Info,
|
||||||
|
|
||||||
/// Download files
|
/// Download files
|
||||||
|
#[command(visible_alias="d")]
|
||||||
Download {
|
Download {
|
||||||
/// MMID to download
|
/// MMID to download
|
||||||
mmid: String,
|
#[arg(value_name = "mmid(s)", required = true)]
|
||||||
|
mmids: Vec<String>,
|
||||||
|
#[arg(short, long, value_name = "out", required = false)]
|
||||||
|
out_directory: Option<PathBuf>
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,15 +145,99 @@ async fn main() -> Result<()> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Commands::Download { mmid } => {
|
Commands::Download { mmids, out_directory } => {
|
||||||
todo!();
|
let out_directory = if let Some(dir) = out_directory {
|
||||||
|
dir
|
||||||
|
} else {
|
||||||
|
let ddir = &config.download_directory;
|
||||||
|
if ddir.as_os_str().is_empty() {
|
||||||
|
exit_error(
|
||||||
|
"Default download directory is empty".into(),
|
||||||
|
Some(format!("Please set it using the {} command", "set".truecolor(246,199,219).bold())),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
} else if !ddir.exists() {
|
||||||
|
exit_error(
|
||||||
|
format!("Default download directory {} does not exist", ddir.display()),
|
||||||
|
Some(format!("Please set it using the {} command", "set".truecolor(246,199,219).bold())),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
ddir
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let url = &config.url;
|
||||||
|
for mmid in mmids {
|
||||||
|
let mmid = if mmid.len() != 8 {
|
||||||
|
if mmid.contains(format!("{url}/f/").as_str()) {
|
||||||
|
let mmid = mmid.replace(format!("{url}/f/").as_str(), "");
|
||||||
|
if mmid.len() != 8 {
|
||||||
|
exit_error("{mmid} is not a valid MMID".into(), Some("MMID must be 8 characters long".into()), None)
|
||||||
|
} else {
|
||||||
|
mmid
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
exit_error("{mmid} is not a valid MMID".into(), Some("MMID must be 8 characters long".into()), None)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unimplemented!();
|
||||||
|
};
|
||||||
|
|
||||||
|
let client = Client::new();
|
||||||
|
|
||||||
|
let info = if let Ok(file) = if let Some(login) = &config.login {
|
||||||
|
client.get(format!("{}/info/{mmid}", url))
|
||||||
|
.basic_auth(&login.user, Some(&login.pass))
|
||||||
|
} else {
|
||||||
|
client.get(format!("{}/info/{mmid}", url))
|
||||||
|
}
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.json::<MochiFile>()
|
||||||
|
.await {
|
||||||
|
file
|
||||||
|
} else {
|
||||||
|
exit_error(format!("File with MMID {mmid} was not found"), None, None)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut file_res = if let Some(login) = &config.login {
|
||||||
|
client.get(format!("{}/f/{mmid}", config.url))
|
||||||
|
.basic_auth(&login.user, Some(&login.pass))
|
||||||
|
} else {
|
||||||
|
client.get(format!("{}/f/{mmid}", config.url))
|
||||||
|
}
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let out_directory = out_directory.join(info.name);
|
||||||
|
let mut out_file: File = tokio::fs::OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.append(true)
|
||||||
|
.read(true)
|
||||||
|
.open(&out_directory).await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
while let Some(next) = file_res.chunk().await.unwrap() {
|
||||||
|
out_file.write(&next).await.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Downloaded to {}", out_directory.display());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Commands::Set { username, password, url } => {
|
Commands::Set {
|
||||||
if username.is_none() && password.is_none() && url.is_none() {
|
username,
|
||||||
|
password,
|
||||||
|
url,
|
||||||
|
dl_dir
|
||||||
|
} => {
|
||||||
|
if username.is_none() && password.is_none() && url.is_none() && dl_dir.is_none() {
|
||||||
exit_error(
|
exit_error(
|
||||||
format!("Please provide an option to set"),
|
format!("Please provide an option to set"),
|
||||||
Some(format!("Allowed options:")),
|
Some(format!("Allowed options:")),
|
||||||
Some(vec!["--username".into(), "--password".into(), "--url".into()]),
|
Some(vec!["--username".into(), "--password".into(), "--url".into(), "--dl-dir".into()]),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,7 +256,7 @@ async fn main() -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
config.save().unwrap();
|
config.save().unwrap();
|
||||||
println!("Set username to \"{u}\"")
|
println!("Username set to \"{u}\"")
|
||||||
}
|
}
|
||||||
if let Some(p) = password {
|
if let Some(p) = password {
|
||||||
if p.is_empty() {
|
if p.is_empty() {
|
||||||
|
@ -181,7 +273,7 @@ async fn main() -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
config.save().unwrap();
|
config.save().unwrap();
|
||||||
println!("Set password")
|
println!("Password set")
|
||||||
}
|
}
|
||||||
if let Some(url) = url {
|
if let Some(url) = url {
|
||||||
if url.is_empty() {
|
if url.is_empty() {
|
||||||
|
@ -196,7 +288,32 @@ async fn main() -> Result<()> {
|
||||||
|
|
||||||
config.url = url.to_string();
|
config.url = url.to_string();
|
||||||
config.save().unwrap();
|
config.save().unwrap();
|
||||||
println!("Set URL to \"{url}\"");
|
println!("URL set to \"{url}\"");
|
||||||
|
}
|
||||||
|
if let Some(mut dir) = dl_dir.clone() {
|
||||||
|
if dir.is_empty() {
|
||||||
|
exit_error(format!("Download directory cannot be blank"), None, None);
|
||||||
|
}
|
||||||
|
if dir.as_str() == "default" {
|
||||||
|
dir = directories::UserDirs::new()
|
||||||
|
.unwrap()
|
||||||
|
.download_dir()
|
||||||
|
.unwrap_or_else(|| exit_error("No Default directory available".into(), None, None))
|
||||||
|
.to_string_lossy()
|
||||||
|
.to_string();
|
||||||
|
}
|
||||||
|
if dir.chars().last() != Some('/') {
|
||||||
|
dir.push('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
let _dir = PathBuf::from(dir.clone());
|
||||||
|
if !_dir.exists() {
|
||||||
|
exit_error(format!("Directory {dir} does not exist"), None, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
config.download_directory = _dir;
|
||||||
|
config.save().unwrap();
|
||||||
|
println!("Download directory set to \"{dir}\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Commands::Info => {
|
Commands::Info => {
|
||||||
|
@ -460,6 +577,7 @@ struct Config {
|
||||||
/// The time when the info was last fetched
|
/// The time when the info was last fetched
|
||||||
info_fetch: Option<DateTime<Utc>>,
|
info_fetch: Option<DateTime<Utc>>,
|
||||||
info: Option<ServerInfo>,
|
info: Option<ServerInfo>,
|
||||||
|
download_directory: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
|
@ -473,6 +591,7 @@ impl Config {
|
||||||
login: None,
|
login: None,
|
||||||
info_fetch: None,
|
info_fetch: None,
|
||||||
info: None,
|
info: None,
|
||||||
|
download_directory: PathBuf::from(DEBUG_DOWNLOAD_DIR)
|
||||||
};
|
};
|
||||||
c.save().unwrap();
|
c.save().unwrap();
|
||||||
return Ok(c);
|
return Ok(c);
|
||||||
|
@ -505,6 +624,7 @@ impl Config {
|
||||||
login: None,
|
login: None,
|
||||||
info: None,
|
info: None,
|
||||||
info_fetch: None,
|
info_fetch: None,
|
||||||
|
download_directory: PathBuf::from(directories::UserDirs::new().unwrap().download_dir().unwrap_or(Path::new("")))
|
||||||
};
|
};
|
||||||
c.save().unwrap();
|
c.save().unwrap();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue