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 ### 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. 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 | | Variable | Description |
| ----------------------- | --------------------------------------------------------------- | | ------------------------------ | --------------------------------------------------------------- |
| WHOOGLE_CONFIG_COUNTRY | Filter results by hosting country | | WHOOGLE_CONFIG_COUNTRY | Filter results by hosting country |
| WHOOGLE_CONFIG_LANGUAGE | Set interface and search result language | | WHOOGLE_CONFIG_LANGUAGE | Set interface language |
| WHOOGLE_CONFIG_DARK | Enable dark theme | | WHOOGLE_CONFIG_SEARCH_LANGUAGE | Set search result language |
| WHOOGLE_CONFIG_SAFE | Enable safe searches | | WHOOGLE_CONFIG_BLOCK | Block websites from search results (use comma-separated list) |
| WHOOGLE_CONFIG_ALTS | Use social media site alternatives (nitter, invidious, etc) | | WHOOGLE_CONFIG_DARK | Enable dark theme |
| WHOOGLE_CONFIG_TOR | Use Tor routing (if available) | | WHOOGLE_CONFIG_SAFE | Enable safe searches |
| WHOOGLE_CONFIG_NEW_TAB | Always open results in new tab | | WHOOGLE_CONFIG_ALTS | Use social media site alternatives (nitter, invidious, etc) |
| WHOOGLE_CONFIG_VIEW_IMAGE | Enable View Image option | | WHOOGLE_CONFIG_TOR | Use Tor routing (if available) |
| WHOOGLE_CONFIG_GET_ONLY | Search using GET requests only | | WHOOGLE_CONFIG_NEW_TAB | Always open results in new tab |
| WHOOGLE_CONFIG_URL | The root url of the instance (`https://<your url>/`) | | WHOOGLE_CONFIG_VIEW_IMAGE | Enable View Image option |
| WHOOGLE_CONFIG_STYLE | The custom CSS to use for styling (must be single line) | | 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 ## Usage
Same as most search engines, with the exception of filtering by time range. Same as most search engines, with the exception of filtering by time range.

View File

@ -71,7 +71,22 @@
"required": false "required": false
}, },
"WHOOGLE_CONFIG_LANGUAGE": { "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": "", "value": "",
"required": false "required": false
}, },

View File

@ -50,7 +50,7 @@ app.config['BANG_FILE'] = os.path.join(
'bangs.json') 'bangs.json')
app.config['CSP'] = 'default-src \'none\';' \ app.config['CSP'] = 'default-src \'none\';' \
'manifest-src \'self\';' \ 'manifest-src \'self\';' \
'img-src \'self\';' \ 'img-src \'self\' data:;' \
'style-src \'self\' \'unsafe-inline\';' \ 'style-src \'self\' \'unsafe-inline\';' \
'script-src \'self\';' \ 'script-src \'self\';' \
'media-src \'self\';' \ 'media-src \'self\';' \

View File

@ -12,12 +12,13 @@ class Config:
app_config = current_app.config app_config = current_app.config
self.url = os.getenv('WHOOGLE_CONFIG_URL', '') 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.lang_interface = os.getenv('WHOOGLE_CONFIG_LANGUAGE', '')
self.style = os.getenv( self.style = os.getenv(
'WHOOGLE_CONFIG_STYLE', 'WHOOGLE_CONFIG_STYLE',
open(os.path.join(app_config['STATIC_FOLDER'], open(os.path.join(app_config['STATIC_FOLDER'],
'css/variables.css')).read()) 'css/variables.css')).read())
self.block = os.getenv('WHOOGLE_CONFIG_BLOCK', '')
self.ctry = os.getenv('WHOOGLE_CONFIG_COUNTRY', '') self.ctry = os.getenv('WHOOGLE_CONFIG_COUNTRY', '')
self.safe = read_config_bool('WHOOGLE_CONFIG_SAFE') self.safe = read_config_bool('WHOOGLE_CONFIG_SAFE')
self.dark = read_config_bool('WHOOGLE_CONFIG_DARK') self.dark = read_config_bool('WHOOGLE_CONFIG_DARK')
@ -38,11 +39,12 @@ class Config:
# Skip setting custom config if there isn't one # Skip setting custom config if there isn't one
if kwargs: if kwargs:
for attr in self.get_mutable_attrs(): mutable_attrs = self.get_mutable_attrs()
if attr not in kwargs.keys(): for attr in mutable_attrs:
setattr(self, attr, '') if attr in kwargs.keys():
else:
setattr(self, attr, kwargs[attr]) setattr(self, attr, kwargs[attr])
elif attr not in kwargs.keys() and mutable_attrs[attr] == bool:
setattr(self, attr, False)
def __getitem__(self, name): def __getitem__(self, name):
return getattr(self, name) return getattr(self, name)
@ -57,7 +59,7 @@ class Config:
return hasattr(self, name) return hasattr(self, name)
def get_mutable_attrs(self): 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("__") if not name.startswith("__")
and (type(attr) is bool or type(attr) is str)} 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 '' ) if config.lang_interface else ''
param_dict['safe'] = '&safe=' + ('active' if config.safe else 'off') 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(): for val in param_dict.values():
if not val: if not val:
continue continue

