0
0
mirror of https://github.com/neon-mmd/websurfx.git synced 2024-12-24 21:38:22 -05:00

Merge branch 'rolling' into rolling

This commit is contained in:
mergify[bot] 2023-12-30 06:58:26 +00:00 committed by GitHub
commit bdc5170c87
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 447 additions and 144 deletions

132
Cargo.lock generated
View File

@ -65,15 +65,15 @@ checksum = "a2e7b88f3804e01bd4191fdb08650430bbfcb43d3d9b2890064df3551ec7d25b"
dependencies = [
"actix-http",
"actix-web",
"futures 0.3.29",
"futures 0.3.30",
"governor",
]
[[package]]
name = "actix-http"
version = "3.4.0"
version = "3.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a92ef85799cba03f76e4f7c10f533e66d87c9a7e7055f3391f09000ad8351bc9"
checksum = "129d4c88e98860e1758c5de288d1632b07970a16d59bdf7b8d66053d582bb71f"
dependencies = [
"actix-codec",
"actix-rt",
@ -111,14 +111,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb"
dependencies = [
"quote 1.0.33",
"syn 2.0.42",
"syn 2.0.43",
]
[[package]]
name = "actix-router"
version = "0.5.1"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d66ff4d247d2b160861fa2866457e85706833527840e4133f8f49aa423a38799"
checksum = "d22475596539443685426b6bdadb926ad0ecaefdfc5fb05e5e3441f15463c511"
dependencies = [
"bytestring",
"http 0.2.11",
@ -177,9 +177,9 @@ dependencies = [
[[package]]
name = "actix-web"
version = "4.4.0"
version = "4.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e4a5b5e29603ca8c94a77c65cf874718ceb60292c5a5c3e5f4ace041af462b9"
checksum = "e43428f3bf11dee6d166b00ec2df4e3aa8cc1606aaa0b7433c146852e2f4e03b"
dependencies = [
"actix-codec",
"actix-http",
@ -224,7 +224,7 @@ dependencies = [
"actix-router",
"proc-macro2 1.0.71",
"quote 1.0.33",
"syn 2.0.42",
"syn 2.0.43",
]
[[package]]
@ -313,9 +313,9 @@ checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
[[package]]
name = "anyhow"
version = "1.0.76"
version = "1.0.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59d2a3357dde987206219e78ecfbbb6e8dad06cbb65292758d3270e6254f7355"
checksum = "c9d19de80eff169429ac1e9f48fffb163916b448a44e8e046186232046d9e1f9"
[[package]]
name = "arc-swap"
@ -369,7 +369,7 @@ checksum = "fdf6721fb0140e4f897002dd086c06f6c27775df19cfe1fccb21181a48fd2c98"
dependencies = [
"proc-macro2 1.0.71",
"quote 1.0.33",
"syn 2.0.42",
"syn 2.0.43",
]
[[package]]
@ -552,9 +552,9 @@ dependencies = [
[[package]]
name = "cargo-platform"
version = "0.1.5"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e34637b3140142bdf929fb439e8aa4ebad7651ebf7b1080b3930aa16ac1459ff"
checksum = "ceed8ef69d8518a5dda55c07425450b58a4e1946f4951eab6d7191ee86c2443d"
dependencies = [
"serde",
]
@ -824,12 +824,12 @@ dependencies = [
[[package]]
name = "crossbeam-channel"
version = "0.5.9"
version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c3242926edf34aec4ac3a77108ad4854bffaa2e4ddc1824124ce59231302d5"
checksum = "82a9b73a36529d9c47029b9fb3a6f0ea3cc916a261195352ba19e770fc1748b2"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-utils 0.8.17",
"crossbeam-utils 0.8.18",
]
[[package]]
@ -882,9 +882,9 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
version = "0.8.17"
version = "0.8.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f"
checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c"
dependencies = [
"cfg-if 1.0.0",
]
@ -941,7 +941,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
dependencies = [
"quote 1.0.33",
"syn 2.0.42",
"syn 2.0.43",
]
[[package]]
@ -1232,9 +1232,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678"
[[package]]
name = "futures"
version = "0.3.29"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335"
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
dependencies = [
"futures-channel",
"futures-core",
@ -1247,9 +1247,9 @@ dependencies = [
[[package]]
name = "futures-channel"
version = "0.3.29"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
dependencies = [
"futures-core",
"futures-sink",
@ -1257,9 +1257,9 @@ dependencies = [
[[package]]
name = "futures-core"
version = "0.3.29"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
[[package]]
name = "futures-cpupool"
@ -1273,9 +1273,9 @@ dependencies = [
[[package]]
name = "futures-executor"
version = "0.3.29"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc"
checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
dependencies = [
"futures-core",
"futures-task",
@ -1284,32 +1284,32 @@ dependencies = [
[[package]]
name = "futures-io"
version = "0.3.29"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
[[package]]
name = "futures-macro"
version = "0.3.29"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2 1.0.71",
"quote 1.0.33",
"syn 2.0.42",
"syn 2.0.43",
]
[[package]]
name = "futures-sink"
version = "0.3.29"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
[[package]]
name = "futures-task"
version = "0.3.29"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
[[package]]
name = "futures-timer"
@ -1319,9 +1319,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c"
[[package]]
name = "futures-util"
version = "0.3.29"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [
"futures-channel",
"futures-core",
@ -1394,7 +1394,7 @@ checksum = "821239e5672ff23e2a7060901fa622950bbd80b649cdaadd78d1c1767ed14eb4"
dependencies = [
"cfg-if 1.0.0",
"dashmap",
"futures 0.3.29",
"futures 0.3.30",
"futures-timer",
"no-std-compat",
"nonzero_ext",
@ -1725,13 +1725,13 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
[[package]]
name = "is-terminal"
version = "0.4.9"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455"
dependencies = [
"hermit-abi",
"rustix",
"windows-sys 0.48.0",
"windows-sys 0.52.0",
]
[[package]]
@ -2018,7 +2018,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23e0b72e7c9042467008b10279fc732326bd605459ae03bda88825909dd19b56"
dependencies = [
"crossbeam-channel",
"crossbeam-utils 0.8.17",
"crossbeam-utils 0.8.18",
"dashmap",
"skeptic",
"smallvec 1.11.2",
@ -2198,9 +2198,9 @@ dependencies = [
[[package]]
name = "object"
version = "0.32.1"
version = "0.32.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
dependencies = [
"memchr",
]
@ -2240,7 +2240,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2 1.0.71",
"quote 1.0.33",
"syn 2.0.42",
"syn 2.0.43",
]
[[package]]
@ -2451,7 +2451,7 @@ dependencies = [
"phf_shared 0.11.2",
"proc-macro2 1.0.71",
"quote 1.0.33",
"syn 2.0.42",
"syn 2.0.43",
]
[[package]]
@ -2498,7 +2498,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
dependencies = [
"proc-macro2 1.0.71",
"quote 1.0.33",
"syn 2.0.42",
"syn 2.0.43",
]
[[package]]
@ -2606,7 +2606,7 @@ version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a17e662a7a8291a865152364c20c7abc5e60486ab2001e8ec10b24862de0b9ab"
dependencies = [
"crossbeam-utils 0.8.17",
"crossbeam-utils 0.8.18",
"libc",
"mach2",
"once_cell",
@ -2798,7 +2798,7 @@ dependencies = [
"async-trait",
"bytes 1.5.0",
"combine",
"futures 0.3.29",
"futures 0.3.30",
"futures-util",
"itoa 1.0.10",
"percent-encoding 2.3.1",
@ -3047,11 +3047,11 @@ dependencies = [
[[package]]
name = "schannel"
version = "0.1.22"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88"
checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534"
dependencies = [
"windows-sys 0.48.0",
"windows-sys 0.52.0",
]
[[package]]
@ -3178,7 +3178,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
dependencies = [
"proc-macro2 1.0.71",
"quote 1.0.33",
"syn 2.0.42",
"syn 2.0.43",
]
[[package]]
@ -3414,9 +3414,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.42"
version = "2.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b7d0a2c048d661a1a59fcd7355baa232f7ed34e0ee4df2eef3c1c1c0d3852d8"
checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53"
dependencies = [
"proc-macro2 1.0.71",
"quote 1.0.33",
@ -3474,15 +3474,15 @@ checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417"
[[package]]
name = "tempfile"
version = "3.8.1"
version = "3.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5"
checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa"
dependencies = [
"cfg-if 1.0.0",
"fastrand",
"redox_syscall 0.4.1",
"rustix",
"windows-sys 0.48.0",
"windows-sys 0.52.0",
]
[[package]]
@ -3655,7 +3655,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2 1.0.71",
"quote 1.0.33",
"syn 2.0.42",
"syn 2.0.43",
]
[[package]]
@ -3993,7 +3993,7 @@ dependencies = [
"once_cell",
"proc-macro2 1.0.71",
"quote 1.0.33",
"syn 2.0.42",
"syn 2.0.43",
"wasm-bindgen-shared",
]
@ -4027,7 +4027,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
dependencies = [
"proc-macro2 1.0.71",
"quote 1.0.33",
"syn 2.0.42",
"syn 2.0.43",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@ -4056,7 +4056,7 @@ checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10"
[[package]]
name = "websurfx"
version = "1.6.8"
version = "1.6.11"
dependencies = [
"actix-cors",
"actix-files",
@ -4070,7 +4070,7 @@ dependencies = [
"env_logger",
"error-stack",
"fake-useragent",
"futures 0.3.29",
"futures 0.3.30",
"lightningcss",
"log",
"maud",
@ -4324,5 +4324,5 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [
"proc-macro2 1.0.71",
"quote 1.0.33",
"syn 2.0.42",
"syn 2.0.43",
]

View File

@ -1,6 +1,6 @@
[package]
name = "websurfx"
version = "1.6.8"
version = "1.6.11"
edition = "2021"
description = "An open-source alternative to Searx that provides clean, ad-free, and organic results with incredible speed while keeping privacy and security in mind."
repository = "https://github.com/neon-mmd/websurfx"

View File

@ -60,4 +60,4 @@
# calls the build function
packages.websurfx = packages.default;
});
}

View File

@ -1,3 +1,62 @@
/**
* 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) {
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')
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
}
})
})
}
}
/**
* 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.
@ -16,9 +75,14 @@ document.addEventListener(
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
document.querySelector('.cookies input').value = cookie.length
? cookie
: 'No cookies have been saved on your system'
if (cookie.length) {
document.querySelector('.cookies input').value = cookie
// This function displays the user provided settings on the settings page.
setClientSettingsOnPage(cookie)
} 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

View File

@ -600,12 +600,20 @@ footer div {
text-transform: capitalize;
}
.settings_container .tab .description {
.settings_container .tab .description,
.settings_container .tab .admin_warning {
font-size: 1.5rem;
margin-bottom: 0.5rem;
}
.settings_container .tab .description {
color: var(--foreground-color);
}
.settings_container .tab .admin_warning {
color: var(--color-two);
}
.settings_container .user_interface select,
.settings_container .general select {
margin: 0.7rem 0;

View File

@ -6,6 +6,7 @@
pub mod brave;
pub mod duckduckgo;
pub mod librex;
pub mod mojeek;
pub mod search_result_parser;
pub mod searx;
pub mod startpage;

151
src/engines/mojeek.rs Normal file
View File

@ -0,0 +1,151 @@
//! The `mojeek` module handles the scraping of results from the mojeek search engine
//! by querying the upstream mojeek search engine with user provided query and with a page
//! number if provided.
use std::collections::HashMap;
use reqwest::header::HeaderMap;
use reqwest::Client;
use scraper::Html;
use crate::models::aggregation_models::SearchResult;
use crate::models::engine_models::{EngineError, SearchEngine};
use error_stack::{Report, Result, ResultExt};
use super::search_result_parser::SearchResultParser;
/// A new Mojeek engine type defined in-order to implement the `SearchEngine` trait which allows to
/// reduce code duplication as well as allows to create vector of different search engines easily.
pub struct Mojeek {
/// The parser, used to interpret the search result.
parser: SearchResultParser,
}
impl Mojeek {
/// Creates the Mojeek parser.
pub fn new() -> Result<Self, EngineError> {
Ok(Self {
parser: SearchResultParser::new(
".result-col",
".results-standard li",
"a span.url",
"h2 a.title",
"p.s",
)?,
})
}
}
#[async_trait::async_trait]
impl SearchEngine for Mojeek {
async fn results(
&self,
query: &str,
page: u32,
user_agent: &str,
client: &Client,
safe_search: u8,
) -> Result<HashMap<String, SearchResult>, EngineError> {
// Mojeek uses `start results from this number` convention
// So, for 10 results per page, page 0 starts at 1, page 1
// starts at 11, and so on.
let results_per_page = 10;
let start_result = results_per_page * page + 1;
let results_per_page = results_per_page.to_string();
let start_result = start_result.to_string();
let search_engines = vec![
"Bing",
"Brave",
"DuckDuckGo",
"Ecosia",
"Google",
"Lilo",
"Metager",
"Qwant",
"Startpage",
"Swisscows",
"Yandex",
"Yep",
"You",
];
let qss = search_engines.join("%2C");
let safe = if safe_search == 0 { "0" } else { "1" };
// Mojeek detects automated requests, these are preferences that are
// able to circumvent the countermeasure. Some of these are
// not documented in their Search API
let query_params: Vec<(&str, &str)> = vec![
("t", results_per_page.as_str()),
("theme", "dark"),
("arc", "none"),
("date", "1"),
("cdate", "1"),
("tlen", "100"),
("ref", "1"),
("hp", "minimal"),
("lb", "en"),
("qss", &qss),
("safe", safe),
];
let mut query_params_string = String::new();
for (k, v) in &query_params {
query_params_string.push_str(&format!("&{k}={v}"));
}
let url: String = match page {
0 => {
format!("https://www.mojeek.com/search?q={query}{query_params_string}")
}
_ => {
format!(
"https://www.mojeek.com/search?q={query}&s={start_result}{query_params_string}"
)
}
};
let mut cookie_string = String::new();
for (k, v) in &query_params {
cookie_string.push_str(&format!("{k}={v}; "));
}
let header_map = HeaderMap::try_from(&HashMap::from([
("USER_AGENT".to_string(), user_agent.to_string()),
("REFERER".to_string(), "https://google.com/".to_string()),
(
"CONTENT_TYPE".to_string(),
"application/x-www-form-urlencoded".to_string(),
),
("COOKIE".to_string(), cookie_string),
]))
.change_context(EngineError::UnexpectedError)?;
let document: Html = Html::parse_document(
&Mojeek::fetch_html_from_upstream(self, &url, header_map, client).await?,
);
if let Some(no_result_msg) = self.parser.parse_for_no_results(&document).nth(0) {
if no_result_msg
.inner_html()
.contains("No pages found matching:")
{
return Err(Report::new(EngineError::EmptyResultSet));
}
}
// scrape all the results from the html
self.parser
.parse_for_results(&document, |title, url, desc| {
Some(SearchResult::new(
title.inner_html().trim(),
url.inner_html().trim(),
desc.inner_html().trim(),
&["mojeek"],
))
})
}
}

View File

@ -162,6 +162,10 @@ impl EngineHandler {
let engine = crate::engines::librex::LibreX::new()?;
("librex", Box::new(engine))
}
"mojeek" => {
let engine = crate::engines::mojeek::Mojeek::new()?;
("mojeek", Box::new(engine))
}
_ => {
return Err(Report::from(EngineError::NoSuchEngineFound(
engine_name.to_string(),

View File

@ -12,14 +12,16 @@ use std::fs::read_to_string;
/// Handles the route of index page or main page of the `websurfx` meta search engine website.
#[get("/")]
pub async fn index(config: web::Data<Config>) -> Result<HttpResponse, Box<dyn std::error::Error>> {
Ok(HttpResponse::Ok().body(
crate::templates::views::index::index(
&config.style.colorscheme,
&config.style.theme,
&config.style.animation,
)
.0,
))
Ok(HttpResponse::Ok()
.content_type("text/html; charset=utf-8")
.body(
crate::templates::views::index::index(
&config.style.colorscheme,
&config.style.theme,
&config.style.animation,
)
.0,
))
}
/// Handles the route of any other accessed route/page which is not provided by the
@ -52,14 +54,16 @@ pub async fn robots_data(_req: HttpRequest) -> Result<HttpResponse, Box<dyn std:
/// Handles the route of about page of the `websurfx` meta search engine website.
#[get("/about")]
pub async fn about(config: web::Data<Config>) -> Result<HttpResponse, Box<dyn std::error::Error>> {
Ok(HttpResponse::Ok().body(
crate::templates::views::about::about(
&config.style.colorscheme,
&config.style.theme,
&config.style.animation,
)
.0,
))
Ok(HttpResponse::Ok()
.content_type("text/html; charset=utf-8")
.body(
crate::templates::views::about::about(
&config.style.colorscheme,
&config.style.theme,
&config.style.animation,
)
.0,
))
}
/// Handles the route of settings page of the `websurfx` meta search engine website.
@ -67,16 +71,16 @@ pub async fn about(config: web::Data<Config>) -> Result<HttpResponse, Box<dyn st
pub async fn settings(
config: web::Data<Config>,
) -> Result<HttpResponse, Box<dyn std::error::Error>> {
Ok(HttpResponse::Ok().body(
crate::templates::views::settings::settings(
&config.style.colorscheme,
&config.style.theme,
&config.style.animation,
&config
.upstream_search_engines
.keys()
.collect::<Vec<&String>>(),
)?
.0,
))
Ok(HttpResponse::Ok()
.content_type("text/html; charset=utf-8")
.body(
crate::templates::views::settings::settings(
config.safe_search,
&config.style.colorscheme,
&config.style.theme,
&config.style.animation,
&config.upstream_search_engines,
)?
.0,
))
}

View File

@ -59,25 +59,27 @@ pub async fn search(
)
};
// .max(1) makes sure that the page > 0.
let page = params.page.unwrap_or(1).max(1);
// .max(1) makes sure that the page >= 0.
let page = params.page.unwrap_or(1).max(1) - 1;
let (_, results, _) = join!(
get_results(page - 1),
get_results(page.saturating_sub(1)),
get_results(page),
get_results(page + 1)
);
Ok(HttpResponse::Ok().body(
crate::templates::views::search::search(
&config.style.colorscheme,
&config.style.theme,
&config.style.animation,
query,
&results?,
)
.0,
))
Ok(HttpResponse::Ok()
.content_type("text/html; charset=utf-8")
.body(
crate::templates::views::search::search(
&config.style.colorscheme,
&config.style.theme,
&config.style.animation,
query,
&results?,
)
.0,
))
}
None => Ok(HttpResponse::TemporaryRedirect()
.insert_header(("location", "/"))

View File

@ -1,17 +1,20 @@
//! A module that handles the engines tab for setting page view in the `websurfx` 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.
///
/// # Arguments
///
/// * `engine_names` - It takes the list of all available engine names as an argument.
/// * `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: &[&String]) -> Markup {
pub fn engines(engine_names: &HashMap<String, bool>) -> Markup {
html!(
div class="engines tab"{
h1{"Engines"}
@ -20,21 +23,49 @@ pub fn engines(engine_names: &[&String]) -> Markup {
"Select the search engines from the list of engines that you want results from"
}
.engine_selection{
.toggle_btn{
label class="switch"{
input type="checkbox" class="select_all" onchange="toggleAllSelection()";
span class="slider round"{}
}
"Select All"
// 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){
.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 in engine_names{
.toggle_btn{
label class="switch"{
input type="checkbox" class="engine";
span class="slider round"{}
@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().to_owned(), engine_name[1..].to_owned()))
}
}
@else {
.toggle_btn {
label class="switch"{
input type="checkbox" class="engine";
span class="slider round"{}
}
(format!("{}{}",engine_name[..1].to_uppercase().to_owned(), engine_name[1..].to_owned()))
}
(format!("{}{}",engine_name[..1].to_uppercase().to_owned(), engine_name[1..].to_owned()))
}
}
}

View File

@ -7,10 +7,14 @@ const SAFE_SEARCH_LEVELS: [(u8, &str); 3] = [(0, "None"), (1, "Low"), (2, "Moder
/// A functions that handles the html code for the general tab for the settings page for the search page.
///
/// # Arguments
///
/// * `safe_search_level` - It takes the safe search level as an argument.
///
/// # Returns
///
/// It returns the compiled html markup code for the general tab.
pub fn general() -> Markup {
pub fn general(safe_search_level: u8) -> Markup {
html!(
div class="general tab active"{
h1{"General"}
@ -18,9 +22,19 @@ pub fn general() -> Markup {
p class="description"{
"Select a safe search level from the menu below to filter content based on the level."
}
select name="safe_search_levels"{
@for (k,v) in SAFE_SEARCH_LEVELS{
option value=(k){(v)}
@if safe_search_level < 3 {
select name="safe_search_levels" {
// Sets the user selected safe_search_level name from the config file as the first option in the selection list.
option value=(safe_search_level){(SAFE_SEARCH_LEVELS.iter().find(|level| level.0 == safe_search_level).unwrap().1)}
@for (k,v) in SAFE_SEARCH_LEVELS.iter().filter(|level| level.0 != safe_search_level){
option value=(k){(v)}
}
}
}
@else {
p class="admin_warning" {"⚠️ This setting is being managed by the server administrator."}
select name="safe_search_levels" disabled {
option value=(SAFE_SEARCH_LEVELS[2].0){(SAFE_SEARCH_LEVELS[2].1)}
}
}
}

View File

@ -4,13 +4,16 @@ 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 names
/// present in the colorschemes and themes folder respectively.
/// 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
///
@ -18,7 +21,8 @@ use std::fs::read_dir;
/// returns a standard error message.
fn style_option_list(
style_type: &str,
) -> Result<Vec<(String, String)>, Box<dyn std::error::Error + '_>> {
selected_style: &str,
) -> Result<Vec<(String, String)>, Box<dyn std::error::Error>> {
let mut style_option_names: Vec<(String, String)> = Vec::new();
for file in read_dir(format!(
"{}static/{}/",
@ -26,7 +30,13 @@ fn style_option_list(
style_type,
))? {
let style_name = file?.file_name().to_str().unwrap().replace(".css", "");
style_option_names.push((style_name.clone(), style_name.replace('-', " ")));
if selected_style != style_name {
style_option_names.push((style_name.clone(), style_name.replace('-', " ")));
}
}
if style_type == "animations" {
style_option_names.push(("".to_owned(), "none".to_owned()))
}
Ok(style_option_names)
@ -38,7 +48,11 @@ fn style_option_list(
///
/// It returns the compiled html markup code for the user interface tab on success otherwise
/// returns a standard error message.
pub fn user_interface() -> Result<Markup, Box<dyn std::error::Error>> {
pub fn user_interface(
theme: &str,
colorscheme: &str,
animation: &Option<String>,
) -> Result<Markup, Box<dyn std::error::Error>> {
Ok(html!(
div class="user_interface tab"{
h1{"User Interface"}
@ -47,7 +61,9 @@ pub fn user_interface() -> Result<Markup, Box<dyn std::error::Error>> {
"Select the theme from the available themes to be used in user interface"
}
select name="themes"{
@for (k,v) in style_option_list("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)}
}
}
@ -56,7 +72,9 @@ pub fn user_interface() -> Result<Markup, Box<dyn std::error::Error>> {
"Select the color scheme for your theme to be used in user interface"
}
select name="colorschemes"{
@for (k,v) in style_option_list("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)}
}
}
@ -65,12 +83,12 @@ pub fn user_interface() -> Result<Markup, Box<dyn std::error::Error>> {
"Select the animation for your theme to be used in user interface"
}
select name="animations"{
option value=""{"none"}
@for (k,v) in style_option_list("animations")?{
// Sets the user selected animation name from the config file as the first option in the selection list.
option value=(animation.as_ref().unwrap_or(&"".to_owned())){(animation.as_ref().unwrap_or(&"".to_owned()).replace('-'," "))}
@for (k,v) in style_option_list("animations", animation.as_ref().unwrap_or(&"".to_owned()))?{
option value=(k){(v)}
}
}
}
))
}

View File

@ -1,5 +1,7 @@
//! A module that handles the view for the settings page in the `websurfx` frontend.
use std::collections::HashMap;
use maud::{html, Markup};
use crate::templates::partials::{
@ -14,8 +16,10 @@ use crate::templates::partials::{
///
/// # 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
@ -23,10 +27,11 @@ use crate::templates::partials::{
/// This function returns a compiled html markup code on success otherwise returns a standard error
/// message.
pub fn settings(
safe_search_level: u8,
colorscheme: &str,
theme: &str,
animation: &Option<String>,
engine_names: &[&String],
engine_names: &HashMap<String, bool>,
) -> Result<Markup, Box<dyn std::error::Error>> {
Ok(html!(
(header(colorscheme, theme, animation))
@ -41,8 +46,8 @@ pub fn settings(
.btn onclick="setActiveTab(this)"{"cookies"}
}
.main_container{
(general())
(user_interface()?)
(general(safe_search_level))
(user_interface(theme, colorscheme, animation)?)
(engines(engine_names))
(cookies())
p class="message"{}

View File

@ -64,4 +64,5 @@ upstream_search_engines = {
Brave = false,
Startpage = false,
LibreX = false,
Mojeek = false,
} -- select the upstream search engines from which the results should be fetched.