89 řádky
1.8 KiB
Rust
89 řádky
1.8 KiB
Rust
use actix_web::{
|
|
get,
|
|
web::{Data, Query},
|
|
HttpRequest, HttpResponse,
|
|
};
|
|
use askama::Template;
|
|
use serde::Deserialize;
|
|
use std::collections::HashMap;
|
|
|
|
use super::tcx::TemplateCtx;
|
|
use crate::{
|
|
ctx::Ctx,
|
|
db::models::{Board, Post},
|
|
error::NekrochanError,
|
|
filters, web::template_response,
|
|
};
|
|
|
|
#[derive(Template)]
|
|
#[template(path = "search.html")]
|
|
struct SearchTemplate {
|
|
tcx: TemplateCtx,
|
|
board_opt: Option<Board>,
|
|
boards: HashMap<String, Board>,
|
|
query: String,
|
|
posts: Vec<Post>,
|
|
page: i64,
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
pub struct SearchQuery {
|
|
board: Option<String>,
|
|
query: String,
|
|
page: Option<i64>,
|
|
}
|
|
|
|
#[get("/search")]
|
|
pub async fn search(
|
|
ctx: Data<Ctx>,
|
|
req: HttpRequest,
|
|
Query(query): Query<SearchQuery>,
|
|
) -> Result<HttpResponse, NekrochanError> {
|
|
let tcx = TemplateCtx::new(&ctx, &req).await?;
|
|
|
|
let board_opt = if let Some(board) = query.board {
|
|
let board = Board::read(&ctx, board.clone())
|
|
.await?
|
|
.ok_or(NekrochanError::BoardNotFound(board))?;
|
|
|
|
Some(board)
|
|
} else {
|
|
None
|
|
};
|
|
|
|
let boards = if board_opt.is_none() {
|
|
Board::read_all_map(&ctx).await?
|
|
} else {
|
|
HashMap::new()
|
|
};
|
|
|
|
let page = query.page.unwrap_or(1);
|
|
|
|
if page <= 0 {
|
|
return Err(NekrochanError::InvalidPageError);
|
|
}
|
|
|
|
let query = query.query;
|
|
|
|
if query.is_empty() || query.len() > 256 {
|
|
return Err(NekrochanError::QueryFormatError);
|
|
}
|
|
|
|
let posts = if let Some(board) = &board_opt {
|
|
Post::read_by_query(&ctx, board, query.clone(), page).await?
|
|
} else {
|
|
Post::read_by_query_overboard(&ctx, query.clone(), page).await?
|
|
};
|
|
|
|
let template = SearchTemplate {
|
|
tcx,
|
|
board_opt,
|
|
boards,
|
|
query,
|
|
posts,
|
|
page,
|
|
};
|
|
|
|
template_response(&template)
|
|
}
|