浏览代码

[enh] autocompleter server side part

Adam Tauber 11 年前
父节点
当前提交
41dd4d9ba3
共有 5 个文件被更改,包括 69 次插入28 次删除
  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
     request_timeout : 2.0 # seconds
5
     request_timeout : 2.0 # seconds
6
     base_url : False
6
     base_url : False
7
 
7
 
8
-client:
9
-    autocompleter : False # only for developers, no real results yet
10
-    
11
 engines:
8
 engines:
12
   - name : wikipedia
9
   - name : wikipedia
13
     engine : wikipedia
10
     engine : wikipedia

+ 1
- 1
searx/static/js/searx.js 查看文件

9
 		        timeout: 5   // Correct option?
9
 		        timeout: 5   // Correct option?
10
 		    },
10
 		    },
11
 		    'minLength': 4,
11
 		    'minLength': 4,
12
-		    'selectMode': 'type-ahead',
12
+		    // 'selectMode': 'type-ahead',
13
 		    cache: true,
13
 		    cache: true,
14
 		    delay: 300
14
 		    delay: 300
15
 	    });
15
 	    });

+ 2
- 2
searx/templates/base.html 查看文件

15
     {% endblock %}
15
     {% endblock %}
16
     <script type="text/javascript">
16
     <script type="text/javascript">
17
         searx = {};
17
         searx = {};
18
-        searx.autocompleter = {% if client.autocompleter %}true{% else %}false{% endif %};
18
+        searx.autocompleter = {% if autocomplete %}true{% else %}false{% endif %};
19
     </script>
19
     </script>
20
 </head>
20
 </head>
21
 <body>
21
 <body>
22
 <div id="container">
22
 <div id="container">
23
 {% block content %}
23
 {% block content %}
24
 {% endblock %}
24
 {% endblock %}
25
-{% if client.autocompleter %}
25
+{% if autocomplete %}
26
 <script src="{{ url_for('static', filename='js/mootools-core-1.4.5-min.js') }}" ></script>
26
 <script src="{{ url_for('static', filename='js/mootools-core-1.4.5-min.js') }}" ></script>
27
 <script src="{{ url_for('static', filename='js/mootools-autocompleter-1.1.2-min.js') }}" ></script>
27
 <script src="{{ url_for('static', filename='js/mootools-autocompleter-1.1.2-min.js') }}" ></script>
28
 {% endif %}
28
 {% endif %}

+ 13
- 2
searx/templates/preferences.html 查看文件

17
         <select name='language'>
17
         <select name='language'>
18
             <option value="all" {% if current_language == 'all' %}selected="selected"{% endif %}>{{ _('Automatic') }}</option>
18
             <option value="all" {% if current_language == 'all' %}selected="selected"{% endif %}>{{ _('Automatic') }}</option>
19
             {% for lang_id,lang_name,country_name in language_codes %}
19
             {% for lang_id,lang_name,country_name in language_codes %}
20
-            <option value={{ lang_id }} {% if lang_id == current_language %}selected="selected"{% endif %}>{{ lang_name}} ({{ country_name }}) - {{ lang_id }}</option>
20
+            <option value="{{ lang_id }}" {% if lang_id == current_language %}selected="selected"{% endif %}>{{ lang_name }} ({{ country_name }}) - {{ lang_id }}</option>
21
             {% endfor %}
21
             {% endfor %}
22
         </select>
22
         </select>
23
         </p>
23
         </p>
27
         <p>
27
         <p>
28
         <select name='locale'>
28
         <select name='locale'>
29
             {% for locale_id,locale_name in locales.items() %}
29
             {% for locale_id,locale_name in locales.items() %}
30
-            <option value={{ locale_id }} {% if locale_id == current_locale %}selected="selected"{% endif %}>{{ locale_name}}</option>
30
+            <option value="{{ locale_id }}" {% if locale_id == current_locale %}selected="selected"{% endif %}>{{ locale_name }}</option>
31
+            {% endfor %}
32
+        </select>
33
+        </p>
34
+    </fieldset>
35
+    <fieldset>
36
+        <legend>{{ _('Autocomplete') }}</legend>
37
+        <p>
38
+        <select name="autocomplete">
39
+            <option value=""> - </option>
40
+            {% for backend in autocomplete_backends %}
41
+            <option value="{{ backend }}" {% if backend == autocomplete %}selected="selected"{% endif %}>{{ backend }}</option>
31
             {% endfor %}
42
             {% endfor %}
32
         </select>
43
         </select>
33
         </p>
44
         </p>

