added some utility functions

This commit is contained in:
Gvidas Juknevičius 2024-04-13 00:02:42 +03:00
parent f4e8f4aca0
commit 33c4e7bd82
Signed by: MCorange
GPG Key ID: 12B1346D720B7FBB
8 changed files with 233 additions and 44 deletions

111
music_mgr/Cargo.lock generated
View File

@ -266,15 +266,18 @@ dependencies = [
name = "music_mgr" name = "music_mgr"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anstyle",
"anyhow", "anyhow",
"camino", "camino",
"clap", "clap",
"env_logger", "env_logger",
"lazy_static", "lazy_static",
"libc",
"log", "log",
"serde", "serde",
"serde_json", "serde_json",
"tokio", "tokio",
"windows",
] ]
[[package]] [[package]]
@ -464,6 +467,59 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "windows"
version = "0.56.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132"
dependencies = [
"windows-core",
"windows-targets 0.52.5",
]
[[package]]
name = "windows-core"
version = "0.56.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6"
dependencies = [
"windows-implement",
"windows-interface",
"windows-result",
"windows-targets 0.52.5",
]
[[package]]
name = "windows-implement"
version = "0.56.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "windows-interface"
version = "0.56.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "windows-result"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "749f0da9cc72d82e600d8d2e44cadd0b9eedb9038f71a1c58556ac1c5791813b"
dependencies = [
"windows-targets 0.52.5",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.48.0" version = "0.48.0"
@ -479,7 +535,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [ dependencies = [
"windows-targets 0.52.4", "windows-targets 0.52.5",
] ]
[[package]] [[package]]
@ -499,17 +555,18 @@ dependencies = [
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [ dependencies = [
"windows_aarch64_gnullvm 0.52.4", "windows_aarch64_gnullvm 0.52.5",
"windows_aarch64_msvc 0.52.4", "windows_aarch64_msvc 0.52.5",
"windows_i686_gnu 0.52.4", "windows_i686_gnu 0.52.5",
"windows_i686_msvc 0.52.4", "windows_i686_gnullvm",
"windows_x86_64_gnu 0.52.4", "windows_i686_msvc 0.52.5",
"windows_x86_64_gnullvm 0.52.4", "windows_x86_64_gnu 0.52.5",
"windows_x86_64_msvc 0.52.4", "windows_x86_64_gnullvm 0.52.5",
"windows_x86_64_msvc 0.52.5",
] ]
[[package]] [[package]]
@ -520,9 +577,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
@ -532,9 +589,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
@ -544,9 +601,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
@ -556,9 +619,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
@ -568,9 +631,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
@ -580,9 +643,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
@ -592,6 +655,6 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.52.4" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"

View File

@ -6,12 +6,15 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
anstyle = "1.0.6"
anyhow = "1.0.81" anyhow = "1.0.81"
camino = "1.1.6" camino = "1.1.6"
clap = { version = "4.5.4", features = ["derive"] } clap = { version = "4.5.4", features = ["derive"] }
env_logger = "0.11.3" env_logger = "0.11.3"
lazy_static = "1.4.0" lazy_static = "1.4.0"
libc = "0.2.153"
log = "0.4.21" log = "0.4.21"
serde = { version = "1.0.197", features = ["derive"] } serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.115" serde_json = "1.0.115"
tokio = { version = "1.37.0", features = ["macros", "rt-multi-thread", "process", "sync"] } tokio = { version = "1.37.0", features = ["macros", "rt-multi-thread", "process", "sync"] }
windows = { version = "0.56.0", features = ["Win32_Foundation", "Win32_Storage_FileSystem", "Win32_System_Console"] }

View File

@ -1,6 +1,8 @@
use camino::Utf8PathBuf; use camino::Utf8PathBuf;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use crate::util::isatty;
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
pub struct CliArgs { pub struct CliArgs {
/// Show more info /// Show more info
@ -17,6 +19,9 @@ pub struct CliArgs {
#[command(subcommand)] #[command(subcommand)]
pub command: Option<CliCommand>, pub command: Option<CliCommand>,
#[clap(skip)]
pub is_tty: bool
} }
#[derive(Debug, Subcommand, Default)] #[derive(Debug, Subcommand, Default)]
@ -28,4 +33,11 @@ pub enum CliCommand {
name: String, name: String,
genre: String genre: String
} }
}
impl CliArgs {
pub fn populate_extra(&mut self) -> &mut Self{
self.is_tty = isatty();
self
}
} }

View File

@ -0,0 +1,22 @@
use crate::{cli::{CliArgs, CliCommand}, downloader::Downloader, manifest::Manifest, util};
pub async fn command_run(cli: &CliArgs, manifest: &Manifest) {
let mut downloader = Downloader::new(util::get_ytdlp_path());
match &cli.command {
None | Some(CliCommand::Download) => {
if let Ok(count) = downloader.download_all(manifest, &cli).await {
log::info!("Downloaded {count} songs");
} else {
log::error!("Failed to download songs");
return;
}
},
Some(c) => {
match c {
CliCommand::Download => unreachable!(),
CliCommand::Add { .. } => todo!(),
}
}
}
}