View File

@ -2,7 +2,6 @@ import argparse
import base64 import base64
import io import io
import json import json
import os
import pickle import pickle
import urllib.parse as urlparse import urllib.parse as urlparse
import uuid import uuid
@ -17,7 +16,7 @@ from app import app
from app.models.config import Config from app.models.config import Config
from app.request import Request, TorError from app.request import Request, TorError
from app.utils.bangs import resolve_bang 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 * from app.utils.search import *
# Load DDG bang json files only on init # Load DDG bang json files only on init

View File

@ -66,7 +66,7 @@ select {
} }
#search-bar { #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; color: var(--whoogle-dark-text) !important;
} }

View File

@ -27,6 +27,11 @@ header {
font-smoothing: antialiased; font-smoothing: antialiased;
} }
.search-bar-desktop {
border-radius: 8px 8px 0 0;
height: 40px !important;
}
.search-div { .search-div {
border-radius: 8px 8px 0 0; border-radius: 8px 8px 0 0;
box-shadow: 0 1px 6px rgba(32, 33, 36, 0.18); box-shadow: 0 1px 6px rgba(32, 33, 36, 0.18);
@ -37,6 +42,7 @@ header {
height: 39px; height: 39px;
display: flex; display: flex;
width: 100%; width: 100%;
margin: 0px;
} }
.search-input { .search-input {
@ -61,7 +67,6 @@ header {
display: block; display: block;
} }
#main>div:focus-within { #main>div:focus-within {
border-radius: 8px; border-radius: 8px;
box-shadow: 0 0 6px 1px #2375e8; 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 { .autocomplete-items div:hover {
background-color: var(--whoogle-element-bg); background-color: var(--whoogle-element-bg);
color: var(--whoogle-contrast-text) !important;
} }
.autocomplete-active { .autocomplete-active {

View File

@ -57,4 +57,13 @@ const checkForTracking = () => {
document.addEventListener("DOMContentLoaded", function() { document.addEventListener("DOMContentLoaded", function() {
checkForTracking(); 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"> <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="viewport" content="width=device-width, initial-scale=1.0">
<meta name="referrer" content="no-referrer"> <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/search.css">
<link rel="stylesheet" href="static/css/variables.css"> <link rel="stylesheet" href="static/css/variables.css">
<link rel="stylesheet" href="static/css/header.css"> <link rel="stylesheet" href="static/css/header.css">

View File

@ -1,7 +1,7 @@
{% if mobile %} {% if mobile %}
<header> <header>
<div class="bz1lBb"> <div style="background-color: {{ 'var(--whoogle-dark-result-bg)' if config.dark else 'var(--whoogle-result-bg)' }} !important;" class="bz1lBb">
<form class="Pg70bf" id="search-form" method="POST"> <form class="search-form Pg70bf" id="search-form" method="POST">
<a class="logo-link mobile-logo" <a class="logo-link mobile-logo"
href="/" href="/"
style="display:flex; justify-content:center; align-items:center;"> style="display:flex; justify-content:center; align-items:center;">
@ -11,11 +11,19 @@
</a> </a>
<div class="H0PQec" style="width: 100%;"> <div class="H0PQec" style="width: 100%;">
<div class="sbc esbc autocomplete"> <div class="sbc esbc autocomplete">
<input id="search-bar" autocapitalize="none" autocomplete="off" class="noHIxc" name="q" <input
style="background-color: {{ 'var(--whoogle-dark-result-bg)' if config.dark else 'var(--whoogle-result-bg)' }} !important; id="search-bar"
color: {{ 'var(--whoogle-dark-text)' if config.dark else 'var(--whoogle-text)' }}; autocapitalize="none"
border: {{ '2px solid var(--whoogle-dark-element-bg)' if config.dark else '' }}; border-radius: 8px;" autocomplete="off"
spellcheck="false" type="text" value="{{ query }}"> 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 name="tbm" value="{{ search_type }}" style="display: none">
<input type="submit" style="display: none;"> <input type="submit" style="display: none;">
<div class="sc"></div> <div class="sc"></div>
@ -37,11 +45,19 @@
<form id="search-form" class="search-form" id="sf" method="POST"> <form id="search-form" class="search-form" id="sf" method="POST">
<div class="autocomplete" style="width: 100%; flex: 1"> <div class="autocomplete" style="width: 100%; flex: 1">
<div style="width: 100%; display: flex"> <div style="width: 100%; display: flex">
<input id="search-bar" autocapitalize="none" autocomplete="off" class="noHIxc" name="q" <input
spellcheck="false" type="text" value="{{ query }}" id="search-bar"
style="background-color: {{ 'var(--whoogle-dark-result-bg)' if config.dark else 'var(--whoogle-result-bg)' }} !important; autocapitalize="none"
color: {{ 'var(--whoogle-dark-text)' if config.dark else 'var(--whoogle-text)' }}; autocomplete="off"
border: {{ '2px solid var(--whoogle-dark-element-bg)' if config.dark else '' }}; border-radius: 8px;"> 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 name="tbm" value="{{ search_type }}" style="display: none">
<input type="submit" style="display: none;"> <input type="submit" style="display: none;">
<div class="sc"></div> <div class="sc"></div>

View File

@ -42,113 +42,137 @@
<form id="search-form" action="search" method="{{ 'get' if config.get_only else 'post' }}"> <form id="search-form" action="search" method="{{ 'get' if config.get_only else 'post' }}">
<div class="search-fields"> <div class="search-fields">
<div class="autocomplete"> <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> </div>
<input type="submit" id="search-submit" value="Search"> <input type="submit" id="search-submit" value="Search">
</div> </div>
</form> </form>
<br/> {% if not config_disabled %}
<button id="config-collapsible" class="collapsible">Configuration</button> <br/>
<div class="content"> <button id="config-collapsible" class="collapsible">Configuration</button>
<div class="config-fields"> <div class="content">
<form id="config-form" action="config" method="post"> <div class="config-fields">
<div class="config-div config-div-ctry"> <form id="config-form" action="config" method="post">
<label for="config-ctry">Filter Results by Country: </label> <div class="config-div config-div-ctry">
<select name="ctry" id="config-ctry"> <label for="config-ctry">Filter Results by Country: </label>
{% for ctry in countries %} <select name="ctry" id="config-ctry">
<option value="{{ ctry.value }}" {% for ctry in countries %}
{% if ctry.value in config.ctry %} <option value="{{ ctry.value }}"
selected {% if ctry.value in config.ctry %}
{% endif %}> selected
{{ ctry.name }} {% endif %}>
</option> {{ ctry.name }}
{% endfor %} </option>
</select> {% endfor %}
<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> </select>
</div> <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 class="config-div config-div-lang"> </div>
<label for="config-lang-interface">Interface Language: </label> <div class="config-div config-div-lang">
<select name="lang_interface" id="config-lang-interface"> <label for="config-lang-interface">Interface Language: </label>
{% for lang in languages %} <select name="lang_interface" id="config-lang-interface">
<option value="{{ lang.value }}" {% for lang in languages %}
{% if lang.value in config.lang_interface %} <option value="{{ lang.value }}"
selected {% if lang.value in config.lang_interface %}
{% endif %}> selected
{{ lang.name }} {% endif %}>
</option> {{ lang.name }}
{% endfor %} </option>
</select> {% endfor %}
</div> </select>
<div class="config-div config-div-search-lang"> </div>
<label for="config-lang-search">Search Language: </label> <div class="config-div config-div-search-lang">
<select name="lang_search" id="config-lang-search"> <label for="config-lang-search">Search Language: </label>
{% for lang in languages %} <select name="lang_search" id="config-lang-search">
<option value="{{ lang.value }}" {% for lang in languages %}
{% if lang.value in config.lang_search %} <option value="{{ lang.value }}"
selected {% if lang.value in config.lang_search %}
{% endif %}> selected
{{ lang.name }} {% endif %}>
</option> {{ lang.name }}
{% endfor %} </option>
</select> {% endfor %}
</div> </select>
<div class="config-div config-div-near"> </div>
<label for="config-near">Near: </label> <div class="config-div config-div-near">
<input type="text" name="near" id="config-near" placeholder="City Name" value="{{ config.near }}"> <label for="config-near">Near: </label>
</div> <input type="text" name="near" id="config-near" placeholder="City Name" value="{{ config.near }}">
<div class="config-div config-div-nojs"> </div>
<label for="config-nojs">Show NoJS Links: </label> <div class="config-div config-div-block">
<input type="checkbox" name="nojs" id="config-nojs" {{ 'checked' if config.nojs else '' }}> <label for="config-block">Block: </label>
</div> <input type="text" name="block" id="config-block" placeholder="Comma-separated site list" value="{{ config.block }}">
<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>
</div> </div>
</div> <div class="config-div config-div-nojs">
</div> <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> <footer>
<p style="color: {{ 'var(--whoogle-dark-text)' if config.dark else 'var(--whoogle-text)' }};"> <p style="color: {{ 'var(--whoogle-dark-text)' if config.dark else 'var(--whoogle-text)' }};">
Whoogle Search v{{ version_number }} || Whoogle Search v{{ version_number }} ||

View File

@ -1,5 +1,4 @@
from app.filter import Filter, get_first_link from app.filter import Filter, get_first_link
from app.utils.session import generate_user_key
from app.request import gen_query from app.request import gen_query
from bs4 import BeautifulSoup as bsoup from bs4 import BeautifulSoup as bsoup
from cryptography.fernet import Fernet, InvalidToken from cryptography.fernet import Fernet, InvalidToken

View File

@ -37,8 +37,8 @@ services:
#- WHOOGLE_ALT_YT=invidious.snopyta.org #- WHOOGLE_ALT_YT=invidious.snopyta.org
#- WHOOGLE_ALT_IG=bibliogram.art/u #- WHOOGLE_ALT_IG=bibliogram.art/u
#- WHOOGLE_ALT_RD=libredd.it #- WHOOGLE_ALT_RD=libredd.it
# Load environment variables from whoogle.env #env_file: # Alternatively, load variables from whoogle.env
#- WHOOGLE_DOTENV=1 #- whoogle.env
ports: ports:
- 5000:5000 - 5000:5000
restart: unless-stopped restart: unless-stopped

View File

@ -16,7 +16,7 @@ MarkupSafe==1.1.1
more-itertools==8.3.0 more-itertools==8.3.0
packaging==20.4 packaging==20.4
pluggy==0.13.1 pluggy==0.13.1
py==1.8.1 py==1.10.0
pycodestyle==2.6.0 pycodestyle==2.6.0
pycparser==2.19 pycparser==2.19
pyOpenSSL==19.1.0 pyOpenSSL==19.1.0

View File

@ -3,6 +3,9 @@ from app.filter import Filter
from app.utils.session import generate_user_key from app.utils.session import generate_user_key
from datetime import datetime from datetime import datetime
from dateutil.parser import * from dateutil.parser import *
from urllib.parse import urlparse
from test.conftest import demo_config
def get_search_results(data): def get_search_results(data):
@ -46,6 +49,29 @@ def test_post_results(client):
assert len(get_search_results(rv.data)) <= 15 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 # TODO: Unit test the site alt method instead -- the results returned
# are too unreliable for this test in particular. # are too unreliable for this test in particular.
# def test_site_alts(client): # def test_site_alts(client):

View File

@ -1,5 +1,8 @@
# You can set Whoogle environment variables here, but must set # You can set Whoogle environment variables here, but must
# WHOOGLE_DOTENV=1 in your deployment to enable these values # 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_TW=nitter.net
#WHOOGLE_ALT_YT=invidious.snopyta.org #WHOOGLE_ALT_YT=invidious.snopyta.org
@ -13,14 +16,44 @@
#WHOOGLE_PROXY_LOC="" #WHOOGLE_PROXY_LOC=""
#HTTPS_ONLY=1 #HTTPS_ONLY=1
#WHOOGLE_CONFIG_COUNTRY=countryUK # See app/static/settings/countries.json for values # See app/static/settings/countries.json for values
#WHOOGLE_CONFIG_LANGUAGE=lang_en # See app/static/settings/languages.json for values #WHOOGLE_CONFIG_COUNTRY=countryUK
#WHOOGLE_CONFIG_DARK=1 # Dark mode
#WHOOGLE_CONFIG_SAFE=1 # Safe searches # See app/static/settings/languages.json for values
#WHOOGLE_CONFIG_ALTS=1 # Use social media site alternatives #WHOOGLE_CONFIG_LANGUAGE=lang_en
#WHOOGLE_CONFIG_TOR=1 # Use Tor if available
#WHOOGLE_CONFIG_NEW_TAB=1 # Open results in new tab # See app/static/settings/languages.json for values
#WHOOGLE_CONFIG_VIEW_IMAGE=1 # Enable View Image option #WHOOGLE_CONFIG_SEARCH_LANGUAGE=lang_en
#WHOOGLE_CONFIG_GET_ONLY=1 # Search using GET requests only
# 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>/ #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; }" #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; }"