Merge branch 'benbusby:develop' into develop

This commit is contained in:
Joao A. Candido Ramos 2021-05-10 09:41:25 +00:00
commit ad336a857b
19 changed files with 304 additions and 155 deletions

View File

@ -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.

View File

@ -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
},

View File

@ -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\';' \

View File

@ -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)}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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
View 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;
}

View File

@ -122,6 +122,7 @@ input {
.autocomplete-items div:hover {
background-color: var(--whoogle-element-bg);
color: var(--whoogle-contrast-text) !important;
}
.autocomplete-active {

View File

@ -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();
});
});

View File

@ -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">

View File

@ -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>

View File

@ -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">&nbsp;
<input type="submit" id="config-submit" value="Apply">&nbsp;
<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">&nbsp;
<input type="submit" id="config-submit" value="Apply">&nbsp;
<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 }} ||

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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):

View File

@ -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; }"