diff --git a/asklyphe-frontend/src/routes/search.rs b/asklyphe-frontend/src/routes/search.rs index 0c90393..51c4608 100644 --- a/asklyphe-frontend/src/routes/search.rs +++ b/asklyphe-frontend/src/routes/search.rs @@ -48,7 +48,8 @@ pub struct SearchResult { pub title: Option, pub description: Option, pub url: String, - pub percentage: String, + pub percentage: f64, + pub percentage_str: String, pub value: String, pub asklyphe: bool, pub bing: bool, @@ -255,7 +256,7 @@ pub async fn search_nojs( } if let Some(token) = jar.get("token") { let token = token.value().to_string(); - let info = match authenticate_user(nats.clone(), token).await { + let info = match authenticate_user(nats.clone(), token.clone()).await { Ok(i) => i, Err(e) => { return ( @@ -300,7 +301,7 @@ pub async fn search_nojs( engines.retain(|v| v != "asklyphe"); } - gather_search_results(nats, query.as_str(), info, complications, Some(engines)) + gather_search_results(nats, query.as_str(), token, info, complications, Some(engines)) .await .into_response() } else { @@ -351,7 +352,7 @@ pub async fn search_json( } if let Some(token) = jar.get("token") { let token = token.value().to_string(); - let info = match authenticate_user(nats.clone(), token).await { + let info = match authenticate_user(nats.clone(), token.clone()).await { Ok(i) => i, Err(e) => { return error_response("not authenticated"); @@ -374,6 +375,7 @@ pub async fn search_json( let result = gather_search_results( nats, query.as_str(), + token, info, Complications::default(), Some(engines), diff --git a/asklyphe-frontend/src/searchbot.rs b/asklyphe-frontend/src/searchbot.rs index ca43ef9..1f7ed81 100644 --- a/asklyphe-frontend/src/searchbot.rs +++ b/asklyphe-frontend/src/searchbot.rs @@ -27,6 +27,8 @@ use tokio::sync::Mutex; use tracing::log::error; use tracing::warn; use ulid::Ulid; +use asklyphe_common::nats::authservice::{AuthServiceQuery, AuthServiceRequest, AuthServiceResponse}; +use asklyphe_common::nats::authservice::deranklist::{DerankEntry, UserFetchActiveDeranksRequest, UserFetchActiveDeranksResponse}; use crate::routes::search::{Complications, ImageSearchResult, ImageSearchTemplate, SearchResult, SearchTemplate}; use crate::routes::UserInfo; use crate::{BUILT_ON, GIT_COMMIT, ALPHA, VERSION, WEBSITE_COUNT, YEAR}; @@ -52,7 +54,38 @@ pub async fn update_website_counter(nats: Arc) { } } -pub async fn gather_search_results(nats: Arc, query: &str, user_info: UserInfo, complications: Complications, engines: Option>) -> SearchTemplate { +async fn user_active_deranks(nats: Arc, token: String) -> Vec { + let result = comms::query_service(comms::Query::AuthService(AuthServiceQuery { + request: AuthServiceRequest::UserFetchActiveDeranksRequest(UserFetchActiveDeranksRequest { + token, + }), + replyto: "".to_string(), + }), nats.deref(), false).await; + + if let Ok(comms::ServiceResponse::AuthService(result)) = result { + match result { + AuthServiceResponse::UserFetchActiveDeranksResponse(v) => match v { + UserFetchActiveDeranksResponse::Success(v) => v, + UserFetchActiveDeranksResponse::InternalServerError => { + warn!("received error while asking for user active deranks (internal server error)"); + vec![] + } + UserFetchActiveDeranksResponse::Logout => { + vec![] + } + } + _ => { + warn!("received invalid response while asking for derank list"); + vec![] + } + } + } else { + error!("{:?}", result.err().unwrap()); + vec![] + } +} + +pub async fn gather_search_results(nats: Arc, query: &str, token: String, user_info: UserInfo, complications: Complications, engines: Option>) -> SearchTemplate { let mut search_results = vec![]; let mut note = None; @@ -119,7 +152,8 @@ pub async fn gather_search_results(nats: Arc, query: &str, u } shortened }), - percentage: format!("{:.2}", ((1.0 - (i as f64 / result_count as f64)) * 50.0) + 40.0), + percentage: ((1.0 - (i as f64 / result_count as f64)) * 50.0) + 40.0, + percentage_str: "".to_string(), value: format!("{}", i), asklyphe: false, bing: true, @@ -194,7 +228,8 @@ pub async fn gather_search_results(nats: Arc, query: &str, u } shortened }), - percentage: format!("{:.2}", ((1.0 - (i as f64 / result_count as f64)) * 50.0) + 40.0), + percentage: ((1.0 - (i as f64 / result_count as f64)) * 50.0) + 40.0, + percentage_str: "".to_string(), value: format!("{}", i), asklyphe: false, bing: false, @@ -286,7 +321,8 @@ pub async fn gather_search_results(nats: Arc, query: &str, u shortened }), url: v.url, - percentage: format!("{:.2}", (v.relevance / results.max_relevance) * 100.0), + percentage: (v.relevance / results.max_relevance) * 100.0, + percentage_str: "".to_string(), value: format!("{:.2}", v.relevance), asklyphe: true, bing: false, @@ -303,10 +339,37 @@ pub async fn gather_search_results(nats: Arc, query: &str, u } } + // apply deranks + let deranks = user_active_deranks(nats.clone(), token).await; + for result in &mut search_results { + for derank in &deranks { + if result.url.contains(&derank.urlmatch) { + // continue if contains unless, or doesn't contain and + if let Some(unless) = &derank.unless { + if result.url.contains(unless) { + continue; + } + } + if let Some(and) = &derank.and { + if !result.url.contains(and) { + continue; + } + } + + // multiply + result.percentage *= derank.multiplier; + } + } + } + search_results.sort_by(|a, b| { - b.percentage.parse::().unwrap().total_cmp(&a.percentage.parse::().unwrap()) + b.percentage.total_cmp(&a.percentage) }); + for result in &mut search_results { + result.percentage_str = format!("{:.2}", result.percentage); + } + let mut already_included = BTreeMap::new(); let mut remove = vec![]; @@ -341,6 +404,7 @@ pub async fn gather_search_results(nats: Arc, query: &str, u search_results.remove(rm - i); } + let theme = user_info.theme.clone(); let querystr = url_encoded_data::stringify(&[("q", query)]); SearchTemplate { diff --git a/asklyphe-frontend/static/js/search.js b/asklyphe-frontend/static/js/search.js index a756bb6..7d3b82c 100644 --- a/asklyphe-frontend/static/js/search.js +++ b/asklyphe-frontend/static/js/search.js @@ -110,7 +110,7 @@ function process(result) { } const relevance = document.createElement("span"); relevance.classList.add("search-relevance"); - relevance.innerText = `(${result_obj.percentage}%, ${result_obj.value} / ${search_results.max_relevance})`; + relevance.innerText = `(${result_obj.percentage_str}%, ${result_obj.value} / ${search_results.max_relevance})`; const enginelist = document.createElement("span"); enginelist.classList.add("enginelist"); if (result_obj.hasOwnProperty("asklyphe")) { diff --git a/asklyphe-frontend/templates/ui/search_result.html b/asklyphe-frontend/templates/ui/search_result.html index 772e511..37a4334 100644 --- a/asklyphe-frontend/templates/ui/search_result.html +++ b/asklyphe-frontend/templates/ui/search_result.html @@ -5,7 +5,7 @@ {% match result.title %} {% when Some with (_) %}{{ result.url }}{% when None %} {% endmatch %} - ({{ result.percentage }}%, {{ result.value }} / {{ max_relevance }}) + ({{ result.percentage_str }}%, {{ result.value }} / {{ max_relevance }}) {% if result.asklyphe %}