View File

@ -33,7 +33,7 @@ impl Downloader {
} }
} }
pub async fn download_all(&mut self, manifest: Manifest, cli: &CliArgs) -> anyhow::Result<usize> { pub async fn download_all(&mut self, manifest: &Manifest, cli: &CliArgs) -> anyhow::Result<usize> {
let format = manifest.format()?; let format = manifest.format()?;
for (genre, songs) in &manifest.genres { for (genre, songs) in &manifest.genres {

View File

@ -7,11 +7,15 @@ mod manifest;
mod logger; mod logger;
mod downloader; mod downloader;
mod util; mod util;
mod commands;
mod prompt;
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
let cli_args = CliArgs::parse(); let mut cli_args = CliArgs::parse();
cli_args.populate_extra();
logger::init_logger(cli_args.debug); logger::init_logger(cli_args.debug);
let manifest = match manifest::Manifest::from_path(&cli_args.manifest.as_std_path()) { let manifest = match manifest::Manifest::from_path(&cli_args.manifest.as_std_path()) {
Ok(m) => m, Ok(m) => m,
Err(e) => { Err(e) => {
@ -20,22 +24,6 @@ async fn main() {
} }
}; };
let mut downloader = Downloader::new(util::get_ytdlp_path());
commands::command_run(&cli_args, &manifest);
match cli_args.command {
None | Some(CliCommand::Download) => {
if let Ok(count) = downloader.download_all(manifest, &cli_args).await {
log::info!("Downloaded {count} songs");
} else {
log::error!("Failed to download songs");
return;
}
},
Some(c) => {
match c {
CliCommand::Download => unreachable!(),
CliCommand::Add { .. } => todo!(),
}
}
}
} }

75
music_mgr/src/prompt.rs Normal file
View File

@ -0,0 +1,75 @@
use std::{collections::HashMap, io::Write};
pub fn simple_prompt(p: &str) -> String {
print!("{c}prompt{r}: {p}",
c=anstyle::AnsiColor::Magenta.render_fg(),
r=anstyle::Style::new().render_reset()
);
// I dont care if it fails
let _ = std::io::stdout().flush();
let mut buf = String::new();
let _ = std::io::stdin().read_line(&mut buf);
buf
}
pub fn prompt_with_options(p: &str, options: &[&str]) -> usize {
println!("{c}prompt{r}: {p}",
c=anstyle::AnsiColor::Magenta.render_fg(),
r=anstyle::Style::new().render_reset()
);
for (i, op) in options.iter().enumerate() {
println!(" - {}: {}", i, op);
}
print!("> ");
// I dont care if it fails
let _ = std::io::stdout().flush();
let mut buf = String::new();
let _ = std::io::stdin().read_line(&mut buf);
if let Ok(num) = buf.parse::<usize>() {
if num <= options.len() {
return num;
} else {
log::error!("Number not in range");
return prompt_with_options(p, options);
}
} else {
log::error!("Not a number");
return prompt_with_options(p, options);
}
}
pub fn prompt_with_named_options(p: &str, options: HashMap<&str, &str>) -> String {
println!("{c}prompt{r}: {p}",
c=anstyle::AnsiColor::Magenta.render_fg(),
r=anstyle::Style::new().render_reset()
);
let mut keys = Vec::new();
for (k, v) in &options {
println!(" - {}: {}", k, v);
keys.push(k.trim().to_lowercase())
}
print!("> ");
// I dont care if it fails
let _ = std::io::stdout().flush();
let mut buf = String::new();
let _ = std::io::stdin().read_line(&mut buf);
if !keys.contains(&buf.trim().to_lowercase()) {
return prompt_with_named_options(p, options);
}
buf
}

View File

@ -19,4 +19,30 @@ pub fn get_ytdlp_path() -> String {
} }
// TODO: Download yt-dlp to ./.bin/yt-dlp if doesnt exist // TODO: Download yt-dlp to ./.bin/yt-dlp if doesnt exist
todo!() todo!()
}
#[cfg(target_family="unix")]
pub fn isatty() -> bool {
use std::{ffi::c_int, os::fd::AsRawFd};
unsafe {
let fd = std::io::stdin().as_raw_fd();
libc::isatty(fd as c_int) == 1
}
}
#[cfg(target_family="windows")]
pub fn isatty() -> bool {
unsafe {
use windows::Win32::System::Console;
use Console::{CONSOLE_MODE, STD_OUTPUT_HANDLE};
let Ok(handle) = Console::GetStdHandle(STD_OUTPUT_HANDLE) else {
return false;
};
let mut out = CONSOLE_MODE(0);
let ret = Console::GetConsoleMode(handle, &mut out);
ret.is_ok()
}
} }