From 4413dec3d604933862e3c899d4f23debf3ae4239 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Aug 2024 09:19:26 +0000 Subject: [PATCH 1/9] :arrow_up: Bump scraper from 0.18.1 to 0.20.0 Bumps [scraper](https://github.com/causal-agent/scraper) from 0.18.1 to 0.20.0. - [Release notes](https://github.com/causal-agent/scraper/releases) - [Commits](https://github.com/causal-agent/scraper/compare/v0.18.1...v0.20.0) --- updated-dependencies: - dependency-name: scraper dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 32 +++++++++++++++++++++----------- Cargo.toml | 2 +- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e644185..8d203cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1188,16 +1188,16 @@ dependencies = [ [[package]] name = "html5ever" -version = "0.26.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" +checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" dependencies = [ "log", "mac", - "markup5ever 0.11.0", + "markup5ever 0.12.1", "proc-macro2 1.0.86", "quote 1.0.36", - "syn 1.0.109", + "syn 2.0.74", ] [[package]] @@ -1598,13 +1598,13 @@ dependencies = [ [[package]] name = "markup5ever" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" +checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" dependencies = [ "log", - "phf 0.10.1", - "phf_codegen 0.10.0", + "phf 0.11.2", + "phf_codegen 0.11.2", "string_cache 0.8.7", "string_cache_codegen 0.5.2", "tendril", @@ -1992,6 +1992,16 @@ dependencies = [ "phf_shared 0.10.0", ] +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", +] + [[package]] name = "phf_generator" version = "0.7.24" @@ -2667,14 +2677,14 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "scraper" -version = "0.18.1" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585480e3719b311b78a573db1c9d9c4c1f8010c2dee4cc59c2efe58ea4dbc3e1" +checksum = "b90460b31bfe1fc07be8262e42c665ad97118d4585869de9345a84d501a9eaf0" dependencies = [ "ahash", "cssparser", "ego-tree", - "html5ever 0.26.0", + "html5ever 0.27.0", "once_cell", "selectors", "tendril", diff --git a/Cargo.toml b/Cargo.toml index 27ddf91..3e42ee6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ serde_json = { version = "1.0.116", default-features = false } maud = { version = "0.26.0", default-features = false, features = [ "actix-web", ] } -scraper = { version = "0.18.1", default-features = false } +scraper = { version = "0.20.0", default-features = false } actix-web = { version = "4.4.0", features = [ "cookies", "macros", From 12d2e1d7971f238a8159aa25234080a13da0a581 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Aug 2024 09:19:39 +0000 Subject: [PATCH 2/9] :arrow_up: Bump serde_json from 1.0.124 to 1.0.125 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.124 to 1.0.125. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.124...1.0.125) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e644185..8533055 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2778,9 +2778,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.124" +version = "1.0.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d" +checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" dependencies = [ "itoa 1.0.11", "memchr", diff --git a/Cargo.toml b/Cargo.toml index 27ddf91..65110fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ tokio = { version = "1.32.0", features = [ "io-util", ], default-features = false } serde = { version = "1.0.196", default-features = false, features = ["derive"] } -serde_json = { version = "1.0.116", default-features = false } +serde_json = { version = "1.0.125", default-features = false } maud = { version = "0.26.0", default-features = false, features = [ "actix-web", ] } From 73fdd635cc2f556880f626cd0f8104a74aa6c12a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Aug 2024 09:19:48 +0000 Subject: [PATCH 3/9] :arrow_up: Bump error-stack from 0.4.1 to 0.5.0 Bumps [error-stack](https://github.com/hashintel/hash) from 0.4.1 to 0.5.0. - [Release notes](https://github.com/hashintel/hash/releases) - [Commits](https://github.com/hashintel/hash/compare/error-stack@0.4.1...error-stack@0.5.0) --- updated-dependencies: - dependency-name: error-stack dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e644185..4e2dd72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -865,9 +865,9 @@ dependencies = [ [[package]] name = "error-stack" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27a72baa257b5e0e2de241967bc5ee8f855d6072351042688621081d66b2a76b" +checksum = "fe413319145d1063f080f27556fd30b1d70b01e2ba10c2a6e40d4be982ffc5d1" dependencies = [ "anyhow", "rustc_version 0.4.0", diff --git a/Cargo.toml b/Cargo.toml index 27ddf91..0ab0cb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,7 +35,7 @@ actix-cors = { version = "0.7.0", default-features = false } fake-useragent = { version = "0.1.3", default-features = false } env_logger = { version = "0.11.1", default-features = false } log = { version = "0.4.21", default-features = false } -error-stack = { version = "0.4.0", default-features = false, features = [ +error-stack = { version = "0.5.0", default-features = false, features = [ "std", ] } async-trait = { version = "0.1.80", default-features = false } From e6663169952d9309dce1e5e2f7ddfbf4e9c9144c Mon Sep 17 00:00:00 2001 From: Milim Date: Thu, 15 Aug 2024 12:18:19 +0200 Subject: [PATCH 4/9] new Engines struct, breaks cookies and frontend --- src/config.rs | 14 ++------ src/engines/bing.rs | 11 +++--- src/engines/brave.rs | 11 +++--- src/engines/duckduckgo.rs | 11 +++--- src/engines/librex.rs | 11 +++--- src/engines/mod.rs | 69 +++++++++++++++++++++++++++++++++++++ src/engines/mojeek.rs | 11 +++--- src/engines/searx.rs | 11 +++--- src/engines/startpage.rs | 11 +++--- src/main.rs | 4 +-- src/models/engine_models.rs | 57 ++++++------------------------ src/models/server_models.rs | 28 --------------- src/server/routes/search.rs | 39 ++++----------------- 13 files changed, 134 insertions(+), 154 deletions(-) diff --git a/src/config.rs b/src/config.rs index d7cf3b1..7addc5c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -4,7 +4,7 @@ use figment::{providers::Serialized, Figment}; use serde::{Deserialize, Serialize}; /// Struct holding config Options -#[derive(Debug, Clone, Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize, Clone)] pub struct Config { /// It stores the parsed port number option on which the server should launch. pub port: u16, @@ -21,7 +21,7 @@ pub struct Config { /// It toggles whether to use adaptive HTTP windows pub adaptive_window: bool, /// It stores all the engine names that were enabled by the user. - pub upstream_search_engines: Vec, + pub upstream_search_engines: crate::engines::Engines, /// It stores the time (secs) which controls the server request timeout. pub request_timeout: u8, /// Set the keep-alive time for client connections to the HTTP server @@ -67,15 +67,7 @@ impl Default for Config { logging: true, debug: false, adaptive_window: false, - upstream_search_engines: vec![ - "bing".into(), - "brave".into(), - "duckduckgo".into(), - "librex".into(), - "mojeek".into(), - "searx".into(), - "startpage".into(), - ], + upstream_search_engines: Default::default(), request_timeout: 2, tcp_connection_keep_alive: 10, pool_idle_connection_timeout: 30, diff --git a/src/engines/bing.rs b/src/engines/bing.rs index cdfb884..8465dbc 100644 --- a/src/engines/bing.rs +++ b/src/engines/bing.rs @@ -24,18 +24,19 @@ pub struct Bing { parser: SearchResultParser, } -impl Bing { +impl Default for Bing { /// Creates the Bing parser. - pub fn new() -> Result { - Ok(Self { + fn default() -> Self { + Self { parser: SearchResultParser::new( ".b_results", ".b_algo", "h2 a", ".tpcn a.tilk", ".b_caption p", - )?, - }) + ) + .expect("somehow you changed the static stings in the binary i guess"), + } } } diff --git a/src/engines/brave.rs b/src/engines/brave.rs index 771ac96..b816f1d 100644 --- a/src/engines/brave.rs +++ b/src/engines/brave.rs @@ -20,18 +20,19 @@ pub struct Brave { parser: SearchResultParser, } -impl Brave { +impl Default for Brave { /// Creates the Brave parser. - pub fn new() -> Result { - Ok(Self { + fn default() -> Self { + Self { parser: SearchResultParser::new( "#results h4", "#results [data-pos]", "a > .url", "a", ".snippet-description", - )?, - }) + ) + .expect("somehow you changed the static stings in the binary i guess"), + } } } diff --git a/src/engines/duckduckgo.rs b/src/engines/duckduckgo.rs index f6743a1..71e5ef5 100644 --- a/src/engines/duckduckgo.rs +++ b/src/engines/duckduckgo.rs @@ -23,18 +23,19 @@ pub struct DuckDuckGo { parser: SearchResultParser, } -impl DuckDuckGo { +impl Default for DuckDuckGo { /// Creates the DuckDuckGo parser. - pub fn new() -> Result { - Ok(Self { + fn default() -> Self { + Self { parser: SearchResultParser::new( ".no-results", ".results>.result", ".result__title>.result__a", ".result__url", ".result__snippet", - )?, - }) + ) + .expect("somehow you changed the static stings in the binary i guess"), + } } } diff --git a/src/engines/librex.rs b/src/engines/librex.rs index 5a0fffe..86053a6 100644 --- a/src/engines/librex.rs +++ b/src/engines/librex.rs @@ -20,22 +20,23 @@ pub struct LibreX { parser: SearchResultParser, } -impl LibreX { +impl Default for LibreX { /// Creates a new instance of LibreX with a default configuration. /// /// # Returns /// /// Returns a `Result` containing `LibreX` if successful, otherwise an `EngineError`. - pub fn new() -> Result { - Ok(Self { + fn default() -> Self { + Self { parser: SearchResultParser::new( ".text-result-container>p", ".text-result-container", ".text-result-wrapper>a>h2", ".text-result-wrapper>a", ".text-result-wrapper>span", - )?, - }) + ) + .expect("somehow you changed the static stings in the binary i guess"), + } } } diff --git a/src/engines/mod.rs b/src/engines/mod.rs index a93c9c2..727747d 100644 --- a/src/engines/mod.rs +++ b/src/engines/mod.rs @@ -3,6 +3,12 @@ //! provide a standard functions to be implemented for all the upstream search engine handling //! code. Moreover, it also provides a custom error for the upstream search engine handling code. +use std::sync::Arc; + +use serde::{Deserialize, Serialize}; + +use crate::models::engine_models::EngineHandler; + pub mod bing; pub mod brave; pub mod duckduckgo; @@ -11,3 +17,66 @@ pub mod mojeek; pub mod search_result_parser; pub mod searx; pub mod startpage; + +/// Struct that keeps track of search engines +#[derive(Debug, Serialize, Deserialize, Clone, Copy)] +pub struct Engines { + bing: bool, + brave: bool, + duckduckgo: bool, + librex: bool, + mojeek: bool, + search_result_parser: bool, + searx: bool, + startpage: bool, +} + +impl Default for Engines { + fn default() -> Self { + Self { + bing: true, + brave: true, + duckduckgo: true, + librex: true, + mojeek: true, + search_result_parser: true, + searx: true, + startpage: true, + } + } +} + +impl From<&Engines> for Vec { + fn from(value: &Engines) -> Self { + let mut v = vec![]; + if value.duckduckgo { + let engine = crate::engines::duckduckgo::DuckDuckGo::default(); + v.push(EngineHandler::new("duckduckgo", Arc::new(engine))); + } + if value.searx { + let engine = crate::engines::searx::Searx::default(); + v.push(EngineHandler::new("searx", Arc::new(engine))); + } + if value.brave { + let engine = crate::engines::brave::Brave::default(); + v.push(EngineHandler::new("brave", Arc::new(engine))); + } + if value.startpage { + let engine = crate::engines::startpage::Startpage::default(); + v.push(EngineHandler::new("startpage", Arc::new(engine))); + } + if value.librex { + let engine = crate::engines::librex::LibreX::default(); + v.push(EngineHandler::new("librex", Arc::new(engine))); + } + if value.mojeek { + let engine = crate::engines::mojeek::Mojeek::default(); + v.push(EngineHandler::new("mojeek", Arc::new(engine))); + } + if value.bing { + let engine = crate::engines::bing::Bing::default(); + v.push(EngineHandler::new("bing", Arc::new(engine))); + } + v + } +} diff --git a/src/engines/mojeek.rs b/src/engines/mojeek.rs index f9cf59b..4da13ec 100644 --- a/src/engines/mojeek.rs +++ b/src/engines/mojeek.rs @@ -23,18 +23,19 @@ pub struct Mojeek { parser: SearchResultParser, } -impl Mojeek { +impl Default for Mojeek { /// Creates the Mojeek parser. - pub fn new() -> Result { - Ok(Self { + fn default() -> Self { + Self { parser: SearchResultParser::new( ".result-col", ".results-standard li", "a span.url", "h2 a.title", "p.s", - )?, - }) + ) + .expect("somehow you changed the static stings in the binary i guess"), + } } } diff --git a/src/engines/searx.rs b/src/engines/searx.rs index 6fef473..842c17d 100644 --- a/src/engines/searx.rs +++ b/src/engines/searx.rs @@ -19,18 +19,19 @@ pub struct Searx { parser: SearchResultParser, } -impl Searx { +impl Default for Searx { /// creates a Searx parser - pub fn new() -> Result { - Ok(Self { + fn default() -> Self { + Self { parser: SearchResultParser::new( "#urls>.dialog-error>p", ".result", "h3>a", "h3>a", ".content", - )?, - }) + ) + .expect("somehow you changed the static stings in the binary i guess"), + } } } diff --git a/src/engines/startpage.rs b/src/engines/startpage.rs index 9c8b070..405b900 100644 --- a/src/engines/startpage.rs +++ b/src/engines/startpage.rs @@ -23,18 +23,19 @@ pub struct Startpage { parser: SearchResultParser, } -impl Startpage { +impl Default for Startpage { /// Creates the Startpage parser. - pub fn new() -> Result { - Ok(Self { + fn default() -> Self { + Self { parser: SearchResultParser::new( ".no-results", ".w-gl__result__main", ".w-gl__result-second-line-container>.w-gl__result-title>h3", ".w-gl__result-url", ".w-gl__description", - )?, - }) + ) + .expect("somehow you changed the static stings in the binary i guess"), + } } } diff --git a/src/main.rs b/src/main.rs index 0763538..5220edf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ //! and register all the routes for the `crabbysearch` meta search engine website. #![forbid(unsafe_code, clippy::panic)] -#![deny(missing_docs, clippy::missing_docs_in_private_items, clippy::perf)] +#![deny(missing_docs, clippy::perf)] #![warn(clippy::cognitive_complexity, rust_2018_idioms)] pub mod cache; @@ -50,7 +50,7 @@ async fn main() { config.port, ); - let listener = TcpListener::bind((config.binding_ip.as_str(), config.port)) + let listener = TcpListener::bind((config.binding_ip.clone(), config.port)) .expect("could not create TcpListener"); let public_folder_path: &str = file_path(FileType::Theme).unwrap(); diff --git a/src/models/engine_models.rs b/src/models/engine_models.rs index 26cb21d..6718062 100644 --- a/src/models/engine_models.rs +++ b/src/models/engine_models.rs @@ -1,10 +1,12 @@ //! This module provides the error enum to handle different errors associated while requesting data from //! the upstream search engines with the search query provided by the user. +use crate::engines; + use super::aggregation_models::SearchResult; use error_stack::{Report, Result, ResultExt}; use reqwest::Client; -use std::fmt; +use std::{fmt, sync::Arc}; /// A custom error type used for handle engine associated errors. #[derive(Debug)] @@ -153,14 +155,17 @@ pub trait SearchEngine: Sync + Send { pub struct EngineHandler { /// It stores the engine struct wrapped in a box smart pointer as the engine struct implements /// the `SearchEngine` trait. - engine: Box, + engine: Arc, /// It stores the name of the engine to which the struct is associated to. name: &'static str, } impl Clone for EngineHandler { fn clone(&self) -> Self { - Self::new(self.name).unwrap() + Self { + engine: self.engine.clone(), + name: self.name.clone(), + } } } @@ -174,53 +179,13 @@ impl EngineHandler { /// # Returns /// /// It returns an option either containing the value or a none if the engine is unknown - pub fn new(engine_name: &str) -> Result { - let engine: (&'static str, Box) = - match engine_name.to_lowercase().as_str() { - "duckduckgo" => { - let engine = crate::engines::duckduckgo::DuckDuckGo::new()?; - ("duckduckgo", Box::new(engine)) - } - "searx" => { - let engine = crate::engines::searx::Searx::new()?; - ("searx", Box::new(engine)) - } - "brave" => { - let engine = crate::engines::brave::Brave::new()?; - ("brave", Box::new(engine)) - } - "startpage" => { - let engine = crate::engines::startpage::Startpage::new()?; - ("startpage", Box::new(engine)) - } - "librex" => { - let engine = crate::engines::librex::LibreX::new()?; - ("librex", Box::new(engine)) - } - "mojeek" => { - let engine = crate::engines::mojeek::Mojeek::new()?; - ("mojeek", Box::new(engine)) - } - "bing" => { - let engine = crate::engines::bing::Bing::new()?; - ("bing", Box::new(engine)) - } - _ => { - return Err(Report::from(EngineError::NoSuchEngineFound( - engine_name.to_string(), - ))) - } - }; - - Ok(Self { - engine: engine.1, - name: engine.0, - }) + pub fn new(name: &'static str, engine: Arc) -> Self { + Self { name, engine } } /// This function converts the EngineHandler type into a tuple containing the engine name and /// the associated engine struct. - pub fn into_name_engine(self) -> (&'static str, Box) { + pub fn into_name_engine(self) -> (&'static str, Arc) { (self.name, self.engine) } } diff --git a/src/models/server_models.rs b/src/models/server_models.rs index a536683..81de741 100644 --- a/src/models/server_models.rs +++ b/src/models/server_models.rs @@ -1,11 +1,7 @@ //! This module provides the models to parse cookies and search parameters from the search //! engine website. -use std::borrow::Cow; use serde::Deserialize; - -use crate::config::Style; - /// A named struct which deserializes all the user provided search parameters and stores them. #[derive(Deserialize)] pub struct SearchParams { @@ -19,27 +15,3 @@ pub struct SearchParams { /// search url. pub safesearch: Option, } - -/// A named struct which is used to deserialize the cookies fetched from the client side. -#[allow(dead_code)] -#[derive(Deserialize)] -pub struct Cookie<'a> { - /// It stores the theme name used in the website. - pub theme: Cow<'a, str>, - /// It stores the colorscheme name used for the website theme. - pub colorscheme: Cow<'a, str>, - /// It stores the user selected upstream search engines selected from the UI. - pub engines: Cow<'a, Vec>>, -} - -impl<'a> Cookie<'a> { - /// server_models::Cookie contructor function - pub fn build(style: &'a Style, mut engines: Vec>) -> Self { - engines.sort(); - Self { - theme: Cow::Borrowed(&style.theme), - colorscheme: Cow::Borrowed(&style.colorscheme), - engines: Cow::Owned(engines), - } - } -} diff --git a/src/server/routes/search.rs b/src/server/routes/search.rs index 95013ab..411d64e 100644 --- a/src/server/routes/search.rs +++ b/src/server/routes/search.rs @@ -3,6 +3,7 @@ use crate::{ cache::Cache, config::Config, + engines::Engines, models::{ aggregation_models::SearchResults, engine_models::EngineHandler, @@ -47,18 +48,9 @@ pub async fn search( let cookie = req.cookie("appCookie"); // Get search settings using the user's cookie or from the server's config - let search_settings: server_models::Cookie<'_> = cookie + let search_settings: crate::engines::Engines = cookie .and_then(|cookie_value| serde_json::from_str(cookie_value.value()).ok()) - .unwrap_or_else(|| { - server_models::Cookie::build( - &config.style, - config - .upstream_search_engines - .iter() - .map(|e| Cow::Borrowed(e.as_str())) - .collect(), - ) - }); + .unwrap(); // Closure wrapping the results function capturing local references let get_results = |page| results(config.clone(), cache.clone(), query, page, &search_settings); @@ -140,16 +132,11 @@ async fn results( cache: web::Data, query: &str, page: u32, - search_settings: &server_models::Cookie<'_>, + upstream: &Engines, ) -> Result<(SearchResults, String), Box> { // eagerly parse cookie value to evaluate safe search level - let cache_key = format!( - "search?q={}&page={}&engines={}", - query, - page, - search_settings.engines.join(",") - ); + let cache_key = format!("search?q={}&page={}&engines={:?}", query, page, upstream); // fetch the cached results json. let response = cache.cached_results(&cache_key); @@ -162,20 +149,8 @@ async fn results( // default selected upstream search engines from the config file otherwise // parse the non-empty cookie and grab the user selected engines from the // UI and use that. - let mut results: SearchResults = match search_settings.engines.is_empty() { - false => { - aggregate( - query, - page, - config, - &search_settings - .engines - .iter() - .filter_map(|engine| EngineHandler::new(engine).ok()) - .collect::>(), - ) - .await? - } + let mut results: SearchResults = match true { + false => aggregate(query, page, config, &Vec::::from(upstream)).await?, true => { let mut search_results = SearchResults::default(); search_results.set_no_engines_selected(); From 0faf8c19a9e7d638596d97da946f2ac2eaff0ed7 Mon Sep 17 00:00:00 2001 From: Milim Date: Thu, 15 Aug 2024 13:20:59 +0200 Subject: [PATCH 5/9] finishing server side engine selection --- src/engines/mod.rs | 15 +++++++++++++++ src/models/engine_models.rs | 14 ++------------ src/server/router.rs | 7 ++++++- src/server/routes/search.rs | 11 +++++------ src/templates/partials/settings_tabs/engines.rs | 6 ++---- src/templates/views/settings.rs | 6 ++---- 6 files changed, 32 insertions(+), 27 deletions(-) diff --git a/src/engines/mod.rs b/src/engines/mod.rs index 727747d..667332c 100644 --- a/src/engines/mod.rs +++ b/src/engines/mod.rs @@ -80,3 +80,18 @@ impl From<&Engines> for Vec { v } } + +impl Engines { + /// Returns a list of all engines + pub fn list(&self) -> Box<[&'static str]> { + Box::new([ + "duckduckgo", + "searx", + "brave", + "startpage", + "librex", + "mojeek", + "bing", + ]) + } +} diff --git a/src/models/engine_models.rs b/src/models/engine_models.rs index 6718062..b7022b6 100644 --- a/src/models/engine_models.rs +++ b/src/models/engine_models.rs @@ -1,10 +1,8 @@ //! This module provides the error enum to handle different errors associated while requesting data from //! the upstream search engines with the search query provided by the user. -use crate::engines; - use super::aggregation_models::SearchResult; -use error_stack::{Report, Result, ResultExt}; +use error_stack::{Result, ResultExt}; use reqwest::Client; use std::{fmt, sync::Arc}; @@ -152,6 +150,7 @@ pub trait SearchEngine: Sync + Send { } /// A named struct which stores the engine struct with the name of the associated engine. +#[derive(Clone)] pub struct EngineHandler { /// It stores the engine struct wrapped in a box smart pointer as the engine struct implements /// the `SearchEngine` trait. @@ -160,15 +159,6 @@ pub struct EngineHandler { name: &'static str, } -impl Clone for EngineHandler { - fn clone(&self) -> Self { - Self { - engine: self.engine.clone(), - name: self.name.clone(), - } - } -} - impl EngineHandler { /// Parses an engine name into an engine handler. /// diff --git a/src/server/router.rs b/src/server/router.rs index 94c974d..12da172 100644 --- a/src/server/router.rs +++ b/src/server/router.rs @@ -70,7 +70,12 @@ pub async fn settings( &config.style.colorscheme, &config.style.theme, &config.style.animation, - //&config.upstream_search_engines, + &config + .upstream_search_engines + .list() + .iter() + .map(|n| (*n, true)) + .collect(), )? .0, )) diff --git a/src/server/routes/search.rs b/src/server/routes/search.rs index 411d64e..25aa14b 100644 --- a/src/server/routes/search.rs +++ b/src/server/routes/search.rs @@ -5,14 +5,12 @@ use crate::{ config::Config, engines::Engines, models::{ - aggregation_models::SearchResults, - engine_models::EngineHandler, - server_models::{self, SearchParams}, + aggregation_models::SearchResults, engine_models::EngineHandler, + server_models::SearchParams, }, results::aggregator::aggregate, }; use actix_web::{get, http::header::ContentType, web, HttpRequest, HttpResponse}; -use std::borrow::Cow; use tokio::join; /// Handles the route of search page of the `crabbysearch` meta search engine website and it takes @@ -50,7 +48,8 @@ pub async fn search( // Get search settings using the user's cookie or from the server's config let search_settings: crate::engines::Engines = cookie .and_then(|cookie_value| serde_json::from_str(cookie_value.value()).ok()) - .unwrap(); + .inspect(|e| log::info!("{e:?}")) + .unwrap_or_default(); // Closure wrapping the results function capturing local references let get_results = |page| results(config.clone(), cache.clone(), query, page, &search_settings); @@ -149,7 +148,7 @@ async fn results( // default selected upstream search engines from the config file otherwise // parse the non-empty cookie and grab the user selected engines from the // UI and use that. - let mut results: SearchResults = match true { + let mut results: SearchResults = match false { false => aggregate(query, page, config, &Vec::::from(upstream)).await?, true => { let mut search_results = SearchResults::default(); diff --git a/src/templates/partials/settings_tabs/engines.rs b/src/templates/partials/settings_tabs/engines.rs index a37f9dd..2d7e0d3 100644 --- a/src/templates/partials/settings_tabs/engines.rs +++ b/src/templates/partials/settings_tabs/engines.rs @@ -1,7 +1,5 @@ //! A module that handles the engines tab for setting page view in the `crabbysearch` frontend. -use std::collections::HashMap; - use maud::{html, Markup}; /// A functions that handles the html code for the engines tab for the settings page for the search page. @@ -14,7 +12,7 @@ use maud::{html, Markup}; /// # Returns /// /// It returns the compiled html markup code for the engines tab. -pub fn engines(engine_names: &HashMap) -> Markup { +pub fn engines(engine_names: &Vec<(&str, bool)>) -> Markup { html!( div class="engines tab"{ h1{"Engines"} @@ -26,7 +24,7 @@ pub fn engines(engine_names: &HashMap) -> Markup { // Checks whether all the engines are selected or not if they are then the // checked `select_all` button is rendered otherwise the unchecked version // is rendered. - @if engine_names.values().all(|selected| *selected){ + @if engine_names.iter().all(|selected| selected.1){ .toggle_btn{ label class="switch"{ input type="checkbox" class="select_all" onchange="toggleAllSelection()" checked; diff --git a/src/templates/views/settings.rs b/src/templates/views/settings.rs index b293e84..d09e42c 100644 --- a/src/templates/views/settings.rs +++ b/src/templates/views/settings.rs @@ -1,7 +1,5 @@ //! A module that handles the view for the settings page in the `crabbysearch` frontend. -use std::collections::HashMap; - use maud::{html, Markup}; use crate::templates::partials::{ @@ -28,7 +26,7 @@ pub fn settings( colorscheme: &str, theme: &str, animation: &Option, - //engine_names: &HashMap, + engine_names: &Vec<(&'static str, bool)>, ) -> Result> { Ok(html!( (header(colorscheme, theme, animation)) @@ -44,7 +42,7 @@ pub fn settings( } .main_container{ (user_interface(theme, colorscheme, animation)?) - //(engines(engine_names)) + (engines(&engine_names)) (cookies()) p class="message"{} button type="submit" onclick="setClientSettings()"{"Save"} From d48201021e28221733ed7471a37f205e49bda5be Mon Sep 17 00:00:00 2001 From: Milim Date: Thu, 15 Aug 2024 14:19:06 +0200 Subject: [PATCH 6/9] update frontend to account for search engine selection changes --- public/static/cookies.js | 51 ++-------- public/static/settings.js | 95 +----------------- src/config.rs | 20 ---- src/engines/mod.rs | 2 - src/server/router.rs | 44 +++------ src/server/routes/search.rs | 18 ++-- src/templates/partials/header.rs | 9 +- src/templates/partials/settings_tabs/mod.rs | 1 - .../partials/settings_tabs/user_interface.rs | 96 ------------------- src/templates/views/about.rs | 16 +--- src/templates/views/index.rs | 4 +- src/templates/views/not_found.rs | 4 +- src/templates/views/search.rs | 10 +- src/templates/views/settings.rs | 8 +- 14 files changed, 43 insertions(+), 335 deletions(-) delete mode 100644 src/templates/partials/settings_tabs/user_interface.rs diff --git a/public/static/cookies.js b/public/static/cookies.js index 3525c5b..a01137e 100644 --- a/public/static/cookies.js +++ b/public/static/cookies.js @@ -10,51 +10,18 @@ * @returns {void} */ function setClientSettingsOnPage(cookie) { - let cookie_value = cookie - .split(';') - .map((item) => item.split('=')) - .reduce((acc, [_, v]) => (acc = JSON.parse(v)) && acc, {}) - // Loop through all select tags and add their values to the cookie dictionary - document.querySelectorAll('select').forEach((select_tag) => { - switch (select_tag.name) { - case 'themes': - select_tag.value = cookie_value['theme'] - break - case 'colorschemes': - select_tag.value = cookie_value['colorscheme'] - break - case 'animations': - select_tag.value = cookie_value['animation'] - break - case 'safe_search_levels': - select_tag.value = cookie_value['safe_search_level'] - break + let engines = document.querySelectorAll('.engine') + + document.querySelector('.select_all').checked = true + + engines.forEach((engine) => { + engine.checked = cookie[engine.parentNode.parentNode.innerText.trim()]; + if (!engine.checked) { + document.querySelector('.select_all').checked = false } }) - let engines = document.querySelectorAll('.engine') - let engines_cookie = cookie_value['engines'] - if (engines_cookie.length === engines.length) { - document.querySelector('.select_all').checked = true - engines.forEach((engine_checkbox) => { - engine_checkbox.checked = true - }) - } else { - engines.forEach((engines_checkbox) => { - engines_checkbox.checked = false - }) - engines_cookie.forEach((engine_name) => { - engines.forEach((engine_checkbox) => { - if ( - engine_checkbox.parentNode.parentNode.innerText.trim() === - engine_name.trim() - ) { - engine_checkbox.checked = true - } - }) - }) - } } /** @@ -78,7 +45,7 @@ document.addEventListener( if (cookie.length) { document.querySelector('.cookies input').value = cookie // This function displays the user provided settings on the settings page. - setClientSettingsOnPage(cookie) + setClientSettingsOnPage(JSON.parse(cookie.replace("appCookie=", ""))) } else { document.querySelector('.cookies input').value = 'No cookies have been saved on your system' diff --git a/public/static/settings.js b/public/static/settings.js index b8d8f88..008136c 100644 --- a/public/static/settings.js +++ b/public/static/settings.js @@ -7,8 +7,8 @@ function toggleAllSelection() { .querySelectorAll('.engine') .forEach( (engine_checkbox) => - (engine_checkbox.checked = - document.querySelector('.select_all').checked), + (engine_checkbox.checked = + document.querySelector('.select_all').checked), ) } @@ -41,35 +41,10 @@ function setClientSettings() { // Create an object to store the user's preferences let cookie_dictionary = new Object() - // Loop through all select tags and add their values to the cookie dictionary - document.querySelectorAll('select').forEach((select_tag) => { - switch (select_tag.name) { - case 'themes': - cookie_dictionary['theme'] = select_tag.value - break - case 'colorschemes': - cookie_dictionary['colorscheme'] = select_tag.value - break - case 'animations': - cookie_dictionary['animation'] = select_tag.value || null - break - case 'safe_search_levels': - cookie_dictionary['safe_search_level'] = Number(select_tag.value) - break - } - }) - - // Loop through all engine checkboxes and add their values to the cookie dictionary - let engines = [] - document.querySelectorAll('.engine').forEach((engine_checkbox) => { - if (engine_checkbox.checked) { - engines.push(engine_checkbox.parentNode.parentNode.innerText.trim()) - } + cookie_dictionary[engine_checkbox.parentNode.parentNode.innerText.trim()] = engine_checkbox.checked }) - cookie_dictionary['engines'] = engines - // Set the expiration date for the cookie to 1 year from the current date let expiration_date = new Date() expiration_date.setFullYear(expiration_date.getFullYear() + 1) @@ -89,67 +64,3 @@ function setClientSettings() { }, 10000) } -/** - * This functions gets the saved cookies if it is present on the user's machine If it - * is available then it is parsed and converted to an object which is then used to - * retrieve the preferences that the user had selected previously and is then loaded in the - * website otherwise the function does nothing and the default server side settings are loaded. - */ -function getClientSettings() { - // Get the appCookie from the user's machine - let cookie = decodeURIComponent(document.cookie) - - // If the cookie is not empty, parse it and use it to set the user's preferences - if (cookie.length) { - let cookie_value = cookie - .split(';') - .map((item) => item.split('=')) - .reduce((acc, [_, v]) => (acc = JSON.parse(v)) && acc, {}) - - let links = Array.from(document.querySelectorAll('link')) - - // A check to determine whether the animation link exists under the head tag or not. - // If it does not exists then create and add a new animation link under the head tag - // and update the other link tags href according to the settings provided by the user - // via the UI. On the other hand if it does exist then just update all the link tags - // href according to the settings provided by the user via the UI. - if (!links.some((item) => item.href.includes('static/animations'))) { - if (cookie_value['animation']) { - let animation_link = document.createElement('link') - animation_link.href = `static/animations/${cookie_value['animation']}.css` - animation_link.rel = 'stylesheet' - animation_link.type = 'text/css' - document.querySelector('head').appendChild(animation_link) - } - // Loop through all link tags and update their href values to match the user's preferences - links.forEach((item) => { - if (item.href.includes('static/themes')) { - item.href = `static/themes/${cookie_value['theme']}.css` - } else if (item.href.includes('static/colorschemes')) { - item.href = `static/colorschemes/${cookie_value['colorscheme']}.css` - } - }) - } else { - // Loop through all link tags and update their href values to match the user's preferences - links.forEach((item) => { - if (item.href.includes('static/themes')) { - item.href = `static/themes/${cookie_value['theme']}.css` - } else if (item.href.includes('static/colorschemes')) { - item.href = `static/colorschemes/${cookie_value['colorscheme']}.css` - } else if ( - item.href.includes('static/animations') && - cookie_value['animation'] - ) { - item.href = `static/colorschemes/${cookie_value['animation']}.css` - } - }) - if (!cookie_value['animation']) { - document - .querySelector('head') - .removeChild( - links.filter((item) => item.href.includes('static/animations')), - ) - } - } - } -} diff --git a/src/config.rs b/src/config.rs index 7addc5c..1c8da5c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -10,8 +10,6 @@ pub struct Config { pub port: u16, /// It stores the parsed ip address option on which the server should launch pub binding_ip: String, - /// It stores the theming options for the website. - pub style: Style, /// Memory cache invalidation time pub cache_expiry_time: u64, /// It stores the option to whether enable or disable logs. @@ -32,19 +30,6 @@ pub struct Config { pub pool_idle_connection_timeout: u8, } -/// A struct holding style config -#[derive(Default, Debug, Clone, Deserialize, Serialize)] -pub struct Style { - /// It stores the parsed theme option used to set a theme for the website. - pub theme: String, - /// It stores the parsed colorscheme option used to set a colorscheme for the - /// theme being used. - pub colorscheme: String, - /// It stores the parsed animation option used to set an animation for the - /// theme being used. - pub animation: Option, -} - /// Configuration options for the rate limiter middleware. pub struct RateLimiter { /// The number of request that are allowed within a provided time limit. @@ -58,11 +43,6 @@ impl Default for Config { Self { port: 8080, binding_ip: "127.0.0.1".into(), - style: Style { - theme: "simple".into(), - colorscheme: "catppuccin-mocha".into(), - animation: Some("simple-frosted-glow".into()), - }, cache_expiry_time: 600, logging: true, debug: false, diff --git a/src/engines/mod.rs b/src/engines/mod.rs index 667332c..80f1ea7 100644 --- a/src/engines/mod.rs +++ b/src/engines/mod.rs @@ -26,7 +26,6 @@ pub struct Engines { duckduckgo: bool, librex: bool, mojeek: bool, - search_result_parser: bool, searx: bool, startpage: bool, } @@ -39,7 +38,6 @@ impl Default for Engines { duckduckgo: true, librex: true, mojeek: true, - search_result_parser: true, searx: true, startpage: true, } diff --git a/src/server/router.rs b/src/server/router.rs index 12da172..07698d3 100644 --- a/src/server/router.rs +++ b/src/server/router.rs @@ -11,30 +11,18 @@ use tokio::fs::read_to_string; /// Handles the route of index page or main page of the `crabbysearch` meta search engine website. #[get("/")] -pub async fn index(config: web::Data) -> Result> { - Ok(HttpResponse::Ok().content_type(ContentType::html()).body( - crate::templates::views::index::index( - &config.style.colorscheme, - &config.style.theme, - &config.style.animation, - ) - .0, - )) +pub async fn index() -> Result> { + Ok(HttpResponse::Ok() + .content_type(ContentType::html()) + .body(crate::templates::views::index::index().0)) } /// Handles the route of any other accessed route/page which is not provided by the /// website essentially the 404 error page. -pub async fn not_found( - config: web::Data, -) -> Result> { - Ok(HttpResponse::Ok().content_type(ContentType::html()).body( - crate::templates::views::not_found::not_found( - &config.style.colorscheme, - &config.style.theme, - &config.style.animation, - ) - .0, - )) +pub async fn not_found() -> Result> { + Ok(HttpResponse::Ok() + .content_type(ContentType::html()) + .body(crate::templates::views::not_found::not_found().0)) } /// Handles the route of robots.txt page of the `crabbysearch` meta search engine website. @@ -49,15 +37,10 @@ pub async fn robots_data(_req: HttpRequest) -> Result) -> Result> { - Ok(HttpResponse::Ok().content_type(ContentType::html()).body( - crate::templates::views::about::about( - &config.style.colorscheme, - &config.style.theme, - &config.style.animation, - ) - .0, - )) +pub async fn about() -> Result> { + Ok(HttpResponse::Ok() + .content_type(ContentType::html()) + .body(crate::templates::views::about::about().0)) } /// Handles the route of settings page of the `crabbysearch` meta search engine website. @@ -67,9 +50,6 @@ pub async fn settings( ) -> Result> { Ok(HttpResponse::Ok().content_type(ContentType::html()).body( crate::templates::views::settings::settings( - &config.style.colorscheme, - &config.style.theme, - &config.style.animation, &config .upstream_search_engines .list() diff --git a/src/server/routes/search.rs b/src/server/routes/search.rs index 25aa14b..e5f1196 100644 --- a/src/server/routes/search.rs +++ b/src/server/routes/search.rs @@ -45,10 +45,11 @@ pub async fn search( let cookie = req.cookie("appCookie"); + log::info!("{cookie:?}"); + // Get search settings using the user's cookie or from the server's config let search_settings: crate::engines::Engines = cookie - .and_then(|cookie_value| serde_json::from_str(cookie_value.value()).ok()) - .inspect(|e| log::info!("{e:?}")) + .and_then(|cookie_value| serde_json::from_str(&cookie_value.value().to_lowercase()).ok()) .unwrap_or_default(); // Closure wrapping the results function capturing local references @@ -99,16 +100,9 @@ pub async fn search( cache.cache_results(&results_list, &cache_keys); } - Ok(HttpResponse::Ok().content_type(ContentType::html()).body( - crate::templates::views::search::search( - &config.style.colorscheme, - &config.style.theme, - &config.style.animation, - query, - &results.0, - ) - .0, - )) + Ok(HttpResponse::Ok() + .content_type(ContentType::html()) + .body(crate::templates::views::search::search(query, &results.0).0)) } /// Fetches the results for a query and page. It First checks the redis cache, if that diff --git a/src/templates/partials/header.rs b/src/templates/partials/header.rs index b88e5cb..43dfe80 100644 --- a/src/templates/partials/header.rs +++ b/src/templates/partials/header.rs @@ -13,7 +13,7 @@ use maud::{html, Markup, PreEscaped, DOCTYPE}; /// # Returns /// /// It returns the compiled html markup code for the header as a result. -pub fn header(colorscheme: &str, theme: &str, animation: &Option) -> Markup { +pub fn header() -> Markup { html!( (DOCTYPE) html lang="en" @@ -22,11 +22,8 @@ pub fn header(colorscheme: &str, theme: &str, animation: &Option) -> Mar title{"crabbysearch"} meta charset="UTF-8"; meta name="viewport" content="width=device-width, initial-scale=1"; - link href=(format!("static/colorschemes/{colorscheme}.css")) rel="stylesheet" type="text/css"; - link href=(format!("static/themes/{theme}.css")) rel="stylesheet" type="text/css"; - @if animation.is_some() { - link href=(format!("static/animations/{}.css", animation.as_ref().unwrap())) rel="stylesheet" type="text/css"; - } + link href=("static/colorschemes/monokai.css") rel="stylesheet" type="text/css"; + link href=("static/themes/simple.css") rel="stylesheet" type="text/css"; } (PreEscaped("")) diff --git a/src/templates/partials/settings_tabs/mod.rs b/src/templates/partials/settings_tabs/mod.rs index b8f42dc..2154977 100644 --- a/src/templates/partials/settings_tabs/mod.rs +++ b/src/templates/partials/settings_tabs/mod.rs @@ -3,4 +3,3 @@ pub mod cookies; pub mod engines; -pub mod user_interface; diff --git a/src/templates/partials/settings_tabs/user_interface.rs b/src/templates/partials/settings_tabs/user_interface.rs deleted file mode 100644 index b191a55..0000000 --- a/src/templates/partials/settings_tabs/user_interface.rs +++ /dev/null @@ -1,96 +0,0 @@ -//! A module that handles the user interface tab for setting page view in the `crabbysearch` frontend. - -use crate::handler::{file_path, FileType}; -use maud::{html, Markup}; -use std::fs::read_dir; - -/// A helper function that helps in building the list of all available colorscheme/theme/animation -/// names present in the colorschemes, animations and themes folder respectively by excluding the -/// ones that have already been selected via the config file. -/// -/// # Arguments -/// -/// * `style_type` - It takes the style type of the values `theme` and `colorscheme` as an -/// argument. -/// * `selected_style` - It takes the currently selected style value provided via the config file -/// as an argument. -/// -/// # Error -/// -/// Returns a list of colorscheme/theme names as a vector of tuple strings on success otherwise -/// returns a standard error message. -fn style_option_list( - style_type: &str, - selected_style: &str, -) -> Result, Box> { - let mut style_option_names: Vec<(String, String)> = Vec::new(); - for file in read_dir(format!( - "{}static/{}/", - file_path(FileType::Theme)?, - style_type, - ))? { - let style_name = file?.file_name().to_str().unwrap().replace(".css", ""); - if selected_style != style_name { - style_option_names.push((style_name.clone(), style_name.replace('-', " "))); - } - } - - if style_type == "animations" { - style_option_names.push((String::default(), "none".to_owned())) - } - - Ok(style_option_names) -} - -/// A functions that handles the html code for the user interface tab for the settings page for the search page. -/// -/// # Error -/// -/// It returns the compiled html markup code for the user interface tab on success otherwise -/// returns a standard error message. -pub fn user_interface( - theme: &str, - colorscheme: &str, - animation: &Option, -) -> Result> { - Ok(html!( - div class="user_interface tab"{ - h1{"User Interface"} - h3{"select theme"} - p class="description"{ - "Select the theme from the available themes to be used in user interface" - } - select name="themes"{ - // Sets the user selected theme name from the config file as the first option in the selection list. - option value=(theme){(theme.replace('-', " "))} - @for (k,v) in style_option_list("themes", theme)?{ - option value=(k){(v)} - } - } - h3{"select color scheme"} - p class="description"{ - "Select the color scheme for your theme to be used in user interface" - } - select name="colorschemes"{ - // Sets the user selected colorscheme name from the config file as the first option in the selection list. - option value=(colorscheme){(colorscheme.replace('-', " "))} - @for (k,v) in style_option_list("colorschemes", colorscheme)?{ - option value=(k){(v)} - } - } - h3{"select animation"} - p class="description"{ - "Select the animation for your theme to be used in user interface" - } - select name="animations"{ - @let default_animation = &String::default(); - @let animation = animation.as_ref().unwrap_or(default_animation); - // Sets the user selected animation name from the config file as the first option in the selection list. - option value=(animation){(animation.replace('-'," "))} - @for (k,v) in style_option_list("animations", animation)?{ - option value=(k){(v)} - } - } - } - )) -} diff --git a/src/templates/views/about.rs b/src/templates/views/about.rs index ccc4c4d..0de3e91 100644 --- a/src/templates/views/about.rs +++ b/src/templates/views/about.rs @@ -14,16 +14,7 @@ use crate::templates::partials::{footer::footer, header::header}; /// # Returns /// /// It returns the compiled html markup code as a result. -pub fn about(colorscheme: &str, theme: &str, animation: &Option) -> Markup { - let logo_svg = r#" - - - - - - - - "#; +pub fn about() -> Markup { let feature_lightning = r#" "#; @@ -43,12 +34,9 @@ pub fn about(colorscheme: &str, theme: &str, animation: &Option) -> Mark "#; html!( - (header(colorscheme, theme, animation)) + (header()) main class="about-container"{ article { - div class="logo-container" { - (PreEscaped(logo_svg)) - } div class="text-block" { h3 class="text-block-title" {"Why crabbysearch?"} diff --git a/src/templates/views/index.rs b/src/templates/views/index.rs index bb8a9f0..bcf5809 100644 --- a/src/templates/views/index.rs +++ b/src/templates/views/index.rs @@ -14,9 +14,9 @@ use crate::templates::partials::{bar::bar, footer::footer, header::header}; /// # Returns /// /// It returns the compiled html markup code as a result. -pub fn index(colorscheme: &str, theme: &str, animation: &Option) -> Markup { +pub fn index() -> Markup { html!( - (header(colorscheme, theme, animation)) + (header()) main class="search-container"{ (bar(&String::default())) (PreEscaped("")) diff --git a/src/templates/views/not_found.rs b/src/templates/views/not_found.rs index f893cc9..f5730a4 100644 --- a/src/templates/views/not_found.rs +++ b/src/templates/views/not_found.rs @@ -13,9 +13,9 @@ use maud::{html, Markup}; /// # Returns /// /// It returns the compiled html markup code as a result. -pub fn not_found(colorscheme: &str, theme: &str, animation: &Option) -> Markup { +pub fn not_found() -> Markup { html!( - (header(colorscheme, theme, animation)) + (header()) main class="error_container"{ img src="images/robot-404.svg" alt="Image of broken robot."; .error_content{ diff --git a/src/templates/views/search.rs b/src/templates/views/search.rs index d38217d..38821c4 100644 --- a/src/templates/views/search.rs +++ b/src/templates/views/search.rs @@ -19,15 +19,9 @@ use crate::{ /// # Returns /// /// It returns the compiled html markup code as a result. -pub fn search( - colorscheme: &str, - theme: &str, - animation: &Option, - query: &str, - search_results: &SearchResults, -) -> Markup { +pub fn search(query: &str, search_results: &SearchResults) -> Markup { html!( - (header(colorscheme, theme, animation)) + (header()) main class="results"{ (search_bar(&search_results.engine_errors_info, search_results.safe_search_level, query)) .results_aggregated{ diff --git a/src/templates/views/settings.rs b/src/templates/views/settings.rs index d09e42c..9d7fc40 100644 --- a/src/templates/views/settings.rs +++ b/src/templates/views/settings.rs @@ -5,7 +5,7 @@ use maud::{html, Markup}; use crate::templates::partials::{ footer::footer, header::header, - settings_tabs::{cookies::cookies, engines::engines, user_interface::user_interface}, + settings_tabs::{cookies::cookies, engines::engines}, }; /// A function that handles the html code for the settings page view in the search engine frontend. @@ -23,13 +23,10 @@ use crate::templates::partials::{ /// This function returns a compiled html markup code on success otherwise returns a standard error /// message. pub fn settings( - colorscheme: &str, - theme: &str, - animation: &Option, engine_names: &Vec<(&'static str, bool)>, ) -> Result> { Ok(html!( - (header(colorscheme, theme, animation)) + (header()) main class="settings"{ h1{"Settings"} hr; @@ -41,7 +38,6 @@ pub fn settings( .btn onclick="setActiveTab(this)"{"cookies"} } .main_container{ - (user_interface(theme, colorscheme, animation)?) (engines(&engine_names)) (cookies()) p class="message"{} From 253de6ff134b2c612f52814ebdde38116a7eea8d Mon Sep 17 00:00:00 2001 From: Milim Date: Thu, 15 Aug 2024 21:11:14 +0200 Subject: [PATCH 7/9] inital no-js frontend --- public/static/cookies.js | 61 --------------- public/static/error_box.js | 7 -- public/static/index.js | 34 --------- public/static/pagination.js | 39 ---------- public/static/search_area_options.js | 18 ----- public/static/settings.js | 66 ---------------- src/main.rs | 1 - src/server/router.rs | 25 +----- src/templates/partials/bar.rs | 13 +++- src/templates/partials/mod.rs | 2 - src/templates/partials/search_bar.rs | 76 ------------------- .../partials/settings_tabs/cookies.rs | 25 ------ .../partials/settings_tabs/engines.rs | 72 ------------------ src/templates/partials/settings_tabs/mod.rs | 5 -- src/templates/views/mod.rs | 1 - src/templates/views/search.rs | 4 +- src/templates/views/settings.rs | 52 ------------- 17 files changed, 13 insertions(+), 488 deletions(-) delete mode 100644 public/static/cookies.js delete mode 100644 public/static/error_box.js delete mode 100644 public/static/index.js delete mode 100644 public/static/pagination.js delete mode 100644 public/static/search_area_options.js delete mode 100644 public/static/settings.js delete mode 100644 src/templates/partials/search_bar.rs delete mode 100644 src/templates/partials/settings_tabs/cookies.rs delete mode 100644 src/templates/partials/settings_tabs/engines.rs delete mode 100644 src/templates/partials/settings_tabs/mod.rs delete mode 100644 src/templates/views/settings.rs diff --git a/public/static/cookies.js b/public/static/cookies.js deleted file mode 100644 index a01137e..0000000 --- a/public/static/cookies.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * This functions gets the saved cookies if it is present on the user's machine If it - * is available then it is parsed and converted to an object which is then used to - * retrieve the preferences that the user had selected previously and is then loaded - * and used for displaying the user provided settings by setting them as the selected - * options in the settings page. - * - * @function - * @param {string} cookie - It takes the client settings cookie as a string. - * @returns {void} - */ -function setClientSettingsOnPage(cookie) { - // Loop through all select tags and add their values to the cookie dictionary - let engines = document.querySelectorAll('.engine') - - document.querySelector('.select_all').checked = true - - engines.forEach((engine) => { - engine.checked = cookie[engine.parentNode.parentNode.innerText.trim()]; - if (!engine.checked) { - document.querySelector('.select_all').checked = false - } - }) - -} - -/** - * This function is executed when any page on the website finishes loading and - * this function retrieves the cookies if it is present on the user's machine. - * If it is available then the saved cookies is display in the cookies tab - * otherwise an appropriate message is displayed if it is not available. - * - * @function - * @listens DOMContentLoaded - * @returns {void} - */ -document.addEventListener( - 'DOMContentLoaded', - () => { - try { - // Decode the cookie value - let cookie = decodeURIComponent(document.cookie) - // Set the value of the input field to the decoded cookie value if it is not empty - // Otherwise, display a message indicating that no cookies have been saved on the user's system - if (cookie.length) { - document.querySelector('.cookies input').value = cookie - // This function displays the user provided settings on the settings page. - setClientSettingsOnPage(JSON.parse(cookie.replace("appCookie=", ""))) - } else { - document.querySelector('.cookies input').value = - 'No cookies have been saved on your system' - } - } catch (error) { - // If there is an error decoding the cookie, log the error to the console - // and display an error message in the input field - console.error('Error decoding cookie:', error) - document.querySelector('.cookies input').value = 'Error decoding cookie' - } - }, - false, -) diff --git a/public/static/error_box.js b/public/static/error_box.js deleted file mode 100644 index 1e2e874..0000000 --- a/public/static/error_box.js +++ /dev/null @@ -1,7 +0,0 @@ -/** - * This function provides the ability for the button to toggle the dropdown error-box - * in the search page. - */ -function toggleErrorBox() { - document.querySelector('.dropdown_error_box').classList.toggle('show') -} diff --git a/public/static/index.js b/public/static/index.js deleted file mode 100644 index 515065a..0000000 --- a/public/static/index.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Selects the input element for the search box - * @type {HTMLInputElement} - */ -const searchBox = document.querySelector('input') - -/** - * Redirects the user to the search results page with the query parameter - */ -function searchWeb() { - const query = searchBox.value.trim() - try { - let safeSearchLevel = document.querySelector('.search_options select').value - if (query) { - window.location.href = `search?q=${encodeURIComponent( - query, - )}&safesearch=${encodeURIComponent(safeSearchLevel)}` - } - } catch (error) { - if (query) { - window.location.href = `search?q=${encodeURIComponent(query)}` - } - } -} - -/** - * Listens for the 'Enter' key press event on the search box and calls the searchWeb function - * @param {KeyboardEvent} e - The keyboard event object - */ -searchBox.addEventListener('keyup', (e) => { - if (e.key === 'Enter') { - searchWeb() - } -}) diff --git a/public/static/pagination.js b/public/static/pagination.js deleted file mode 100644 index bdbfb39..0000000 --- a/public/static/pagination.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Navigates to the next page by incrementing the current page number in the URL query string. - * @returns {void} - */ -function navigate_forward() { - let url = new URL(window.location); - let searchParams = url.searchParams; - - let q = searchParams.get('q'); - let page = parseInt(searchParams.get('page')); - - if (isNaN(page)) { - page = 1; - } else { - page++; - } - - window.location.href = `${url.origin}${url.pathname}?q=${encodeURIComponent(q)}&page=${page}`; -} - -/** - * Navigates to the previous page by decrementing the current page number in the URL query string. - * @returns {void} - */ -function navigate_backward() { - let url = new URL(window.location); - let searchParams = url.searchParams; - - let q = searchParams.get('q'); - let page = parseInt(searchParams.get('page')); - - if (isNaN(page)) { - page = 0; - } else if (page > 0) { - page--; - } - - window.location.href = `${url.origin}${url.pathname}?q=${encodeURIComponent(q)}&page=${page}`; -} diff --git a/public/static/search_area_options.js b/public/static/search_area_options.js deleted file mode 100644 index 10e0390..0000000 --- a/public/static/search_area_options.js +++ /dev/null @@ -1,18 +0,0 @@ -document.addEventListener( - 'DOMContentLoaded', - () => { - let url = new URL(window.location) - let searchParams = url.searchParams - - let safeSearchLevel = searchParams.get('safesearch') - - if ( - safeSearchLevel >= 0 && - safeSearchLevel <= 2 && - safeSearchLevel !== null - ) { - document.querySelector('.search_options select').value = safeSearchLevel - } - }, - false, -) diff --git a/public/static/settings.js b/public/static/settings.js deleted file mode 100644 index 008136c..0000000 --- a/public/static/settings.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * This function handles the toggling of selections of all upstream search engines - * options in the settings page under the tab engines. - */ -function toggleAllSelection() { - document - .querySelectorAll('.engine') - .forEach( - (engine_checkbox) => - (engine_checkbox.checked = - document.querySelector('.select_all').checked), - ) -} - -/** - * This function adds the functionality to sidebar buttons to only show settings - * related to that tab. - * @param {HTMLElement} current_tab - The current tab that was clicked. - */ -function setActiveTab(current_tab) { - // Remove the active class from all tabs and buttons - document - .querySelectorAll('.tab') - .forEach((tab) => tab.classList.remove('active')) - document - .querySelectorAll('.btn') - .forEach((tab) => tab.classList.remove('active')) - - // Add the active class to the current tab and its corresponding settings - current_tab.classList.add('active') - document - .querySelector(`.${current_tab.innerText.toLowerCase().replace(' ', '_')}`) - .classList.add('active') -} - -/** - * This function adds the functionality to save all the user selected preferences - * to be saved in a cookie on the users machine. - */ -function setClientSettings() { - // Create an object to store the user's preferences - let cookie_dictionary = new Object() - - document.querySelectorAll('.engine').forEach((engine_checkbox) => { - cookie_dictionary[engine_checkbox.parentNode.parentNode.innerText.trim()] = engine_checkbox.checked - }) - - // Set the expiration date for the cookie to 1 year from the current date - let expiration_date = new Date() - expiration_date.setFullYear(expiration_date.getFullYear() + 1) - - // Save the cookie to the user's machine - document.cookie = `appCookie=${JSON.stringify( - cookie_dictionary, - )}; expires=${expiration_date.toUTCString()}` - - // Display a success message to the user - document.querySelector('.message').innerText = - '✅ The settings have been saved sucessfully!!' - - // Clear the success message after 10 seconds - setTimeout(() => { - document.querySelector('.message').innerText = '' - }, 10000) -} - diff --git a/src/main.rs b/src/main.rs index 5220edf..63efb07 100644 --- a/src/main.rs +++ b/src/main.rs @@ -86,7 +86,6 @@ async fn main() { .service(router::index) // index page .service(server::routes::search::search) // search page .service(router::about) // about page - .service(router::settings) // settings page .default_service(web::route().to(router::not_found)) // error page }) // Start server on 127.0.0.1 with the user provided port number. for example 127.0.0.1:8080. diff --git a/src/server/router.rs b/src/server/router.rs index 07698d3..e37c93e 100644 --- a/src/server/router.rs +++ b/src/server/router.rs @@ -2,11 +2,8 @@ //! meta search engine website and provide appropriate response to each route/page //! when requested. -use crate::{ - config::Config, - handler::{file_path, FileType}, -}; -use actix_web::{get, http::header::ContentType, web, HttpRequest, HttpResponse}; +use crate::handler::{file_path, FileType}; +use actix_web::{get, http::header::ContentType, HttpRequest, HttpResponse}; use tokio::fs::read_to_string; /// Handles the route of index page or main page of the `crabbysearch` meta search engine website. @@ -42,21 +39,3 @@ pub async fn about() -> Result> { .content_type(ContentType::html()) .body(crate::templates::views::about::about().0)) } - -/// Handles the route of settings page of the `crabbysearch` meta search engine website. -#[get("/settings")] -pub async fn settings( - config: web::Data, -) -> Result> { - Ok(HttpResponse::Ok().content_type(ContentType::html()).body( - crate::templates::views::settings::settings( - &config - .upstream_search_engines - .list() - .iter() - .map(|n| (*n, true)) - .collect(), - )? - .0, - )) -} diff --git a/src/templates/partials/bar.rs b/src/templates/partials/bar.rs index a7cd39a..7fb71d9 100644 --- a/src/templates/partials/bar.rs +++ b/src/templates/partials/bar.rs @@ -14,10 +14,15 @@ use maud::{html, Markup, PreEscaped}; /// It returns the compiled html code for the search bar as a result. pub fn bar(query: &str) -> Markup { html!( - (PreEscaped("
")) - input type="search" name="search-box" value=(query) placeholder="Type to search"; - button type="submit" onclick="searchWeb()" { - img src="./images/magnifying_glass.svg" alt="Info icon for error box"; + .search_container { + (PreEscaped("
")) + form action="/search" method="get" { + input type="search" name="query" value=(query) placeholder="Type to search"; + input type="hidden" name="page" value="0"; + button type="submit" { + img src="./images/magnifying_glass.svg" alt="Info icon for error box"; + } } + } ) } diff --git a/src/templates/partials/mod.rs b/src/templates/partials/mod.rs index 815909c..6aaab27 100644 --- a/src/templates/partials/mod.rs +++ b/src/templates/partials/mod.rs @@ -4,5 +4,3 @@ pub mod bar; pub mod footer; pub mod header; pub mod navbar; -pub mod search_bar; -pub mod settings_tabs; diff --git a/src/templates/partials/search_bar.rs b/src/templates/partials/search_bar.rs deleted file mode 100644 index 2e7b046..0000000 --- a/src/templates/partials/search_bar.rs +++ /dev/null @@ -1,76 +0,0 @@ -//! A module that handles `search bar` partial for the search page in the `crabbysearch` frontend. - -use maud::{html, Markup, PreEscaped}; - -use crate::{models::aggregation_models::EngineErrorInfo, templates::partials::bar::bar}; - -/// A constant holding the named safe search level options for the corresponding values 0, 1 and 2. -const SAFE_SEARCH_LEVELS_NAME: [&str; 3] = ["None", "Low", "Moderate"]; - -/// A functions that handles the html code for the search bar for the search page. -/// -/// # Arguments -/// -/// * `engine_errors_info` - It takes the engine errors list containing errors for each upstream -/// search engine which failed to provide results as an argument. -/// * `safe_search_level` - It takes the safe search level with values from 0-2 as an argument. -/// * `query` - It takes the current search query provided by user as an argument. -/// -/// # Returns -/// -/// It returns the compiled html code for the search bar as a result. -pub fn search_bar( - engine_errors_info: &[EngineErrorInfo], - safe_search_level: u8, - query: &str, -) -> Markup { - html!( - .search_area{ - (bar(query)) - .error_box { - @if !engine_errors_info.is_empty(){ - button onclick="toggleErrorBox()" class="error_box_toggle_button"{ - img src="./images/warning.svg" alt="Info icon for error box"; - } - .dropdown_error_box{ - @for errors in engine_errors_info{ - .error_item{ - span class="engine_name"{(errors.engine)} - span class="engine_name"{(errors.error)} - span class="severity_color" style="background: {{{this.severity_color}}};"{} - } - } - } - } - @else { - button onclick="toggleErrorBox()" class="error_box_toggle_button"{ - img src="./images/info.svg" alt="Warning icon for error box"; - } - .dropdown_error_box { - .no_errors{ - "Everything looks good 🙂!!" - } - } - } - } - (PreEscaped("
")) - .search_options { - @if safe_search_level >= 3 { - (PreEscaped("")) - } - @for (idx, name) in SAFE_SEARCH_LEVELS_NAME.iter().enumerate() { - @if (safe_search_level as usize) == idx { - option value=(idx) selected {(format!("SafeSearch: {name}"))} - } - @else{ - option value=(idx) {(format!("SafeSearch: {name}"))} - } - } - (PreEscaped("")) - } - } - ) -} diff --git a/src/templates/partials/settings_tabs/cookies.rs b/src/templates/partials/settings_tabs/cookies.rs deleted file mode 100644 index f17185b..0000000 --- a/src/templates/partials/settings_tabs/cookies.rs +++ /dev/null @@ -1,25 +0,0 @@ -//! A module that handles the engines tab for setting page view in the `crabbysearch` frontend. - -use maud::{html, Markup}; - -/// A functions that handles the html code for the cookies tab for the settings page for the search page. -/// -/// # Returns -/// -/// It returns the compiled html markup code for the cookies tab. -pub fn cookies() -> Markup { - html!( - div class="cookies tab"{ - h1{"Cookies"} - p class="description"{ - "This is the cookies are saved on your system and it contains the preferences - you chose in the settings page" - } - input type="text" name="cookie_field" value="" readonly; - p class="description"{ - "The cookies stored are not used by us for any malicious intend or for - tracking you in any way." - } - } - ) -} diff --git a/src/templates/partials/settings_tabs/engines.rs b/src/templates/partials/settings_tabs/engines.rs deleted file mode 100644 index 2d7e0d3..0000000 --- a/src/templates/partials/settings_tabs/engines.rs +++ /dev/null @@ -1,72 +0,0 @@ -//! A module that handles the engines tab for setting page view in the `crabbysearch` frontend. - -use maud::{html, Markup}; - -/// A functions that handles the html code for the engines tab for the settings page for the search page. -/// -/// # Arguments -/// -/// * `engine_names` - It takes the key value pair list of all available engine names and there corresponding -/// selected (enabled/disabled) value as an argument. -/// -/// # Returns -/// -/// It returns the compiled html markup code for the engines tab. -pub fn engines(engine_names: &Vec<(&str, bool)>) -> Markup { - html!( - div class="engines tab"{ - h1{"Engines"} - h3{"select search engines"} - p class="description"{ - "Select the search engines from the list of engines that you want results from" - } - .engine_selection{ - // Checks whether all the engines are selected or not if they are then the - // checked `select_all` button is rendered otherwise the unchecked version - // is rendered. - @if engine_names.iter().all(|selected| selected.1){ - .toggle_btn{ - label class="switch"{ - input type="checkbox" class="select_all" onchange="toggleAllSelection()" checked; - span class="slider round"{} - } - "Select All" - } - } - @else{ - .toggle_btn { - label class="switch"{ - input type="checkbox" class="select_all" onchange="toggleAllSelection()"; - span class="slider round"{} - } - "Select All" - } - } - hr; - @for (engine_name, selected) in engine_names{ - // Checks whether the `engine_name` is selected or not if they are then the - // checked `engine` button is rendered otherwise the unchecked version is - // rendered. - @if *selected { - .toggle_btn{ - label class="switch"{ - input type="checkbox" class="engine" checked; - span class="slider round"{} - } - (format!("{}{}",&engine_name[..1].to_uppercase(), &engine_name[1..])) - } - } - @else { - .toggle_btn { - label class="switch"{ - input type="checkbox" class="engine"; - span class="slider round"{} - } - (format!("{}{}",&engine_name[..1], &engine_name[1..])) - } - } - } - } - } - ) -} diff --git a/src/templates/partials/settings_tabs/mod.rs b/src/templates/partials/settings_tabs/mod.rs deleted file mode 100644 index 2154977..0000000 --- a/src/templates/partials/settings_tabs/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -//! This module provides other modules to handle the partials for the tabs for the settings page -//! view in the `crabbysearch` frontend. - -pub mod cookies; -pub mod engines; diff --git a/src/templates/views/mod.rs b/src/templates/views/mod.rs index a68e9bc..abfc190 100644 --- a/src/templates/views/mod.rs +++ b/src/templates/views/mod.rs @@ -5,4 +5,3 @@ pub mod about; pub mod index; pub mod not_found; pub mod search; -pub mod settings; diff --git a/src/templates/views/search.rs b/src/templates/views/search.rs index 38821c4..7a0dd63 100644 --- a/src/templates/views/search.rs +++ b/src/templates/views/search.rs @@ -4,7 +4,7 @@ use maud::{html, Markup, PreEscaped}; use crate::{ models::aggregation_models::SearchResults, - templates::partials::{footer::footer, header::header, search_bar::search_bar}, + templates::partials::{bar::bar, footer::footer, header::header}, }; /// A function that handles the html code for the search page view in the search engine frontend. @@ -23,7 +23,7 @@ pub fn search(query: &str, search_results: &SearchResults) -> Markup { html!( (header()) main class="results"{ - (search_bar(&search_results.engine_errors_info, search_results.safe_search_level, query)) + (bar(query)) .results_aggregated{ @if !search_results.results.is_empty() { @for result in search_results.results.iter(){ diff --git a/src/templates/views/settings.rs b/src/templates/views/settings.rs deleted file mode 100644 index 9d7fc40..0000000 --- a/src/templates/views/settings.rs +++ /dev/null @@ -1,52 +0,0 @@ -//! A module that handles the view for the settings page in the `crabbysearch` frontend. - -use maud::{html, Markup}; - -use crate::templates::partials::{ - footer::footer, - header::header, - settings_tabs::{cookies::cookies, engines::engines}, -}; - -/// A function that handles the html code for the settings page view in the search engine frontend. -/// -/// # Arguments -/// -/// * `safe_search_level` - It takes the safe search level as an argument. -/// * `colorscheme` - It takes the colorscheme name as an argument. -/// * `theme` - It takes the theme name as an argument. -/// * `animation` - It takes the animation name as an argument. -/// * `engine_names` - It takes a list of engine names as an argument. -/// -/// # Error -/// -/// This function returns a compiled html markup code on success otherwise returns a standard error -/// message. -pub fn settings( - engine_names: &Vec<(&'static str, bool)>, -) -> Result> { - Ok(html!( - (header()) - main class="settings"{ - h1{"Settings"} - hr; - .settings_container{ - .sidebar{ - div class="btn active" onclick="setActiveTab(this)"{"general"} - .btn onclick="setActiveTab(this)"{"user interface"} - .btn onclick="setActiveTab(this)"{"engines"} - .btn onclick="setActiveTab(this)"{"cookies"} - } - .main_container{ - (engines(&engine_names)) - (cookies()) - p class="message"{} - button type="submit" onclick="setClientSettings()"{"Save"} - } - } - } - script src="static/settings.js"{} - script src="static/cookies.js"{} - (footer()) - )) -} From 834131068491045bdd84384e70f6dd58b7585384 Mon Sep 17 00:00:00 2001 From: Milim Date: Thu, 15 Aug 2024 21:14:11 +0200 Subject: [PATCH 8/9] remove remains of query filtering anti-feature --- src/models/aggregation_models.rs | 21 +------------------- src/server/routes/search.rs | 9 ++------- src/templates/views/search.rs | 34 -------------------------------- 3 files changed, 3 insertions(+), 61 deletions(-) diff --git a/src/models/aggregation_models.rs b/src/models/aggregation_models.rs index c3c210b..4cad531 100644 --- a/src/models/aggregation_models.rs +++ b/src/models/aggregation_models.rs @@ -113,14 +113,6 @@ pub struct SearchResults { /// Stores the information on which engines failed with their engine name /// and the type of error that caused it. pub engine_errors_info: Vec, - /// Stores the flag option which holds the check value that the following - /// search query was disallowed when the safe search level set to 4 and it - /// was present in the `Blocklist` file. - pub disallowed: bool, - /// Stores the flag option which holds the check value that the following - /// search query was filtered when the safe search level set to 3 and it - /// was present in the `Blocklist` file. - pub filtered: bool, /// Stores the safe search level `safesearch` provided in the search url. pub safe_search_level: u8, /// Stores the flag option which holds the check value that whether any search engines were @@ -143,23 +135,12 @@ impl SearchResults { Self { results, engine_errors_info: engine_errors_info.to_owned(), - disallowed: Default::default(), - filtered: Default::default(), + safe_search_level: Default::default(), no_engines_selected: Default::default(), } } - /// A setter function that sets disallowed to true. - pub fn set_disallowed(&mut self) { - self.disallowed = true; - } - - /// A setter function that sets the filtered to true. - pub fn set_filtered(&mut self, filtered: bool) { - self.filtered = filtered; - } - /// A getter function that gets the value of `engine_errors_info`. pub fn engine_errors_info(&mut self) -> Vec { std::mem::take(&mut self.engine_errors_info) diff --git a/src/server/routes/search.rs b/src/server/routes/search.rs index e5f1196..ae6cf74 100644 --- a/src/server/routes/search.rs +++ b/src/server/routes/search.rs @@ -142,7 +142,7 @@ async fn results( // default selected upstream search engines from the config file otherwise // parse the non-empty cookie and grab the user selected engines from the // UI and use that. - let mut results: SearchResults = match false { + let results: SearchResults = match false { false => aggregate(query, page, config, &Vec::::from(upstream)).await?, true => { let mut search_results = SearchResults::default(); @@ -150,12 +150,7 @@ async fn results( search_results } }; - let (engine_errors_info, results_empty_check, no_engines_selected) = ( - results.engine_errors_info().is_empty(), - results.results().is_empty(), - results.no_engines_selected(), - ); - results.set_filtered(engine_errors_info & results_empty_check & !no_engines_selected); + cache.cache_results(&[results.clone()], &[cache_key.clone()]); Ok((results, cache_key)) } diff --git a/src/templates/views/search.rs b/src/templates/views/search.rs index 7a0dd63..94ca508 100644 --- a/src/templates/views/search.rs +++ b/src/templates/views/search.rs @@ -39,40 +39,6 @@ pub fn search(query: &str, search_results: &SearchResults) -> Markup { } } } - @else if search_results.disallowed{ - .result_disallowed{ - .description{ - p{ - "Your search - "{span class="user_query"{(query)}}" - - has been disallowed." - } - p class="description_paragraph"{"Dear user,"} - p class="description_paragraph"{ - "The query - "{span class="user_query"{(query)}}" - has - been blacklisted via server configuration and hence disallowed by the - server. Henceforth no results could be displayed for your query." - } - } - img src="./images/barricade.png" alt="Image of a Barricade"; - } - } - @else if search_results.filtered { - .result_filtered{ - .description{ - p{ - "Your search - "{span class="user_query"{(query)}}" - - has been filtered." - } - p class="description_paragraph"{"Dear user,"} - p class="description_paragraph"{ - "All the search results contain results that has been configured to be - filtered out via server configuration and henceforth has been - completely filtered out." - } - } - img src="./images/filter.png" alt="Image of a paper inside a funnel"; - } - } @else if search_results.no_engines_selected { .result_engine_not_selected{ .description{ From 7f7367a34d62ac7aefc33ef39fa01f264df82ba1 Mon Sep 17 00:00:00 2001 From: morrigan Date: Sun, 16 Feb 2025 16:35:39 +0100 Subject: [PATCH 9/9] remove github stuf --- .github/dependabot.yml | 14 ------------ public/static/themes/simple.css | 36 ++++++++++++++--------------- src/models/server_models.rs | 2 +- src/results/aggregator.rs | 4 +--- src/server/routes/search.rs | 5 ++-- src/templates/partials/bar.rs | 39 ++++++++++++++++++++++++++------ src/templates/partials/header.rs | 5 +--- src/templates/partials/mod.rs | 1 - src/templates/partials/navbar.rs | 19 ---------------- src/templates/views/index.rs | 14 ++++-------- src/templates/views/search.rs | 2 +- 11 files changed, 61 insertions(+), 80 deletions(-) delete mode 100644 .github/dependabot.yml delete mode 100644 src/templates/partials/navbar.rs diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index dc1715a..0000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,14 +0,0 @@ -version: 2 -updates: - - package-ecosystem: "cargo" - directory: "/" - schedule: - interval: "monthly" - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "monthly" - - package-ecosystem: "docker" - directory: "/" - schedule: - interval: "monthly" diff --git a/public/static/themes/simple.css b/public/static/themes/simple.css index 8f5fcc7..770cb04 100644 --- a/public/static/themes/simple.css +++ b/public/static/themes/simple.css @@ -35,19 +35,19 @@ button { /* styles for the index page */ -.search-container { +.search_container { display: flex; - flex-direction: column; + flex-direction: row; gap: 5rem; justify-content: center; align-items: center; } -.search-container svg { +.search_container svg { color: var(--logo-color); } -.search-container div { +.search_container div { display: flex; } @@ -102,10 +102,10 @@ button { } .search_bar button img { - position:absolute; - left:50%; - top:50%; - transform:translate(-50%, -50%); + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); } .search_bar button:active { @@ -336,7 +336,7 @@ footer div { .results_aggregated { display: flex; flex-direction: column; - justify-content: space-between; + justify-content: space-between; margin: 2rem 0; content-visibility: auto; } @@ -593,7 +593,7 @@ footer div { font-size: 2.5rem; } -.settings > h1 { +.settings>h1 { margin-bottom: 4rem; margin-left: 2rem; } @@ -603,7 +603,7 @@ footer div { margin: 0.3rem 0 1rem; } -.settings > hr { +.settings>hr { margin-left: 2rem; } @@ -796,15 +796,15 @@ footer div { transition: .2s; } -input:checked + .slider { +input:checked+.slider { background-color: var(--color-three); } -input:focus + .slider { +input:focus+.slider { box-shadow: 0 0 1px var(--color-three); } -input:checked + .slider::before { +input:checked+.slider::before { transform: translateX(2.6rem); } @@ -817,7 +817,7 @@ input:checked + .slider::before { border-radius: 50%; } -@media screen and (width <= 1136px) { +@media screen and (width <=1136px) { .hero-text-container { width: unset; } @@ -827,7 +827,7 @@ input:checked + .slider::before { } } -@media screen and (width <= 706px) { +@media screen and (width <=706px) { .about-container article .logo-container svg { width: clamp(200px, 290px, 815px); } @@ -851,7 +851,7 @@ input:checked + .slider::before { .features { grid-template-columns: 1fr; } - + .feature-list { padding: 35px 0; } @@ -859,4 +859,4 @@ input:checked + .slider::before { .feature-card { border-radius: 0; } -} +} \ No newline at end of file diff --git a/src/models/server_models.rs b/src/models/server_models.rs index 81de741..c73352c 100644 --- a/src/models/server_models.rs +++ b/src/models/server_models.rs @@ -7,7 +7,7 @@ use serde::Deserialize; pub struct SearchParams { /// It stores the search parameter option `q` (or query in simple words) /// of the search url. - pub q: Option, + pub query: Option, /// It stores the search parameter `page` (or pageno in simple words) /// of the search url. pub page: Option, diff --git a/src/results/aggregator.rs b/src/results/aggregator.rs index 7386bb2..a7116c6 100644 --- a/src/results/aggregator.rs +++ b/src/results/aggregator.rs @@ -147,9 +147,7 @@ pub async fn aggregate( }; } - let mut results: Vec = - result_map.iter().map(|(_, value)| value.clone()).collect(); + let results: Vec = result_map.iter().map(|(_, value)| value.clone()).collect(); - results.sort_by(|a, b| a.description.len().cmp(&b.description.len())); Ok(SearchResults::new(results, &engine_errors_info)) } diff --git a/src/server/routes/search.rs b/src/server/routes/search.rs index ae6cf74..d2f34af 100644 --- a/src/server/routes/search.rs +++ b/src/server/routes/search.rs @@ -35,13 +35,14 @@ pub async fn search( ) -> Result> { let params = web::Query::::from_query(req.query_string())?; - if params.q.as_ref().is_some_and(|q| q.trim().is_empty()) || params.q.is_none() { + if params.query.as_ref().is_some_and(|q| q.trim().is_empty()) || params.query.is_none() { + log::info!("wha!"); return Ok(HttpResponse::TemporaryRedirect() .insert_header(("location", "/")) .finish()); } - let query = params.q.as_ref().unwrap().trim(); + let query = params.query.as_ref().unwrap().trim(); let cookie = req.cookie("appCookie"); diff --git a/src/templates/partials/bar.rs b/src/templates/partials/bar.rs index 7fb71d9..1ad9288 100644 --- a/src/templates/partials/bar.rs +++ b/src/templates/partials/bar.rs @@ -1,6 +1,6 @@ //! A module that handles `bar` partial for the `search_bar` partial and the home/index/main page in the `crabbysearch` frontend. -use maud::{html, Markup, PreEscaped}; +use maud::{html, Markup}; /// A functions that handles the html code for the bar for the `search_bar` partial and the /// home/index/main page in the search engine frontend. @@ -12,15 +12,40 @@ use maud::{html, Markup, PreEscaped}; /// # Returns /// /// It returns the compiled html code for the search bar as a result. -pub fn bar(query: &str) -> Markup { +pub fn bar(query: &str, engines: Vec<(&'static str, bool)>) -> Markup { html!( .search_container { - (PreEscaped("
")) form action="/search" method="get" { - input type="search" name="query" value=(query) placeholder="Type to search"; - input type="hidden" name="page" value="0"; - button type="submit" { - img src="./images/magnifying_glass.svg" alt="Info icon for error box"; + div class="search_bar" { + input type="search" name="query" value=(query) placeholder="Type to search"; + input type="hidden" name="page" value="1"; + button type="submit" { + img src="./images/magnifying_glass.svg" alt="Info icon for error box"; + } + } + div class="search_bar" { + .engine_selection { + @for (name, selected) in engines{ + @if selected { + .toggle_btn{ + span {(name)} + label class="switch"{ + input type="checkbox" class="engine" checked; + span class="slider round"{} + } + } + } + @else { + .toggle_btn { + (name) + label class="switch"{ + input type="checkbox" class="engine"; + span class="slider round"{} + } + } + } + } + } } } } diff --git a/src/templates/partials/header.rs b/src/templates/partials/header.rs index 43dfe80..38e4de4 100644 --- a/src/templates/partials/header.rs +++ b/src/templates/partials/header.rs @@ -1,7 +1,6 @@ //! A module that handles the header for all the pages in the `crabbysearch` frontend. -use crate::templates::partials::navbar::navbar; -use maud::{html, Markup, PreEscaped, DOCTYPE}; +use maud::{html, Markup, DOCTYPE}; /// A function that handles the html code for the header for all the pages in the search engine frontend. /// @@ -26,10 +25,8 @@ pub fn header() -> Markup { link href=("static/themes/simple.css") rel="stylesheet" type="text/css"; } - (PreEscaped("")) header{ h1{a href="/"{"crabbysearch"}} - (navbar()) } ) } diff --git a/src/templates/partials/mod.rs b/src/templates/partials/mod.rs index 6aaab27..b2c71da 100644 --- a/src/templates/partials/mod.rs +++ b/src/templates/partials/mod.rs @@ -3,4 +3,3 @@ pub mod bar; pub mod footer; pub mod header; -pub mod navbar; diff --git a/src/templates/partials/navbar.rs b/src/templates/partials/navbar.rs deleted file mode 100644 index 92d6450..0000000 --- a/src/templates/partials/navbar.rs +++ /dev/null @@ -1,19 +0,0 @@ -//! A module that handles `navbar` partial for the header partial in the `crabbysearch` frontend. - -use maud::{html, Markup}; - -/// A functions that handles the html code for the header partial. -/// -/// # Returns -/// -/// It returns the compiled html code for the navbar as a result. -pub fn navbar() -> Markup { - html!( - nav{ - ul{ - li{a href="about"{"about"}} - li{a href="settings"{"settings"}} - } - } - ) -} diff --git a/src/templates/views/index.rs b/src/templates/views/index.rs index bcf5809..ac2a807 100644 --- a/src/templates/views/index.rs +++ b/src/templates/views/index.rs @@ -1,6 +1,6 @@ //! A module that handles the view for the index/home/main page in the `crabbysearch` frontend. -use maud::{html, Markup, PreEscaped}; +use maud::{html, Markup}; use crate::templates::partials::{bar::bar, footer::footer, header::header}; @@ -15,13 +15,7 @@ use crate::templates::partials::{bar::bar, footer::footer, header::header}; /// /// It returns the compiled html markup code as a result. pub fn index() -> Markup { - html!( - (header()) - main class="search-container"{ - (bar(&String::default())) - (PreEscaped("
")) - } - script src="static/index.js"{} - (footer()) - ) + html!((header())(bar(&String::default(), vec![("bing", true)]))( + footer() + )) } diff --git a/src/templates/views/search.rs b/src/templates/views/search.rs index 94ca508..254025c 100644 --- a/src/templates/views/search.rs +++ b/src/templates/views/search.rs @@ -23,7 +23,7 @@ pub fn search(query: &str, search_results: &SearchResults) -> Markup { html!( (header()) main class="results"{ - (bar(query)) + (bar(query, vec![("Bing", true)])) .results_aggregated{ @if !search_results.results.is_empty() { @for result in search_results.results.iter(){