Add time constraint to search options (#888)

Introduces the ability to refine searches by time period:
- Past hour
- Past 24 hours
- Past week
- Past month
- Past year

Co-authored-by: Ben Busby <contact@benbusby.com>
main
fiestasiesta 2022-12-21 15:24:27 -05:00 committed by GitHub
parent 424e6dd341
commit 7041b43db9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 246 additions and 26 deletions

View File

@ -110,6 +110,11 @@
"value": "", "value": "",
"required": false "required": false
}, },
"WHOOGLE_CONFIG_TIME_PERIOD" : {
"description": "[CONFIG] The time period to use for restricting search results",
"value": "",
"required": false
},
"WHOOGLE_CONFIG_LANGUAGE": { "WHOOGLE_CONFIG_LANGUAGE": {
"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)", "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": "", "value": "",

View File

@ -53,6 +53,9 @@ app.config['LANGUAGES'] = json.load(open(
app.config['COUNTRIES'] = json.load(open( app.config['COUNTRIES'] = json.load(open(
os.path.join(app.config['STATIC_FOLDER'], 'settings/countries.json'), os.path.join(app.config['STATIC_FOLDER'], 'settings/countries.json'),
encoding='utf-8')) encoding='utf-8'))
app.config['TIME_PERIODS'] = json.load(open(
os.path.join(app.config['STATIC_FOLDER'], 'settings/time_periods.json'),
encoding='utf-8'))
app.config['TRANSLATIONS'] = json.load(open( app.config['TRANSLATIONS'] = json.load(open(
os.path.join(app.config['STATIC_FOLDER'], 'settings/translations.json'), os.path.join(app.config['STATIC_FOLDER'], 'settings/translations.json'),
encoding='utf-8')) encoding='utf-8'))

View File

@ -24,6 +24,7 @@ class Config:
self.block_title = os.getenv('WHOOGLE_CONFIG_BLOCK_TITLE', '') self.block_title = os.getenv('WHOOGLE_CONFIG_BLOCK_TITLE', '')
self.block_url = os.getenv('WHOOGLE_CONFIG_BLOCK_URL', '') self.block_url = os.getenv('WHOOGLE_CONFIG_BLOCK_URL', '')
self.country = os.getenv('WHOOGLE_CONFIG_COUNTRY', '') self.country = os.getenv('WHOOGLE_CONFIG_COUNTRY', '')
self.tbs = os.getenv('WHOOGLE_CONFIG_TIME_PERIOD', '')
self.theme = os.getenv('WHOOGLE_CONFIG_THEME', 'system') self.theme = os.getenv('WHOOGLE_CONFIG_THEME', 'system')
self.safe = read_config_bool('WHOOGLE_CONFIG_SAFE') self.safe = read_config_bool('WHOOGLE_CONFIG_SAFE')
self.dark = read_config_bool('WHOOGLE_CONFIG_DARK') # deprecated self.dark = read_config_bool('WHOOGLE_CONFIG_DARK') # deprecated
@ -52,7 +53,8 @@ class Config:
'safe', 'safe',
'nojs', 'nojs',
'anon_view', 'anon_view',
'preferences_encrypted' 'preferences_encrypted',
'tbs'
] ]
# Skip setting custom config if there isn't one # Skip setting custom config if there isn't one

View File

@ -91,8 +91,8 @@ def gen_query(query, args, config) -> str:
if ':past' in query and 'tbs' not in args: if ':past' in query and 'tbs' not in args:
time_range = str.strip(query.split(':past', 1)[-1]) time_range = str.strip(query.split(':past', 1)[-1])
param_dict['tbs'] = '&tbs=' + ('qdr:' + str.lower(time_range[0])) param_dict['tbs'] = '&tbs=' + ('qdr:' + str.lower(time_range[0]))
elif 'tbs' in args: elif 'tbs' in args or 'tbs' in config:
result_tbs = args.get('tbs') result_tbs = args.get('tbs') if 'tbs' in args else config['tbs']
param_dict['tbs'] = '&tbs=' + result_tbs param_dict['tbs'] = '&tbs=' + result_tbs
# Occasionally the 'tbs' param provided by google also contains a # Occasionally the 'tbs' param provided by google also contains a

View File

@ -205,6 +205,7 @@ def index():
has_update=app.config['HAS_UPDATE'], has_update=app.config['HAS_UPDATE'],
languages=app.config['LANGUAGES'], languages=app.config['LANGUAGES'],
countries=app.config['COUNTRIES'], countries=app.config['COUNTRIES'],
time_periods=app.config['TIME_PERIODS'],
themes=app.config['THEMES'], themes=app.config['THEMES'],
autocomplete_enabled=autocomplete_enabled, autocomplete_enabled=autocomplete_enabled,
translation=app.config['TRANSLATIONS'][ translation=app.config['TRANSLATIONS'][
@ -318,6 +319,12 @@ def search():
translation = app.config['TRANSLATIONS'][localization_lang] translation = app.config['TRANSLATIONS'][localization_lang]
translate_to = localization_lang.replace('lang_', '') translate_to = localization_lang.replace('lang_', '')
# removing st-card to only use whoogle time selector
soup = bsoup(response, "html.parser");
for x in soup.find_all(attrs={"id": "st-card"}):
x.replace_with("")
response = str(soup)
# Return 503 if temporarily blocked by captcha # Return 503 if temporarily blocked by captcha
if has_captcha(str(response)): if has_captcha(str(response)):
return render_template( return render_template(
@ -380,6 +387,7 @@ def search():
translation=translation, translation=translation,
languages=app.config['LANGUAGES'], languages=app.config['LANGUAGES'],
countries=app.config['COUNTRIES'], countries=app.config['COUNTRIES'],
time_periods=app.config['TIME_PERIODS'],
logo=render_template('logo.html', dark=g.user_config.dark), logo=render_template('logo.html', dark=g.user_config.dark),
query=urlparse.unquote(query), query=urlparse.unquote(query),
search_type=search_util.search_type, search_type=search_util.search_type,

View File

@ -3,6 +3,7 @@ document.addEventListener("DOMContentLoaded", () => {
const advSearchDiv = document.getElementById("adv-search-div"); const advSearchDiv = document.getElementById("adv-search-div");
const searchBar = document.getElementById("search-bar"); const searchBar = document.getElementById("search-bar");
const countrySelect = document.getElementById("result-country"); const countrySelect = document.getElementById("result-country");
const timePeriodSelect = document.getElementById("result-time-period");
const arrowKeys = [37, 38, 39, 40]; const arrowKeys = [37, 38, 39, 40];
let searchValue = searchBar.value; let searchValue = searchBar.value;
@ -10,12 +11,32 @@ document.addEventListener("DOMContentLoaded", () => {
let str = window.location.href; let str = window.location.href;
n = str.lastIndexOf("/search"); n = str.lastIndexOf("/search");
if (n > 0) { if (n > 0) {
str = str.substring(0, n) + str = str.substring(0, n) + `/search?q=${searchBar.value}`;
`/search?q=${searchBar.value}&country=${countrySelect.value}`; str = tackOnParams(str);
window.location.href = str; window.location.href = str;
} }
} }
timePeriodSelect.onchange = () => {
let str = window.location.href;
n = str.lastIndexOf("/search");
if (n > 0) {
str = str.substring(0, n) + `/search?q=${searchBar.value}`;
str = tackOnParams(str);
window.location.href = str;
}
}
function tackOnParams(str) {
if (timePeriodSelect.value != "") {
str = str + `&tbs=${timePeriodSelect.value}`;
}
if (countrySelect.value != "") {
str = str + `&country=${countrySelect.value}`;
}
return str;
}
const toggleAdvancedSearch = on => { const toggleAdvancedSearch = on => {
if (on) { if (on) {
advSearchDiv.style.maxHeight = "70px"; advSearchDiv.style.maxHeight = "70px";

View File

@ -0,0 +1,8 @@
[
{"name": "Any time", "value": ""},
{"name": "Past hour", "value": "qdr:h"},
{"name": "Past 24 hours", "value": "qdr:d"},
{"name": "Past week", "value": "qdr:w"},
{"name": "Past month", "value": "qdr:m"},
{"name": "Past year", "value": "qdr:y"}
]

View File

@ -1,5 +1,6 @@
{ {
"lang_en": { "lang_en": {
"": "--",
"search": "Search", "search": "Search",
"config": "Configuration", "config": "Configuration",
"config-country": "Country", "config-country": "Country",
@ -30,6 +31,7 @@
"config-pref-encryption": "Encrypt Preferences", "config-pref-encryption": "Encrypt Preferences",
"config-pref-help": "Requires WHOOGLE_CONFIG_PREFERENCES_KEY, otherwise this will be ignored.", "config-pref-help": "Requires WHOOGLE_CONFIG_PREFERENCES_KEY, otherwise this will be ignored.",
"config-css": "Custom CSS", "config-css": "Custom CSS",
"config-time-period": "Time Period",
"load": "Load", "load": "Load",
"apply": "Apply", "apply": "Apply",
"save-as": "Save As...", "save-as": "Save As...",
@ -46,7 +48,12 @@
"videos": "Videos", "videos": "Videos",
"news": "News", "news": "News",
"books": "Books", "books": "Books",
"anon-view": "Anonymous View" "anon-view": "Anonymous View",
"qdr:h": "Past hour",
"qdr:d": "Past 24 hours",
"qdr:w": "Past week",
"qdr:m": "Past month",
"qdr:y": "Past year"
}, },
"lang_nl": { "lang_nl": {
"search": "Zoeken", "search": "Zoeken",
@ -95,7 +102,14 @@
"videos": "Videos", "videos": "Videos",
"news": "Nieuws", "news": "Nieuws",
"books": "Boeken", "books": "Boeken",
"anon-view": "Anonieme Weergave" "anon-view": "Anonieme Weergave",
"": "--",
"qdr:h": "Afgelopen uur",
"qdr:d": "Afgelopen 24 uur",
"qdr:w": "Vorige week",
"qdr:m": "Afgelopen maand",
"qdr:y": "Afgelopen jaar",
"config-time-period": "Tijdsperiode"
}, },
"lang_de": { "lang_de": {
"search": "Suchen", "search": "Suchen",
@ -144,7 +158,14 @@
"videos": "Videos", "videos": "Videos",
"news": "Nachrichten", "news": "Nachrichten",
"books": "Bücher", "books": "Bücher",
"anon-view": "Anonyme Ansicht" "anon-view": "Anonyme Ansicht",
"": "--",
"qdr:h": "Letzte Stunde",
"qdr:d": "Vergangene 24 Stunden",
"qdr:w": "Letzte Woche",
"qdr:m": "Letzten Monat",
"qdr:y": "Vergangenes Jahr",
"config-time-period": "Zeitraum"
}, },
"lang_es": { "lang_es": {
"search": "Buscar", "search": "Buscar",
@ -193,7 +214,14 @@
"videos": "Vídeos", "videos": "Vídeos",
"news": "Noticias", "news": "Noticias",
"books": "Libros", "books": "Libros",
"anon-view": "Vista Anónima" "anon-view": "Vista Anónima",
"": "--",
"qdr:h": "Hora pasada",
"qdr:d": "últimas 24 horas",
"qdr:w": "Semana pasada",
"qdr:m": "El mes pasado",
"qdr:y": "Año pasado",
"config-time-period": "Periodo de tiempo"
}, },
"lang_it": { "lang_it": {
"search": "Cerca", "search": "Cerca",
@ -242,7 +270,14 @@
"videos": "Video", "videos": "Video",
"news": "Notizie", "news": "Notizie",
"books": "Libri", "books": "Libri",
"anon-view": "Vista Anonima" "anon-view": "Vista Anonima",
"": "--",
"qdr:h": "Ultima ora",
"qdr:d": "Ultime 24 ore",
"qdr:w": "Settimana scorsa",
"qdr:m": "Mese scorso",
"qdr:y": "L'anno scorso",
"config-time-period": "Periodo di tempo"
}, },
"lang_pt": { "lang_pt": {
"search": "Pesquisar", "search": "Pesquisar",
@ -291,7 +326,14 @@
"videos": "Vídeos", "videos": "Vídeos",
"news": "Notícias", "news": "Notícias",
"books": "Livros", "books": "Livros",
"anon-view": "Visualização Anônima" "anon-view": "Visualização Anônima",
"": "--",
"qdr:h": "Hora passada",
"qdr:d": "últimas 24 horas",
"qdr:w": "Semana passada",
"qdr:m": "Mês passado",
"qdr:y": "Ano passado",
"config-time-period": "Período de tempo"
}, },
"lang_ru": { "lang_ru": {
"search": "Поиск", "search": "Поиск",
@ -340,7 +382,14 @@
"videos": "Видео", "videos": "Видео",
"news": "Новости", "news": "Новости",
"books": "Книги", "books": "Книги",
"anon-view": "Анонимный просмотр" "anon-view": "Анонимный просмотр",
"": "--",
"qdr:h": "Прошедший час",
"qdr:d": "Последние 24 часа",
"qdr:w": "На прошлой неделе",
"qdr:m": "Прошлый месяц",
"qdr:y": "Прошлый год",
"config-time-period": "Временной период"
}, },
"lang_zh-CN": { "lang_zh-CN": {
"search": "搜索", "search": "搜索",
@ -389,7 +438,14 @@
"videos": "视频", "videos": "视频",
"news": "新闻", "news": "新闻",
"books": "书籍", "books": "书籍",
"anon-view": "匿名视图" "anon-view": "匿名视图",
"": "--",
"qdr:h": "过去一小时",
"qdr:d": "过去 24 小时",
"qdr:w": "上周",
"qdr:m": "过去一个月",
"qdr:y": "过去一年",
"config-time-period": "时间段"
}, },
"lang_si": { "lang_si": {
"search": "සොයන්න", "search": "සොයන්න",
@ -438,7 +494,14 @@
"videos": "වීඩියෝ", "videos": "වීඩියෝ",
"news": "අනුරූප", "news": "අනුරූප",
"books": "පොත්", "books": "පොත්",
"anon-view": "නිර්නාමික දසුන" "anon-view": "නිර්නාමික දසුන",
"": "--",
"qdr:h": "පසුගිය පැය",
"qdr:d": "පසුගිය පැය 24",
"qdr:w": "පසුගිය සතිය",
"qdr:m": "පසුගිය මාසය",
"qdr:y": "පසුගිය වසර",
"config-time-period": "කාල සීමාව"
}, },
"lang_fr": { "lang_fr": {
"search": "Chercher", "search": "Chercher",
@ -487,7 +550,14 @@
"videos": "Vidéos", "videos": "Vidéos",
"news": "Actualités", "news": "Actualités",
"books": "Livres", "books": "Livres",
"anon-view": "Vue anonyme" "anon-view": "Vue anonyme",
"": "--",
"qdr:h": "Heure passée",
"qdr:d": "Dernières 24 heures",
"qdr:w": "La semaine dernière",
"qdr:m": "Mois passé",
"qdr:y": "L'année passée",
"config-time-period": "Période de temps"
}, },
"lang_fa": { "lang_fa": {
"search": "جستجو", "search": "جستجو",
@ -536,7 +606,14 @@
"videos": "ویدئوها", "videos": "ویدئوها",
"news": "اخبار", "news": "اخبار",
"books": "کتاب‌ها", "books": "کتاب‌ها",
"anon-view": "نمای ناشناس" "anon-view": "نمای ناشناس",
"": "--",
"qdr:h": "ساعت گذشته",
"qdr:d": "24 ساعت گذشته",
"qdr:w": "هفته گذشته",
"qdr:m": "ماه گذشته",
"qdr:y": "سال گذشته",
"config-time-period": "بازه زمانی"
}, },
"lang_cs": { "lang_cs": {
"search": "Hledat", "search": "Hledat",
@ -585,7 +662,14 @@
"videos": "Videa", "videos": "Videa",
"news": "Zprávy", "news": "Zprávy",
"books": "Knihy", "books": "Knihy",
"anon-view": "Anonymní pohled" "anon-view": "Anonymní pohled",
"": "--",
"qdr:h": "Poslední hodina",
"qdr:d": "Posledních 24 hodin",
"qdr:w": "Minulý týden",
"qdr:m": "Minulý měsíc",
"qdr:y": "Minulý rok",
"config-time-period": "Časový úsek"
}, },
"lang_zh-TW": { "lang_zh-TW": {
"search": "搜尋", "search": "搜尋",
@ -634,7 +718,14 @@
"videos": "影片", "videos": "影片",
"news": "新聞", "news": "新聞",
"books": "書籍", "books": "書籍",
"anon-view": "匿名檢視" "anon-view": "匿名檢視",
"": "--",
"qdr:h": "过去一小时",
"qdr:d": "过去 24 小时",
"qdr:w": "上周",
"qdr:m": "过去一个月",
"qdr:y": "过去一年",
"config-time-period": "时间段"
}, },
"lang_bg": { "lang_bg": {
"search": "Търсене", "search": "Търсене",
@ -683,7 +774,14 @@
"videos": "Новини", "videos": "Новини",
"news": "Карти", "news": "Карти",
"books": "Книги", "books": "Книги",
"anon-view": "Анонимен изглед" "anon-view": "Анонимен изглед",
"": "--",
"qdr:h": "Последния час",
"qdr:d": "Последните 24 часа",
"qdr:w": "Миналата седмица",
"qdr:m": "Миналия месец",
"qdr:y": "Изминалата година",
"config-time-period": "Времеви период"
}, },
"lang_hi": { "lang_hi": {
"search": "खोज", "search": "खोज",
@ -732,7 +830,14 @@
"videos": "मैप", "videos": "मैप",
"news": "समाचार", "news": "समाचार",
"books": "किताबें", "books": "किताबें",
"anon-view": "अनाम दृश्य" "anon-view": "अनाम दृश्य",
"": "--",
"qdr:h": "पिछले घंटे",
"qdr:d": "पिछले 24 घंटे",
"qdr:w": "पिछले सप्ताह",
"qdr:m": "पिछले महीने",
"qdr:y": "पिछला वर्ष",
"config-time-period": "समय सीमा"
}, },
"lang_ja": { "lang_ja": {
"search": "検索", "search": "検索",
@ -781,7 +886,14 @@
"videos": "動画", "videos": "動画",
"news": "ニュース", "news": "ニュース",
"books": "書籍", "books": "書籍",
"anon-view": "匿名ビュー" "anon-view": "匿名ビュー",
"": "--",
"qdr:h": "過去 1 時間",
"qdr:d": "過去 24 時間",
"qdr:w": "この1週間",
"qdr:m": "先月",
"qdr:y": "過年度",
"config-time-period": "期間"
}, },
"lang_ko": { "lang_ko": {
"search": "검색", "search": "검색",
@ -830,7 +942,14 @@
"videos": "동영상", "videos": "동영상",
"news": "뉴스", "news": "뉴스",
"books": "도서", "books": "도서",
"anon-view": "익명 보기" "anon-view": "익명 보기",
"": "--",
"qdr:h": "지난 시간",
"qdr:d": "지난 24시간",
"qdr:w": "지난 주",
"qdr:m": "지난달",
"qdr:y": "지난 해",
"config-time-period": "기간"
}, },
"lang_ku": { "lang_ku": {
"search": "Bigere", "search": "Bigere",
@ -879,7 +998,14 @@
"videos": "Vîdyo", "videos": "Vîdyo",
"news": "Nûçe", "news": "Nûçe",
"books": "Pirtûk", "books": "Pirtûk",
"anon-view": "Dîtina Nenas" "anon-view": "Dîtina Nenas",
"": "--",
"qdr:h": "Saet berê",
"qdr:d": "24 saetên borî",
"qdr:w": "Hefteya borî",
"qdr:m": "Meha borî",
"qdr:y": "Sala borî",
"config-time-period": "Dem Period"
}, },
"lang_th": { "lang_th": {
"search": "ค้นหา", "search": "ค้นหา",
@ -928,7 +1054,14 @@
"videos": "วิดีโอ", "videos": "วิดีโอ",
"news": "ข่าว", "news": "ข่าว",
"books": "หนังสือ", "books": "หนังสือ",
"anon-view": "มุมมองที่ไม่ระบุตัวตน" "anon-view": "มุมมองที่ไม่ระบุตัวตน",
"": "--",
"qdr:h": "ชั่วโมงที่ผ่านมา",
"qdr:d": "24 ชั่วโมงที่ผ่านมา",
"qdr:w": "สัปดาห์ที่ผ่านมา",
"qdr:m": "เดือนที่ผ่านมา",
"qdr:y": "ปีที่ผ่านมา",
"config-time-period": "ระยะเวลา"
}, },
"lang_cy": { "lang_cy": {
"search": "Chwiliwch", "search": "Chwiliwch",
@ -977,6 +1110,13 @@
"videos": "Fideos", "videos": "Fideos",
"news": "Newyddion", "news": "Newyddion",
"books": "Llyfrau", "books": "Llyfrau",
"anon-view": "Golwg Anhysbys" "anon-view": "Golwg Anhysbys",
"": "--",
"qdr:h": "Yr awr ddiwethaf",
"qdr:d": "24 awr diwethaf",
"qdr:w": "Yr wythnos ddiwethaf",
"qdr:m": "Mis diwethaf",
"qdr:y": "Y flwyddyn ddiwethaf",
"config-time-period": "Cyfnod Amser"
} }
} }

View File

@ -89,6 +89,7 @@
dir="auto"> dir="auto">
<input name="tbm" value="{{ search_type }}" style="display: none"> <input name="tbm" value="{{ search_type }}" style="display: none">
<input name="country" value="{{ config.country }}" style="display: none;"> <input name="country" value="{{ config.country }}" style="display: none;">
<input name="tbs" value="{{ config.tbs }}" style="display: none;">
<input type="submit" style="display: none;"> <input type="submit" style="display: none;">
<div class="sc"></div> <div class="sc"></div>
</div> </div>
@ -135,6 +136,21 @@
</option> </option>
{% endfor %} {% endfor %}
</select> </select>
<label for="config-time-period">{{ translation['config-time-period'] }}: </label>
<select name="tbs" id="result-time-period">
{% for time_period in time_periods %}
<option value="{{ time_period.value }}"
{% if (
config.tbs != '' and config.tbs in time_period.value
) or (
config.tbs == '' and time_period.value == '')
%}
selected
{% endif %}>
{{ translation[time_period.value] }}
</option>
{% endfor %}
</select>
</div> </div>
</div> </div>

View File

@ -108,6 +108,23 @@
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
<div class="config-div">
<label for="config-time-period">{{ translation['config-time-period'] }}</label>
<select name="tbs" id="config-time-period">
{% for time_period in time_periods %}
<option value="{{ time_period.value }}"
{% if (
config.tbs != '' and config.tbs in time_period.value
) or (
config.tbs == '' and time_period.value == '')
%}
selected
{% endif %}>
{{ translation[time_period.value] }}
</option>
{% endfor %}
</select>
</div>
<div class="config-div config-div-lang"> <div class="config-div config-div-lang">
<label for="config-lang-interface">{{ translation['config-lang'] }}: </label> <label for="config-lang-interface">{{ translation['config-lang'] }}: </label>
<select name="lang_interface" id="config-lang-interface"> <select name="lang_interface" id="config-lang-interface">