Merge remote-tracking branch 'origin/main' into heroku-app
This commit is contained in:
commit
21a6b4bdad
5
app.json
5
app.json
|
@ -80,6 +80,11 @@
|
|||
"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_DARK": {
|
||||
"description": "[CONFIG] Enable dark mode (set to 1 or leave blank)",
|
||||
"value": "",
|
||||
|
|
|
@ -39,6 +39,7 @@ app.config['CONFIG_PATH'] = os.getenv(
|
|||
app.config['DEFAULT_CONFIG'] = os.path.join(
|
||||
app.config['CONFIG_PATH'],
|
||||
'config.json')
|
||||
app.config['CONFIG_DISABLE'] = os.getenv('WHOOGLE_CONFIG_DISABLE', '')
|
||||
app.config['SESSION_FILE_DIR'] = os.path.join(
|
||||
app.config['CONFIG_PATH'],
|
||||
'session')
|
||||
|
|
|
@ -129,6 +129,7 @@ def index():
|
|||
logo=render_template(
|
||||
'logo.html',
|
||||
dark=g.user_config.dark),
|
||||
config_disabled=app.config['CONFIG_DISABLE'],
|
||||
config=g.user_config,
|
||||
tor_available=int(os.environ.get('TOR_AVAILABLE')),
|
||||
version_number=app.config['VERSION_NUMBER'])
|
||||
|
@ -237,9 +238,10 @@ def search():
|
|||
@app.route('/config', methods=['GET', 'POST', 'PUT'])
|
||||
@auth_required
|
||||
def config():
|
||||
config_disabled = app.config['CONFIG_DISABLE']
|
||||
if request.method == 'GET':
|
||||
return json.dumps(g.user_config.__dict__)
|
||||
elif request.method == 'PUT':
|
||||
elif request.method == 'PUT' and not config_disabled:
|
||||
if 'name' in request.args:
|
||||
config_pkl = os.path.join(
|
||||
app.config['CONFIG_PATH'],
|
||||
|
@ -250,7 +252,7 @@ def config():
|
|||
return json.dumps(session['config'])
|
||||
else:
|
||||
return json.dumps({})
|
||||
else:
|
||||
elif not config_disabled:
|
||||
config_data = request.form.to_dict()
|
||||
if 'url' not in config_data or not config_data['url']:
|
||||
config_data['url'] = g.user_config.url
|
||||
|
@ -270,6 +272,8 @@ def config():
|
|||
|
||||
session['config'] = config_data
|
||||
return redirect(config_data['url'])
|
||||
else:
|
||||
return redirect(url_for('.index'), code=403)
|
||||
|
||||
|
||||
@app.route('/url', methods=['GET'])
|
||||
|
|
|
@ -56,111 +56,113 @@
|
|||
<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-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>
|
||||
</div>
|
||||
{% 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-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-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 }} ||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from app import app
|
||||
|
||||
import json
|
||||
|
||||
from test.conftest import demo_config
|
||||
|
@ -52,6 +54,17 @@ def test_config(client):
|
|||
assert rv._status_code == 200
|
||||
assert custom_config.replace('&', '&') in str(rv.data)
|
||||
|
||||
# Test disabling changing config from client
|
||||
app.config['CONFIG_DISABLE'] = 1
|
||||
dark_mod = not demo_config['dark']
|
||||
demo_config['dark'] = dark_mod
|
||||
rv = client.post('/config', data=demo_config)
|
||||
assert rv._status_code == 403
|
||||
|
||||
rv = client.get('/config')
|
||||
config = json.loads(rv.data)
|
||||
assert config['dark'] != dark_mod
|
||||
|
||||
|
||||
def test_opensearch(client):
|
||||
rv = client.get('/opensearch.xml')
|
||||
|
|
38
whoogle.env
38
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,27 @@
|
|||
#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_SEARCH_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_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
|
||||
# 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
|
||||
# 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