Files
music-agregator/src/api/indexer_controller.rs
T
Alexander 1aaaab4640 feat: add indexer and torrent REST controllers with service layer
- Add config module for yaml config (database, indexers, torrent)
- Add indexer module with Torznab protocol support
- Add IndexerService and TorrentService for business logic
- Add REST controllers for indexer search and torrent management
- Add Docker Compose for PostgreSQL and Jackett
- Add ERD documentation for database schema
2026-04-28 18:53:50 +02:00

93 lines
2.4 KiB
Rust

use axum::{
extract::{Path, State},
http::StatusCode,
routing::{get, post},
Json, Router,
};
use serde::{Deserialize, Serialize};
use crate::indexer::{MusicSearchCriteria, SearchResult};
use crate::services::IndexerInfo;
use crate::AppState;
pub fn routes() -> Router<AppState> {
Router::new()
.route("/", get(list_indexers))
.route("/search", post(search))
.route("/:name/test", get(test_indexer))
}
async fn list_indexers(State(state): State<AppState>) -> Json<Vec<IndexerInfo>> {
let state = state.read().await;
Json(state.indexer_service.list_indexers())
}
#[derive(Debug, Deserialize)]
pub struct SearchRequest {
pub artist: String,
pub album: Option<String>,
pub year: Option<u32>,
pub limit: Option<u32>,
pub indexer: Option<String>,
}
#[derive(Debug, Serialize)]
pub struct SearchResponse {
pub results: Vec<SearchResult>,
pub total: usize,
}
async fn search(
State(state): State<AppState>,
Json(req): Json<SearchRequest>,
) -> Result<Json<SearchResponse>, (StatusCode, String)> {
let mut criteria = MusicSearchCriteria::new(&req.artist);
if let Some(album) = &req.album {
criteria = criteria.with_album(album);
}
if let Some(year) = req.year {
criteria = criteria.with_year(year);
}
if let Some(limit) = req.limit {
criteria = criteria.with_limit(limit);
}
let state = state.read().await;
let results = state
.indexer_service
.search(&criteria, req.indexer.as_deref())
.await
.map_err(|e| (StatusCode::BAD_GATEWAY, e.to_string()))?;
let total = results.len();
Ok(Json(SearchResponse { results, total }))
}
#[derive(Debug, Serialize)]
pub struct TestResponse {
pub success: bool,
pub message: String,
}
async fn test_indexer(
State(state): State<AppState>,
Path(name): Path<String>,
) -> Result<Json<TestResponse>, (StatusCode, Json<TestResponse>)> {
let state = state.read().await;
match state.indexer_service.test_indexer(&name).await {
Ok(()) => Ok(Json(TestResponse {
success: true,
message: "Connection successful".to_string(),
})),
Err(e) => Err((
StatusCode::BAD_GATEWAY,
Json(TestResponse {
success: false,
message: e.to_string(),
}),
)),
}
}