|
a/webui.py |
|
b/webui.py |
1 |
#!env python
|
1 |
#!env python
|
2 |
#{{{ imports
|
2 |
#{{{ imports
|
3 |
import os
|
3 |
import os
|
4 |
import bottle
|
4 |
import bottle
|
5 |
import time
|
5 |
import time
|
|
|
6 |
import sys
|
|
|
7 |
|
6 |
try:
|
8 |
try:
|
7 |
from recoll import recoll
|
9 |
from recoll import recoll
|
|
|
10 |
from recoll import rclextract
|
|
|
11 |
hasrclextract = True
|
8 |
except:
|
12 |
except:
|
9 |
import recoll
|
13 |
import recoll
|
|
|
14 |
hasrclextract = False
|
10 |
|
15 |
|
11 |
import datetime
|
16 |
import datetime
|
12 |
import glob
|
17 |
import glob
|
13 |
import hashlib
|
18 |
import hashlib
|
14 |
import json
|
19 |
import json
|
|
... |
|
... |
164 |
qs += " date:%s/%s" % (q['after'], q['before'])
|
169 |
qs += " date:%s/%s" % (q['after'], q['before'])
|
165 |
if q['dir'] != '<all>':
|
170 |
if q['dir'] != '<all>':
|
166 |
qs += " dir:\"%s\" " % q['dir']
|
171 |
qs += " dir:\"%s\" " % q['dir']
|
167 |
return qs
|
172 |
return qs
|
168 |
#}}}
|
173 |
#}}}
|
169 |
#{{{ recoll_search
|
174 |
#{{{ recoll_initsearch
|
170 |
def recoll_search(q):
|
175 |
def recoll_initsearch(q):
|
171 |
config = get_config()
|
176 |
config = get_config()
|
172 |
tstart = datetime.datetime.now()
|
|
|
173 |
results = []
|
|
|
174 |
db = recoll.connect(config['confdir'])
|
177 |
db = recoll.connect(config['confdir'])
|
175 |
db.setAbstractParams(config['maxchars'], config['context'])
|
178 |
db.setAbstractParams(config['maxchars'], config['context'])
|
176 |
query = db.query()
|
179 |
query = db.query()
|
177 |
query.sortby(q['sort'], q['ascending'])
|
180 |
query.sortby(q['sort'], q['ascending'])
|
178 |
try:
|
181 |
try:
|
179 |
qs = query_to_recoll_string(q)
|
182 |
qs = query_to_recoll_string(q)
|
180 |
nres = query.execute(qs, config['stem'])
|
183 |
query.execute(qs, config['stem'])
|
181 |
except:
|
184 |
except:
|
182 |
nres = 0
|
185 |
pass
|
|
|
186 |
return query
|
|
|
187 |
#}}}
|
|
|
188 |
#{{{ recoll_search
|
|
|
189 |
def recoll_search(q):
|
|
|
190 |
config = get_config()
|
|
|
191 |
tstart = datetime.datetime.now()
|
|
|
192 |
results = []
|
|
|
193 |
query = recoll_initsearch(q)
|
|
|
194 |
nres = query.rowcount
|
|
|
195 |
|
183 |
if config['maxresults'] == 0:
|
196 |
if config['maxresults'] == 0:
|
184 |
config['maxresults'] = nres
|
197 |
config['maxresults'] = nres
|
185 |
if nres > config['maxresults']:
|
198 |
if nres > config['maxresults']:
|
186 |
nres = config['maxresults']
|
199 |
nres = config['maxresults']
|
187 |
if config['perpage'] == 0 or q['page'] == 0:
|
200 |
if config['perpage'] == 0 or q['page'] == 0:
|
188 |
config['perpage'] = nres
|
201 |
config['perpage'] = nres
|
189 |
q['page'] = 1
|
202 |
q['page'] = 1
|
190 |
offset = (q['page'] - 1) * config['perpage']
|
203 |
offset = (q['page'] - 1) * config['perpage']
|
191 |
|
204 |
|
|
|
205 |
if query.rowcount > 0:
|
192 |
if type(query.next) == int:
|
206 |
if type(query.next) == int:
|
193 |
query.next = offset
|
207 |
query.next = offset
|
194 |
else:
|
208 |
else:
|
195 |
query.scroll(offset)
|
209 |
query.scroll(offset, mode='absolute')
|
|
|
210 |
|
196 |
for i in range(config['perpage']):
|
211 |
for i in range(config['perpage']):
|
197 |
try:
|
212 |
try:
|
198 |
doc = query.fetchone()
|
213 |
doc = query.fetchone()
|
199 |
except:
|
214 |
except:
|
200 |
break
|
215 |
break
|
|
... |
|
... |
206 |
else:
|
221 |
else:
|
207 |
d[f] = ''
|
222 |
d[f] = ''
|
208 |
d['label'] = select([d['title'], d['filename'], '?'], [None, ''])
|
223 |
d['label'] = select([d['title'], d['filename'], '?'], [None, ''])
|
209 |
d['sha'] = hashlib.sha1(d['url']+d['ipath']).hexdigest()
|
224 |
d['sha'] = hashlib.sha1(d['url']+d['ipath']).hexdigest()
|
210 |
d['time'] = timestr(d['mtime'], config['timefmt'])
|
225 |
d['time'] = timestr(d['mtime'], config['timefmt'])
|
211 |
d['snippet'] = db.makeDocAbstract(doc, query).encode('utf-8')
|
226 |
d['snippet'] = query.makedocabstract(doc).encode('utf-8')
|
212 |
results.append(d)
|
227 |
results.append(d)
|
213 |
tend = datetime.datetime.now()
|
228 |
tend = datetime.datetime.now()
|
214 |
return results, nres, tend - tstart
|
229 |
return results, nres, tend - tstart
|
215 |
#}}}
|
230 |
#}}}
|
216 |
#}}}
|
231 |
#}}}
|
|
... |
|
... |
239 |
if config['maxresults'] == 0:
|
254 |
if config['maxresults'] == 0:
|
240 |
config['maxresults'] = nres
|
255 |
config['maxresults'] = nres
|
241 |
if config['perpage'] == 0:
|
256 |
if config['perpage'] == 0:
|
242 |
config['perpage'] = nres
|
257 |
config['perpage'] = nres
|
243 |
return { 'res': res, 'time': timer, 'query': query, 'dirs':
|
258 |
return { 'res': res, 'time': timer, 'query': query, 'dirs':
|
244 |
get_dirs(config['dirs'], config['dirdepth']),'qs': qs, 'sorts': SORTS, 'config': config,
|
259 |
get_dirs(config['dirs'], config['dirdepth']),
|
|
|
260 |
'qs': qs, 'sorts': SORTS, 'config': config,
|
245 |
'query_string': bottle.request.query_string, 'nres': nres }
|
261 |
'query_string': bottle.request.query_string, 'nres': nres,
|
|
|
262 |
'hasrclextract': hasrclextract }
|
|
|
263 |
#}}}
|
|
|
264 |
#{{{ preview
|
|
|
265 |
@bottle.route('/preview/<resnum:int>')
|
|
|
266 |
def preview(resnum):
|
|
|
267 |
if not hasrclextract:
|
|
|
268 |
return 'Sorry, needs recoll version 1.19 or later'
|
|
|
269 |
query = get_query()
|
|
|
270 |
qs = query_to_recoll_string(query)
|
|
|
271 |
rclq = recoll_initsearch(query)
|
|
|
272 |
if resnum > rclq.rowcount - 1:
|
|
|
273 |
return 'Bad result index %d' % resnum
|
|
|
274 |
rclq.scroll(resnum)
|
|
|
275 |
doc = rclq.fetchone()
|
|
|
276 |
xt = rclextract.Extractor(doc)
|
|
|
277 |
tdoc = xt.textextract(doc.ipath)
|
|
|
278 |
if tdoc.mimetype == 'text/html':
|
|
|
279 |
bottle.response.content_type = 'text/html; charset=utf-8'
|
|
|
280 |
else:
|
|
|
281 |
bottle.response.content_type = 'text/plain; charset=utf-8'
|
|
|
282 |
return tdoc.text
|
|
|
283 |
#}}}
|
|
|
284 |
#{{{ edit
|
|
|
285 |
@bottle.route('/edit/<resnum:int>')
|
|
|
286 |
def edit(resnum):
|
|
|
287 |
if not hasrclextract:
|
|
|
288 |
return 'Sorry, needs recoll version 1.19 or later'
|
|
|
289 |
query = get_query()
|
|
|
290 |
qs = query_to_recoll_string(query)
|
|
|
291 |
rclq = recoll_initsearch(query)
|
|
|
292 |
if resnum > rclq.rowcount - 1:
|
|
|
293 |
return 'Bad result index %d' % resnum
|
|
|
294 |
rclq.scroll(resnum)
|
|
|
295 |
doc = rclq.fetchone()
|
|
|
296 |
bottle.response.content_type = doc.mimetype
|
|
|
297 |
# If ipath is null, we can just return the file
|
|
|
298 |
pathismine = False
|
|
|
299 |
if doc.ipath == '':
|
|
|
300 |
path = doc.url.replace('file://','')
|
|
|
301 |
else:
|
|
|
302 |
xt = rclextract.Extractor(doc)
|
|
|
303 |
path = xt.idoctofile(doc.ipath, doc.mimetype)
|
|
|
304 |
pathismine = True
|
|
|
305 |
print >> sys.stderr, "Sending %s with mimetype %s" % (path, doc.mimetype)
|
|
|
306 |
f = open(path, 'r')
|
|
|
307 |
if pathismine:
|
|
|
308 |
os.unlink(path)
|
|
|
309 |
return f
|
246 |
#}}}
|
310 |
#}}}
|
247 |
#{{{ json
|
311 |
#{{{ json
|
248 |
@bottle.route('/json')
|
312 |
@bottle.route('/json')
|
249 |
def get_json():
|
313 |
def get_json():
|
250 |
query = get_query()
|
314 |
query = get_query()
|