From 8a1d67166f3f31c77e937ec9b6c8e7bb4292c7e9 Mon Sep 17 00:00:00 2001 From: John Rogers Date: Sun, 17 Aug 2025 14:01:03 +0100 Subject: [PATCH 1/8] refactor: Convert jamdl shell script to a Rust application Co-authored-by: aider (gemini/gemini-2.5-pro-preview-05-06) --- Cargo.toml | 11 ++++++ src/main.rs | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 Cargo.toml create mode 100644 src/main.rs diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..be5b04c --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "jamdl" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.82" +clap = { version = "4.5.4", features = ["derive"] } +tempfile = "3.10.1" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..e4f408b --- /dev/null +++ b/src/main.rs @@ -0,0 +1,100 @@ +use anyhow::{Context, Result}; +use clap::Parser; +use std::fs; +use std::path::Path; +use std::process::Command; +use tempfile::TempDir; + +// ==== CONFIGURATION ==== +const NAS_HOST: &str = "(localaddress)"; +const NAS_USER: &str = "ssh_user"; +const NAS_PATH: &str = "/path/to/files/on/nas"; +const COOKIES_FILE: &str = "/location/of/apple-music-cookies-file.txt"; + +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +struct Args { + /// The URL of the video/music to download + #[arg(name = "URL")] + url: String, +} + +fn main() -> Result<()> { + let args = Args::parse(); + + // Create temp directory + let temp_dir = TempDir::new().context("Failed to create temporary directory")?; + let temp_path = temp_dir.path(); + println!( + "[INFO] Created temporary directory at: {}", + temp_path.display() + ); + + download_media(&args.url, temp_path)?; + transfer_files(temp_path)?; + + // Cleanup is handled by TempDir's Drop trait + println!("[INFO] Cleaning up..."); + Ok(()) +} + +fn download_media(video_url: &str, download_path: &Path) -> Result<()> { + let mut cmd: Command; + + if video_url.contains("music.apple.com") { + println!("[INFO] Apple Music link detected. Using gamdl..."); + cmd = Command::new("gamdl"); + if Path::new(COOKIES_FILE).exists() { + cmd.args(["--cookies-path", COOKIES_FILE, video_url]); + } else { + println!( + "[WARN] cookies.txt not found at {} — running gamdl without it", + COOKIES_FILE + ); + cmd.arg(video_url); + } + } else if video_url.contains("soundcloud.com") { + println!("[INFO] Soundcloud link detected. Using scdl..."); + cmd = Command::new("scdl"); + cmd.args(["-l", video_url]); + } else { + println!("[INFO] Non-Apple Music link. Using yt-dlp..."); + cmd = Command::new("yt-dlp"); + cmd.args(["-o", "%(title)s.%(ext)s", video_url]); + } + + cmd.current_dir(download_path); + let status = cmd + .status() + .with_context(|| format!("Failed to execute command: {:?}", cmd))?; + + if !status.success() { + anyhow::bail!("Download command failed with status: {}", status); + } + + Ok(()) +} + +fn transfer_files(source_path: &Path) -> Result<()> { + let is_empty = fs::read_dir(source_path)?.next().is_none(); + + if !is_empty { + println!("[INFO] Transferring files to NAS..."); + let mut scp_cmd = Command::new("scp"); + let source = format!( + "{}/.", + source_path.to_str().context("Invalid source path")? + ); + let destination = format!("{}@{}:{}", NAS_USER, NAS_HOST, NAS_PATH); + scp_cmd.args(["-r", &source, &destination]); + + let status = scp_cmd.status().context("Failed to execute scp")?; + if !status.success() { + anyhow::bail!("scp failed with status: {}", status); + } + } else { + println!("[WARN] No files found to transfer."); + } + + Ok(()) +} -- 2.49.1 From ae2e2b9e77ac5cc311e84b221fd7bef2fff317e0 Mon Sep 17 00:00:00 2001 From: John Rogers Date: Sun, 17 Aug 2025 14:02:31 +0100 Subject: [PATCH 2/8] deelgte --- jamdl.sh | 49 ------------------------------------------------- 1 file changed, 49 deletions(-) delete mode 100644 jamdl.sh diff --git a/jamdl.sh b/jamdl.sh deleted file mode 100644 index 65475df..0000000 --- a/jamdl.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash - -# ==== CONFIGURATION ==== -VIDEO_URL="$1" -NAS_HOST="(localaddress)" -NAS_USER="ssh_user" -NAS_PATH="/path/to/files/on/nas" -TEMP_DIR="/tmp/yt-nas-transfer" -COOKIES_FILE="/location/of/apple-music-cookies-file.txt" - -# ==== BASIC CHECK ==== -if [[ -z "$VIDEO_URL" ]]; then - echo "[ERROR] No URL provided. Usage: jamdl \"\"" - exit 1 -fi - -# Create temp directory -mkdir -p "$TEMP_DIR" -cd "$TEMP_DIR" || exit 1 - -# ==== DOWNLOAD SECTION ==== -if [[ "$VIDEO_URL" == *"music.apple.com"* ]]; then - echo "[INFO] Apple Music link detected. Using gamdl..." - if [[ -f "$COOKIES_FILE" ]]; then - gamdl --cookies-path "$COOKIES_FILE" "$VIDEO_URL" - else - echo "[WARN] cookies.txt not found at $COOKIES_FILE — running gamdl without it" - gamdl "$VIDEO_URL" - fi -elif [[ "$VIDEO_URL" == *"soundcloud.com"* ]]; then - echo "[INFO] Soundcloud link detected. Using scdl..." - scdl -l "$VIDEO_URL" -else - echo "[INFO] Non-Apple Music link. Using yt-dlp..." - yt-dlp -o "%(title)s.%(ext)s" "$VIDEO_URL" -fi - -# ==== TRANSFER IF FILES EXIST ==== -if compgen -G "$TEMP_DIR/*" > /dev/null; then - echo "[INFO] Transferring files to NAS..." - scp -r "$TEMP_DIR"/* "$NAS_USER@$NAS_HOST:$NAS_PATH" -else - echo "[WARN] No files found to transfer." -fi - - -# Cleanup -echo "[INFO] Cleaning up..." -rm -rf "$TEMP_DIR"/*% \ No newline at end of file -- 2.49.1 From 26824c458d029dbe1b982b9ba3f51aae634c8b7f Mon Sep 17 00:00:00 2001 From: John Rogers Date: Sun, 17 Aug 2025 14:02:38 +0100 Subject: [PATCH 3/8] added --- .gitignore | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4d97691 --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +.aider* +# Generated by Cargo +# will have compiled files and executables +debug +target +# These are backup files generated by rustfmt +**/*.rs.bk +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb +# Generated by cargo mutants +# Contains mutation testing data +**/mutants.out*/ +# RustRover +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ -- 2.49.1 From 8d58e508472ac66538476695a4763dd0693b2ab8 Mon Sep 17 00:00:00 2001 From: John Rogers Date: Sun, 17 Aug 2025 14:03:12 +0100 Subject: [PATCH 4/8] feat: use local copy when NAS_HOST is localhost Co-authored-by: aider (gemini/gemini-2.5-pro-preview-05-06) --- Cargo.toml | 1 + src/main.rs | 30 +++++++++++++++++++----------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index be5b04c..ad29e98 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,5 @@ edition = "2021" [dependencies] anyhow = "1.0.82" clap = { version = "4.5.4", features = ["derive"] } +fs_extra = "1.3.0" tempfile = "3.10.1" diff --git a/src/main.rs b/src/main.rs index e4f408b..c636a54 100644 --- a/src/main.rs +++ b/src/main.rs @@ -79,18 +79,26 @@ fn transfer_files(source_path: &Path) -> Result<()> { let is_empty = fs::read_dir(source_path)?.next().is_none(); if !is_empty { - println!("[INFO] Transferring files to NAS..."); - let mut scp_cmd = Command::new("scp"); - let source = format!( - "{}/.", - source_path.to_str().context("Invalid source path")? - ); - let destination = format!("{}@{}:{}", NAS_USER, NAS_HOST, NAS_PATH); - scp_cmd.args(["-r", &source, &destination]); + if NAS_HOST == "localhost" { + println!("[INFO] NAS_HOST is localhost, copying files locally..."); + let mut options = fs_extra::dir::CopyOptions::new(); + options.content_only = true; + fs_extra::dir::copy(source_path, NAS_PATH, &options) + .context("Failed to copy files locally")?; + } else { + println!("[INFO] Transferring files to NAS via scp..."); + let mut scp_cmd = Command::new("scp"); + let source = format!( + "{}/.", + source_path.to_str().context("Invalid source path")? + ); + let destination = format!("{}@{}:{}", NAS_USER, NAS_HOST, NAS_PATH); + scp_cmd.args(["-r", &source, &destination]); - let status = scp_cmd.status().context("Failed to execute scp")?; - if !status.success() { - anyhow::bail!("scp failed with status: {}", status); + let status = scp_cmd.status().context("Failed to execute scp")?; + if !status.success() { + anyhow::bail!("scp failed with status: {}", status); + } } } else { println!("[WARN] No files found to transfer."); -- 2.49.1 From c740e0df0e83d45a881cc07d97bb98c7423a589a Mon Sep 17 00:00:00 2001 From: John Rogers Date: Sun, 17 Aug 2025 14:16:24 +0100 Subject: [PATCH 5/8] feat: load settings from a configuration file Co-authored-by: aider (gemini/gemini-2.5-pro-preview-05-06) --- Cargo.toml | 3 +++ src/main.rs | 54 +++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ad29e98..2be4c81 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,5 +8,8 @@ edition = "2021" [dependencies] anyhow = "1.0.82" clap = { version = "4.5.4", features = ["derive"] } +config = "0.14.0" +dirs = "5.0.1" fs_extra = "1.3.0" +serde = { version = "1.0", features = ["derive"] } tempfile = "3.10.1" diff --git a/src/main.rs b/src/main.rs index c636a54..b37a47f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,15 +1,18 @@ use anyhow::{Context, Result}; use clap::Parser; +use serde::Deserialize; use std::fs; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::process::Command; use tempfile::TempDir; -// ==== CONFIGURATION ==== -const NAS_HOST: &str = "(localaddress)"; -const NAS_USER: &str = "ssh_user"; -const NAS_PATH: &str = "/path/to/files/on/nas"; -const COOKIES_FILE: &str = "/location/of/apple-music-cookies-file.txt"; +#[derive(Debug, Deserialize)] +struct Settings { + nas_host: String, + nas_user: String, + nas_path: String, + cookies_file: String, +} #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] @@ -22,6 +25,22 @@ struct Args { fn main() -> Result<()> { let args = Args::parse(); + let config_path = dirs::config_dir() + .context("Could not find config directory")? + .join("jamdl/config.toml"); + + if !config_path.exists() { + anyhow::bail!( + "Config file not found. Please create it at: {}", + config_path.display() + ); + } + + let settings = config::Config::builder() + .add_source(config::File::from(config_path)) + .build()? + .try_deserialize::()?; + // Create temp directory let temp_dir = TempDir::new().context("Failed to create temporary directory")?; let temp_path = temp_dir.path(); @@ -30,26 +49,26 @@ fn main() -> Result<()> { temp_path.display() ); - download_media(&args.url, temp_path)?; - transfer_files(temp_path)?; + download_media(&args.url, temp_path, &settings)?; + transfer_files(temp_path, &settings)?; // Cleanup is handled by TempDir's Drop trait println!("[INFO] Cleaning up..."); Ok(()) } -fn download_media(video_url: &str, download_path: &Path) -> Result<()> { +fn download_media(video_url: &str, download_path: &Path, settings: &Settings) -> Result<()> { let mut cmd: Command; if video_url.contains("music.apple.com") { println!("[INFO] Apple Music link detected. Using gamdl..."); cmd = Command::new("gamdl"); - if Path::new(COOKIES_FILE).exists() { - cmd.args(["--cookies-path", COOKIES_FILE, video_url]); + if Path::new(&settings.cookies_file).exists() { + cmd.args(["--cookies-path", &settings.cookies_file, video_url]); } else { println!( "[WARN] cookies.txt not found at {} — running gamdl without it", - COOKIES_FILE + settings.cookies_file ); cmd.arg(video_url); } @@ -75,15 +94,15 @@ fn download_media(video_url: &str, download_path: &Path) -> Result<()> { Ok(()) } -fn transfer_files(source_path: &Path) -> Result<()> { +fn transfer_files(source_path: &Path, settings: &Settings) -> Result<()> { let is_empty = fs::read_dir(source_path)?.next().is_none(); if !is_empty { - if NAS_HOST == "localhost" { + if settings.nas_host == "localhost" { println!("[INFO] NAS_HOST is localhost, copying files locally..."); let mut options = fs_extra::dir::CopyOptions::new(); options.content_only = true; - fs_extra::dir::copy(source_path, NAS_PATH, &options) + fs_extra::dir::copy(source_path, &settings.nas_path, &options) .context("Failed to copy files locally")?; } else { println!("[INFO] Transferring files to NAS via scp..."); @@ -92,7 +111,10 @@ fn transfer_files(source_path: &Path) -> Result<()> { "{}/.", source_path.to_str().context("Invalid source path")? ); - let destination = format!("{}@{}:{}", NAS_USER, NAS_HOST, NAS_PATH); + let destination = format!( + "{}@{}:{}", + settings.nas_user, settings.nas_host, settings.nas_path + ); scp_cmd.args(["-r", &source, &destination]); let status = scp_cmd.status().context("Failed to execute scp")?; -- 2.49.1 From d2f03406266024b6ef02085eb32301263ab14f2a Mon Sep 17 00:00:00 2001 From: John Rogers Date: Sun, 17 Aug 2025 14:25:35 +0100 Subject: [PATCH 6/8] feat: create default config on first run Co-authored-by: aider (gemini/gemini-2.5-pro-preview-05-06) --- config.toml | 7 +++++++ src/main.rs | 19 ++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 config.toml diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..4ce1ced --- /dev/null +++ b/config.toml @@ -0,0 +1,7 @@ +# Default configuration for jamdl +# Please edit these values to match your setup. + +nas_host = "localhost" +nas_user = "your_ssh_user" +nas_path = "/path/on/nas" +cookies_file = "/path/to/your/apple-music-cookies-file.txt" diff --git a/src/main.rs b/src/main.rs index b37a47f..7c89e2d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ use anyhow::{Context, Result}; use clap::Parser; use serde::Deserialize; use std::fs; -use std::path::{Path, PathBuf}; +use std::path::Path; use std::process::Command; use tempfile::TempDir; @@ -25,15 +25,24 @@ struct Args { fn main() -> Result<()> { let args = Args::parse(); - let config_path = dirs::config_dir() + let config_dir = dirs::config_dir() .context("Could not find config directory")? - .join("jamdl/config.toml"); + .join("jamdl"); + let config_path = config_dir.join("config.toml"); if !config_path.exists() { - anyhow::bail!( - "Config file not found. Please create it at: {}", + println!("[INFO] No config file found, creating a default one..."); + fs::create_dir_all(&config_dir).context("Failed to create config directory")?; + + let default_config = include_str!("../config.toml"); + fs::write(&config_path, default_config).context("Failed to write default config file")?; + + println!( + "[INFO] A default config file was created at: {}", config_path.display() ); + println!("[INFO] Please edit this file with your settings and re-run the command."); + return Ok(()); } let settings = config::Config::builder() -- 2.49.1 From 53870e5a4301de6e21fe4bedbb1d38638817ffc8 Mon Sep 17 00:00:00 2001 From: John Rogers Date: Sun, 17 Aug 2025 14:26:12 +0100 Subject: [PATCH 7/8] cargo lock --- Cargo.lock | 1119 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1119 insertions(+) create mode 100644 Cargo.lock diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..1e8f4a8 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1119 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "anstream" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +dependencies = [ + "windows-sys 0.60.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.60.2", +] + +[[package]] +name = "anyhow" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" + +[[package]] +name = "arraydeque" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bitflags" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29" +dependencies = [ + "serde", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "clap" +version = "4.5.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "config" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68578f196d2a33ff61b27fae256c3164f65e36382648e30666dde05b8cc9dfdf" +dependencies = [ + "async-trait", + "convert_case", + "json5", + "nom", + "pathdiff", + "ron", + "rust-ini", + "serde", + "serde_json", + "toml", + "yaml-rust2", +] + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom 0.2.16", + "once_cell", + "tiny-keccak", +] + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "dlv-list" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" +dependencies = [ + "const-random", +] + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" + +[[package]] +name = "hashlink" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" +dependencies = [ + "hashbrown 0.14.5", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "indexmap" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +dependencies = [ + "equivalent", + "hashbrown 0.15.5", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jamdl" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "config", + "dirs", + "fs_extra", + "serde", + "tempfile", +] + +[[package]] +name = "json5" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" +dependencies = [ + "pest", + "pest_derive", + "serde", +] + +[[package]] +name = "libc" +version = "0.2.175" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" + +[[package]] +name = "libredox" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" +dependencies = [ + "bitflags", + "libc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "ordered-multimap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" +dependencies = [ + "dlv-list", + "hashbrown 0.14.5", +] + +[[package]] +name = "pathdiff" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" + +[[package]] +name = "pest" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323" +dependencies = [ + "memchr", + "thiserror 2.0.15", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb056d9e8ea77922845ec74a1c4e8fb17e7c218cc4fc11a15c5d25e189aa40bc" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e404e638f781eb3202dc82db6760c8ae8a1eeef7fb3fa8264b2ef280504966" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pest_meta" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd1101f170f5903fde0914f899bb503d9ff5271d7ba76bbb70bea63690cc0d5" +dependencies = [ + "pest", + "sha2", +] + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.16", + "libredox", + "thiserror 1.0.69", +] + +[[package]] +name = "ron" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +dependencies = [ + "base64", + "bitflags", + "serde", + "serde_derive", +] + +[[package]] +name = "rust-ini" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0698206bcb8882bf2a9ecb4c1e7785db57ff052297085a6efd4fe42302068a" +dependencies = [ + "cfg-if", + "ordered-multimap", +] + +[[package]] +name = "rustix" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.60.2", +] + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.142" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +dependencies = [ + "fastrand", + "getrandom 0.3.3", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d76d3f064b981389ecb4b6b7f45a0bf9fdac1d5b9204c7bd6714fecc302850" +dependencies = [ + "thiserror-impl 2.0.15", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d29feb33e986b6ea906bd9c3559a856983f92371b3eaa5e83782a351623de0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "toml_write", + "winnow", +] + +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + +[[package]] +name = "typenum" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" + +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.3", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "winnow" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + +[[package]] +name = "yaml-rust2" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8902160c4e6f2fb145dbe9d6760a75e3c9522d8bf796ed7047c85919ac7115f8" +dependencies = [ + "arraydeque", + "encoding_rs", + "hashlink", +] + +[[package]] +name = "zerocopy" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] -- 2.49.1 From bd767eb8bec39fd18713eb426c4f474096cad9e7 Mon Sep 17 00:00:00 2001 From: John Rogers Date: Sun, 17 Aug 2025 14:54:33 +0100 Subject: [PATCH 8/8] docs: update README for Rust application Co-authored-by: aider (gemini/gemini-2.5-pro-preview-05-06) --- README.md | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ccc0351..e54b700 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,62 @@ # jamdl -A shell script to download music using SCDL for soudcloud and gamdl for apple music \ No newline at end of file +A command-line tool to download music from various sources like Apple Music, SoundCloud, and others supported by yt-dlp. + +## Description + +`jamdl` is a wrapper around popular downloaders (`gamdl`, `scdl`, `yt-dlp`) that automates the process of downloading media and transferring it to a specified location, such as a local directory or a remote NAS via SCP. + +## Prerequisites + +You must have the following command-line tools installed and available in your system's `PATH`: +- `gamdl` (for Apple Music) +- `scdl` (for SoundCloud) +- `yt-dlp` (for other sources) + +## Installation + +You can install `jamdl` using `cargo`: + +### From source + +Clone this repository and install using cargo: +```bash +cargo install --path . +``` + +### From a git repository + +You can also install it directly from a git repository: +```bash +cargo install --git +``` + +## Configuration + +The first time you run `jamdl`, it will create a default configuration file at `~/.config/jamdl/config.toml`. + +You **must** edit this file to match your setup before you can use `jamdl`. + +The configuration file looks like this: +```toml +# Default configuration for jamdl +# Please edit these values to match your setup. + +nas_host = "localhost" +nas_user = "your_ssh_user" +nas_path = "/path/on/nas" +cookies_file = "/path/to/your/apple-music-cookies-file.txt" +``` + +- `nas_host`: The hostname or IP address of your NAS. If set to `"localhost"`, files will be copied locally instead of using SCP. +- `nas_user`: The SSH username for your NAS. +- `nas_path`: The destination path on your NAS or local filesystem. +- `cookies_file`: The path to your Apple Music cookies file for `gamdl`. + +## Usage + +Once configured, you can download media by passing a URL to `jamdl`: + +```bash +jamdl "https://music.apple.com/us/album/some-album/123456789" +``` -- 2.49.1