nekrochan/src/web/search.rs

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)
}