[enh] autocompleter server side part

This commit is contained in:
Adam Tauber 2014-03-29 16:29:19 +01:00
parent 20504a0e83
commit 41dd4d9ba3
5 changed files with 69 additions and 28 deletions

View File

@ -5,9 +5,6 @@ server:
request_timeout : 2.0 # seconds request_timeout : 2.0 # seconds
base_url : False base_url : False
client:
autocompleter : False # only for developers, no real results yet
engines: engines:
- name : wikipedia - name : wikipedia
engine : wikipedia engine : wikipedia

View File

@ -9,7 +9,7 @@ if(searx.autocompleter) {
timeout: 5 // Correct option? timeout: 5 // Correct option?
}, },
'minLength': 4, 'minLength': 4,
'selectMode': 'type-ahead', // 'selectMode': 'type-ahead',
cache: true, cache: true,
delay: 300 delay: 300
}); });

View File

@ -15,14 +15,14 @@
{% endblock %} {% endblock %}
<script type="text/javascript"> <script type="text/javascript">
searx = {}; searx = {};
searx.autocompleter = {% if client.autocompleter %}true{% else %}false{% endif %}; searx.autocompleter = {% if autocomplete %}true{% else %}false{% endif %};
</script> </script>
</head> </head>
<body> <body>
<div id="container"> <div id="container">
{% block content %} {% block content %}
{% endblock %} {% endblock %}
{% if client.autocompleter %} {% if autocomplete %}
<script src="{{ url_for('static', filename='js/mootools-core-1.4.5-min.js') }}" ></script> <script src="{{ url_for('static', filename='js/mootools-core-1.4.5-min.js') }}" ></script>
<script src="{{ url_for('static', filename='js/mootools-autocompleter-1.1.2-min.js') }}" ></script> <script src="{{ url_for('static', filename='js/mootools-autocompleter-1.1.2-min.js') }}" ></script>
{% endif %} {% endif %}

View File

@ -17,7 +17,7 @@
<select name='language'> <select name='language'>
<option value="all" {% if current_language == 'all' %}selected="selected"{% endif %}>{{ _('Automatic') }}</option> <option value="all" {% if current_language == 'all' %}selected="selected"{% endif %}>{{ _('Automatic') }}</option>
{% for lang_id,lang_name,country_name in language_codes %} {% for lang_id,lang_name,country_name in language_codes %}
<option value={{ lang_id }} {% if lang_id == current_language %}selected="selected"{% endif %}>{{ lang_name}} ({{ country_name }}) - {{ lang_id }}</option> <option value="{{ lang_id }}" {% if lang_id == current_language %}selected="selected"{% endif %}>{{ lang_name }} ({{ country_name }}) - {{ lang_id }}</option>
{% endfor %} {% endfor %}
</select> </select>
</p> </p>
@ -27,7 +27,18 @@
<p> <p>
<select name='locale'> <select name='locale'>
{% for locale_id,locale_name in locales.items() %} {% for locale_id,locale_name in locales.items() %}
<option value={{ locale_id }} {% if locale_id == current_locale %}selected="selected"{% endif %}>{{ locale_name}}</option> <option value="{{ locale_id }}" {% if locale_id == current_locale %}selected="selected"{% endif %}>{{ locale_name }}</option>
{% endfor %}
</select>
</p>
</fieldset>
<fieldset>
<legend>{{ _('Autocomplete') }}</legend>
<p>
<select name="autocomplete">
<option value=""> - </option>
{% for backend in autocomplete_backends %}
<option value="{{ backend }}" {% if backend == autocomplete %}selected="selected"{% endif %}>{{ backend }}</option>
{% endfor %} {% endfor %}
</select> </select>
</p> </p>

View File

