95 lines
2.6 KiB
Rust
95 lines
2.6 KiB
Rust
use crate::config::WebConfig;
|
|
use crate::web::IndexAccess;
|
|
use crate::webutil::{internal_error, TemplatedHtml};
|
|
use askama::Template;
|
|
use axum::extract::{Extension, Query};
|
|
use axum::response::IntoResponse;
|
|
use quickpeep_index::auxiliary::icon_store::IconStore;
|
|
use serde::Deserialize;
|
|
use std::sync::Arc;
|
|
|
|
#[derive(Clone, Template)]
|
|
#[template(path = "search.html.askama")]
|
|
pub struct SearchTemplate {
|
|
pub search_term: String,
|
|
pub results: Vec<SearchResult>,
|
|
pub contact: Vec<(String, String)>,
|
|
pub show_spiel: bool,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct SearchResult {
|
|
pub favicon_url: Option<String>,
|
|
pub url: String,
|
|
pub title: String,
|
|
pub excerpt: String,
|
|
pub tags: Vec<String>,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct ExcerptFragment {
|
|
pub text: String,
|
|
pub mark: bool,
|
|
}
|
|
|
|
pub async fn search_root(Extension(web_config): Extension<WebConfig>) -> impl IntoResponse {
|
|
TemplatedHtml(SearchTemplate {
|
|
search_term: String::with_capacity(0),
|
|
results: vec![],
|
|
contact: web_config.web.contact.clone(),
|
|
show_spiel: true,
|
|
})
|
|
}
|
|
|
|
#[derive(Deserialize, Debug, Clone)]
|
|
pub struct QueryParameters {
|
|
/// The search query
|
|
q: String,
|
|
}
|
|
|
|
pub async fn search_search(
|
|
web_config: Extension<WebConfig>,
|
|
index_access: Extension<IndexAccess>,
|
|
params: Query<QueryParameters>,
|
|
icon_store: Extension<Arc<IconStore>>,
|
|
) -> impl IntoResponse {
|
|
search_search_inner(web_config, index_access, params, icon_store)
|
|
.await
|
|
.map_err(internal_error)
|
|
}
|
|
|
|
pub async fn search_search_inner(
|
|
Extension(web_config): Extension<WebConfig>,
|
|
Extension(index_access): Extension<IndexAccess>,
|
|
Query(params): Query<QueryParameters>,
|
|
Extension(icon_store): Extension<Arc<IconStore>>,
|
|
) -> anyhow::Result<impl IntoResponse> {
|
|
let raw_results = index_access.backend.query(params.q.clone())?;
|
|
|
|
let mut results = Vec::with_capacity(raw_results.len());
|
|
|
|
let txn = icon_store.env.ro_txn()?;
|
|
|
|
for search_doc in raw_results {
|
|
let favicon_url_hash: [u8; 8] = search_doc.favicon_url_hash.to_le_bytes();
|
|
let favicon_url = icon_store
|
|
.icons
|
|
.get(&txn, &favicon_url_hash)?
|
|
.map(|_| format!("{:016x}", search_doc.favicon_url_hash));
|
|
results.push(SearchResult {
|
|
favicon_url,
|
|
url: search_doc.url,
|
|
title: search_doc.title,
|
|
excerpt: search_doc.excerpt,
|
|
tags: search_doc.tags,
|
|
});
|
|
}
|
|
|
|
Ok(TemplatedHtml(SearchTemplate {
|
|
search_term: params.q.clone(),
|
|
results,
|
|
contact: web_config.web.contact.clone(),
|
|
show_spiel: false,
|
|
}))
|
|
}
|