pinakes/crates/pinakes-server/src/routes/search.rs
NotAShelf 9c67c81a79
pinakes-server: relativize media paths against configured root directories
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I9f113e6402030c46ad97f636985b5d6c6a6a6964
2026-03-12 19:41:05 +03:00

102 lines
2.5 KiB
Rust

use axum::{
Json,
extract::{Query, State},
};
use pinakes_core::{
model::Pagination,
search::{SearchRequest, SortOrder, parse_search_query},
};
use crate::{
dto::{MediaResponse, SearchParams, SearchRequestBody, SearchResponse},
error::ApiError,
state::AppState,
};
fn resolve_sort(sort: Option<&str>) -> SortOrder {
match sort {
Some("date_asc") => SortOrder::DateAsc,
Some("date_desc") => SortOrder::DateDesc,
Some("name_asc") => SortOrder::NameAsc,
Some("name_desc") => SortOrder::NameDesc,
Some("size_asc") => SortOrder::SizeAsc,
Some("size_desc") => SortOrder::SizeDesc,
_ => SortOrder::Relevance,
}
}
pub async fn search(
State(state): State<AppState>,
Query(params): Query<SearchParams>,
) -> Result<Json<SearchResponse>, ApiError> {
if params.q.len() > 2048 {
return Err(ApiError(
pinakes_core::error::PinakesError::InvalidOperation(
"search query exceeds maximum length of 2048 characters".into(),
),
));
}
let query = parse_search_query(&params.q)?;
let sort = resolve_sort(params.sort.as_deref());
let request = SearchRequest {
query,
sort,
pagination: Pagination::new(
params.offset.unwrap_or(0),
params.limit.unwrap_or(50).min(1000),
None,
),
};
let results = state.storage.search(&request).await?;
let roots = state.config.read().await.directories.roots.clone();
Ok(Json(SearchResponse {
items: results
.items
.into_iter()
.map(|item| MediaResponse::new(item, &roots))
.collect(),
total_count: results.total_count,
}))
}
pub async fn search_post(
State(state): State<AppState>,
Json(body): Json<SearchRequestBody>,
) -> Result<Json<SearchResponse>, ApiError> {
if body.q.len() > 2048 {
return Err(ApiError(
pinakes_core::error::PinakesError::InvalidOperation(
"search query exceeds maximum length of 2048 characters".into(),
),
));
}
let query = parse_search_query(&body.q)?;
let sort = resolve_sort(body.sort.as_deref());
let request = SearchRequest {
query,
sort,
pagination: Pagination::new(
body.offset.unwrap_or(0),
body.limit.unwrap_or(50).min(1000),
None,
),
};
let results = state.storage.search(&request).await?;
let roots = state.config.read().await.directories.roots.clone();
Ok(Json(SearchResponse {
items: results
.items
.into_iter()
.map(|item| MediaResponse::new(item, &roots))
.collect(),
total_count: results.total_count,
}))
}