Browse Source

[enh] autocompleter server side part

Adam Tauber 11 years ago
parent
commit
41dd4d9ba3
5 changed files with 69 additions and 28 deletions
  1. 0 3
      searx/settings.yml
  2. 1 1
      searx/static/js/searx.js
  3. 2 2
      searx/templates/base.html
  4. 13 2
      searx/templates/preferences.html
  5. 53 20
      searx/webapp.py

+ 0 - 3
searx/settings.yml

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

+ 1 - 1
searx/static/js/searx.js

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

+ 2 - 2
searx/templates/base.html

@@ -15,14 +15,14 @@
     {% endblock %}
     <script type="text/javascript">
         searx = {};
-        searx.autocompleter = {% if client.autocompleter %}true{% else %}false{% endif %};
+        searx.autocompleter = {% if autocomplete %}true{% else %}false{% endif %};
     </script>
 </head>
 <body>
 <div id="container">
 {% block content %}
 {% 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-autocompleter-1.1.2-min.js') }}" ></script>
 {% endif %}

+ 13 - 2
searx/templates/preferences.html

@@ -17,7 +17,7 @@
         <select name='language'>
             <option value="all" {% if current_language == 'all' %}selected="selected"{% endif %}>{{ _('Automatic') }}</option>
             {% 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 %}
         </select>
         </p>
@@ -27,7 +27,18 @@
         <p>
         <select name='locale'>
             {% 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 %}
         </select>
         </p>

+ 53 - 20
searx/webapp.py

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