Merge branch 'develop' into patch-2

This commit is contained in:
Ben Busby 2021-03-22 10:18:46 -04:00 committed by GitHub
commit 9e6f54696b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 394 additions and 216 deletions

View File

@ -48,7 +48,7 @@ ENV WHOOGLE_ALT_TW=$twitter_alt
ARG youtube_alt='invidious.snopyta.org'
ENV WHOOGLE_ALT_YT=$youtube_alt
ARG instagram_alt='bibliogram.art/u'
ENV WHOOGLE_ALT_YT=$instagram_alt
ENV WHOOGLE_ALT_IG=$instagram_alt
ARG reddit_alt='libredd.it'
ENV WHOOGLE_ALT_RD=$reddit_alt

View File

@ -341,6 +341,8 @@ A lot of the app currently piggybacks on Google's existing support for fetching
- [https://whoogle.sdf.org](https://whoogle.sdf.org)
- [https://whoogle.tormentasolar.win/](https://whoogle.tormentasolar.win/)
- [https://whoogle.himiko.cloud](https://whoogle.himiko.cloud)
- [https://whoogle.kavin.rocks](https://whoogle.kavin.rocks) or [http://whoogledq5f5wly5p4i2ohnvjwlihnlg4oajjum2oeddfwqdwupbuhqd.onion](http://whoogledq5f5wly5p4i2ohnvjwlihnlg4oajjum2oeddfwqdwupbuhqd.onion)
## Screenshots
#### Desktop

View File

@ -18,13 +18,13 @@ app.config['VERSION_NUMBER'] = '0.3.1'
app.config['APP_ROOT'] = os.getenv(
'APP_ROOT',
os.path.dirname(os.path.abspath(__file__)))
app.config['LANGUAGES'] = json.load(open(
os.path.join(app.config['APP_ROOT'], 'misc/languages.json')))
app.config['COUNTRIES'] = json.load(open(
os.path.join(app.config['APP_ROOT'], 'misc/countries.json')))
app.config['STATIC_FOLDER'] = os.getenv(
'STATIC_FOLDER',
os.path.join(app.config['APP_ROOT'], 'static'))
app.config['LANGUAGES'] = json.load(open(
os.path.join(app.config['STATIC_FOLDER'], 'settings/languages.json')))
app.config['COUNTRIES'] = json.load(open(
os.path.join(app.config['STATIC_FOLDER'], 'settings/countries.json')))
app.config['CONFIG_PATH'] = os.getenv(
'CONFIG_VOLUME',
os.path.join(app.config['STATIC_FOLDER'], 'config'))
@ -41,6 +41,7 @@ app.config['BANG_FILE'] = os.path.join(
app.config['BANG_PATH'],
'bangs.json')
app.config['CSP'] = 'default-src \'none\';' \
'manifest-src \'self\';' \
'img-src \'self\';' \
'style-src \'self\' \'unsafe-inline\';' \
'script-src \'self\';' \

View File

@ -1,8 +1,15 @@
from flask import current_app
import os
class Config:
def __init__(self, **kwargs):
app_config = current_app.config
self.url = ''
self.lang_search = ''
self.lang_interface = ''
self.style = open(os.path.join(app_config['STATIC_FOLDER'],
'css/variables.css')).read()
self.ctry = ''
self.safe = False
self.dark = False

View File

@ -229,20 +229,23 @@ def search():
# the element key can be regenerated
app.user_elements[session['uuid']] = elements
# Return 503 if temporarily blocked by captcha
resp_code = 503 if has_captcha(str(response)) else 200
return render_template(
'display.html',
query=urlparse.unquote(query),
search_type=search_util.search_type,
dark_mode=g.user_config.dark,
config=g.user_config,
response=response,
version_number=app.config['VERSION_NUMBER'],
search_header=(render_template(
'header.html',
dark_mode=g.user_config.dark,
config=g.user_config,
query=urlparse.unquote(query),
search_type=search_util.search_type,
mobile=g.user_request.mobile)
if 'isch' not in search_util.search_type else ''))
if 'isch' not in search_util.search_type else '')), resp_code
@app.route('/config', methods=['GET', 'POST', 'PUT'])

View File

@ -1,13 +1,17 @@
html {
background-color: #222 !important;
background: var(--whoogle-dark-background) !important;
}
body {
background-color: #222 !important;
background: var(--whoogle-dark-background) !important;
}
div {
color: #fff !important;
color: var(--whoogle-dark-text) !important;
}
label {
color: var(--whoogle-dark-contrast-text) !important;
}
li a {
@ -15,43 +19,113 @@ li a {
}
li {
color: #fff !important;
color: var(--whoogle-dark-text) !important;
}
textarea {
background: var(--whoogle-dark-background) !important;
color: var(--whoogle-dark-text) !important;
}
a:visited h3 div {
color: #bbbbff !important;
color: var(--whoogle-dark-result-visited) !important;
}
a:link h3 div {
color: #4b8eea !important;
color: var(--whoogle-dark-result-title) !important;
}
a:link div {
color: #aaffaa !important;
color: var(--whoogle-dark-result-url) !important;
}
div span {
color: #bbb !important;
color: var(--whoogle-dark-secondary-text) !important;
}
input {
background-color: #111 !important;
color: #fff !important;
background-color: var(--whoogle-dark-background) !important;
color: var(--whoogle-dark-text) !important;
}
#search-bar {
color: #fff !important;
background-color: #222 !important;
select {
background: var(--whoogle-dark-background) !important;
color: var(--whoogle-dark-text) !important;
}
.search-container {
background-color: #222 !important;
background-color: var(--whoogle-dark-background) !important;
}
.ZINbbc{
background-color: #1a1a1a !important;
.ZINbbc {
background-color: var(--whoogle-dark-result-bg) !important;
}
.bRsWnc{
background-color: #1a1a1a !important;
.bRsWnc {
background-color: var(--whoogle-dark-result-bg) !important;
}
#search-bar {
border: 2px solid var(--whoogle-dark-accent) !important;
color: var(--whoogle-dark-text) !important;
}
#search-bar:focus {
color: var(--whoogle-dark-text) !important;
}
#search-submit {
border: 1px solid var(--whoogle-dark-accent) !important;
background: var(--whoogle-dark-accent) !important;
color: var(--whoogle-dark-background) !important;
}
.info-text {
color: var(--whoogle-dark-contrast-text) !important;
opacity: 75%;
}
.collapsible {
color: var(--whoogle-dark-accent) !important;
}
.collapsible:after {
color: var(--whoogle-dark-accent) !important;
}
.active {
background-color: var(--whoogle-dark-accent) !important;
color: var(--whoogle-dark-contrast-text) !important;
}
.content {
background-color: var(--whoogle-dark-accent) !important;
color: var(--whoogle-contrast-text) !important;
}
.active:after {
color: var(--whoogle-dark-contrast-text);
}
#gh-link {
color: var(--whoogle-dark-accent);
}
.autocomplete-items {
border: 1px solid #685e79;
}
.autocomplete-items div {
color: #fff;
background-color: #222;
border-bottom: 1px solid #242424;
}
.autocomplete-items div:hover {
background-color: #404040;
}
.autocomplete-active {
background-color: var(--whoogle-dark-accent) !important;
color: var(--whoogle-dark-background) !important;
}

View File

@ -0,0 +1,130 @@
html {
background: var(--whoogle-background) !important;
}
body {
background: var(--whoogle-background) !important;
}
div {
color: var(--whoogle-text) !important;
}
label {
color: var(--whoogle-contrast-text) !important;
}
li a {
color: #4b8eaa !important;
}
li {
color: var(--whoogle-text) !important;
}
textarea {
background: var(--whoogle-background) !important;
color: var(--whoogle-text) !important;
}
select {
background: var(--whoogle-background) !important;
color: var(--whoogle-text) !important;
}
.ZINbbc {
background-color: var(--whoogle-result-bg) !important;
}
.bRsWnc {
background-color: var(--whoogle-result-bg) !important;
}
a:visited h3 div {
color: var(--whoogle-result-visited) !important;
}
a:link h3 div {
color: var(--whoogle-result-title) !important;
}
a:link div {
color: var(--whoogle-result-url) !important;
}
div span {
color: var(--whoogle-secondary-text) !important;
}
input {
background-color: var(--whoogle-background) !important;
color: var(--whoogle-text) !important;
}
#search-bar {
color: var(--whoogle-text) !important;
background-color: var(--whoogle-background);
}
.home-search {
border: 3px solid var(--whoogle-accent) !important;
}
.search-container {
background-color: var(--whoogle-background) !important;
}
#search-submit {
border: 1px solid var(--whoogle-accent) !important;
background: var(--whoogle-accent) !important;
color: var(--whoogle-background) !important;
}
.info-text {
color: var(--whoogle-contrast-text) !important;
opacity: 75%;
}
.collapsible {
color: var(--whoogle-accent) !important;
}
.collapsible:after {
color: var(--whoogle-accent) !important;
}
.active {
background-color: var(--whoogle-accent) !important;
color: var(--whoogle-contrast-text) !important;
}
.content {
background-color: var(--whoogle-accent) !important;
color: var(--whoogle-contrast-text) !important;
}
.active:after {
color: var(--whoogle-contrast-text);
}
#gh-link {
color: var(--whoogle-accent);
}
.autocomplete-items {
border: 1px solid #d4d4d4;
}
.autocomplete-items div {
background-color: #fff;
border-bottom: 1px solid #d4d4d4;
}
.autocomplete-items div:hover {
background-color: #e9e9e9;
}
.autocomplete-active {
background-color: var(--whoogle-accent) !important;
color: var(--whoogle-background) !important;
}

