3aaeade4d3
- Add DownloadService to orchestrate metadata → indexer → torrent flow - Add POST /api/sync/artist endpoint for syncing artist albums - Add StubTorrentClient for testing (logs requests to file) - Refactor TorrentConfig to tagged enum (client_type: qbittorrent|stub|none) - Add POST /api/reload endpoint for hot config reload - Add chrono dependency for timestamps
117 lines
3.5 KiB
Rust
117 lines
3.5 KiB
Rust
use std::sync::Arc;
|
|
use tokio::sync::RwLock;
|
|
|
|
use axum::Router;
|
|
use clap::Parser;
|
|
use music_agregator::{
|
|
api, config,
|
|
services::{IndexerService, MetadataService, TorrentService},
|
|
AppServices, AppState,
|
|
};
|
|
use tower_http::cors::{Any, CorsLayer};
|
|
use tower_http::trace::TraceLayer;
|
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
|
|
|
#[derive(Parser)]
|
|
#[command(name = "music-agregator")]
|
|
#[command(about = "Music aggregation service with torrent and metadata integration")]
|
|
struct Args {
|
|
#[arg(short, long, default_value = "config.yaml")]
|
|
config: String,
|
|
|
|
#[arg(short, long)]
|
|
port: Option<u16>,
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() {
|
|
tracing_subscriber::registry()
|
|
.with(tracing_subscriber::fmt::layer())
|
|
.with(tracing_subscriber::EnvFilter::from_default_env())
|
|
.init();
|
|
|
|
let args = Args::parse();
|
|
|
|
let config = match config::Config::load(&args.config) {
|
|
Ok(cfg) => {
|
|
tracing::info!("loaded config from {}", args.config);
|
|
cfg
|
|
}
|
|
Err(e) => {
|
|
tracing::error!("failed to load config: {}", e);
|
|
std::process::exit(1);
|
|
}
|
|
};
|
|
|
|
let indexer_service = match IndexerService::from_config(&config.indexers) {
|
|
Ok(svc) => {
|
|
tracing::info!("initialized {} indexer(s)", config.indexers.len());
|
|
svc
|
|
}
|
|
Err(e) => {
|
|
tracing::error!("failed to initialize indexer service: {}", e);
|
|
std::process::exit(1);
|
|
}
|
|
};
|
|
|
|
let torrent_service = match TorrentService::from_config(&config.torrent).await {
|
|
Ok(svc) => {
|
|
match &config.torrent {
|
|
config::TorrentConfig::QBittorrent { url, .. } => {
|
|
tracing::info!("connected to qBittorrent at {}", url);
|
|
}
|
|
config::TorrentConfig::Stub { log_path, .. } => {
|
|
tracing::info!("using stub torrent client, logging to {}", log_path);
|
|
}
|
|
config::TorrentConfig::None => {
|
|
tracing::info!("no torrent client configured");
|
|
}
|
|
}
|
|
svc
|
|
}
|
|
Err(e) => {
|
|
tracing::warn!("failed to init torrent client: {} (continuing without)", e);
|
|
TorrentService::new()
|
|
}
|
|
};
|
|
|
|
let mut metadata_service = MetadataService::new(&config.metadata.endpoint);
|
|
match metadata_service.connect().await {
|
|
Ok(()) => {
|
|
tracing::info!(
|
|
"connected to metadata service at {}",
|
|
config.metadata.endpoint
|
|
);
|
|
}
|
|
Err(e) => {
|
|
tracing::warn!(
|
|
"failed to connect to metadata service: {} (continuing without metadata)",
|
|
e
|
|
);
|
|
}
|
|
}
|
|
|
|
let state: AppState = Arc::new(RwLock::new(AppServices::new(
|
|
indexer_service,
|
|
torrent_service,
|
|
metadata_service,
|
|
args.config.clone(),
|
|
)));
|
|
|
|
let cors = CorsLayer::new()
|
|
.allow_origin(Any)
|
|
.allow_methods(Any)
|
|
.allow_headers(Any);
|
|
|
|
let app = Router::new()
|
|
.nest("/api", api::routes(state))
|
|
.layer(cors)
|
|
.layer(TraceLayer::new_for_http());
|
|
|
|
let port = args.port.unwrap_or(config.app.port);
|
|
let addr = format!("0.0.0.0:{}", port);
|
|
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
|
|
tracing::info!("listening on {}", listener.local_addr().unwrap());
|
|
axum::serve(listener, app).await.unwrap();
|
|
}
|