Merge branch 'rolling' into feat-inform-user-when-no-engines-are-selected
Browse files- README.md +20 -27
- public/static/cookies.js +4 -3
- public/static/index.js +18 -9
- public/static/pagination.js +4 -4
- public/static/search_area_options.js +18 -0
- public/static/settings.js +28 -22
- public/static/themes/simple.css +26 -2
- public/templates/engines_tab.html +1 -0
- public/templates/general_tab.html +10 -1
- public/templates/search.html +1 -0
- public/templates/search_bar.html +31 -22
- public/templates/user_interface_tab.html +1 -0
- src/models/server_models.rs +2 -0
- src/server/routes/search.rs +37 -24
README.md
CHANGED
@@ -4,6 +4,7 @@
|
|
4 |
<p align="center">
|
5 |
<b align="center"><a href="README.md">Readme</a></b> |
|
6 |
<b><a href="https://discord.gg/SWnda7Mw5u">Discord</a></b> |
|
|
|
7 |
<b><a href="https://github.com/neon-mmd/websurfx">GitHub</a></b> |
|
8 |
<b><a href="../../tree/HEAD/docs/">Documentation</a></b>
|
9 |
<br /><br />
|
@@ -57,28 +58,19 @@
|
|
57 |
<p>
|
58 |
|
59 |
- **Getting Started**
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
- **Feature Overview**
|
65 |
-
|
66 |
-
|
67 |
-
- **Community**
|
68 |
-
- [π System Requirements](#system-requirements-)
|
69 |
-
- [π¨οΈ FAQ (Frequently Asked Questions)](#faq-frequently-asked-questions-)
|
70 |
-
- [π£ More Contributors Wanted](#more-contributors-wanted-)
|
71 |
-
- [π Supporting Websurfx](#supporting-websurfx-)
|
72 |
-
- [π Documentation](#documentation-)
|
73 |
-
- [π£οΈ Roadmap](#roadmap-)
|
74 |
-
- [π Contributing](#contributing-)
|
75 |
-
- [π License](#license-)
|
76 |
-
- [π€ Credits](#credits-)
|
77 |
|
78 |
</p>
|
79 |
</details>
|
80 |
|
81 |
-
# Preview π
|
82 |
|
83 |
## Home Page
|
84 |
|
@@ -94,7 +86,7 @@
|
|
94 |
|
95 |
**[β¬οΈ Back to Top](#--)**
|
96 |
|
97 |
-
# Features π
|
98 |
|
99 |
- π¨ Make Websurfx uniquely yours with twelve color schemes provided by default. It also supports creation of custom themes and color schemes in a quick and easy way, so unleash your creativity!
|
100 |
- π Fast, private, and secure
|
@@ -104,7 +96,7 @@
|
|
104 |
|
105 |
**[β¬οΈ Back to Top](#--)**
|
106 |
|
107 |
-
# Installation and Testing π οΈ
|
108 |
|
109 |
> For full setup instructions, see: [**Installation**](./docs/installation.md)
|
110 |
|
@@ -112,7 +104,7 @@ Before you can start building `websurfx`, you will need to have `Cargo` installe
|
|
112 |
|
113 |
To get started with Websurfx, clone the repository, edit the config file, which is located in the `websurfx/` directory, and install the Redis server by following the instructions located [here](https://redis.io/docs/getting-started/) and then run the websurfx server and redis server using the following commands:
|
114 |
|
115 |
-
```
|
116 |
git clone https://github.com/neon-mmd/websurfx.git
|
117 |
cd websurfx
|
118 |
git checkout stable
|
@@ -128,7 +120,7 @@ Once you have started the server, open your preferred web browser and navigate t
|
|
128 |
|
129 |
**[β¬οΈ Back to Top](#--)**
|
130 |
|
131 |
-
# Configuration π§
|
132 |
|
133 |
> For full configuration instructions, see: [**Configuration**](./docs/configuration.md)
|
134 |
|
@@ -136,7 +128,7 @@ Websurfx is configured through the config.lua file, located at `websurfx/config.
|
|
136 |
|
137 |
**[β¬οΈ Back to Top](#--)**
|
138 |
|
139 |
-
# Theming π¨
|
140 |
|
141 |
> For full theming and customization instructions, see: [**Theming**](./docs/theming.md)
|
142 |
|
@@ -173,7 +165,7 @@ Websurfx is based on Rust due to its memory safety features, which prevents vuln
|
|
173 |
|
174 |
**[β¬οΈ Back to Top](#--)**
|
175 |
|
176 |
-
# More Contributors Wanted π£
|
177 |
|
178 |
We are looking for more willing contributors to help grow this project. For more information on how you can contribute, check out the [project board](https://github.com/neon-mmd/websurfx/projects?query=is%3Aopen) and the [CONTRIBUTING.md](CONTRIBUTING.md) file for guidelines and rules for making contributions.
|
179 |
|
@@ -186,6 +178,7 @@ We are looking for more willing contributors to help grow this project. For more
|
|
186 |
If you use Websurfx and would like to contribute to its development, we're glad to have you on board! Contributions of any size or type are always welcome, and we will always acknowledge your efforts.
|
187 |
|
188 |
Several areas that we need a bit of help with at the moment are:
|
|
|
189 |
- **Better and more color schemes**: Help fix color schemes and add other famous color schemes.
|
190 |
- **Improve evasion code for bot detection** - Help improve code related to evading IP blocking and emulating human behaviors located in everyone's engine file.
|
191 |
- **Logo** - Help create a logo for the project and website.
|
@@ -198,7 +191,7 @@ Several areas that we need a bit of help with at the moment are:
|
|
198 |
# Documentation π
|
199 |
|
200 |
> **Note**
|
201 |
-
> We welcome any contributions to the [documentation](../../tree/HEAD/docs/) as this will benefit everyone who uses this project.
|
202 |
|
203 |
**[β¬οΈ Back to Top](#--)**
|
204 |
|
@@ -208,7 +201,7 @@ Several areas that we need a bit of help with at the moment are:
|
|
208 |
|
209 |
**[β¬οΈ Back to Top](#--)**
|
210 |
|
211 |
-
# Contributing π
|
212 |
|
213 |
Contributions are welcome from anyone. It doesn't matter who you are; you can still contribute to the project in your own way.
|
214 |
|
@@ -222,13 +215,13 @@ If you are a developer, have a look at the [CONTRIBUTING.org](CONTRIBUTING.md) d
|
|
222 |
|
223 |
**[β¬οΈ Back to Top](#--)**
|
224 |
|
225 |
-
# License π
|
226 |
|
227 |
Websurfx is licensed under the [AGPLv3](LICENSE) license.
|
228 |
|
229 |
**[β¬οΈ Back to Top](#--)**
|
230 |
|
231 |
-
# Credits π€
|
232 |
|
233 |
We would like to thank the following people for their contributions and support:
|
234 |
|
|
|
4 |
<p align="center">
|
5 |
<b align="center"><a href="README.md">Readme</a></b> |
|
6 |
<b><a href="https://discord.gg/SWnda7Mw5u">Discord</a></b> |
|
7 |
+
<b><a href="https://discord.gg/VKCAememnr">User Showcase</a></b> |
|
8 |
<b><a href="https://github.com/neon-mmd/websurfx">GitHub</a></b> |
|
9 |
<b><a href="../../tree/HEAD/docs/">Documentation</a></b>
|
10 |
<br /><br />
|
|
|
58 |
<p>
|
59 |
|
60 |
- **Getting Started**
|
61 |
+
- [π Preview](#preview-)
|
62 |
+
- [π Features](#features-)
|
63 |
+
- [π οΈ Installation and Testing](#installation-and-testing-%EF%B8%8F)
|
64 |
+
- [π§ Configuration](#configuration-)
|
65 |
- **Feature Overview**
|
66 |
+
- [π¨ Theming](#theming-)
|
67 |
+
- [π Multi-Language Support](#multi-language-support-)
|
68 |
+
- **Community** - [π System Requirements](#system-requirements-) - [π¨οΈ FAQ (Frequently Asked Questions)](#faq-frequently-asked-questions-) - [π£ More Contributors Wanted](#more-contributors-wanted-) - [π Supporting Websurfx](#supporting-websurfx-) - [π Documentation](#documentation-) - [π£οΈ Roadmap](#roadmap-) - [π Contributing](#contributing-) - [π License](#license-) - [π€ Credits](#credits-)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
|
70 |
</p>
|
71 |
</details>
|
72 |
|
73 |
+
# Preview π
|
74 |
|
75 |
## Home Page
|
76 |
|
|
|
86 |
|
87 |
**[β¬οΈ Back to Top](#--)**
|
88 |
|
89 |
+
# Features π
|
90 |
|
91 |
- π¨ Make Websurfx uniquely yours with twelve color schemes provided by default. It also supports creation of custom themes and color schemes in a quick and easy way, so unleash your creativity!
|
92 |
- π Fast, private, and secure
|
|
|
96 |
|
97 |
**[β¬οΈ Back to Top](#--)**
|
98 |
|
99 |
+
# Installation and Testing π οΈ
|
100 |
|
101 |
> For full setup instructions, see: [**Installation**](./docs/installation.md)
|
102 |
|
|
|
104 |
|
105 |
To get started with Websurfx, clone the repository, edit the config file, which is located in the `websurfx/` directory, and install the Redis server by following the instructions located [here](https://redis.io/docs/getting-started/) and then run the websurfx server and redis server using the following commands:
|
106 |
|
107 |
+
```shell
|
108 |
git clone https://github.com/neon-mmd/websurfx.git
|
109 |
cd websurfx
|
110 |
git checkout stable
|
|
|
120 |
|
121 |
**[β¬οΈ Back to Top](#--)**
|
122 |
|
123 |
+
# Configuration π§
|
124 |
|
125 |
> For full configuration instructions, see: [**Configuration**](./docs/configuration.md)
|
126 |
|
|
|
128 |
|
129 |
**[β¬οΈ Back to Top](#--)**
|
130 |
|
131 |
+
# Theming π¨
|
132 |
|
133 |
> For full theming and customization instructions, see: [**Theming**](./docs/theming.md)
|
134 |
|
|
|
165 |
|
166 |
**[β¬οΈ Back to Top](#--)**
|
167 |
|
168 |
+
# More Contributors Wanted π£
|
169 |
|
170 |
We are looking for more willing contributors to help grow this project. For more information on how you can contribute, check out the [project board](https://github.com/neon-mmd/websurfx/projects?query=is%3Aopen) and the [CONTRIBUTING.md](CONTRIBUTING.md) file for guidelines and rules for making contributions.
|
171 |
|
|
|
178 |
If you use Websurfx and would like to contribute to its development, we're glad to have you on board! Contributions of any size or type are always welcome, and we will always acknowledge your efforts.
|
179 |
|
180 |
Several areas that we need a bit of help with at the moment are:
|
181 |
+
|
182 |
- **Better and more color schemes**: Help fix color schemes and add other famous color schemes.
|
183 |
- **Improve evasion code for bot detection** - Help improve code related to evading IP blocking and emulating human behaviors located in everyone's engine file.
|
184 |
- **Logo** - Help create a logo for the project and website.
|
|
|
191 |
# Documentation π
|
192 |
|
193 |
> **Note**
|
194 |
+
> We welcome any contributions to the [documentation](../../tree/HEAD/docs/) as this will benefit everyone who uses this project.
|
195 |
|
196 |
**[β¬οΈ Back to Top](#--)**
|
197 |
|
|
|
201 |
|
202 |
**[β¬οΈ Back to Top](#--)**
|
203 |
|
204 |
+
# Contributing π
|
205 |
|
206 |
Contributions are welcome from anyone. It doesn't matter who you are; you can still contribute to the project in your own way.
|
207 |
|
|
|
215 |
|
216 |
**[β¬οΈ Back to Top](#--)**
|
217 |
|
218 |
+
# License π
|
219 |
|
220 |
Websurfx is licensed under the [AGPLv3](LICENSE) license.
|
221 |
|
222 |
**[β¬οΈ Back to Top](#--)**
|
223 |
|
224 |
+
# Credits π€
|
225 |
|
226 |
We would like to thank the following people for their contributions and support:
|
227 |
|
public/static/cookies.js
CHANGED
@@ -16,8 +16,9 @@ document.addEventListener(
|
|
16 |
let cookie = decodeURIComponent(document.cookie)
|
17 |
// Set the value of the input field to the decoded cookie value if it is not empty
|
18 |
// Otherwise, display a message indicating that no cookies have been saved on the user's system
|
19 |
-
document.querySelector('.cookies input').value =
|
20 |
-
|
|
|
21 |
} catch (error) {
|
22 |
// If there is an error decoding the cookie, log the error to the console
|
23 |
// and display an error message in the input field
|
@@ -25,5 +26,5 @@ document.addEventListener(
|
|
25 |
document.querySelector('.cookies input').value = 'Error decoding cookie'
|
26 |
}
|
27 |
},
|
28 |
-
false
|
29 |
)
|
|
|
16 |
let cookie = decodeURIComponent(document.cookie)
|
17 |
// Set the value of the input field to the decoded cookie value if it is not empty
|
18 |
// Otherwise, display a message indicating that no cookies have been saved on the user's system
|
19 |
+
document.querySelector('.cookies input').value = cookie.length
|
20 |
+
? cookie
|
21 |
+
: 'No cookies have been saved on your system'
|
22 |
} catch (error) {
|
23 |
// If there is an error decoding the cookie, log the error to the console
|
24 |
// and display an error message in the input field
|
|
|
26 |
document.querySelector('.cookies input').value = 'Error decoding cookie'
|
27 |
}
|
28 |
},
|
29 |
+
false,
|
30 |
)
|
public/static/index.js
CHANGED
@@ -2,16 +2,25 @@
|
|
2 |
* Selects the input element for the search box
|
3 |
* @type {HTMLInputElement}
|
4 |
*/
|
5 |
-
const searchBox = document.querySelector('input')
|
6 |
|
7 |
/**
|
8 |
* Redirects the user to the search results page with the query parameter
|
9 |
*/
|
10 |
function searchWeb() {
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
}
|
16 |
|
17 |
/**
|
@@ -19,7 +28,7 @@ function searchWeb() {
|
|
19 |
* @param {KeyboardEvent} e - The keyboard event object
|
20 |
*/
|
21 |
searchBox.addEventListener('keyup', (e) => {
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
})
|
|
|
2 |
* Selects the input element for the search box
|
3 |
* @type {HTMLInputElement}
|
4 |
*/
|
5 |
+
const searchBox = document.querySelector('input')
|
6 |
|
7 |
/**
|
8 |
* Redirects the user to the search results page with the query parameter
|
9 |
*/
|
10 |
function searchWeb() {
|
11 |
+
const query = searchBox.value.trim()
|
12 |
+
try {
|
13 |
+
let safeSearchLevel = document.querySelector('.search_options select').value
|
14 |
+
if (query) {
|
15 |
+
window.location.href = `search?q=${encodeURIComponent(
|
16 |
+
query,
|
17 |
+
)}&safesearch=${encodeURIComponent(safeSearchLevel)}`
|
18 |
+
}
|
19 |
+
} catch (error) {
|
20 |
+
if (query) {
|
21 |
+
window.location.href = `search?q=${encodeURIComponent(query)}`
|
22 |
+
}
|
23 |
+
}
|
24 |
}
|
25 |
|
26 |
/**
|
|
|
28 |
* @param {KeyboardEvent} e - The keyboard event object
|
29 |
*/
|
30 |
searchBox.addEventListener('keyup', (e) => {
|
31 |
+
if (e.key === 'Enter') {
|
32 |
+
searchWeb()
|
33 |
+
}
|
34 |
+
})
|
public/static/pagination.js
CHANGED
@@ -3,8 +3,8 @@
|
|
3 |
* @returns {void}
|
4 |
*/
|
5 |
function navigate_forward() {
|
6 |
-
|
7 |
-
|
8 |
|
9 |
let q = searchParams.get('q');
|
10 |
let page = parseInt(searchParams.get('page'));
|
@@ -23,8 +23,8 @@ function navigate_forward() {
|
|
23 |
* @returns {void}
|
24 |
*/
|
25 |
function navigate_backward() {
|
26 |
-
|
27 |
-
|
28 |
|
29 |
let q = searchParams.get('q');
|
30 |
let page = parseInt(searchParams.get('page'));
|
|
|
3 |
* @returns {void}
|
4 |
*/
|
5 |
function navigate_forward() {
|
6 |
+
let url = new URL(window.location);
|
7 |
+
let searchParams = url.searchParams;
|
8 |
|
9 |
let q = searchParams.get('q');
|
10 |
let page = parseInt(searchParams.get('page'));
|
|
|
23 |
* @returns {void}
|
24 |
*/
|
25 |
function navigate_backward() {
|
26 |
+
let url = new URL(window.location);
|
27 |
+
let searchParams = url.searchParams;
|
28 |
|
29 |
let q = searchParams.get('q');
|
30 |
let page = parseInt(searchParams.get('page'));
|
public/static/search_area_options.js
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
document.addEventListener(
|
2 |
+
'DOMContentLoaded',
|
3 |
+
() => {
|
4 |
+
let url = new URL(window.location)
|
5 |
+
let searchParams = url.searchParams
|
6 |
+
|
7 |
+
let safeSearchLevel = searchParams.get('safesearch')
|
8 |
+
|
9 |
+
if (
|
10 |
+
safeSearchLevel >= 0 &&
|
11 |
+
safeSearchLevel <= 2 &&
|
12 |
+
safeSearchLevel !== null
|
13 |
+
) {
|
14 |
+
document.querySelector('.search_options select').value = safeSearchLevel
|
15 |
+
}
|
16 |
+
},
|
17 |
+
false,
|
18 |
+
)
|
public/static/settings.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
/**
|
2 |
-
* This function handles the toggling of selections of all upstream search engines
|
3 |
* options in the settings page under the tab engines.
|
4 |
*/
|
5 |
function toggleAllSelection() {
|
@@ -8,12 +8,12 @@ function toggleAllSelection() {
|
|
8 |
.forEach(
|
9 |
(engine_checkbox) =>
|
10 |
(engine_checkbox.checked =
|
11 |
-
document.querySelector('.select_all').checked)
|
12 |
)
|
13 |
}
|
14 |
|
15 |
/**
|
16 |
-
* This function adds the functionality to sidebar buttons to only show settings
|
17 |
* related to that tab.
|
18 |
* @param {HTMLElement} current_tab - The current tab that was clicked.
|
19 |
*/
|
@@ -43,20 +43,28 @@ function setClientSettings() {
|
|
43 |
|
44 |
// Loop through all select tags and add their values to the cookie dictionary
|
45 |
document.querySelectorAll('select').forEach((select_tag) => {
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
}
|
51 |
})
|
52 |
|
53 |
// Loop through all engine checkboxes and add their values to the cookie dictionary
|
54 |
let engines = []
|
|
|
55 |
document.querySelectorAll('.engine').forEach((engine_checkbox) => {
|
56 |
-
if (engine_checkbox.checked
|
57 |
engines.push(engine_checkbox.parentNode.parentNode.innerText.trim())
|
58 |
}
|
59 |
})
|
|
|
60 |
cookie_dictionary['engines'] = engines
|
61 |
|
62 |
// Set the expiration date for the cookie to 1 year from the current date
|
@@ -65,7 +73,7 @@ function setClientSettings() {
|
|
65 |
|
66 |
// Save the cookie to the user's machine
|
67 |
document.cookie = `appCookie=${JSON.stringify(
|
68 |
-
cookie_dictionary
|
69 |
)}; expires=${expiration_date.toUTCString()}`
|
70 |
|
71 |
// Display a success message to the user
|
@@ -79,9 +87,9 @@ function setClientSettings() {
|
|
79 |
}
|
80 |
|
81 |
/**
|
82 |
-
* This functions gets the saved cookies if it is present on the user's machine If it
|
83 |
-
* is available then it is parsed and converted to an object which is then used to
|
84 |
-
* retrieve the preferences that the user had selected previously and is then loaded in the
|
85 |
* website otherwise the function does nothing and the default server side settings are loaded.
|
86 |
*/
|
87 |
function getClientSettings() {
|
@@ -89,21 +97,19 @@ function getClientSettings() {
|
|
89 |
let cookie = decodeURIComponent(document.cookie)
|
90 |
|
91 |
// If the cookie is not empty, parse it and use it to set the user's preferences
|
92 |
-
if (cookie
|
93 |
-
let cookie_value =
|
94 |
.split(';')
|
95 |
.map((item) => item.split('='))
|
96 |
.reduce((acc, [_, v]) => (acc = JSON.parse(v)) && acc, {})
|
97 |
|
98 |
// Loop through all link tags and update their href values to match the user's preferences
|
99 |
-
|
100 |
-
(item)
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
item.href = `static/colorschemes/${cookie_value['colorscheme']}.css`
|
105 |
-
}
|
106 |
}
|
107 |
-
)
|
108 |
}
|
109 |
}
|
|
|
1 |
/**
|
2 |
+
* This function handles the toggling of selections of all upstream search engines
|
3 |
* options in the settings page under the tab engines.
|
4 |
*/
|
5 |
function toggleAllSelection() {
|
|
|
8 |
.forEach(
|
9 |
(engine_checkbox) =>
|
10 |
(engine_checkbox.checked =
|
11 |
+
document.querySelector('.select_all').checked),
|
12 |
)
|
13 |
}
|
14 |
|
15 |
/**
|
16 |
+
* This function adds the functionality to sidebar buttons to only show settings
|
17 |
* related to that tab.
|
18 |
* @param {HTMLElement} current_tab - The current tab that was clicked.
|
19 |
*/
|
|
|
43 |
|
44 |
// Loop through all select tags and add their values to the cookie dictionary
|
45 |
document.querySelectorAll('select').forEach((select_tag) => {
|
46 |
+
switch (select_tag.name) {
|
47 |
+
case 'themes':
|
48 |
+
cookie_dictionary['theme'] = select_tag.value
|
49 |
+
break
|
50 |
+
case 'colorschemes':
|
51 |
+
cookie_dictionary['colorscheme'] = select_tag.value
|
52 |
+
break
|
53 |
+
case 'safe_search_levels':
|
54 |
+
cookie_dictionary['safe_search_level'] = Number(select_tag.value)
|
55 |
+
break
|
56 |
}
|
57 |
})
|
58 |
|
59 |
// Loop through all engine checkboxes and add their values to the cookie dictionary
|
60 |
let engines = []
|
61 |
+
|
62 |
document.querySelectorAll('.engine').forEach((engine_checkbox) => {
|
63 |
+
if (engine_checkbox.checked) {
|
64 |
engines.push(engine_checkbox.parentNode.parentNode.innerText.trim())
|
65 |
}
|
66 |
})
|
67 |
+
|
68 |
cookie_dictionary['engines'] = engines
|
69 |
|
70 |
// Set the expiration date for the cookie to 1 year from the current date
|
|
|
73 |
|
74 |
// Save the cookie to the user's machine
|
75 |
document.cookie = `appCookie=${JSON.stringify(
|
76 |
+
cookie_dictionary,
|
77 |
)}; expires=${expiration_date.toUTCString()}`
|
78 |
|
79 |
// Display a success message to the user
|
|
|
87 |
}
|
88 |
|
89 |
/**
|
90 |
+
* This functions gets the saved cookies if it is present on the user's machine If it
|
91 |
+
* is available then it is parsed and converted to an object which is then used to
|
92 |
+
* retrieve the preferences that the user had selected previously and is then loaded in the
|
93 |
* website otherwise the function does nothing and the default server side settings are loaded.
|
94 |
*/
|
95 |
function getClientSettings() {
|
|
|
97 |
let cookie = decodeURIComponent(document.cookie)
|
98 |
|
99 |
// If the cookie is not empty, parse it and use it to set the user's preferences
|
100 |
+
if (cookie.length) {
|
101 |
+
let cookie_value = cookie
|
102 |
.split(';')
|
103 |
.map((item) => item.split('='))
|
104 |
.reduce((acc, [_, v]) => (acc = JSON.parse(v)) && acc, {})
|
105 |
|
106 |
// Loop through all link tags and update their href values to match the user's preferences
|
107 |
+
Array.from(document.querySelectorAll('link')).forEach((item) => {
|
108 |
+
if (item.href.includes('static/themes')) {
|
109 |
+
item.href = `static/themes/${cookie_value['theme']}.css`
|
110 |
+
} else if (item.href.includes('static/colorschemes')) {
|
111 |
+
item.href = `static/colorschemes/${cookie_value['colorscheme']}.css`
|
|
|
|
|
112 |
}
|
113 |
+
})
|
114 |
}
|
115 |
}
|
public/static/themes/simple.css
CHANGED
@@ -70,6 +70,28 @@ body {
|
|
70 |
filter: brightness(1.2);
|
71 |
}
|
72 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
.result_not_found {
|
74 |
display: flex;
|
75 |
flex-direction: column;
|
@@ -503,7 +525,8 @@ footer {
|
|
503 |
color: var(--foreground-color);
|
504 |
}
|
505 |
|
506 |
-
.settings_container .user_interface select
|
|
|
507 |
margin: 0.7rem 0;
|
508 |
width: 20rem;
|
509 |
background-color: var(--background-color);
|
@@ -515,7 +538,8 @@ footer {
|
|
515 |
text-transform: capitalize;
|
516 |
}
|
517 |
|
518 |
-
.settings_container .user_interface option:hover
|
|
|
519 |
background-color: var(--color-one);
|
520 |
}
|
521 |
|
|
|
70 |
filter: brightness(1.2);
|
71 |
}
|
72 |
|
73 |
+
.search_area .search_options {
|
74 |
+
display: flex;
|
75 |
+
justify-content: space-between;
|
76 |
+
align-items: center;
|
77 |
+
}
|
78 |
+
|
79 |
+
.search_area .search_options select {
|
80 |
+
margin: 0.7rem 0;
|
81 |
+
width: 20rem;
|
82 |
+
background-color: var(--color-one);
|
83 |
+
color: var(--foreground-color);
|
84 |
+
padding: 1rem 2rem;
|
85 |
+
border-radius: 0.5rem;
|
86 |
+
outline: none;
|
87 |
+
border: none;
|
88 |
+
text-transform: capitalize;
|
89 |
+
}
|
90 |
+
|
91 |
+
.search_area .search_options option:hover {
|
92 |
+
background-color: var(--color-one);
|
93 |
+
}
|
94 |
+
|
95 |
.result_not_found {
|
96 |
display: flex;
|
97 |
flex-direction: column;
|
|
|
525 |
color: var(--foreground-color);
|
526 |
}
|
527 |
|
528 |
+
.settings_container .user_interface select,
|
529 |
+
.settings_container .general select {
|
530 |
margin: 0.7rem 0;
|
531 |
width: 20rem;
|
532 |
background-color: var(--background-color);
|
|
|
538 |
text-transform: capitalize;
|
539 |
}
|
540 |
|
541 |
+
.settings_container .user_interface option:hover,
|
542 |
+
.settings_container .general option:hover {
|
543 |
background-color: var(--color-one);
|
544 |
}
|
545 |
|
public/templates/engines_tab.html
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
<div class="engines tab">
|
|
|
2 |
<h3>select search engines</h3>
|
3 |
<p class="description">
|
4 |
Select the search engines from the list of engines that you want results
|
|
|
1 |
<div class="engines tab">
|
2 |
+
<h1>Engines</h1>
|
3 |
<h3>select search engines</h3>
|
4 |
<p class="description">
|
5 |
Select the search engines from the list of engines that you want results
|
public/templates/general_tab.html
CHANGED
@@ -1,4 +1,13 @@
|
|
1 |
<div class="general tab active">
|
2 |
<h1>General</h1>
|
3 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
</div>
|
|
|
1 |
<div class="general tab active">
|
2 |
<h1>General</h1>
|
3 |
+
<h3>Select a safe search level</h3>
|
4 |
+
<p class="description">
|
5 |
+
Select a safe search level from the menu below to filter content based on
|
6 |
+
the level.
|
7 |
+
</p>
|
8 |
+
<select name="safe_search_levels">
|
9 |
+
<option value=0>None</option>
|
10 |
+
<option value=1>Low</option>
|
11 |
+
<option value=2>Moderate</option>
|
12 |
+
</select>
|
13 |
</div>
|
public/templates/search.html
CHANGED
@@ -80,6 +80,7 @@
|
|
80 |
</div>
|
81 |
</main>
|
82 |
<script src="static/index.js"></script>
|
|
|
83 |
<script src="static/pagination.js"></script>
|
84 |
<script src="static/error_box.js"></script>
|
85 |
{{>footer}}
|
|
|
80 |
</div>
|
81 |
</main>
|
82 |
<script src="static/index.js"></script>
|
83 |
+
<script src="static/search_area_options.js"></script>
|
84 |
<script src="static/pagination.js"></script>
|
85 |
<script src="static/error_box.js"></script>
|
86 |
{{>footer}}
|
public/templates/search_bar.html
CHANGED
@@ -1,27 +1,36 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
<
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
<
|
11 |
-
|
12 |
-
|
|
|
|
|
|
|
13 |
</div>
|
14 |
-
{{
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
<
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
Everything looks good π!!
|
23 |
</div>
|
|
|
24 |
</div>
|
25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
</div>
|
27 |
</div>
|
|
|
1 |
+
<div class="search_area">
|
2 |
+
{{>bar this}}
|
3 |
+
<div class="error_box">
|
4 |
+
{{#if engineErrorsInfo}}
|
5 |
+
<button onclick="toggleErrorBox()" class="error_box_toggle_button">
|
6 |
+
<img src="./images/warning.svg" alt="Info icon for error box" />
|
7 |
+
</button>
|
8 |
+
<div class="dropdown_error_box">
|
9 |
+
{{#each engineErrorsInfo}}
|
10 |
+
<div class="error_item">
|
11 |
+
<span class="engine_name">{{{this.engine}}}</span>
|
12 |
+
<span class="engine_name">{{{this.error}}}</span>
|
13 |
+
<span class="severity_color" style="background: {{{this.severity_color}}};"></span>
|
14 |
+
</div>
|
15 |
+
{{/each}}
|
16 |
</div>
|
17 |
+
{{else}}
|
18 |
+
<button onclick="toggleErrorBox()" class="error_box_toggle_button">
|
19 |
+
<img src="./images/info.svg" alt="Warning icon for error box" />
|
20 |
+
</button>
|
21 |
+
<div class="dropdown_error_box">
|
22 |
+
<div class="no_errors">
|
23 |
+
Everything looks good π!!
|
24 |
+
</div>
|
|
|
25 |
</div>
|
26 |
+
{{/if}}
|
27 |
</div>
|
28 |
+
</div>
|
29 |
+
<div class="search_options">
|
30 |
+
<select name="safe_search_levels" {{#if (gte safeSearchLevel 3)}} disabled {{/if}}>
|
31 |
+
<option value=0 {{#if (eq safeSearchLevel 0)}} selected {{/if}}>SafeSearch: None</option>
|
32 |
+
<option value=1 {{#if (eq safeSearchLevel 1)}} selected {{/if}}>SafeSearch: Low</option>
|
33 |
+
<option value=2 {{#if (eq safeSearchLevel 2)}} selected {{/if}}>SafeSearch: Moderate</option>
|
34 |
+
</select>
|
35 |
</div>
|
36 |
</div>
|
public/templates/user_interface_tab.html
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
<div class="user_interface tab">
|
|
|
2 |
<h3>select theme</h3>
|
3 |
<p class="description">
|
4 |
Select the theme from the available themes to be used in user interface
|
|
|
1 |
<div class="user_interface tab">
|
2 |
+
<h1>User Interface</h1>
|
3 |
<h3>select theme</h3>
|
4 |
<p class="description">
|
5 |
Select the theme from the available themes to be used in user interface
|
src/models/server_models.rs
CHANGED
@@ -26,4 +26,6 @@ pub struct Cookie<'a> {
|
|
26 |
pub colorscheme: &'a str,
|
27 |
/// It stores the user selected upstream search engines selected from the UI.
|
28 |
pub engines: Vec<&'a str>,
|
|
|
|
|
29 |
}
|
|
|
26 |
pub colorscheme: &'a str,
|
27 |
/// It stores the user selected upstream search engines selected from the UI.
|
28 |
pub engines: Vec<&'a str>,
|
29 |
+
/// It stores the user selected safe search level from the UI.
|
30 |
+
pub safe_search_level: u8,
|
31 |
}
|
src/server/routes/search.rs
CHANGED
@@ -67,61 +67,48 @@ pub async fn search(
|
|
67 |
None => 1,
|
68 |
};
|
69 |
|
70 |
-
let safe_search: u8 = match config.safe_search {
|
71 |
-
3..=4 => config.safe_search,
|
72 |
-
_ => match ¶ms.safesearch {
|
73 |
-
Some(safesearch) => match safesearch {
|
74 |
-
0..=2 => *safesearch,
|
75 |
-
_ => 1,
|
76 |
-
},
|
77 |
-
None => config.safe_search,
|
78 |
-
},
|
79 |
-
};
|
80 |
-
|
81 |
let (_, results, _) = join!(
|
82 |
results(
|
83 |
format!(
|
84 |
-
"http://{}:{}/search?q={}&page={}&safesearch=
|
85 |
config.binding_ip,
|
86 |
config.port,
|
87 |
query,
|
88 |
page - 1,
|
89 |
-
safe_search
|
90 |
),
|
91 |
&config,
|
92 |
&cache,
|
93 |
query,
|
94 |
page - 1,
|
95 |
req.clone(),
|
96 |
-
|
97 |
),
|
98 |
results(
|
99 |
format!(
|
100 |
-
"http://{}:{}/search?q={}&page={}&safesearch=
|
101 |
-
config.binding_ip, config.port, query, page
|
102 |
),
|
103 |
&config,
|
104 |
&cache,
|
105 |
query,
|
106 |
page,
|
107 |
req.clone(),
|
108 |
-
|
109 |
),
|
110 |
results(
|
111 |
format!(
|
112 |
-
"http://{}:{}/search?q={}&page={}&safesearch=
|
113 |
config.binding_ip,
|
114 |
config.port,
|
115 |
query,
|
116 |
page + 1,
|
117 |
-
safe_search
|
118 |
),
|
119 |
&config,
|
120 |
&cache,
|
121 |
query,
|
122 |
page + 1,
|
123 |
req.clone(),
|
124 |
-
|
125 |
)
|
126 |
);
|
127 |
|
@@ -156,7 +143,7 @@ async fn results(
|
|
156 |
query: &str,
|
157 |
page: u32,
|
158 |
req: HttpRequest,
|
159 |
-
safe_search: u8
|
160 |
) -> Result<SearchResults, Box<dyn std::error::Error>> {
|
161 |
// fetch the cached results json.
|
162 |
let cached_results = cache.cached_json(&url).await;
|
@@ -165,7 +152,18 @@ async fn results(
|
|
165 |
match cached_results {
|
166 |
Ok(results) => Ok(results),
|
167 |
Err(_) => {
|
168 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
169 |
let mut results: SearchResults = SearchResults::default();
|
170 |
let mut _flag: bool =
|
171 |
is_match_from_filter_list(file_path(FileType::BlockList)?, query)?;
|
@@ -176,6 +174,7 @@ async fn results(
|
|
176 |
results.add_style(&config.style);
|
177 |
results.set_page_query(query);
|
178 |
cache.cache_results(&results, &url).await?;
|
|
|
179 |
return Ok(results);
|
180 |
}
|
181 |
}
|
@@ -195,6 +194,17 @@ async fn results(
|
|
195 |
.filter_map(|name| EngineHandler::new(name))
|
196 |
.collect();
|
197 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
198 |
match engines.is_empty() {
|
199 |
false => {
|
200 |
aggregate(
|
@@ -224,7 +234,7 @@ async fn results(
|
|
224 |
config.debug,
|
225 |
&config.upstream_search_engines,
|
226 |
config.request_timeout,
|
227 |
-
|
228 |
)
|
229 |
.await?
|
230 |
}
|
@@ -236,7 +246,10 @@ async fn results(
|
|
236 |
results.set_filtered();
|
237 |
}
|
238 |
results.add_style(&config.style);
|
239 |
-
cache
|
|
|
|
|
|
|
240 |
Ok(results)
|
241 |
}
|
242 |
}
|
|
|
67 |
None => 1,
|
68 |
};
|
69 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
let (_, results, _) = join!(
|
71 |
results(
|
72 |
format!(
|
73 |
+
"http://{}:{}/search?q={}&page={}&safesearch=",
|
74 |
config.binding_ip,
|
75 |
config.port,
|
76 |
query,
|
77 |
page - 1,
|
|
|
78 |
),
|
79 |
&config,
|
80 |
&cache,
|
81 |
query,
|
82 |
page - 1,
|
83 |
req.clone(),
|
84 |
+
¶ms.safesearch
|
85 |
),
|
86 |
results(
|
87 |
format!(
|
88 |
+
"http://{}:{}/search?q={}&page={}&safesearch=",
|
89 |
+
config.binding_ip, config.port, query, page
|
90 |
),
|
91 |
&config,
|
92 |
&cache,
|
93 |
query,
|
94 |
page,
|
95 |
req.clone(),
|
96 |
+
¶ms.safesearch
|
97 |
),
|
98 |
results(
|
99 |
format!(
|
100 |
+
"http://{}:{}/search?q={}&page={}&safesearch=",
|
101 |
config.binding_ip,
|
102 |
config.port,
|
103 |
query,
|
104 |
page + 1,
|
|
|
105 |
),
|
106 |
&config,
|
107 |
&cache,
|
108 |
query,
|
109 |
page + 1,
|
110 |
req.clone(),
|
111 |
+
¶ms.safesearch
|
112 |
)
|
113 |
);
|
114 |
|
|
|
143 |
query: &str,
|
144 |
page: u32,
|
145 |
req: HttpRequest,
|
146 |
+
safe_search: &Option<u8>,
|
147 |
) -> Result<SearchResults, Box<dyn std::error::Error>> {
|
148 |
// fetch the cached results json.
|
149 |
let cached_results = cache.cached_json(&url).await;
|
|
|
152 |
match cached_results {
|
153 |
Ok(results) => Ok(results),
|
154 |
Err(_) => {
|
155 |
+
let mut safe_search_level: u8 = match config.safe_search {
|
156 |
+
3..=4 => config.safe_search,
|
157 |
+
_ => match safe_search {
|
158 |
+
Some(safesearch) => match safesearch {
|
159 |
+
0..=2 => *safesearch,
|
160 |
+
_ => config.safe_search,
|
161 |
+
},
|
162 |
+
None => config.safe_search,
|
163 |
+
},
|
164 |
+
};
|
165 |
+
|
166 |
+
if safe_search_level == 4 {
|
167 |
let mut results: SearchResults = SearchResults::default();
|
168 |
let mut _flag: bool =
|
169 |
is_match_from_filter_list(file_path(FileType::BlockList)?, query)?;
|
|
|
174 |
results.add_style(&config.style);
|
175 |
results.set_page_query(query);
|
176 |
cache.cache_results(&results, &url).await?;
|
177 |
+
results.set_safe_search_level(safe_search_level);
|
178 |
return Ok(results);
|
179 |
}
|
180 |
}
|
|
|
194 |
.filter_map(|name| EngineHandler::new(name))
|
195 |
.collect();
|
196 |
|
197 |
+
safe_search_level = match config.safe_search {
|
198 |
+
3..=4 => config.safe_search,
|
199 |
+
_ => match safe_search {
|
200 |
+
Some(safesearch) => match safesearch {
|
201 |
+
0..=2 => *safesearch,
|
202 |
+
_ => config.safe_search,
|
203 |
+
},
|
204 |
+
None => cookie_value.safe_search_level,
|
205 |
+
},
|
206 |
+
};
|
207 |
+
|
208 |
match engines.is_empty() {
|
209 |
false => {
|
210 |
aggregate(
|
|
|
234 |
config.debug,
|
235 |
&config.upstream_search_engines,
|
236 |
config.request_timeout,
|
237 |
+
safe_search_level,
|
238 |
)
|
239 |
.await?
|
240 |
}
|
|
|
246 |
results.set_filtered();
|
247 |
}
|
248 |
results.add_style(&config.style);
|
249 |
+
cache
|
250 |
+
.cache_results(&results, &(format!("{url}{safe_search_level}")))
|
251 |
+
.await?;
|
252 |
+
results.set_safe_search_level(safe_search_level);
|
253 |
Ok(results)
|
254 |
}
|
255 |
}
|