View File

@ -10,6 +10,7 @@ body {
}
.search-container {
background: transparent !important;
width: 80%;
position: absolute;
top: 50%;
@ -26,29 +27,21 @@ body {
}
#search-bar {
background: transparent !important;
width: 100%;
border: 3px solid #685e79;
padding: 5px;
height: 40px;
outline: none;
font-size: 24px;
color: #685e79;
border-radius: 10px 10px 0 0;
max-width: 600px;
background: rgba(0, 0, 0, 0);
}
#search-bar:focus {
color: #685e79;
}
#search-submit {
width: 100%;
height: 40px;
border: 1px solid #685e79;
background: #685e79 !important;
text-align: center;
color: #fff;
cursor: pointer;
font-size: 20px;
align-content: center;
@ -70,7 +63,6 @@ button::-moz-focus-inner {
.collapsible {
outline: 0;
background-color: rgba(0, 0, 0, 0);
color: #685e79;
cursor: pointer;
padding: 18px;
width: 100%;
@ -81,14 +73,8 @@ button::-moz-focus-inner {
border-radius: 10px 10px 0 0;
}
.active {
background-color: #685e79;
color: white;
}
.collapsible:after {
content: '\002B';
color: #685e79;
font-weight: bold;
float: right;
margin-left: 5px;
@ -96,7 +82,6 @@ button::-moz-focus-inner {
.active:after {
content: "\2212";
color: white;
}
.content {
@ -104,8 +89,6 @@ button::-moz-focus-inner {
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
background-color: #685e79;
color: white;
border-radius: 0 0 10px 10px;
}
@ -113,12 +96,6 @@ button::-moz-focus-inner {
padding-bottom: 20px;
}
.ua-span {
color: white;
-webkit-box-decoration-break: clone;
box-decoration-break: clone;
}
.hidden {
display: none;
}
@ -135,3 +112,49 @@ footer {
font-style: italic;
font-size: 12px;
}
#config-style {
resize: none;
overflow-y: scroll;
width: 100%;
height: 100px;
}
.whoogle-logo {
display: none;
}
.whoogle-svg {
width: 80%;
display: block;
margin: auto;
padding-bottom: 10px;
}
.autocomplete {
position: relative;
display: inline-block;
width: 100%;
}
.autocomplete-items {
position: absolute;
border-bottom: none;
border-top: none;
z-index: 99;
/*position the autocomplete items to be the same width as the container:*/
top: 100%;
left: 0;
right: 0;
}
.autocomplete-items div {
padding: 10px;
cursor: pointer;
}
details summary {
padding: 10px;
font-weight: bold;
}

View File

@ -1,40 +0,0 @@
.autocomplete {
position: relative;
display: inline-block;
width: 100%;
}
.autocomplete-items {
position: absolute;
border: 1px solid #685e79;
border-bottom: none;
border-top: none;
z-index: 99;
/*position the autocomplete items to be the same width as the container:*/
top: 100%;
left: 0;
right: 0;
}
.autocomplete-items div {
padding: 10px;
cursor: pointer;
color: #fff;
background-color: #222;
border-bottom: 1px solid #242424;
}
.autocomplete-items div:hover {
background-color: #404040;
}
.autocomplete-active {
background-color: #685e79 !important;
color: #ffffff;
}
details summary {
padding: 10px;
font-weight: bold;
}

View File

@ -1,39 +0,0 @@
.autocomplete {
position: relative;
display: inline-block;
width: 100%;
}
.autocomplete-items {
position: absolute;
border: 1px solid #d4d4d4;
border-bottom: none;
border-top: none;
z-index: 99;
/*position the autocomplete items to be the same width as the container:*/
top: 100%;
left: 0;
right: 0;
}
.autocomplete-items div {
padding: 10px;
cursor: pointer;
background-color: #fff;
border-bottom: 1px solid #d4d4d4;
}
.autocomplete-items div:hover {
background-color: #e9e9e9;
}
.autocomplete-active {
background-color: #685e79 !important;
color: #ffffff;
}
details summary {
padding: 10px;
font-weight: bold;
}

View File

@ -0,0 +1,24 @@
/* Colors */
:root {
/* LIGHT THEME COLORS */
--whoogle-background: #fff;
--whoogle-accent: #685e79;
--whoogle-text: #000;
--whoogle-contrast-text: #fff;
--whoogle-secondary-text: #70757a;
--whoogle-result-bg: #fff;
--whoogle-result-title: #1967d2;
--whoogle-result-url: #0d652d;
--whoogle-result-visited: #4b11a8;
/* 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;
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@ -1,14 +1,3 @@
// Whoogle configurations that use boolean values and checkboxes
CONFIG_BOOLS = [
"nojs", "dark", "safe", "alts", "new_tab", "get_only", "tor"
];
// Whoogle configurations that use string values and input fields
CONFIG_STRS = [
"near", "url"
];
const setupSearchLayout = () => {
// Setup search field
const searchBar = document.getElementById("search-bar");
@ -28,33 +17,6 @@ const setupSearchLayout = () => {
});
};
const fillConfigValues = () => {
// Request existing config info
let xhrGET = new XMLHttpRequest();
xhrGET.open("GET", "config");
xhrGET.onload = function() {
if (xhrGET.readyState === 4 && xhrGET.status !== 200) {
alert("Error loading Whoogle config");
return;
}
// Allow for updating/saving config values
let configSettings = JSON.parse(xhrGET.responseText);
CONFIG_STRS.forEach(function(item) {
let configElement = document.getElementById("config-" + item.replace("_", "-"));
configElement.value = configSettings[item] ? configSettings[item] : "";
});
CONFIG_BOOLS.forEach(function(item) {
let configElement = document.getElementById("config-" + item.replace("_", "-"));
configElement.checked = !!configSettings[item];
});
};
xhrGET.send();
};
const setupConfigLayout = () => {
// Setup whoogle config
const collapsible = document.getElementById("config-collapsible");
@ -69,8 +31,6 @@ const setupConfigLayout = () => {
content.classList.toggle("open");
});
fillConfigValues();
};
const loadConfig = event => {

View File

@ -5,11 +5,10 @@
<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/{{ 'search-dark' if dark_mode else 'search' }}.css">
<link rel="stylesheet" href="static/css/variables.css">
<link rel="stylesheet" href="static/css/header.css">
{% if dark_mode %}
<link rel="stylesheet" href="static/css/dark-theme.css"/>
{% endif %}
<link rel="stylesheet" href="static/css/{{ 'dark' if config.dark else 'light' }}-theme.css"/>
<style>{{ config.style }}</style>
<title>{{ query }} - Whoogle Search</title>
</head>
<body>
@ -17,7 +16,7 @@
{{ response|safe }}
</body>
<footer>
<p style="color: {{ '#fff' if dark_mode else '#000' }};">
<p style="color: {{ '#fff' if config.dark else '#000' }};">
Whoogle Search v{{ version_number }} ||
<a style="color: #685e79" href="https://github.com/benbusby/whoogle-search">View on GitHub</a>
</p>

View File

@ -5,14 +5,14 @@
<a class="logo-link mobile-logo"
href="/"
style="display:flex; justify-content:center; align-items:center; color:#685e79; font-size:18px; ">
<span style="color: #685e79">Whoogle</span>
<span style="color: {{ 'var(--whoogle-dark-accent)' if config.dark else 'var(--whoogle-accent)' }} !important">Whoogle</span>
</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: {{ '#000' if dark_mode else '#fff' }};
color: {{ '#685e79' if dark_mode else '#000' }};
border: {{ '1px solid #685e79' if dark_mode else '' }}"
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-accent)' if config.dark else '' }}; border-radius: 8px;"
spellcheck="false" type="text" value="{{ query }}">
<input name="tbm" value="{{ search_type }}" style="display: none">
<input type="submit" style="display: none;">
@ -26,7 +26,7 @@
<header>
<div class="logo-div">
<a class="logo-link" href="/">
<span style="color: #685e79">Whoogle</span>
<span style="color: {{ 'var(--whoogle-dark-accent)' if config.dark else 'var(--whoogle-accent)' }} !important">Whoogle</span>
</a>
</div>
<div class="search-div">
@ -35,9 +35,9 @@
<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: {{ '#000' if dark_mode else '#fff' }};
color: {{ '#685e79' if dark_mode else '#000' }};
border: {{ '1px solid #685e79' if dark_mode else '' }}">
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-accent)' if config.dark else '' }}; border-radius: 8px;">
<input name="tbm" value="{{ search_type }}" style="display: none">
<input type="submit" style="display: none;">
<div class="sc"></div>

View File

@ -21,27 +21,50 @@
<script type="text/javascript" src="static/js/controller.js"></script>
<link rel="search" href="opensearch.xml" type="application/opensearchdescription+xml" title="Whoogle Search">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="static/css/{{ 'search-dark' if config.dark else 'search' }}.css">
<link rel="stylesheet" href="static/css/variables.css">
<link rel="stylesheet" href="static/css/main.css">
{% if config.dark %}
<link rel="stylesheet" href="static/css/dark-theme.css"/>
{% endif %}
<link rel="stylesheet" href="static/css/{{ 'dark' if config.dark else 'light' }}-theme.css"/>
<noscript>
<style>
#main { display: inherit !important; }
.content { max-height: 520px; padding: 18px; border-radius: 10px; }
.content { max-height: 720px; padding: 18px; border-radius: 10px; }
.collapsible { display: none; }
</style>
</noscript>
<style>{{ config.style }}</style>
<title>Whoogle Search</title>
</head>
<body id="main" style="display: none; background-color: {{ '#000' if config.dark else '#fff' }}">
<div class="search-container">
<img class="logo" src="static/img/logo.png">
<img class="whoogle-logo" src="static/img/whoogle.svg">
<svg id="Layer_1" class="whoogle-svg" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1028 254">
<defs>
<style>
.cls-1 {
fill: transparent;
}
path {
fill: {{ 'var(--whoogle-dark-accent)' if config.dark else 'var(--whoogle-accent)' }};
}
</style>
</defs>
<path class="cls-1" d="M1197,667H446V413H1474V667H1208a26.41,26.41,0,0,1,4.26-1.16c32.7-3.35,55.65-27.55,56.45-60.44.57-23.65.27-47.33.32-71,0-17.84-.16-35.67.11-53.5.07-4.92-1.57-6.54-6.3-6.11a74.65,74.65,0,0,1-11,0c-3.63-.2-5.18,1.13-5,4.87.22,4.22.05,8.45.05,12.68a6.16,6.16,0,0,1-3.78-2c-20-23.41-53.18-26.6-77.53-7.84-34,26.17-33.8,79.89-7.68,107.44,24.9,26.24,66,24.37,85.69-1.54a14.39,14.39,0,0,1,2.73-2c0,6.94.39,13.22-.08,19.42-1.18,15.5-7.79,28.06-22.32,34.72-15,6.85-30.27,7.21-44-2.92-5.82-4.28-10.1-10.66-15.66-16.71l-19.87,8.29c8.77,16.61,20.28,29.09,38.17,34.48C1187.28,665.12,1192.18,665.92,1197,667ZM447.16,414.27c.39,1.85.57,3,.86,4q25.22,91.07,50.4,182.12c.92,3.32,2.43,4.55,5.92,4.29a82,82,0,0,1,13.48,0c4.6.43,6.56-1.13,8-5.68,12.37-38.63,25-77.15,37.66-115.7.52-1.6,1.26-3.12,1.89-4.67l1.35.06c.81,2.26,1.68,4.51,2.42,6.79q18.62,57.13,37.12,114.31c1.13,3.5,2.61,5.23,6.58,4.89a80.69,80.69,0,0,1,14,0c4.15.37,5.75-1.19,6.79-5.11Q655,518.89,676.57,438.23c2.07-7.78,4.06-15.58,6.24-24-6.92,0-13.07.29-19.19-.11-4.21-.27-5.6,1.31-6.59,5.25q-17.61,70.1-35.6,140.11c-.42,1.61-1.07,3.17-1.62,4.75a10,10,0,0,1-3.16-4.88q-17.11-51.6-34.21-103.21c-1.72-5.19-2.29-12.33-6-14.86-3.9-2.7-10.86-.78-16.45-1.28-4.1-.37-5.73,1.25-7,5.08q-18.7,57.12-37.79,114.11c-.59,1.77-1.43,3.45-2.15,5.18a9.31,9.31,0,0,1-2.68-4.69Q500.5,522.88,490.62,486c-6-22.47-12-45-18.13-67.39-.44-1.63-2-4.13-3.12-4.19C462.13,414.08,454.86,414.27,447.16,414.27ZM1473.38,543.71c-1-8.62-1.16-16.45-2.77-24-5.08-23.65-18.41-40.82-42.31-47.12-24.75-6.52-47.33-2-65,18.14-15.82,18.09-19.77,39.44-16.45,62.6,4,27.73,26.6,52.65,58.1,54.81,21.42,1.46,39.91-3.91,54.24-20.46,3.51-4.05,6.13-8.88,9.54-13.92l-20.94-8.68c-13.71,20.22-30.84,26.7-50.55,19.53-17.08-6.21-29-23.88-27.23-40.92Zm-746-51.07-1.12-.55V414.65H703.69V604.22h23v-6.36c0-21.84-.08-43.68,0-65.52.07-11.59,3.84-21.92,11.82-30.46,9.41-10.07,21.15-11.89,34-8.78,11.13,2.72,17.67,10.23,20.26,21.14a55.72,55.72,0,0,1,1.46,12.34c.13,24,.07,48,.07,72v5.6h23.49v-4.87c0-24.84.05-49.68-.06-74.52a101.29,101.29,0,0,0-1.06-13.91c-2.8-19.45-15.29-34.48-32.34-38.55-21.17-5-39.58-.47-54.11,16.51C729.19,490.07,728.29,491.38,727.34,492.64Zm179.93-22.47c-38.65,0-66.92,28.86-67,68.47-.06,40.49,28.07,70,66.72,70,38.38,0,66.64-29.26,66.67-69C973.71,499.1,946.09,470.21,907.27,470.17Zm82.22,69.31c.57,5.12.76,10.32,1.76,15.35,10.69,53.81,69.71,66.73,104.35,41.39,20.15-14.74,27.8-35.52,27.31-60.14-.88-44.18-40.84-78.15-90-62.12C1006.24,482.67,989.72,508.59,989.49,539.48Zm333.81,64.95V414.62h-22.65V604.43Z" transform="translate(-446 -413)"/>
<path d="M1197,667c-4.82-1.08-9.72-1.88-14.44-3.3-17.89-5.39-29.4-17.87-38.17-34.48l19.87-8.29c5.56,6.05,9.84,12.43,15.66,16.71,13.75,10.13,29.07,9.77,44,2.92,14.53-6.66,21.14-19.22,22.32-34.72.47-6.2.08-12.48.08-19.42a14.39,14.39,0,0,0-2.73,2c-19.7,25.91-60.79,27.78-85.69,1.54-26.12-27.55-26.3-81.27,7.68-107.44,24.35-18.76,57.56-15.57,77.53,7.84a6.16,6.16,0,0,0,3.78,2c0-4.23.17-8.46-.05-12.68-.19-3.74,1.36-5.07,5-4.87a74.65,74.65,0,0,0,11,0c4.73-.43,6.37,1.19,6.3,6.11-.27,17.83-.08,35.66-.11,53.5,0,23.67.25,47.35-.32,71-.8,32.89-23.75,57.09-56.45,60.44A26.41,26.41,0,0,0,1208,667Zm50-127.58c-.58-4.61-.86-9.29-1.79-13.83a42.26,42.26,0,0,0-37.31-33.75c-16.16-1.75-33.25,8.46-40.62,24.47-5.34,11.62-5.79,23.83-3.48,36.18,5.94,31.62,42.76,45.77,66.74,25.67C1242.58,568.08,1246.76,554.62,1247,539.42Z" transform="translate(-446 -413)"/>
<path d="M447.16,414.27c7.7,0,15-.19,22.21.19,1.14.06,2.68,2.56,3.12,4.19,6.13,22.44,12.1,44.92,18.13,67.39q9.88,36.84,19.81,73.66a9.31,9.31,0,0,0,2.68,4.69c.72-1.73,1.56-3.41,2.15-5.18q19-57,37.79-114.11c1.25-3.83,2.88-5.45,7-5.08,5.59.5,12.55-1.42,16.45,1.28,3.67,2.53,4.24,9.67,6,14.86q17.14,51.58,34.21,103.21a10,10,0,0,0,3.16,4.88c.55-1.58,1.2-3.14,1.62-4.75q17.87-70,35.6-140.11c1-3.94,2.38-5.52,6.59-5.25,6.12.4,12.27.11,19.19.11-2.18,8.4-4.17,16.2-6.24,24q-21.5,80.68-42.93,161.39c-1,3.92-2.64,5.48-6.79,5.11a80.69,80.69,0,0,0-14,0c-4,.34-5.45-1.39-6.58-4.89q-18.43-57.2-37.12-114.31c-.74-2.28-1.61-4.53-2.42-6.79l-1.35-.06c-.63,1.55-1.37,3.07-1.89,4.67-12.61,38.55-25.29,77.07-37.66,115.7-1.46,4.55-3.42,6.11-8,5.68a82,82,0,0,0-13.48,0c-3.49.26-5-1-5.92-4.29Q473.31,509.34,448,418.3C447.73,417.23,447.55,416.12,447.16,414.27Z" transform="translate(-446 -413)"/>
<path d="M1473.38,543.71H1370c-1.76,17,10.15,34.71,27.23,40.92,19.71,7.17,36.84.69,50.55-19.53l20.94,8.68c-3.41,5-6,9.87-9.54,13.92-14.33,16.55-32.82,21.92-54.24,20.46-31.5-2.16-54.12-27.08-58.1-54.81-3.32-23.16.63-44.51,16.45-62.6,17.64-20.17,40.22-24.66,65-18.14,23.9,6.3,37.23,23.47,42.31,47.12C1472.22,527.26,1472.43,535.09,1473.38,543.71Zm-26.69-19.8c2.09-14-14.21-30.54-31.43-32.19-22.21-2.13-43.06,13.12-43.63,32.19Z" transform="translate(-446 -413)"/>
<path d="M727.34,492.64c.95-1.26,1.85-2.57,2.88-3.77,14.53-17,32.94-21.55,54.11-16.51,17,4.07,29.54,19.1,32.34,38.55a101.29,101.29,0,0,1,1.06,13.91c.11,24.84.06,49.68.06,74.52v4.87H794.3v-5.6c0-24,.06-48-.07-72a55.72,55.72,0,0,0-1.46-12.34c-2.59-10.91-9.13-18.42-20.26-21.14-12.81-3.11-24.55-1.29-34,8.78-8,8.54-11.75,18.87-11.82,30.46-.12,21.84,0,43.68,0,65.52v6.36h-23V414.65h22.53v77.44Z" transform="translate(-446 -413)"/>
<path d="M907.27,470.17c38.82,0,66.44,28.93,66.41,69.47,0,39.73-28.29,69-66.67,69-38.65,0-66.78-29.5-66.72-70C840.35,499,868.62,470.13,907.27,470.17Zm43.24,69.26c-.43-3.79-.72-7.61-1.31-11.37-2.94-18.67-19.1-34.56-36.86-36.35-19.93-2-37.94,8.92-45,27.58-3.74,9.85-4.19,20-2.68,30.44,4,27.42,32.55,44.52,57.87,34.41C939.6,577.32,950.2,560.25,950.51,539.43Z" transform="translate(-446 -413)"/>
<path d="M989.49,539.48c.23-30.89,16.75-56.81,43.45-65.52,49.13-16,89.09,17.94,90,62.12.49,24.62-7.16,45.4-27.31,60.14-34.64,25.34-93.66,12.42-104.35-41.39C990.25,549.8,990.06,544.6,989.49,539.48Zm110.22-.09c-.48-4.29-.7-8.62-1.5-12.84-3.43-18.06-19.37-33.16-36.57-34.84-20.05-2-37.75,8.9-45,27.62-3.51,9.06-3.74,18.45-3,28,2.23,27.4,30.07,46.21,55.87,37.67C1088,578.9,1099.32,561.53,1099.71,539.39Z" transform="translate(-446 -413)"/>
<path d="M1323.3,604.43h-22.65V414.62h22.65Z" transform="translate(-446 -413)"/>
<path class="cls-1" d="M1247,539.42c-.24,15.2-4.42,28.66-16.46,38.74-24,20.1-60.8,6-66.74-25.67-2.31-12.35-1.86-24.56,3.48-36.18,7.37-16,24.46-26.22,40.62-24.47a42.26,42.26,0,0,1,37.31,33.75C1246.14,530.13,1246.42,534.81,1247,539.42Z" transform="translate(-446 -413)"/>
<path class="cls-1" d="M1446.69,523.91h-75.06c.57-19.07,21.42-34.32,43.63-32.19C1432.48,493.37,1448.78,509.88,1446.69,523.91Z" transform="translate(-446 -413)"/>
<path class="cls-1" d="M950.51,539.43c-.31,20.82-10.91,37.89-28,44.71-25.32,10.11-53.89-7-57.87-34.41-1.51-10.43-1.06-20.59,2.68-30.44,7.08-18.66,25.09-29.59,45-27.58,17.76,1.79,33.92,17.68,36.86,36.35C949.79,531.82,950.08,535.64,950.51,539.43Z" transform="translate(-446 -413)"/>
<path class="cls-1" d="M1099.71,539.39c-.39,22.14-11.74,39.51-30.16,45.6-25.8,8.54-53.64-10.27-55.87-37.67-.78-9.54-.55-18.93,3-28,7.25-18.72,24.95-29.59,45-27.62,17.2,1.68,33.14,16.78,36.57,34.84C1099,530.77,1099.23,535.1,1099.71,539.39Z" transform="translate(-446 -413)"/>
</svg>
<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" autofocus="autofocus" autocapitalize="none" autocomplete="off">
<input type="text" name="q" id="search-bar" class="home-search" autofocus="autofocus" autocapitalize="none" autocomplete="off">
</div>
<input type="submit" id="search-submit" value="Search">
</div>
@ -51,7 +74,7 @@
<div class="content">
<div class="config-fields">
<form id="config-form" action="config" method="post">
<div class="config-div">
<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 %}
@ -65,7 +88,7 @@
</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">
<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 %}
@ -78,7 +101,7 @@
{% endfor %}
</select>
</div>
<div class="config-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 %}
@ -91,43 +114,47 @@
{% endfor %}
</select>
</div>
<div class="config-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">
<input type="text" name="near" id="config-near" placeholder="City Name" value="{{ config.near }}">
</div>
<div class="config-div">
<div class="config-div config-div-nojs">
<label for="config-nojs">Show NoJS Links: </label>
<input type="checkbox" name="nojs" id="config-nojs">
<input type="checkbox" name="nojs" id="config-nojs" {{ 'checked' if config.nojs else '' }}>
</div>
<div class="config-div">
<div class="config-div config-div-dark">
<label for="config-dark">Dark Mode: </label>
<input type="checkbox" name="dark" id="config-dark">
<input type="checkbox" name="dark" id="config-dark" {{ 'checked' if config.dark else '' }}>
</div>
<div class="config-div">
<div class="config-div config-div-safe">
<label for="config-safe">Safe Search: </label>
<input type="checkbox" name="safe" id="config-safe">
<input type="checkbox" name="safe" id="config-safe" {{ 'checked' if config.safe else '' }}>
</div>
<div class="config-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">
<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">
<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">
<input type="checkbox" name="new_tab" id="config-new-tab" {{ 'checked' if config.new_tab else '' }}>
</div>
<div class="config-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' }}>
<input type="checkbox" name="tor" id="config-tor" {{ '' if tor_available else 'hidden' }} {{ 'checked' if config.tor else '' }}>
</div>
<div class="config-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">
<input type="checkbox" name="get_only" id="config-get-only" {{ 'checked' if config.get_only else '' }}>
</div>
<div class="config-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="">
<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" onclick="loadConfig(event)" value="Load">&nbsp;
@ -141,7 +168,7 @@
<footer>
<p style="color: {{ '#fff' if config.dark else '#000' }};">
Whoogle Search v{{ version_number }} ||
<a style="color: #685e79" href="https://github.com/benbusby/whoogle-search">View on GitHub</a>
<a id="gh-link" href="https://github.com/benbusby/whoogle-search">View on GitHub</a>
</p>
</footer>
</body>

View File

@ -8,6 +8,7 @@ from typing import Any, Tuple
import os
TOR_BANNER = '<hr><h1 style="text-align: center">You are using Tor</h1><hr>'
CAPTCHA = 'div class="g-recaptcha"'
def needs_https(url: str) -> bool:
@ -30,6 +31,10 @@ def needs_https(url: str) -> bool:
return (is_heroku and is_http) or (https_only and is_http)
def has_captcha(site_contents: str) -> bool:
return CAPTCHA in site_contents
class Search:
"""Search query preprocessor - used before submitting the query or
redirecting to another site

View File

@ -11,7 +11,7 @@ Flask==1.1.1
Flask-Session==0.3.2
idna==2.9
itsdangerous==1.1.0
Jinja2==2.10.3
Jinja2==2.11.3
MarkupSafe==1.1.1
more-itertools==8.3.0
packaging==20.4

6
run
View File

@ -12,12 +12,14 @@ SUBDIR="${1:-app}"
export APP_ROOT="$SCRIPT_DIR/$SUBDIR"
export STATIC_FOLDER="$APP_ROOT/static"
mkdir -p "$STATIC_FOLDER"
# Check for regular vs test run
if [[ "$SUBDIR" == "test" ]]; then
# Set up static files for testing
rm -rf "$STATIC_FOLDER"
ln -s "$SCRIPT_DIR/app/static" "$STATIC_FOLDER"
pytest -sv
else
mkdir -p "$STATIC_FOLDER"
python3 -um app \
--host "${ADDRESS:-0.0.0.0}" \
--port "${PORT:-"${EXPOSE_PORT:-5000}"}"

View File

@ -1 +0,0 @@
../app/misc/