Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I9f113e6402030c46ad97f636985b5d6c6a6a6964
102 lines
2.5 KiB
Rust
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(¶ms.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,
|
|
}))
|
|
}
|