@ -41,6 +41,7 @@ from searx.engines import (
from searx.utils import UnicodeWriter, highlight_content, html_to_text from searx.utils import UnicodeWriter, highlight_content, html_to_text
from searx.languages import language_codes from searx.languages import language_codes
from searx.search import Search from searx.search import Search
from searx.autocomplete import backends as autocomplete_backends
app = Flask( app = Flask(
@ -91,16 +92,25 @@ def get_base_url():
def render(template_name, **kwargs): def render(template_name, **kwargs):
blocked_engines = request.cookies.get('blocked_engines', '').split(',') blocked_engines = request.cookies.get('blocked_engines', '').split(',')
autocomplete = request.cookies.get('autocomplete')
if autocomplete not in autocomplete_backends:
autocomplete = None
nonblocked_categories = (engines[e].categories nonblocked_categories = (engines[e].categories
for e in engines for e in engines
if e not in blocked_engines) if e not in blocked_engines)
nonblocked_categories = set(chain.from_iterable(nonblocked_categories)) nonblocked_categories = set(chain.from_iterable(nonblocked_categories))
if not 'categories' in kwargs: if not 'categories' in kwargs:
kwargs['categories'] = ['general'] kwargs['categories'] = ['general']
kwargs['categories'].extend(x for x in kwargs['categories'].extend(x for x in
sorted(categories.keys()) sorted(categories.keys())
if x != 'general' if x != 'general'
and x in nonblocked_categories) and x in nonblocked_categories)
if not 'selected_categories' in kwargs: if not 'selected_categories' in kwargs:
kwargs['selected_categories'] = [] kwargs['selected_categories'] = []
cookie_categories = request.cookies.get('categories', '').split(',') cookie_categories = request.cookies.get('categories', '').split(',')
@ -109,6 +119,10 @@ def render(template_name, **kwargs):
kwargs['selected_categories'].append(ccateg) kwargs['selected_categories'].append(ccateg)
if not kwargs['selected_categories']: if not kwargs['selected_categories']:
kwargs['selected_categories'] = ['general'] kwargs['selected_categories'] = ['general']
if not 'autocomplete' in kwargs:
kwargs['autocomplete'] = autocomplete
return render_template(template_name, **kwargs) return render_template(template_name, **kwargs)
@ -122,7 +136,6 @@ def index():
if not request.args and not request.form: if not request.args and not request.form:
return render( return render(
'index.html', 'index.html',
client=settings.get('client', None)
) )
try: try:
@ -130,7 +143,6 @@ def index():
except: except:
return render( return render(
'index.html', 'index.html',
client=settings.get('client', None)
) )
# TODO moar refactor - do_search integration into Search class # TODO moar refactor - do_search integration into Search class
@ -212,7 +224,6 @@ def index():
return render( return render(
'results.html', 'results.html',
results=search.results, results=search.results,
client=settings.get('client', None),
q=search.request_data['q'], q=search.request_data['q'],
selected_categories=search.categories, selected_categories=search.categories,
paging=search.paging, paging=search.paging,
@ -227,7 +238,6 @@ def about():
"""Render about page""" """Render about page"""
return render( return render(
'about.html', 'about.html',
client=settings.get('client', None)
) )
@ -235,27 +245,35 @@ def about():
def autocompleter(): def autocompleter():
"""Return autocompleter results""" """Return autocompleter results"""
request_data = {} request_data = {}
if request.method == 'POST': if request.method == 'POST':
request_data = request.form request_data = request.form
else: else:
request_data = request.args request_data = request.args
# TODO fix XSS-vulnerability # TODO fix XSS-vulnerability
autocompleter.querry = request_data.get('q') query = request_data.get('q')
autocompleter.results = []
if not query:
if settings['client']['autocompleter']: return
#TODO remove test code and add real autocompletion
if autocompleter.querry: completer = autocomplete_backends.get(request.cookies.get('autocomplete'))
autocompleter.results = [autocompleter.querry + " result-1",autocompleter.querry + " result-2",autocompleter.querry + " result-3",autocompleter.querry + " result-4"]
if not completer:
return
try:
results = completer(query)
except Exception, e:
print e
results = []
if request_data.get('format') == 'x-suggestions': if request_data.get('format') == 'x-suggestions':
return Response(json.dumps([autocompleter.querry,autocompleter.results]), return Response(json.dumps([query, results]),
mimetype='application/json') mimetype='application/json')
else: else:
return Response(json.dumps(autocompleter.results), return Response(json.dumps(results),
mimetype='application/json') mimetype='application/json')
@app.route('/preferences', methods=['GET', 'POST']) @app.route('/preferences', methods=['GET', 'POST'])
@ -276,6 +294,7 @@ def preferences():
else: else:
selected_categories = [] selected_categories = []
locale = None locale = None
autocomplete = ''
for pd_name, pd in request.form.items(): for pd_name, pd in request.form.items():
if pd_name.startswith('category_'): if pd_name.startswith('category_'):
category = pd_name[9:] category = pd_name[9:]
@ -284,6 +303,8 @@ def preferences():
selected_categories.append(category) selected_categories.append(category)
elif pd_name == 'locale' and pd in settings['locales']: elif pd_name == 'locale' and pd in settings['locales']:
locale = pd locale = pd
elif pd_name == 'autocomplete':
autocomplete = pd
elif pd_name == 'language' and (pd == 'all' or elif pd_name == 'language' and (pd == 'all' or
pd in (x[0] for pd in (x[0] for
x in language_codes)): x in language_codes)):
@ -319,8 +340,14 @@ def preferences():
# cookie max age: 4 weeks # cookie max age: 4 weeks
resp.set_cookie( resp.set_cookie(
'categories', ','.join(selected_categories), 'categories', ','.join(selected_categories),
max_age=60 * 60 * 24 * 7 * 4 max_age=cookie_max_age
) )
resp.set_cookie(
'autocomplete', autocomplete,
max_age=cookie_max_age
)
return resp return resp
return render('preferences.html', return render('preferences.html',
client=settings.get('client', None), client=settings.get('client', None),
@ -330,6 +357,7 @@ def preferences():
language_codes=language_codes, language_codes=language_codes,
categs=categories.items(), categs=categories.items(),
blocked_engines=blocked_engines, blocked_engines=blocked_engines,
autocomplete_backends=autocomplete_backends,
shortcuts={y: x for x, y in engine_shortcuts.items()}) shortcuts={y: x for x, y in engine_shortcuts.items()})
@ -361,7 +389,12 @@ def opensearch():
# chrome/chromium only supports HTTP GET.... # chrome/chromium only supports HTTP GET....
if request.headers.get('User-Agent', '').lower().find('webkit') >= 0: if request.headers.get('User-Agent', '').lower().find('webkit') >= 0:
method = 'get' method = 'get'
ret = render('opensearch.xml', method=method, host=get_base_url(),client=settings['client'])
ret = render('opensearch.xml',
method=method,
host=get_base_url(),
client=settings['client'])
resp = Response(response=ret, resp = Response(response=ret,
status=200, status=200,
mimetype="application/xml") mimetype="application/xml")