+ 53
- 20
searx/webapp.py 查看文件

41
 from searx.utils import UnicodeWriter, highlight_content, html_to_text
41
 from searx.utils import UnicodeWriter, highlight_content, html_to_text
42
 from searx.languages import language_codes
42
 from searx.languages import language_codes
43
 from searx.search import Search
43
 from searx.search import Search
44
+from searx.autocomplete import backends as autocomplete_backends
44
 
45
 
45
 
46
 
46
 app = Flask(
47
 app = Flask(
91
 
92
 
92
 def render(template_name, **kwargs):
93
 def render(template_name, **kwargs):
93
     blocked_engines = request.cookies.get('blocked_engines', '').split(',')
94
     blocked_engines = request.cookies.get('blocked_engines', '').split(',')
95
+
96
+    autocomplete = request.cookies.get('autocomplete')
97
+
98
+    if autocomplete not in autocomplete_backends:
99
+        autocomplete = None
100
+
94
     nonblocked_categories = (engines[e].categories
101
     nonblocked_categories = (engines[e].categories
95
                              for e in engines
102
                              for e in engines
96
                              if e not in blocked_engines)
103
                              if e not in blocked_engines)
104
+
97
     nonblocked_categories = set(chain.from_iterable(nonblocked_categories))
105
     nonblocked_categories = set(chain.from_iterable(nonblocked_categories))
106
+
98
     if not 'categories' in kwargs:
107
     if not 'categories' in kwargs:
99
         kwargs['categories'] = ['general']
108
         kwargs['categories'] = ['general']
100
         kwargs['categories'].extend(x for x in
109
         kwargs['categories'].extend(x for x in
101
                                     sorted(categories.keys())
110
                                     sorted(categories.keys())
102
                                     if x != 'general'
111
                                     if x != 'general'
103
                                     and x in nonblocked_categories)
112
                                     and x in nonblocked_categories)
113
+
104
     if not 'selected_categories' in kwargs:
114
     if not 'selected_categories' in kwargs:
105
         kwargs['selected_categories'] = []
115
         kwargs['selected_categories'] = []
106
         cookie_categories = request.cookies.get('categories', '').split(',')
116
         cookie_categories = request.cookies.get('categories', '').split(',')
109
                 kwargs['selected_categories'].append(ccateg)
119
                 kwargs['selected_categories'].append(ccateg)
110
         if not kwargs['selected_categories']:
120
         if not kwargs['selected_categories']:
111
             kwargs['selected_categories'] = ['general']
121
             kwargs['selected_categories'] = ['general']
122
+
123
+    if not 'autocomplete' in kwargs:
124
+        kwargs['autocomplete'] = autocomplete
125
+
112
     return render_template(template_name, **kwargs)
126
     return render_template(template_name, **kwargs)
113
 
127
 
114
 
128
 
122
     if not request.args and not request.form:
136
     if not request.args and not request.form:
123
         return render(
137
         return render(
124
             'index.html',
138
             'index.html',
125
-            client=settings.get('client', None)
126
         )
139
         )
127
 
140
 
128
     try:
141
     try:
130
     except:
143
     except:
131
         return render(
144
         return render(
132
             'index.html',
145
             'index.html',
133
-            client=settings.get('client', None)
134
         )
146
         )
135
 
147
 
136
     # TODO moar refactor - do_search integration into Search class
148
     # TODO moar refactor - do_search integration into Search class
212
     return render(
224
     return render(
213
         'results.html',
225
         'results.html',
214
         results=search.results,
226
         results=search.results,
215
-        client=settings.get('client', None),
216
         q=search.request_data['q'],
227
         q=search.request_data['q'],
217
         selected_categories=search.categories,
228
         selected_categories=search.categories,
218
         paging=search.paging,
229
         paging=search.paging,
227
     """Render about page"""
238
     """Render about page"""
228
     return render(
239
     return render(
229
         'about.html',
240
         'about.html',
230
-        client=settings.get('client', None)
231
     )
241
     )
232
 
242
 
233
 
243
 
235
 def autocompleter():
245
 def autocompleter():
236
     """Return autocompleter results"""
246
     """Return autocompleter results"""
237
     request_data = {}
247
     request_data = {}
238
-    
248
+
239
     if request.method == 'POST':
249
     if request.method == 'POST':
240
         request_data = request.form
250
         request_data = request.form
241
     else:
251
     else:
242
         request_data = request.args
252
         request_data = request.args
243
-    
253
+
244
     # TODO fix XSS-vulnerability
254
     # TODO fix XSS-vulnerability
245
-    autocompleter.querry = request_data.get('q')
246
-    autocompleter.results = []
247
-    
248
-    if settings['client']['autocompleter']:
249
-        #TODO remove test code and add real autocompletion
250
-        if autocompleter.querry:
251
-            autocompleter.results = [autocompleter.querry + " result-1",autocompleter.querry + " result-2",autocompleter.querry + " result-3",autocompleter.querry + " result-4"]
252
-    
255
+    query = request_data.get('q')
256
+
257
+    if not query:
258
+        return
259
+
260
+    completer = autocomplete_backends.get(request.cookies.get('autocomplete'))
261
+
262
+    if not completer:
263
+        return
264
+
265
+    try:
266
+        results = completer(query)
267
+    except Exception, e:
268
+        print e
269
+        results = []
270
+
253
     if request_data.get('format') == 'x-suggestions':
271
     if request_data.get('format') == 'x-suggestions':
254
-        return Response(json.dumps([autocompleter.querry,autocompleter.results]),
255
-                                   mimetype='application/json')
272
+        return Response(json.dumps([query, results]),
273
+                        mimetype='application/json')
256
     else:
274
     else:
257
-        return Response(json.dumps(autocompleter.results),
258
-                                   mimetype='application/json')
275
+        return Response(json.dumps(results),
276
+                        mimetype='application/json')
259
 
277
 
260
 
278
 
261
 @app.route('/preferences', methods=['GET', 'POST'])
279
 @app.route('/preferences', methods=['GET', 'POST'])
276
     else:
294
     else:
277
         selected_categories = []
295
         selected_categories = []
278
         locale = None
296
         locale = None
297
+        autocomplete = ''
279
         for pd_name, pd in request.form.items():
298
         for pd_name, pd in request.form.items():
280
             if pd_name.startswith('category_'):
299
             if pd_name.startswith('category_'):
281
                 category = pd_name[9:]
300
                 category = pd_name[9:]
284
                 selected_categories.append(category)
303
                 selected_categories.append(category)
285
             elif pd_name == 'locale' and pd in settings['locales']:
304
             elif pd_name == 'locale' and pd in settings['locales']:
286
                 locale = pd
305
                 locale = pd
306
+            elif pd_name == 'autocomplete':
307
+                autocomplete = pd
287
             elif pd_name == 'language' and (pd == 'all' or
308
             elif pd_name == 'language' and (pd == 'all' or
288
                                             pd in (x[0] for
309
                                             pd in (x[0] for
289
                                                    x in language_codes)):
310
                                                    x in language_codes)):
319
             # cookie max age: 4 weeks
340
             # cookie max age: 4 weeks
320
             resp.set_cookie(
341
             resp.set_cookie(
321
                 'categories', ','.join(selected_categories),
342
                 'categories', ','.join(selected_categories),
322
-                max_age=60 * 60 * 24 * 7 * 4
343
+                max_age=cookie_max_age
323
             )
344
             )
345
+
346
+            resp.set_cookie(
347
+                'autocomplete', autocomplete,
348
+                max_age=cookie_max_age
349
+            )
350
+
324
         return resp
351
         return resp
325
     return render('preferences.html',
352
     return render('preferences.html',
326
                   client=settings.get('client', None),
353
                   client=settings.get('client', None),
330
                   language_codes=language_codes,
357
                   language_codes=language_codes,
331
                   categs=categories.items(),
358
                   categs=categories.items(),
332
                   blocked_engines=blocked_engines,
359
                   blocked_engines=blocked_engines,
360
+                  autocomplete_backends=autocomplete_backends,
333
                   shortcuts={y: x for x, y in engine_shortcuts.items()})
361
                   shortcuts={y: x for x, y in engine_shortcuts.items()})
334
 
362
 
335
 
363
 
361
     # chrome/chromium only supports HTTP GET....
389
     # chrome/chromium only supports HTTP GET....
362
     if request.headers.get('User-Agent', '').lower().find('webkit') >= 0:
390
     if request.headers.get('User-Agent', '').lower().find('webkit') >= 0:
363
         method = 'get'
391
         method = 'get'
364
-    ret = render('opensearch.xml', method=method, host=get_base_url(),client=settings['client'])
392
+
393
+    ret = render('opensearch.xml',
394
+                 method=method,
395
+                 host=get_base_url(),
396
+                 client=settings['client'])
397
+
365
     resp = Response(response=ret,
398
     resp = Response(response=ret,
366
                     status=200,
399
                     status=200,
367
                     mimetype="application/xml")
400
                     mimetype="application/xml")