Merge branch 'benbusby:develop' into develop
This commit is contained in:
commit
ad336a857b
29
README.md
29
README.md
|
@ -258,20 +258,21 @@ There are a few optional environment variables available for customizing a Whoog
|
|||
### Config Environment Variables
|
||||
These environment variables allow setting default config values, but can be overwritten manually by using the home page config menu. These allow a shortcut for destroying/rebuilding an instance to the same config state every time.
|
||||
|
||||
| Variable | Description |
|
||||
| ----------------------- | --------------------------------------------------------------- |
|
||||
| WHOOGLE_CONFIG_COUNTRY | Filter results by hosting country |
|
||||
| WHOOGLE_CONFIG_LANGUAGE | Set interface and search result language |
|
||||
| WHOOGLE_CONFIG_DARK | Enable dark theme |
|
||||
| WHOOGLE_CONFIG_SAFE | Enable safe searches |
|
||||
| WHOOGLE_CONFIG_ALTS | Use social media site alternatives (nitter, invidious, etc) |
|
||||
| WHOOGLE_CONFIG_TOR | Use Tor routing (if available) |
|
||||
| WHOOGLE_CONFIG_NEW_TAB | Always open results in new tab |
|
||||
| WHOOGLE_CONFIG_VIEW_IMAGE | Enable View Image option |
|
||||
| WHOOGLE_CONFIG_GET_ONLY | Search using GET requests only |
|
||||
| WHOOGLE_CONFIG_URL | The root url of the instance (`https://<your url>/`) |
|
||||
| WHOOGLE_CONFIG_STYLE | The custom CSS to use for styling (must be single line) |
|
||||
|
||||
| Variable | Description |
|
||||
| ------------------------------ | --------------------------------------------------------------- |
|
||||
| WHOOGLE_CONFIG_COUNTRY | Filter results by hosting country |
|
||||
| WHOOGLE_CONFIG_LANGUAGE | Set interface language |
|
||||
| WHOOGLE_CONFIG_SEARCH_LANGUAGE | Set search result language |
|
||||
| WHOOGLE_CONFIG_BLOCK | Block websites from search results (use comma-separated list) |
|
||||
| WHOOGLE_CONFIG_DARK | Enable dark theme |
|
||||
| WHOOGLE_CONFIG_SAFE | Enable safe searches |
|
||||
| WHOOGLE_CONFIG_ALTS | Use social media site alternatives (nitter, invidious, etc) |
|
||||
| WHOOGLE_CONFIG_TOR | Use Tor routing (if available) |
|
||||
| WHOOGLE_CONFIG_NEW_TAB | Always open results in new tab |
|
||||
| WHOOGLE_CONFIG_VIEW_IMAGE | Enable View Image option |
|
||||
| WHOOGLE_CONFIG_GET_ONLY | Search using GET requests only |
|
||||
| WHOOGLE_CONFIG_URL | The root url of the instance (`https://<your url>/`) |
|
||||
| WHOOGLE_CONFIG_STYLE | The custom CSS to use for styling (should be single line) |
|
||||
|
||||
## Usage
|
||||
Same as most search engines, with the exception of filtering by time range.
|
||||
|
|
17
app.json
17
app.json
|
@ -71,7 +71,22 @@
|
|||
"required": false
|
||||
},
|
||||
"WHOOGLE_CONFIG_LANGUAGE": {
|
||||
"description": "[CONFIG] The language to use for search results and interface (use values from https://raw.githubusercontent.com/benbusby/whoogle-search/develop/app/static/settings/languages.json)",
|
||||
"description": "[CONFIG] The language to use for the interface (use values from https://raw.githubusercontent.com/benbusby/whoogle-search/develop/app/static/settings/languages.json)",
|
||||
"value": "",
|
||||
"required": false
|
||||
},
|
||||
"WHOOGLE_CONFIG_SEARCH_LANGUAGE": {
|
||||
"description": "[CONFIG] The language to use for search results (use values from https://raw.githubusercontent.com/benbusby/whoogle-search/develop/app/static/settings/languages.json)",
|
||||
"value": "",
|
||||
"required": false
|
||||
},
|
||||
"WHOOGLE_CONFIG_DISABLE": {
|
||||
"description": "[CONFIG] Disable ability for client to change config (set to 1 or leave blank)",
|
||||
"value": "",
|
||||
"required": false
|
||||
},
|
||||
"WHOOGLE_CONFIG_BLOCK": {
|
||||
"description": "[CONFIG] Block websites from search results (comma-separated list)",
|
||||
"value": "",
|
||||
"required": false
|
||||
},
|
||||
|
|
|
@ -50,7 +50,7 @@ app.config['BANG_FILE'] = os.path.join(
|
|||
'bangs.json')
|
||||
app.config['CSP'] = 'default-src \'none\';' \
|
||||
'manifest-src \'self\';' \
|
||||
'img-src \'self\';' \
|
||||
'img-src \'self\' data:;' \
|
||||
'style-src \'self\' \'unsafe-inline\';' \
|
||||
'script-src \'self\';' \
|
||||
'media-src \'self\';' \
|
||||
|
|
|
@ -12,12 +12,13 @@ class Config:
|
|||
|
||||
app_config = current_app.config
|
||||
self.url = os.getenv('WHOOGLE_CONFIG_URL', '')
|
||||
self.lang_search = os.getenv('WHOOGLE_CONFIG_LANGUAGE', '')
|
||||
self.lang_search = os.getenv('WHOOGLE_CONFIG_SEARCH_LANGUAGE', '')
|
||||
self.lang_interface = os.getenv('WHOOGLE_CONFIG_LANGUAGE', '')
|
||||
self.style = os.getenv(
|
||||
'WHOOGLE_CONFIG_STYLE',
|
||||
open(os.path.join(app_config['STATIC_FOLDER'],
|
||||
'css/variables.css')).read())
|
||||
self.block = os.getenv('WHOOGLE_CONFIG_BLOCK', '')
|
||||
self.ctry = os.getenv('WHOOGLE_CONFIG_COUNTRY', '')
|
||||
self.safe = read_config_bool('WHOOGLE_CONFIG_SAFE')
|
||||
self.dark = read_config_bool('WHOOGLE_CONFIG_DARK')
|
||||
|
@ -38,11 +39,12 @@ class Config:
|
|||
|
||||
# Skip setting custom config if there isn't one
|
||||
if kwargs:
|
||||
for attr in self.get_mutable_attrs():
|
||||
if attr not in kwargs.keys():
|
||||
setattr(self, attr, '')
|
||||
else:
|
||||
mutable_attrs = self.get_mutable_attrs()
|
||||
for attr in mutable_attrs:
|
||||
if attr in kwargs.keys():
|
||||
setattr(self, attr, kwargs[attr])
|
||||
elif attr not in kwargs.keys() and mutable_attrs[attr] == bool:
|
||||
setattr(self, attr, False)
|
||||
|
||||
def __getitem__(self, name):
|
||||
return getattr(self, name)
|
||||
|
@ -57,7 +59,7 @@ class Config:
|
|||
return hasattr(self, name)
|
||||
|
||||
def get_mutable_attrs(self):
|
||||
return {name: attr for name, attr in self.__dict__.items()
|
||||
return {name: type(attr) for name, attr in self.__dict__.items()
|
||||
if not name.startswith("__")
|
||||
and (type(attr) is bool or type(attr) is str)}
|
||||
|
||||
|
|
|
@ -120,6 +120,10 @@ def gen_query(query, args, config, near_city=None) -> str:
|
|||
) if config.lang_interface else ''
|
||||
param_dict['safe'] = '&safe=' + ('active' if config.safe else 'off')
|
||||
|
||||
# Block all sites specified in the user config
|
||||
for blocked in config.block.split(','):
|
||||
query += (' -site:' + blocked) if blocked else ''
|
||||
|
||||
for val in param_dict.values():
|
||||
if not val:
|
||||
continue
|
||||
|
|
|
@ -2,7 +2,6 @@ import argparse
|
|||
import base64
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
import pickle
|
||||
import urllib.parse as urlparse
|
||||
import uuid
|
||||
|
@ -17,7 +16,7 @@ from app import app
|
|||
from app.models.config import Config
|
||||
from app.request import Request, TorError
|
||||
from app.utils.bangs import resolve_bang
|
||||
from app.utils.session import valid_user_session
|
||||
from app.utils.session import generate_user_key, valid_user_session
|
||||
from app.utils.search import *
|
||||
|
||||
# Load DDG bang json files only on init
|
||||
|
|
|
@ -66,7 +66,7 @@ select {
|
|||
}
|
||||
|
||||
#search-bar {
|
||||
border: 2px solid var(--whoogle-dark-element-bg) !important;
|
||||
border-color: var(--whoogle-dark-element-bg) !important;
|
||||
color: var(--whoogle-dark-text) !important;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,11 @@ header {
|
|||
font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
.search-bar-desktop {
|
||||
border-radius: 8px 8px 0 0;
|
||||
height: 40px !important;
|
||||
}
|
||||
|
||||
.search-div {
|
||||
border-radius: 8px 8px 0 0;
|
||||
box-shadow: 0 1px 6px rgba(32, 33, 36, 0.18);
|
||||
|
@ -37,6 +42,7 @@ header {
|
|||
height: 39px;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
|
@ -61,7 +67,6 @@ header {
|
|||
display: block;
|
||||
}
|
||||
|
||||
|
||||
#main>div:focus-within {
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 0 6px 1px #2375e8;
|
||||
|
|
14
app/static/css/input.css
Normal file
14
app/static/css/input.css
Normal file
|
@ -0,0 +1,14 @@
|
|||
#search-bar {
|
||||
background: transparent !important;
|
||||
padding-right: 50px;
|
||||
}
|
||||
|
||||
#search-reset {
|
||||
all: unset;
|
||||
margin-left: -50px;
|
||||
text-align: center;
|
||||
background-color: transparent !important;
|
||||
cursor: pointer;
|
||||
height: 40px;
|
||||
width: 50px;
|
||||
}
|
|
@ -122,6 +122,7 @@ input {
|
|||
|
||||
.autocomplete-items div:hover {
|
||||
background-color: var(--whoogle-element-bg);
|
||||
color: var(--whoogle-contrast-text) !important;
|
||||
}
|
||||
|
||||
.autocomplete-active {
|
||||
|
|
|
@ -57,4 +57,13 @@ const checkForTracking = () => {
|
|||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
checkForTracking();
|
||||
|
||||
// Clear input if reset button tapped
|
||||
const search = document.getElementById("search-bar");
|
||||
const resetBtn = document.getElementById("search-reset");
|
||||
resetBtn.addEventListener("click", event => {
|
||||
event.preventDefault();
|
||||
search.value = "";
|
||||
search.focus();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
<link rel="search" href="opensearch.xml" type="application/opensearchdescription+xml" title="Whoogle Search">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="referrer" content="no-referrer">
|
||||
<link rel="stylesheet" href="static/css/input.css">
|
||||
<link rel="stylesheet" href="static/css/search.css">
|
||||
<link rel="stylesheet" href="static/css/variables.css">
|
||||
<link rel="stylesheet" href="static/css/header.css">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% if mobile %}
|
||||
<header>
|
||||
<div class="bz1lBb">
|
||||
<form class="Pg70bf" id="search-form" method="POST">
|
||||
<div style="background-color: {{ 'var(--whoogle-dark-result-bg)' if config.dark else 'var(--whoogle-result-bg)' }} !important;" class="bz1lBb">
|
||||
<form class="search-form Pg70bf" id="search-form" method="POST">
|
||||
<a class="logo-link mobile-logo"
|
||||
href="/"
|
||||
style="display:flex; justify-content:center; align-items:center;">
|
||||
|
@ -11,11 +11,19 @@
|
|||
</a>
|
||||
<div class="H0PQec" style="width: 100%;">
|
||||
<div class="sbc esbc autocomplete">
|
||||
<input id="search-bar" autocapitalize="none" autocomplete="off" class="noHIxc" name="q"
|
||||
style="background-color: {{ 'var(--whoogle-dark-result-bg)' if config.dark else 'var(--whoogle-result-bg)' }} !important;
|
||||
color: {{ 'var(--whoogle-dark-text)' if config.dark else 'var(--whoogle-text)' }};
|
||||
border: {{ '2px solid var(--whoogle-dark-element-bg)' if config.dark else '' }}; border-radius: 8px;"
|
||||
spellcheck="false" type="text" value="{{ query }}">
|
||||
<input
|
||||
id="search-bar"
|
||||
autocapitalize="none"
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
spellcheck="false"
|
||||
class="noHIxc"
|
||||
name="q"
|
||||
style="background-color: {{ 'var(--whoogle-dark-result-bg)' if config.dark else 'var(--whoogle-result-bg)' }} !important;
|
||||
color: {{ 'var(--whoogle-dark-text)' if config.dark else 'var(--whoogle-text)' }};
|
||||
type="text"
|
||||
value="{{ query[:query.find('-site:')] }}">
|
||||
<input style="color: {{ 'var(--whoogle-dark-text)' if config.dark else 'var(--whoogle-text)' }}" id="search-reset" type="reset" value="x">
|
||||
<input name="tbm" value="{{ search_type }}" style="display: none">
|
||||
<input type="submit" style="display: none;">
|
||||
<div class="sc"></div>
|
||||
|
@ -37,11 +45,19 @@
|
|||
<form id="search-form" class="search-form" id="sf" method="POST">
|
||||
<div class="autocomplete" style="width: 100%; flex: 1">
|
||||
<div style="width: 100%; display: flex">
|
||||
<input id="search-bar" autocapitalize="none" autocomplete="off" class="noHIxc" name="q"
|
||||
spellcheck="false" type="text" value="{{ query }}"
|
||||
style="background-color: {{ 'var(--whoogle-dark-result-bg)' if config.dark else 'var(--whoogle-result-bg)' }} !important;
|
||||
color: {{ 'var(--whoogle-dark-text)' if config.dark else 'var(--whoogle-text)' }};
|
||||
border: {{ '2px solid var(--whoogle-dark-element-bg)' if config.dark else '' }}; border-radius: 8px;">
|
||||
<input
|
||||
id="search-bar"
|
||||
autocapitalize="none"
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
class="search-bar-desktop noHIxc"
|
||||
name="q"
|
||||
spellcheck="false"
|
||||
type="text"
|
||||
value="{{ query[:query.find('-site:')] }}"
|
||||
style="background-color: {{ 'var(--whoogle-dark-result-bg)' if config.dark else 'var(--whoogle-result-bg)' }} !important;
|
||||
color: {{ 'var(--whoogle-dark-text)' if config.dark else 'var(--whoogle-text)' }};
|
||||
border-bottom: {{ '2px solid var(--whoogle-dark-element-bg)' if config.dark else '0px' }};">
|
||||
<input name="tbm" value="{{ search_type }}" style="display: none">
|
||||
<input type="submit" style="display: none;">
|
||||
<div class="sc"></div>
|
||||
|
|
|
@ -42,113 +42,137 @@
|
|||
<form id="search-form" action="search" method="{{ 'get' if config.get_only else 'post' }}">
|
||||
<div class="search-fields">
|
||||
<div class="autocomplete">
|
||||
<input type="text" name="q" id="search-bar" class="home-search" autofocus="autofocus" autocapitalize="none" autocomplete="off">
|
||||
<input
|
||||
type="text"
|
||||
name="q"
|
||||
id="search-bar"
|
||||
class="home-search"
|
||||
autofocus="autofocus"
|
||||
autocapitalize="none"
|
||||
spellcheck="false"
|
||||
autocorrect="off"
|
||||
autocomplete="off">
|
||||
</div>
|
||||
<input type="submit" id="search-submit" value="Search">
|
||||
</div>
|
||||
</form>
|
||||
<br/>
|
||||
<button id="config-collapsible" class="collapsible">Configuration</button>
|
||||
<div class="content">
|
||||
<div class="config-fields">
|
||||
<form id="config-form" action="config" method="post">
|
||||
<div class="config-div config-div-ctry">
|
||||
<label for="config-ctry">Filter Results by Country: </label>
|
||||
<select name="ctry" id="config-ctry">
|
||||
{% for ctry in countries %}
|
||||
<option value="{{ ctry.value }}"
|
||||
{% if ctry.value in config.ctry %}
|
||||
selected
|
||||
{% endif %}>
|
||||
{{ ctry.name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<div><span class="info-text"> — Note: If enabled, a website will only appear in the results if it is *hosted* in the selected country.</span></div>
|
||||
</div>
|
||||
<div class="config-div config-div-lang">
|
||||
<label for="config-lang-interface">Interface Language: </label>
|
||||
<select name="lang_interface" id="config-lang-interface">
|
||||
{% for lang in languages %}
|
||||
<option value="{{ lang.value }}"
|
||||
{% if lang.value in config.lang_interface %}
|
||||
selected
|
||||
{% endif %}>
|
||||
{{ lang.name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="config-div config-div-search-lang">
|
||||
<label for="config-lang-search">Search Language: </label>
|
||||
<select name="lang_search" id="config-lang-search">
|
||||
{% for lang in languages %}
|
||||
<option value="{{ lang.value }}"
|
||||
{% if lang.value in config.lang_search %}
|
||||
selected
|
||||
{% endif %}>
|
||||
{{ lang.name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="config-div config-div-near">
|
||||
<label for="config-near">Near: </label>
|
||||
<input type="text" name="near" id="config-near" placeholder="City Name" value="{{ config.near }}">
|
||||
</div>
|
||||
<div class="config-div config-div-nojs">
|
||||
<label for="config-nojs">Show NoJS Links: </label>
|
||||
<input type="checkbox" name="nojs" id="config-nojs" {{ 'checked' if config.nojs else '' }}>
|
||||
</div>
|
||||
<div class="config-div config-div-dark">
|
||||
<label for="config-dark">Dark Mode: </label>
|
||||
<input type="checkbox" name="dark" id="config-dark" {{ 'checked' if config.dark else '' }}>
|
||||
</div>
|
||||
<div class="config-div config-div-safe">
|
||||
<label for="config-safe">Safe Search: </label>
|
||||
<input type="checkbox" name="safe" id="config-safe" {{ 'checked' if config.safe else '' }}>
|
||||
</div>
|
||||
<div class="config-div config-div-alts">
|
||||
<label class="tooltip" for="config-alts">Replace Social Media Links: </label>
|
||||
<input type="checkbox" name="alts" id="config-alts" {{ 'checked' if config.alts else '' }}>
|
||||
<div><span class="info-text"> — Replaces Twitter/YouTube/Instagram/Reddit links
|
||||
with Nitter/Invidious/Bibliogram/Libreddit links.</span></div>
|
||||
</div>
|
||||
<div class="config-div config-div-new-tab">
|
||||
<label for="config-new-tab">Open Links in New Tab: </label>
|
||||
<input type="checkbox" name="new_tab" id="config-new-tab" {{ 'checked' if config.new_tab else '' }}>
|
||||
</div>
|
||||
<div class="config-div config-div-view-image">
|
||||
<label for="config-view-image">View image: </label>
|
||||
<input type="checkbox" name="view_image" id="config-view-image" {{ 'checked' if config.view_image else '' }}>
|
||||
<div><span class="info-text"> — Adds the "View Image" option to image search results.
|
||||
Note: This will cause image result thumbnails to be lower resolution.</span></div>
|
||||
</div>
|
||||
<div class="config-div config-div-tor">
|
||||
<label for="config-tor">Use Tor: {{ '' if tor_available else 'Unavailable' }}</label>
|
||||
<input type="checkbox" name="tor" id="config-tor" {{ '' if tor_available else 'hidden' }} {{ 'checked' if config.tor else '' }}>
|
||||
</div>
|
||||
<div class="config-div config-div-get-only">
|
||||
<label for="config-get-only">GET Requests Only: </label>
|
||||
<input type="checkbox" name="get_only" id="config-get-only" {{ 'checked' if config.get_only else '' }}>
|
||||
</div>
|
||||
<div class="config-div config-div-root-url">
|
||||
<label for="config-url">Root URL: </label>
|
||||
<input type="text" name="url" id="config-url" value="{{ config.url }}">
|
||||
</div>
|
||||
<div class="config-div config-div-custom-css">
|
||||
<label for="config-style">Custom CSS:</label>
|
||||
<textarea name="style" id="config-style" value="">{{ config.style }}</textarea>
|
||||
</div>
|
||||
<div class="config-div">
|
||||
<input type="submit" id="config-load" value="Load">
|
||||
<input type="submit" id="config-submit" value="Apply">
|
||||
<input type="submit" id="config-save" value="Save As...">
|
||||
</div>
|
||||
</form>
|
||||
{% if not config_disabled %}
|
||||
<br/>
|
||||
<button id="config-collapsible" class="collapsible">Configuration</button>
|
||||
<div class="content">
|
||||
<div class="config-fields">
|
||||
<form id="config-form" action="config" method="post">
|
||||
<div class="config-div config-div-ctry">
|
||||
<label for="config-ctry">Filter Results by Country: </label>
|
||||
<select name="ctry" id="config-ctry">
|
||||
{% for ctry in countries %}
|
||||
<option value="{{ ctry.value }}"
|
||||
{% if ctry.value in config.ctry %}
|
||||
selected
|
||||
{% endif %}>
|
||||
{{ ctry.name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<div><span class="info-text"> — Note: If enabled, a website will only appear in the results if it is *hosted* in the selected country.</span></div>
|
||||
</div>
|
||||
<div class="config-div config-div-lang">
|
||||
<label for="config-lang-interface">Interface Language: </label>
|
||||
<select name="lang_interface" id="config-lang-interface">
|
||||
{% for lang in languages %}
|
||||
<option value="{{ lang.value }}"
|
||||
{% if lang.value in config.lang_interface %}
|
||||
selected
|
||||
{% endif %}>
|
||||
{{ lang.name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="config-div config-div-search-lang">
|
||||
<label for="config-lang-search">Search Language: </label>
|
||||
<select name="lang_search" id="config-lang-search">
|
||||
{% for lang in languages %}
|
||||
<option value="{{ lang.value }}"
|
||||
{% if lang.value in config.lang_search %}
|
||||
selected
|
||||
{% endif %}>
|
||||
{{ lang.name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="config-div config-div-near">
|
||||
<label for="config-near">Near: </label>
|
||||
<input type="text" name="near" id="config-near" placeholder="City Name" value="{{ config.near }}">
|
||||
</div>
|
||||
<div class="config-div config-div-block">
|
||||
<label for="config-block">Block: </label>
|
||||
<input type="text" name="block" id="config-block" placeholder="Comma-separated site list" value="{{ config.block }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="config-div config-div-nojs">
|
||||
<label for="config-nojs">Show NoJS Links: </label>
|
||||
<input type="checkbox" name="nojs" id="config-nojs" {{ 'checked' if config.nojs else '' }}>
|
||||
</div>
|
||||
<div class="config-div config-div-dark">
|
||||
<label for="config-dark">Dark Mode: </label>
|
||||
<input type="checkbox" name="dark" id="config-dark" {{ 'checked' if config.dark else '' }}>
|
||||
</div>
|
||||
<div class="config-div config-div-safe">
|
||||
<label for="config-safe">Safe Search: </label>
|
||||
<input type="checkbox" name="safe" id="config-safe" {{ 'checked' if config.safe else '' }}>
|
||||
</div>
|
||||
<div class="config-div config-div-alts">
|
||||
<label class="tooltip" for="config-alts">Replace Social Media Links: </label>
|
||||
<input type="checkbox" name="alts" id="config-alts" {{ 'checked' if config.alts else '' }}>
|
||||
<div><span class="info-text"> — Replaces Twitter/YouTube/Instagram/Reddit links
|
||||
with Nitter/Invidious/Bibliogram/Libreddit links.</span></div>
|
||||
</div>
|
||||
<div class="config-div config-div-new-tab">
|
||||
<label for="config-new-tab">Open Links in New Tab: </label>
|
||||
<input type="checkbox" name="new_tab" id="config-new-tab" {{ 'checked' if config.new_tab else '' }}>
|
||||
</div>
|
||||
<div class="config-div config-div-view-image">
|
||||
<label for="config-view-image">View Image: </label>
|
||||
<input type="checkbox" name="view_image" id="config-view-image" {{ 'checked' if config.view_image else '' }}>
|
||||
<div><span class="info-text"> — Adds the "View Image" option to image search results.
|
||||
Note: This will cause image result thumbnails to be lower resolution.</span></div>
|
||||
</div>
|
||||
<div class="config-div config-div-tor">
|
||||
<label for="config-tor">Use Tor: {{ '' if tor_available else 'Unavailable' }}</label>
|
||||
<input type="checkbox" name="tor" id="config-tor" {{ '' if tor_available else 'hidden' }} {{ 'checked' if config.tor else '' }}>
|
||||
</div>
|
||||
<div class="config-div config-div-get-only">
|
||||
<label for="config-get-only">GET Requests Only: </label>
|
||||
<input type="checkbox" name="get_only" id="config-get-only" {{ 'checked' if config.get_only else '' }}>
|
||||
</div>
|
||||
<div class="config-div config-div-root-url">
|
||||
<label for="config-url">Root URL: </label>
|
||||
<input type="text" name="url" id="config-url" value="{{ config.url }}">
|
||||
</div>
|
||||
<div class="config-div config-div-custom-css">
|
||||
<label for="config-style">Custom CSS:</label>
|
||||
<textarea
|
||||
name="style"
|
||||
id="config-style"
|
||||
autocapitalize="off"
|
||||
autocomplete="off"
|
||||
spellcheck="false"
|
||||
autocorrect="off"
|
||||
value="">
|
||||
{{ config.style }}
|
||||
</textarea>
|
||||
</div>
|
||||
<div class="config-div">
|
||||
<input type="submit" id="config-load" value="Load">
|
||||
<input type="submit" id="config-submit" value="Apply">
|
||||
<input type="submit" id="config-save" value="Save As...">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<footer>
|
||||
<p style="color: {{ 'var(--whoogle-dark-text)' if config.dark else 'var(--whoogle-text)' }};">
|
||||
Whoogle Search v{{ version_number }} ||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from app.filter import Filter, get_first_link
|
||||
from app.utils.session import generate_user_key
|
||||
from app.request import gen_query
|
||||
from bs4 import BeautifulSoup as bsoup
|
||||
from cryptography.fernet import Fernet, InvalidToken
|
||||
|
|
|
@ -37,8 +37,8 @@ services:
|
|||
#- WHOOGLE_ALT_YT=invidious.snopyta.org
|
||||
#- WHOOGLE_ALT_IG=bibliogram.art/u
|
||||
#- WHOOGLE_ALT_RD=libredd.it
|
||||
# Load environment variables from whoogle.env
|
||||
#- WHOOGLE_DOTENV=1
|
||||
#env_file: # Alternatively, load variables from whoogle.env
|
||||
#- whoogle.env
|
||||
ports:
|
||||
- 5000:5000
|
||||
restart: unless-stopped
|
||||
|
|
|
@ -16,7 +16,7 @@ MarkupSafe==1.1.1
|
|||
more-itertools==8.3.0
|
||||
packaging==20.4
|
||||
pluggy==0.13.1
|
||||
py==1.8.1
|
||||
py==1.10.0
|
||||
pycodestyle==2.6.0
|
||||
pycparser==2.19
|
||||
pyOpenSSL==19.1.0
|
||||
|
|
|
@ -3,6 +3,9 @@ from app.filter import Filter
|
|||
from app.utils.session import generate_user_key
|
||||
from datetime import datetime
|
||||
from dateutil.parser import *
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from test.conftest import demo_config
|
||||
|
||||
|
||||
def get_search_results(data):
|
||||
|
@ -46,6 +49,29 @@ def test_post_results(client):
|
|||
assert len(get_search_results(rv.data)) <= 15
|
||||
|
||||
|
||||
def test_block_results(client):
|
||||
rv = client.post('/search', data=dict(q='pinterest'))
|
||||
assert rv._status_code == 200
|
||||
|
||||
has_pinterest = False
|
||||
for link in BeautifulSoup(rv.data, 'html.parser').find_all('a', href=True):
|
||||
if 'pinterest.com' in urlparse(link['href']).netloc:
|
||||
has_pinterest = True
|
||||
break
|
||||
|
||||
assert has_pinterest
|
||||
|
||||
demo_config['block'] = 'pinterest.com'
|
||||
rv = client.post('/config', data=demo_config)
|
||||
assert rv._status_code == 302
|
||||
|
||||
rv = client.post('/search', data=dict(q='pinterest'))
|
||||
assert rv._status_code == 200
|
||||
|
||||
for link in BeautifulSoup(rv.data, 'html.parser').find_all('a', href=True):
|
||||
assert 'pinterest.com' not in urlparse(link['href']).netloc
|
||||
|
||||
|
||||
# TODO: Unit test the site alt method instead -- the results returned
|
||||
# are too unreliable for this test in particular.
|
||||
# def test_site_alts(client):
|
||||
|
|
55
whoogle.env
55
whoogle.env
|
@ -1,5 +1,8 @@
|
|||
# You can set Whoogle environment variables here, but must set
|
||||
# WHOOGLE_DOTENV=1 in your deployment to enable these values
|
||||
# You can set Whoogle environment variables here, but must
|
||||
# modify your deployment to enable these values:
|
||||
# - Local: Set WHOOGLE_DOTENV=1
|
||||
# - docker-compose: Uncomment the env_file option
|
||||
# - docker: Add "--env-file ./whoogle.env" to your build command
|
||||
|
||||
#WHOOGLE_ALT_TW=nitter.net
|
||||
#WHOOGLE_ALT_YT=invidious.snopyta.org
|
||||
|
@ -13,14 +16,44 @@
|
|||
#WHOOGLE_PROXY_LOC=""
|
||||
#HTTPS_ONLY=1
|
||||
|
||||
#WHOOGLE_CONFIG_COUNTRY=countryUK # See app/static/settings/countries.json for values
|
||||
#WHOOGLE_CONFIG_LANGUAGE=lang_en # See app/static/settings/languages.json for values
|
||||
#WHOOGLE_CONFIG_DARK=1 # Dark mode
|
||||
#WHOOGLE_CONFIG_SAFE=1 # Safe searches
|
||||
#WHOOGLE_CONFIG_ALTS=1 # Use social media site alternatives
|
||||
#WHOOGLE_CONFIG_TOR=1 # Use Tor if available
|
||||
#WHOOGLE_CONFIG_NEW_TAB=1 # Open results in new tab
|
||||
#WHOOGLE_CONFIG_VIEW_IMAGE=1 # Enable View Image option
|
||||
#WHOOGLE_CONFIG_GET_ONLY=1 # Search using GET requests only
|
||||
# See app/static/settings/countries.json for values
|
||||
#WHOOGLE_CONFIG_COUNTRY=countryUK
|
||||
|
||||
# See app/static/settings/languages.json for values
|
||||
#WHOOGLE_CONFIG_LANGUAGE=lang_en
|
||||
|
||||
# See app/static/settings/languages.json for values
|
||||
#WHOOGLE_CONFIG_SEARCH_LANGUAGE=lang_en
|
||||
|
||||
# Disable changing of config from client
|
||||
#WHOOGLE_CONFIG_DISABLE=1
|
||||
|
||||
# Block websites from search results (comma-separated list)
|
||||
#WHOOGLE_CONFIG_BLOCK=pinterest.com,whitehouse.gov
|
||||
|
||||
# Dark mode
|
||||
#WHOOGLE_CONFIG_DARK=1
|
||||
|
||||
# Safe search mode
|
||||
#WHOOGLE_CONFIG_SAFE=1
|
||||
|
||||
# Use social media site alternatives (nitter, bibliogram, etc)
|
||||
#WHOOGLE_CONFIG_ALTS=1
|
||||
|
||||
# Enable "View Image" option
|
||||
#WHOOGLE_CONFIG_VIEW_IMAGE=1
|
||||
|
||||
# Use Tor if available
|
||||
#WHOOGLE_CONFIG_TOR=1
|
||||
|
||||
# Open results in new tab
|
||||
#WHOOGLE_CONFIG_NEW_TAB=1
|
||||
|
||||
# Search using GET requests only (exposes query in logs)
|
||||
#WHOOGLE_CONFIG_GET_ONLY=1
|
||||
|
||||
# Set instance URL
|
||||
#WHOOGLE_CONFIG_URL=https://<whoogle url>/
|
||||
|
||||
# Set custom CSS styling/theming
|
||||
#WHOOGLE_CONFIG_STYLE=":root { /* LIGHT THEME COLORS */ --whoogle-background: #d8dee9; --whoogle-accent: #2e3440; --whoogle-text: #3B4252; --whoogle-contrast-text: #eceff4; --whoogle-secondary-text: #70757a; --whoogle-result-bg: #fff; --whoogle-result-title: #4c566a; --whoogle-result-url: #81a1c1; --whoogle-result-visited: #a3be8c; /* DARK THEME COLORS */ --whoogle-dark-background: #222; --whoogle-dark-accent: #685e79; --whoogle-dark-text: #fff; --whoogle-dark-contrast-text: #000; --whoogle-dark-secondary-text: #bbb; --whoogle-dark-result-bg: #000; --whoogle-dark-result-title: #1967d2; --whoogle-dark-result-url: #4b11a8; --whoogle-dark-result-visited: #bbbbff; }"
|
||||
|
|
Loading…
Reference in New Issue
Block a user