forked from zaclys/searxng
[enh] add ability to send engine data to subsequent requests
This commit is contained in:
parent
87f4cc4a9e
commit
44f4a9d49a
|
@ -327,6 +327,7 @@ def _set_https_support_for_engine(engine):
|
||||||
'is_test': True,
|
'is_test': True,
|
||||||
'category': 'files',
|
'category': 'files',
|
||||||
'raise_for_status': True,
|
'raise_for_status': True,
|
||||||
|
'engine_data': {},
|
||||||
})
|
})
|
||||||
|
|
||||||
if 'url' not in params:
|
if 'url' not in params:
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import re
|
import re
|
||||||
|
from collections import defaultdict
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
from threading import RLock
|
from threading import RLock
|
||||||
from urllib.parse import urlparse, unquote
|
from urllib.parse import urlparse, unquote
|
||||||
|
@ -144,7 +145,7 @@ class ResultContainer:
|
||||||
"""docstring for ResultContainer"""
|
"""docstring for ResultContainer"""
|
||||||
|
|
||||||
__slots__ = '_merged_results', 'infoboxes', 'suggestions', 'answers', 'corrections', '_number_of_results',\
|
__slots__ = '_merged_results', 'infoboxes', 'suggestions', 'answers', 'corrections', '_number_of_results',\
|
||||||
'_ordered', 'paging', 'unresponsive_engines', 'timings', 'redirect_url'
|
'_ordered', 'paging', 'unresponsive_engines', 'timings', 'redirect_url', 'engine_data'
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
@ -154,6 +155,7 @@ class ResultContainer:
|
||||||
self.answers = {}
|
self.answers = {}
|
||||||
self.corrections = set()
|
self.corrections = set()
|
||||||
self._number_of_results = []
|
self._number_of_results = []
|
||||||
|
self.engine_data = defaultdict(dict)
|
||||||
self._ordered = False
|
self._ordered = False
|
||||||
self.paging = False
|
self.paging = False
|
||||||
self.unresponsive_engines = set()
|
self.unresponsive_engines = set()
|
||||||
|
@ -175,6 +177,8 @@ class ResultContainer:
|
||||||
self._merge_infobox(result)
|
self._merge_infobox(result)
|
||||||
elif 'number_of_results' in result:
|
elif 'number_of_results' in result:
|
||||||
self._number_of_results.append(result['number_of_results'])
|
self._number_of_results.append(result['number_of_results'])
|
||||||
|
elif 'engine_data' in result:
|
||||||
|
self.engine_data[engine_name][result['key']] = result['engine_data']
|
||||||
else:
|
else:
|
||||||
# standard result (url, title, content)
|
# standard result (url, title, content)
|
||||||
if 'url' in result and not isinstance(result['url'], str):
|
if 'url' in result and not isinstance(result['url'], str):
|
||||||
|
|
|
@ -111,6 +111,8 @@ class Search:
|
||||||
if request_params is None:
|
if request_params is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
request_params['engine_data'] = self.search_query.engine_data.get(engineref.name, {})
|
||||||
|
|
||||||
with threading.RLock():
|
with threading.RLock():
|
||||||
processor.engine.stats['sent_search_count'] += 1
|
processor.engine.stats['sent_search_count'] += 1
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ class SearchQuery:
|
||||||
"""container for all the search parameters (query, language, etc...)"""
|
"""container for all the search parameters (query, language, etc...)"""
|
||||||
|
|
||||||
__slots__ = 'query', 'engineref_list', 'lang', 'safesearch', 'pageno', 'time_range',\
|
__slots__ = 'query', 'engineref_list', 'lang', 'safesearch', 'pageno', 'time_range',\
|
||||||
'timeout_limit', 'external_bang'
|
'timeout_limit', 'external_bang', 'engine_data'
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
query: str,
|
query: str,
|
||||||
|
@ -35,7 +35,8 @@ class SearchQuery:
|
||||||
pageno: int=1,
|
pageno: int=1,
|
||||||
time_range: typing.Optional[str]=None,
|
time_range: typing.Optional[str]=None,
|
||||||
timeout_limit: typing.Optional[float]=None,
|
timeout_limit: typing.Optional[float]=None,
|
||||||
external_bang: typing.Optional[str]=None):
|
external_bang: typing.Optional[str]=None,
|
||||||
|
engine_data: typing.Optional[dict]=None):
|
||||||
self.query = query
|
self.query = query
|
||||||
self.engineref_list = engineref_list
|
self.engineref_list = engineref_list
|
||||||
self.lang = lang
|
self.lang = lang
|
||||||
|
@ -44,6 +45,9 @@ class SearchQuery:
|
||||||
self.time_range = time_range
|
self.time_range = time_range
|
||||||
self.timeout_limit = timeout_limit
|
self.timeout_limit = timeout_limit
|
||||||
self.external_bang = external_bang
|
self.external_bang = external_bang
|
||||||
|
self.engine_data = engine_data
|
||||||
|
if engine_data is None:
|
||||||
|
self.engine_data = {}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def categories(self):
|
def categories(self):
|
||||||
|
|
|
@ -7,6 +7,13 @@
|
||||||
<input type="hidden" name="language" value="{{ current_language }}" />{{- "" -}}
|
<input type="hidden" name="language" value="{{ current_language }}" />{{- "" -}}
|
||||||
{% if timeout_limit %}<input type="hidden" name="timeout_limit" value="{{ timeout_limit|e }}" />{% endif -%}
|
{% if timeout_limit %}<input type="hidden" name="timeout_limit" value="{{ timeout_limit|e }}" />{% endif -%}
|
||||||
{%- endmacro %}
|
{%- endmacro %}
|
||||||
|
{% macro engine_data_form(engine_data) -%}
|
||||||
|
{% for engine_name, kv_data in engine_data.items() %}
|
||||||
|
{% for k, v in kv_data.items() %}
|
||||||
|
<input type="hidden" name="engine_data-{{ engine_name }}-{{ k|e }}" value="{{ v|e }}" />
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
{%- endmacro %}
|
||||||
{%- macro search_url() %}{{ url_for('search', _external=True) }}?q={{ q|urlencode }}{% if selected_categories %}&categories={{ selected_categories|join(",") | replace(' ','+') }}{% endif %}{% if pageno > 1 %}&pageno={{ pageno }}{% endif %}{% if time_range %}&time_range={{ time_range }}{% endif %}{% if current_language != 'all' %}&language={{ current_language }}{% endif %}{% endmacro -%}
|
{%- macro search_url() %}{{ url_for('search', _external=True) }}?q={{ q|urlencode }}{% if selected_categories %}&categories={{ selected_categories|join(",") | replace(' ','+') }}{% endif %}{% if pageno > 1 %}&pageno={{ pageno }}{% endif %}{% if time_range %}&time_range={{ time_range }}{% endif %}{% if current_language != 'all' %}&language={{ current_language }}{% endif %}{% endmacro -%}
|
||||||
|
|
||||||
{% block title %}{{ q|e }} - {% endblock %}
|
{% block title %}{{ q|e }} - {% endblock %}
|
||||||
|
@ -142,12 +149,14 @@
|
||||||
<div class="pull-left">{{- "" -}}
|
<div class="pull-left">{{- "" -}}
|
||||||
<form method="{{ method or 'POST' }}" action="{{ url_for('search') }}" class="pull-left">
|
<form method="{{ method or 'POST' }}" action="{{ url_for('search') }}" class="pull-left">
|
||||||
{{- search_form_attrs(pageno+1) -}}
|
{{- search_form_attrs(pageno+1) -}}
|
||||||
|
{{- engine_data_form(engine_data) -}}
|
||||||
<button type="submit" class="btn btn-default"><span class="glyphicon glyphicon-backward"></span> {{ _('next page') }}</button>{{- "" -}}
|
<button type="submit" class="btn btn-default"><span class="glyphicon glyphicon-backward"></span> {{ _('next page') }}</button>{{- "" -}}
|
||||||
</form>{{- "" -}}
|
</form>{{- "" -}}
|
||||||
</div>
|
</div>
|
||||||
<div class="pull-right">{{- "" -}}
|
<div class="pull-right">{{- "" -}}
|
||||||
<form method="{{ method or 'POST' }}" action="{{ url_for('search') }}" class="pull-left">
|
<form method="{{ method or 'POST' }}" action="{{ url_for('search') }}" class="pull-left">
|
||||||
{{- search_form_attrs(pageno-1) -}}
|
{{- search_form_attrs(pageno-1) -}}
|
||||||
|
{{- engine_data_form(engine_data) -}}
|
||||||
<button type="submit" class="btn btn-default" {% if pageno == 1 %}disabled{% endif %}><span class="glyphicon glyphicon-forward"></span> {{ _('previous page') }}</button>{{- "" -}}
|
<button type="submit" class="btn btn-default" {% if pageno == 1 %}disabled{% endif %}><span class="glyphicon glyphicon-forward"></span> {{ _('previous page') }}</button>{{- "" -}}
|
||||||
</form>{{- "" -}}
|
</form>{{- "" -}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -158,12 +167,14 @@
|
||||||
<div class="pull-left">{{- "" -}}
|
<div class="pull-left">{{- "" -}}
|
||||||
<form method="{{ method or 'POST' }}" action="{{ url_for('search') }}" class="pull-left">
|
<form method="{{ method or 'POST' }}" action="{{ url_for('search') }}" class="pull-left">
|
||||||
{{- search_form_attrs(pageno-1) -}}
|
{{- search_form_attrs(pageno-1) -}}
|
||||||
|
{{- engine_data_form(engine_data) -}}
|
||||||
<button type="submit" class="btn btn-default" {% if pageno == 1 %}disabled{% endif %}><span class="glyphicon glyphicon-backward"></span> {{ _('previous page') }}</button>{{- "" -}}
|
<button type="submit" class="btn btn-default" {% if pageno == 1 %}disabled{% endif %}><span class="glyphicon glyphicon-backward"></span> {{ _('previous page') }}</button>{{- "" -}}
|
||||||
</form>{{- "" -}}
|
</form>{{- "" -}}
|
||||||
</div>
|
</div>
|
||||||
<div class="pull-right">{{- "" -}}
|
<div class="pull-right">{{- "" -}}
|
||||||
<form method="{{ method or 'POST' }}" action="{{ url_for('search') }}" class="pull-left">
|
<form method="{{ method or 'POST' }}" action="{{ url_for('search') }}" class="pull-left">
|
||||||
{{- search_form_attrs(pageno+1) -}}
|
{{- search_form_attrs(pageno+1) -}}
|
||||||
|
{{- engine_data_form(engine_data) -}}
|
||||||
<button type="submit" class="btn btn-default"><span class="glyphicon glyphicon-forward"></span> {{ _('next page') }}</button>{{- "" -}}
|
<button type="submit" class="btn btn-default"><span class="glyphicon glyphicon-forward"></span> {{ _('next page') }}</button>{{- "" -}}
|
||||||
</form>{{- "" -}}
|
</form>{{- "" -}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
{% extends "simple/base.html" %}
|
{% extends "simple/base.html" %}
|
||||||
{% from 'simple/macros.html' import icon, icon_small %}
|
{% from 'simple/macros.html' import icon, icon_small %}
|
||||||
|
{% macro engine_data_form(engine_data) -%}
|
||||||
|
{% for engine_name, kv_data in engine_data.items() %}
|
||||||
|
{% for k, v in kv_data.items() %}
|
||||||
|
<input type="hidden" name="engine_data-{{ engine_name }}-{{ k|e }}" value="{{ v|e }}" />
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
{%- endmacro %}
|
||||||
{% block title %}{% if method == 'GET' %}{{- q|e -}} -{% endif %}{% endblock %}
|
{% block title %}{% if method == 'GET' %}{{- q|e -}} -{% endif %}{% endblock %}
|
||||||
{% block meta %}<link rel="alternate" type="application/rss+xml" title="Searx search: {{ q|e }}" href="{{ url_for('search', _external=True) }}?q={{ q|urlencode }}&categories={{ selected_categories|join(",") | replace(' ','+') }}&pageno={{ pageno }}&time_range={{ time_range }}&language={{ current_language }}&safesearch={{ safesearch }}&format=rss">{% endblock %}
|
{% block meta %}<link rel="alternate" type="application/rss+xml" title="Searx search: {{ q|e }}" href="{{ url_for('search', _external=True) }}?q={{ q|urlencode }}&categories={{ selected_categories|join(",") | replace(' ','+') }}&pageno={{ pageno }}&time_range={{ time_range }}&language={{ current_language }}&safesearch={{ safesearch }}&format=rss">{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
@ -136,6 +143,7 @@
|
||||||
<form method="{{ method or 'POST' }}" action="{{ url_for('search') }}">
|
<form method="{{ method or 'POST' }}" action="{{ url_for('search') }}">
|
||||||
<div class="{% if rtl %}right{% else %}left{% endif %}">
|
<div class="{% if rtl %}right{% else %}left{% endif %}">
|
||||||
<input type="hidden" name="q" value="{{ q|e }}" >
|
<input type="hidden" name="q" value="{{ q|e }}" >
|
||||||
|
{{- engine_data_form(engine_data) -}}
|
||||||
{% for category in selected_categories %}
|
{% for category in selected_categories %}
|
||||||
<input type="hidden" name="category_{{ category }}" value="1" >
|
<input type="hidden" name="category_{{ category }}" value="1" >
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -152,6 +160,7 @@
|
||||||
<form method="{{ method or 'POST' }}" action="{{ url_for('search') }}">
|
<form method="{{ method or 'POST' }}" action="{{ url_for('search') }}">
|
||||||
<div class="{% if rtl %}left{% else %}right{% endif %}">
|
<div class="{% if rtl %}left{% else %}right{% endif %}">
|
||||||
<input type="hidden" name="q" value="{{ q|e }}" >
|
<input type="hidden" name="q" value="{{ q|e }}" >
|
||||||
|
{{- engine_data_form(engine_data) -}}
|
||||||
{% for category in selected_categories %}
|
{% for category in selected_categories %}
|
||||||
<input type="hidden" name="category_{{ category }}" value="1" >
|
<input type="hidden" name="category_{{ category }}" value="1" >
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from collections import defaultdict
|
||||||
from typing import Dict, List, Optional, Tuple
|
from typing import Dict, List, Optional, Tuple
|
||||||
from searx.exceptions import SearxParameterException
|
from searx.exceptions import SearxParameterException
|
||||||
from searx.webutils import VALID_LANGUAGE_CODE
|
from searx.webutils import VALID_LANGUAGE_CODE
|
||||||
|
@ -196,6 +197,15 @@ def parse_generic(preferences: Preferences, form: Dict[str, str], disabled_engin
|
||||||
return query_engineref_list
|
return query_engineref_list
|
||||||
|
|
||||||
|
|
||||||
|
def parse_engine_data(form):
|
||||||
|
engine_data = defaultdict(dict)
|
||||||
|
for k, v in form.items():
|
||||||
|
if k.startswith("engine_data"):
|
||||||
|
_, engine, key = k.split('-')
|
||||||
|
engine_data[engine][key] = v
|
||||||
|
return engine_data
|
||||||
|
|
||||||
|
|
||||||
def get_search_query_from_webapp(preferences: Preferences, form: Dict[str, str])\
|
def get_search_query_from_webapp(preferences: Preferences, form: Dict[str, str])\
|
||||||
-> Tuple[SearchQuery, RawTextQuery, List[EngineRef], List[EngineRef]]:
|
-> Tuple[SearchQuery, RawTextQuery, List[EngineRef], List[EngineRef]]:
|
||||||
# no text for the query ?
|
# no text for the query ?
|
||||||
|
@ -217,6 +227,7 @@ def get_search_query_from_webapp(preferences: Preferences, form: Dict[str, str])
|
||||||
query_time_range = parse_time_range(form)
|
query_time_range = parse_time_range(form)
|
||||||
query_timeout = parse_timeout(form, raw_text_query)
|
query_timeout = parse_timeout(form, raw_text_query)
|
||||||
external_bang = raw_text_query.external_bang
|
external_bang = raw_text_query.external_bang
|
||||||
|
engine_data = parse_engine_data(form)
|
||||||
|
|
||||||
if not is_locked('categories') and raw_text_query.enginerefs and raw_text_query.specific:
|
if not is_locked('categories') and raw_text_query.enginerefs and raw_text_query.specific:
|
||||||
# if engines are calculated from query,
|
# if engines are calculated from query,
|
||||||
|
@ -232,7 +243,8 @@ def get_search_query_from_webapp(preferences: Preferences, form: Dict[str, str])
|
||||||
validate_engineref_list(query_engineref_list, preferences)
|
validate_engineref_list(query_engineref_list, preferences)
|
||||||
|
|
||||||
return (SearchQuery(query, query_engineref_list, query_lang, query_safesearch, query_pageno,
|
return (SearchQuery(query, query_engineref_list, query_lang, query_safesearch, query_pageno,
|
||||||
query_time_range, query_timeout, external_bang=external_bang),
|
query_time_range, query_timeout, external_bang=external_bang,
|
||||||
|
engine_data=engine_data),
|
||||||
raw_text_query,
|
raw_text_query,
|
||||||
query_engineref_list_unknown,
|
query_engineref_list_unknown,
|
||||||
query_engineref_list_notoken)
|
query_engineref_list_notoken)
|
||||||
|
|
|
@ -730,6 +730,7 @@ def search():
|
||||||
answers=result_container.answers,
|
answers=result_container.answers,
|
||||||
corrections=correction_urls,
|
corrections=correction_urls,
|
||||||
infoboxes=result_container.infoboxes,
|
infoboxes=result_container.infoboxes,
|
||||||
|
engine_data=result_container.engine_data,
|
||||||
paging=result_container.paging,
|
paging=result_container.paging,
|
||||||
unresponsive_engines=__get_translated_errors(result_container.unresponsive_engines),
|
unresponsive_engines=__get_translated_errors(result_container.unresponsive_engines),
|
||||||
current_language=match_language(search_query.lang,
|
current_language=match_language(search_query.lang,
|
||||||
|
|
|
@ -57,7 +57,8 @@ class ViewsTestCase(SearxTestCase):
|
||||||
results_number=lambda: 3,
|
results_number=lambda: 3,
|
||||||
results_length=lambda: len(test_results),
|
results_length=lambda: len(test_results),
|
||||||
get_timings=lambda: timings,
|
get_timings=lambda: timings,
|
||||||
redirect_url=None)
|
redirect_url=None,
|
||||||
|
engine_data={})
|
||||||
|
|
||||||
self.setattr4test(Search, 'search', search_mock)
|
self.setattr4test(Search, 'search', search_mock)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue