99 lines
2.6 KiB
Rust
99 lines
2.6 KiB
Rust
use std::path::PathBuf;
|
|
|
|
use clap::Parser;
|
|
use tracing_subscriber::EnvFilter;
|
|
|
|
use shanty_db::Database;
|
|
use shanty_tag::{MusicBrainzClient, TagConfig, run_tagging};
|
|
|
|
#[derive(Parser)]
|
|
#[command(
|
|
name = "shanty-tag",
|
|
about = "Fill in missing metadata on music files via MusicBrainz"
|
|
)]
|
|
struct Cli {
|
|
/// Database URL. Defaults to sqlite://<XDG_DATA_HOME>/shanty/shanty.db?mode=rwc
|
|
#[arg(long, env = "SHANTY_DATABASE_URL")]
|
|
database: Option<String>,
|
|
|
|
/// Tag all untagged tracks in the database.
|
|
#[arg(long)]
|
|
all: bool,
|
|
|
|
/// Tag a specific track by its database ID.
|
|
#[arg(long)]
|
|
track: Option<i32>,
|
|
|
|
/// Preview matches without writing to DB or files.
|
|
#[arg(long)]
|
|
dry_run: bool,
|
|
|
|
/// Write updated tags back to music files.
|
|
#[arg(long)]
|
|
write_tags: bool,
|
|
|
|
/// Minimum match confidence (0.0 - 1.0).
|
|
#[arg(long, default_value = "0.8")]
|
|
confidence: f64,
|
|
|
|
/// Increase verbosity (-v info, -vv debug, -vvv trace).
|
|
#[arg(short, long, action = clap::ArgAction::Count)]
|
|
verbose: u8,
|
|
}
|
|
|
|
fn default_database_url() -> String {
|
|
let data_dir = dirs::data_dir()
|
|
.unwrap_or_else(|| PathBuf::from("."))
|
|
.join("shanty");
|
|
std::fs::create_dir_all(&data_dir).ok();
|
|
let db_path = data_dir.join("shanty.db");
|
|
format!("sqlite://{}?mode=rwc", db_path.display())
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() -> anyhow::Result<()> {
|
|
let cli = Cli::parse();
|
|
|
|
// Set up tracing
|
|
let filter = match cli.verbose {
|
|
0 => "warn",
|
|
1 => "info,shanty_tag=info",
|
|
2 => "info,shanty_tag=debug",
|
|
_ => "debug,shanty_tag=trace",
|
|
};
|
|
tracing_subscriber::fmt()
|
|
.with_env_filter(
|
|
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(filter)),
|
|
)
|
|
.init();
|
|
|
|
// Validate args
|
|
if !cli.all && cli.track.is_none() {
|
|
anyhow::bail!("specify either --all or --track <id>");
|
|
}
|
|
|
|
// Connect to database
|
|
let database_url = cli.database.unwrap_or_else(default_database_url);
|
|
tracing::info!(url = %database_url, "connecting to database");
|
|
let db = Database::new(&database_url).await?;
|
|
|
|
// Create MusicBrainz client
|
|
let provider = MusicBrainzClient::new()?;
|
|
|
|
// Run tagging
|
|
let config = TagConfig {
|
|
dry_run: cli.dry_run,
|
|
write_tags: cli.write_tags,
|
|
confidence: cli.confidence,
|
|
};
|
|
|
|
if config.dry_run {
|
|
println!("DRY RUN — no changes will be written");
|
|
}
|
|
|
|
let stats = run_tagging(db.conn(), &provider, &config, cli.track).await?;
|
|
println!("\nTagging complete: {stats}");
|
|
|
|
Ok(())
|
|
}
|