on master help sign in
Merge branch 'master' into http1.1
a88768eAlexandre Flament
.travis.yml+5
@@ -4,6 +4,8 @@ cache:
4 - npm
4 - npm
5 - directories:
5 - directories:
6 - $HOME/.cache/pip
6 - $HOME/.cache/pip
7+addons:
8+ firefox: "latest"
7language: python
9language: python
8python:
10python:
9 - "2.7"
11 - "2.7"
@@ -12,6 +14,9 @@ before_install:
12 - "sh -e /etc/init.d/xvfb start"
14 - "sh -e /etc/init.d/xvfb start"
13 - npm install less grunt-cli
15 - npm install less grunt-cli
14 - ( cd searx/static/themes/oscar;npm install; cd - )
16 - ( cd searx/static/themes/oscar;npm install; cd - )
17+ - mkdir -p ~/drivers; export PATH=~/drivers:$PATH;
18+ - GECKODRIVER_URL="https://github.com/mozilla/geckodriver/releases/download/v0.11.1/geckodriver-v0.11.1-linux64.tar.gz";
19+ - FILE=`mktemp`; wget "$GECKODRIVER_URL" -qO $FILE && tar xz -C ~/drivers -f $FILE geckodriver; rm $FILE; chmod 777 ~/drivers/geckodriver;
15install:
20install:
16 - ./manage.sh update_dev_packages
21 - ./manage.sh update_dev_packages
17 - pip install coveralls
22 - pip install coveralls
AUTHORS.rst+2
@@ -58,3 +58,5 @@ generally made searx better:
58- marc @a01200356
58- marc @a01200356
59- Harry Wood @harry-wood
59- Harry Wood @harry-wood
60- Thomas Renard @threnard
60- Thomas Renard @threnard
61+- Pydo `<https://github.com/pydo>`_
62+- Athemis `<https://github.com/Athemis>`_
manage.sh+2−2
@@ -53,8 +53,8 @@ build_style() {
53
53
54styles() {
54styles() {
55 echo '[!] Building styles'
55 echo '[!] Building styles'
56− build_style themes/default/less/style.less themes/default/css/style.css
56+ build_style themes/legacy/less/style.less themes/legacy/css/style.css
57− build_style themes/default/less/style-rtl.less themes/default/css/style-rtl.css
57+ build_style themes/legacy/less/style-rtl.less themes/legacy/css/style-rtl.css
58 build_style themes/courgette/less/style.less themes/courgette/css/style.css
58 build_style themes/courgette/less/style.less themes/courgette/css/style.css
59 build_style themes/courgette/less/style-rtl.less themes/courgette/css/style-rtl.css
59 build_style themes/courgette/less/style-rtl.less themes/courgette/css/style-rtl.css
60 build_style less/bootstrap/bootstrap.less css/bootstrap.min.css
60 build_style less/bootstrap/bootstrap.less css/bootstrap.min.css
requirements-dev.txt+3−3
@@ -3,8 +3,8 @@ mock==2.0.0
3nose2[coverage-plugin]
3nose2[coverage-plugin]
4pep8==1.7.0
4pep8==1.7.0
5plone.testing==5.0.0
5plone.testing==5.0.0
6−robotframework-selenium2library==1.7.4
6+robotframework-selenium2library==1.8.0
7robotsuite==1.7.0
7robotsuite==1.7.0
8−transifex-client==0.11
8+transifex-client==0.12.2
9unittest2==1.1.0
9unittest2==1.1.0
10−zope.testrunner==4.4.10
10+zope.testrunner==4.5.1
requirements.txt+1−1
@@ -1,4 +1,4 @@
1−certifi==2016.2.28
1+certifi==2016.9.26
2flask==0.11.1
2flask==0.11.1
3flask-babel==0.11.1
3flask-babel==0.11.1
4lxml==3.6.0
4lxml==3.6.0
searx/engines/__init__.py+9−3
@@ -57,11 +57,17 @@ def load_module(filename):
57
57
58
58
59def load_engine(engine_data):
59def load_engine(engine_data):
60+
61+ if '_' in engine_data['name']:
62+ logger.error('Engine name conains underscore: "{}"'.format(engine_data['name']))
63+ sys.exit(1)
64+
60− engine_name = engine_data['engine']
65+ engine_module = engine_data['engine']
66+
61 try:
67 try:
62− engine = load_module(engine_name + '.py')
68+ engine = load_module(engine_module + '.py')
63 except:
69 except:
64− logger.exception('Cannot load engine "{}"'.format(engine_name))
70+ logger.exception('Cannot load engine "{}"'.format(engine_module))
65 return None
71 return None
66
72
67 for param_name in engine_data:
73 for param_name in engine_data:
searx/engines/digbt.py+1−1
@@ -40,7 +40,7 @@ def response(resp):
40 results = list()
40 results = list()
41 for result in search_res:
41 for result in search_res:
42 url = urljoin(URL, result.xpath('.//a[@title]/@href')[0])
42 url = urljoin(URL, result.xpath('.//a[@title]/@href')[0])
43− title = result.xpath('.//a[@title]/text()')[0]
43+ title = extract_text(result.xpath('.//a[@title]'))
44 content = extract_text(result.xpath('.//div[@class="files"]'))
44 content = extract_text(result.xpath('.//div[@class="files"]'))
45 files_data = extract_text(result.xpath('.//div[@class="tail"]')).split()
45 files_data = extract_text(result.xpath('.//div[@class="tail"]')).split()
46 filesize = get_torrent_size(files_data[FILESIZE], files_data[FILESIZE_MULTIPLIER])
46 filesize = get_torrent_size(files_data[FILESIZE], files_data[FILESIZE_MULTIPLIER])
searx/engines/kickass.py+11−35
@@ -16,13 +16,14 @@ from urllib import quote
16from lxml import html
16from lxml import html
17from operator import itemgetter
17from operator import itemgetter
18from searx.engines.xpath import extract_text
18from searx.engines.xpath import extract_text
19+from searx.utils import get_torrent_size, convert_str_to_int
19
20
20# engine dependent config
21# engine dependent config
21categories = ['videos', 'music', 'files']
22categories = ['videos', 'music', 'files']
22paging = True
23paging = True
23
24
24# search-url
25# search-url
25−url = 'https://kickass.to/'
26+url = 'https://kickass.cd/'
26search_url = url + 'search/{search_term}/{pageno}/'
27search_url = url + 'search/{search_term}/{pageno}/'
27
28
28# specific xpath variables
29# specific xpath variables
@@ -57,41 +58,16 @@ def response(resp):
57 href = urljoin(url, link.attrib['href'])
58 href = urljoin(url, link.attrib['href'])
58 title = extract_text(link)
59 title = extract_text(link)
59 content = escape(extract_text(result.xpath(content_xpath)))
60 content = escape(extract_text(result.xpath(content_xpath)))
60− seed = result.xpath('.//td[contains(@class, "green")]/text()')[0]
61+ seed = extract_text(result.xpath('.//td[contains(@class, "green")]'))
61− leech = result.xpath('.//td[contains(@class, "red")]/text()')[0]
62+ leech = extract_text(result.xpath('.//td[contains(@class, "red")]'))
62− filesize = result.xpath('.//td[contains(@class, "nobr")]/text()')[0]
63− filesize_multiplier = result.xpath('.//td[contains(@class, "nobr")]//span/text()')[0]
63+ filesize_info = extract_text(result.xpath('.//td[contains(@class, "nobr")]'))
64− files = result.xpath('.//td[contains(@class, "center")][2]/text()')[0]
64+ files = extract_text(result.xpath('.//td[contains(@class, "center")][2]'))
65−
66− # convert seed to int if possible
67− if seed.isdigit():
68− seed = int(seed)
69− else:
70− seed = 0
71
65
72− # convert leech to int if possible
66+ seed = convert_str_to_int(seed)
73− if leech.isdigit():
67+ leech = convert_str_to_int(leech)
74− leech = int(leech)
68+
75− else:
69+ filesize, filesize_multiplier = filesize_info.split()
76− leech = 0
77−
78− # convert filesize to byte if possible
79− try:
80− filesize = float(filesize)
81−
82− # convert filesize to byte
83− if filesize_multiplier == 'TB':
84− filesize = int(filesize * 1024 * 1024 * 1024 * 1024)
85− elif filesize_multiplier == 'GB':
86− filesize = int(filesize * 1024 * 1024 * 1024)
87− elif filesize_multiplier == 'MB':
88− filesize = int(filesize * 1024 * 1024)
89− elif filesize_multiplier == 'KB':
70+ filesize = get_torrent_size(filesize, filesize_multiplier)
90− filesize = int(filesize * 1024)
91− except:
92− filesize = None
93−
94− # convert files to int if possible
95 if files.isdigit():
71 if files.isdigit():
96 files = int(files)
72 files = int(files)
97 else:
73 else:
searx/engines/pdbe.pynew file+109
@@ -0,0 +1,109 @@
1+"""
2+ PDBe (Protein Data Bank in Europe)
3+
4+ @website https://www.ebi.ac.uk/pdbe
5+ @provide-api yes (https://www.ebi.ac.uk/pdbe/api/doc/search.html),
6+ unlimited
7+ @using-api yes
8+ @results python dictionary (from json)
9+ @stable yes
10+ @parse url, title, content, img_src
11+"""
12+
13+from json import loads
14+from flask_babel import gettext
15+
16+categories = ['science']
17+
18+hide_obsolete = False
19+
20+# status codes of unpublished entries
21+pdb_unpublished_codes = ['HPUB', 'HOLD', 'PROC', 'WAIT', 'AUTH', 'AUCO', 'REPL', 'POLC', 'REFI', 'TRSF', 'WDRN']
22+# url for api query
23+pdbe_solr_url = 'https://www.ebi.ac.uk/pdbe/search/pdb/select?'
24+# base url for results
25+pdbe_entry_url = 'https://www.ebi.ac.uk/pdbe/entry/pdb/{pdb_id}'
26+# link to preview image of structure
27+pdbe_preview_url = 'https://www.ebi.ac.uk/pdbe/static/entry/{pdb_id}_deposited_chain_front_image-200x200.png'
28+
29+
30+def request(query, params):
31+
32+ params['url'] = pdbe_solr_url
33+ params['method'] = 'POST'
34+ params['data'] = {
35+ 'q': query,
36+ 'wt': "json" # request response in parsable format
37+ }
38+ return params
39+
40+
41+def construct_body(result):
42+ # set title
43+ title = result['title']
44+
45+ # construct content body
46+ content = """{title}<br />{authors} {journal} <strong>{volume}</strong>&nbsp;{page} ({year})"""
47+
48+ # replace placeholders with actual content
49+ try:
50+ if result['journal']:
51+ content = content.format(
52+ title=result['citation_title'],
53+ authors=result['entry_author_list'][0], journal=result['journal'], volume=result['journal_volume'],
54+ page=result['journal_page'], year=result['citation_year'])
55+ else:
56+ content = content.format(
57+ title=result['citation_title'],
58+ authors=result['entry_author_list'][0], journal='', volume='', page='', year=result['release_year'])
59+ img_src = pdbe_preview_url.format(pdb_id=result['pdb_id'])
60+ except (KeyError):
61+ content = None
62+ img_src = None
63+
64+ # construct url for preview image
65+ try:
66+ img_src = pdbe_preview_url.format(pdb_id=result['pdb_id'])
67+ except (KeyError):
68+ img_src = None
69+
70+ return [title, content, img_src]
71+
72+
73+def response(resp):
74+
75+ results = []
76+ json = loads(resp.text)['response']['docs']
77+
78+ # parse results
79+ for result in json:
80+ # catch obsolete entries and mark them accordingly
81+ if result['status'] in pdb_unpublished_codes:
82+ continue
83+ if hide_obsolete:
84+ continue
85+ if result['status'] == 'OBS':
86+ # expand title to add some sort of warning message
87+ title = gettext('{title}&nbsp;(OBSOLETE)').format(title=result['title'])
88+ superseded_url = pdbe_entry_url.format(pdb_id=result['superseded_by'])
89+
90+ # since we can't construct a proper body from the response, we'll make up our own
91+ msg_superseded = gettext("This entry has been superseded by")
92+ content = '<em>{msg_superseded} \<a href="{url}">{pdb_id}</a></em>'.format(
93+ msg_superseded=msg_superseded,
94+ url=superseded_url,
95+ pdb_id=result['superseded_by'], )
96+
97+ # obsoleted entries don't have preview images
98+ img_src = None
99+ else:
100+ title, content, img_src = construct_body(result)
101+
102+ results.append({
103+ 'url': pdbe_entry_url.format(pdb_id=result['pdb_id']),
104+ 'title': title,
105+ 'content': content,
106+ 'img_src': img_src
107+ })
108+
109+ return results
searx/engines/seedpeer.pynew file+78
@@ -0,0 +1,78 @@
1+# Seedpeer (Videos, Music, Files)
2+#
3+# @website http://seedpeer.eu
4+# @provide-api no (nothing found)
5+#
6+# @using-api no
7+# @results HTML (using search portal)
8+# @stable yes (HTML can change)
9+# @parse url, title, content, seed, leech, magnetlink
10+
11+from urlparse import urljoin
12+from cgi import escape
13+from urllib import quote
14+from lxml import html
15+from operator import itemgetter
16+from searx.engines.xpath import extract_text
17+
18+
19+url = 'http://www.seedpeer.eu/'
20+search_url = url + 'search/{search_term}/7/{page_no}.html'
21+# specific xpath variables
22+torrent_xpath = '//*[@id="body"]/center/center/table[2]/tr/td/a'
23+alternative_torrent_xpath = '//*[@id="body"]/center/center/table[1]/tr/td/a'
24+title_xpath = '//*[@id="body"]/center/center/table[2]/tr/td/a/text()'
25+alternative_title_xpath = '//*[@id="body"]/center/center/table/tr/td/a'
26+seeds_xpath = '//*[@id="body"]/center/center/table[2]/tr/td[4]/font/text()'
27+alternative_seeds_xpath = '//*[@id="body"]/center/center/table/tr/td[4]/font/text()'
28+peers_xpath = '//*[@id="body"]/center/center/table[2]/tr/td[5]/font/text()'
29+alternative_peers_xpath = '//*[@id="body"]/center/center/table/tr/td[5]/font/text()'
30+age_xpath = '//*[@id="body"]/center/center/table[2]/tr/td[2]/text()'
31+alternative_age_xpath = '//*[@id="body"]/center/center/table/tr/td[2]/text()'
32+size_xpath = '//*[@id="body"]/center/center/table[2]/tr/td[3]/text()'
33+alternative_size_xpath = '//*[@id="body"]/center/center/table/tr/td[3]/text()'
34+
35+
36+# do search-request
37+def request(query, params):
38+ params['url'] = search_url.format(search_term=quote(query),
39+ page_no=params['pageno'] - 1)
40+ return params
41+
42+
43+# get response from search-request
44+def response(resp):
45+ results = []
46+ dom = html.fromstring(resp.text)
47+ torrent_links = dom.xpath(torrent_xpath)
48+ if len(torrent_links) > 0:
49+ seeds = dom.xpath(seeds_xpath)
50+ peers = dom.xpath(peers_xpath)
51+ titles = dom.xpath(title_xpath)
52+ sizes = dom.xpath(size_xpath)
53+ ages = dom.xpath(age_xpath)
54+ else: # under ~5 results uses a different xpath
55+ torrent_links = dom.xpath(alternative_torrent_xpath)
56+ seeds = dom.xpath(alternative_seeds_xpath)
57+ peers = dom.xpath(alternative_peers_xpath)
58+ titles = dom.xpath(alternative_title_xpath)
59+ sizes = dom.xpath(alternative_size_xpath)
60+ ages = dom.xpath(alternative_age_xpath)
61+ # return empty array if nothing is found
62+ if not torrent_links:
63+ return []
64+
65+ # parse results
66+ for index, result in enumerate(torrent_links):
67+ link = result.attrib.get('href')
68+ href = urljoin(url, link)
69+ results.append({'url': href,
70+ 'title': titles[index].text_content(),
71+ 'content': '{}, {}'.format(sizes[index], ages[index]),
72+ 'seed': seeds[index],
73+ 'leech': peers[index],
74+
75+ 'template': 'torrent.html'})
76+
77+ # return results sorted by seeder
78+ return sorted(results, key=itemgetter('seed'), reverse=True)
searx/settings.yml+26−1
@@ -18,6 +18,12 @@ ui:
18 default_theme : oscar # ui theme
18 default_theme : oscar # ui theme
19 default_locale : "" # Default interface locale - leave blank to detect from browser information or use codes from the 'locales' config section
19 default_locale : "" # Default interface locale - leave blank to detect from browser information or use codes from the 'locales' config section
20
20
21+# searx supports result proxification using an external service: https://github.com/asciimoo/morty
22+# uncomment below section if you have running morty proxy
23+#result_proxy:
24+# url : http://127.0.0.1:3000/
25+# key : your_morty_proxy_key
26+
21outgoing: # communication with search engines
27outgoing: # communication with search engines
22 request_timeout : 2.0 # seconds
28 request_timeout : 2.0 # seconds
23 useragent_suffix : "" # suffix of searx_useragent, could contain informations like an email address to the administrator
29 useragent_suffix : "" # suffix of searx_useragent, could contain informations like an email address to the administrator
@@ -301,6 +307,12 @@ engines:
301 timeout : 6.0
307 timeout : 6.0
302 disabled : True
308 disabled : True
303
309
310+ - name: kickass
311+ engine : kickass
312+ shortcut : kc
313+ timeout : 4.0
314+ disabled : True
315+
304 - name : microsoft academic
316 - name : microsoft academic
305 engine : json_engine
317 engine : json_engine
306 paging : True
318 paging : True
@@ -339,6 +351,13 @@ engines:
339 disabled : True
351 disabled : True
340 shortcut : or
352 shortcut : or
341
353
354+ - name : pdbe
355+ engine : pdbe
356+ shortcut : pdb
357+# Hide obsolete PDB entries.
358+# Default is not to hide obsolete structures
359+# hide_obsolete : False
360+
342 - name : photon
361 - name : photon
343 engine : photon
362 engine : photon
344 shortcut : ph
363 shortcut : ph
@@ -377,7 +396,7 @@ engines:
377 timeout : 10.0
396 timeout : 10.0
378 disabled : True
397 disabled : True
379
398
380− - name : scanr_structures
399+ - name : scanr structures
381 shortcut: scs
400 shortcut: scs
382 engine : scanr_structures
401 engine : scanr_structures
383 disabled : True
402 disabled : True
@@ -495,6 +514,12 @@ engines:
495 timeout: 6.0
514 timeout: 6.0
496 categories : science
515 categories : science
497
516
517+ - name : seedpeer
518+ engine : seedpeer
519+ shortcut: speu
520+ categories: files, music, videos
521+ disabled: True
522+
498 - name : dictzone
523 - name : dictzone
499 engine : dictzone
524 engine : dictzone
500 shortcut : dc
525 shortcut : dc
searx/settings_robot.yml+3−3
@@ -15,7 +15,7 @@ server:
15
15
16ui:
16ui:
17 themes_path : ""
17 themes_path : ""
18− default_theme : default
18+ default_theme : legacy
19 default_locale : ""
19 default_locale : ""
20
20
21outgoing:
21outgoing:
@@ -23,12 +23,12 @@ outgoing:
23 useragent_suffix : ""
23 useragent_suffix : ""
24
24
25engines:
25engines:
26− - name : general_dummy
26+ - name : general dummy
27 engine : dummy
27 engine : dummy
28 categories : general
28 categories : general
29 shortcut : gd
29 shortcut : gd
30
30
31− - name : dummy_dummy
31+ - name : dummy dummy
32 engine : dummy
32 engine : dummy
33 categories : dummy
33 categories : dummy
34 shortcut : dd
34 shortcut : dd
searx/static/themes/default/css/style-rtl.css → searx/static/themes/legacy/css/style-rtl.cssrenamed

The content is the same.

searx/static/themes/default/css/style.css → searx/static/themes/legacy/css/style.cssrenamed

The content is the same.

searx/static/themes/default/img/favicon.png → searx/static/themes/legacy/img/favicon.pngrenamed

Binary file not shown.

searx/static/themes/default/img/github_ribbon.png → searx/static/themes/legacy/img/github_ribbon.pngrenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_500px.ico → searx/static/themes/legacy/img/icons/icon_500px.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_bing.ico → searx/static/themes/legacy/img/icons/icon_bing.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_dailymotion.ico → searx/static/themes/legacy/img/icons/icon_dailymotion.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_deezer.ico → searx/static/themes/legacy/img/icons/icon_deezer.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_deviantart.ico → searx/static/themes/legacy/img/icons/icon_deviantart.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_digg.ico → searx/static/themes/legacy/img/icons/icon_digg.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_duckduckgo.ico → searx/static/themes/legacy/img/icons/icon_duckduckgo.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_flickr.ico → searx/static/themes/legacy/img/icons/icon_flickr.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_github.ico → searx/static/themes/legacy/img/icons/icon_github.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_google play apps.ico → searx/static/themes/legacy/img/icons/icon_google play apps.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_google play movies.ico → searx/static/themes/legacy/img/icons/icon_google play movies.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_google play music.ico → searx/static/themes/legacy/img/icons/icon_google play music.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_google.ico → searx/static/themes/legacy/img/icons/icon_google.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_kickass.ico → searx/static/themes/legacy/img/icons/icon_kickass.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_openstreetmap.ico → searx/static/themes/legacy/img/icons/icon_openstreetmap.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_searchcode code.ico → searx/static/themes/legacy/img/icons/icon_searchcode code.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_searchcode doc.ico → searx/static/themes/legacy/img/icons/icon_searchcode doc.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_searchcode.ico → searx/static/themes/legacy/img/icons/icon_searchcode.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_soundcloud.ico → searx/static/themes/legacy/img/icons/icon_soundcloud.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_stackoverflow.ico → searx/static/themes/legacy/img/icons/icon_stackoverflow.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_startpage.ico → searx/static/themes/legacy/img/icons/icon_startpage.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_subtitleseeker.ico → searx/static/themes/legacy/img/icons/icon_subtitleseeker.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_twitter.ico → searx/static/themes/legacy/img/icons/icon_twitter.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_vimeo.ico → searx/static/themes/legacy/img/icons/icon_vimeo.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_wikipedia.ico → searx/static/themes/legacy/img/icons/icon_wikipedia.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_yahoo.ico → searx/static/themes/legacy/img/icons/icon_yahoo.icorenamed

Binary file not shown.

searx/static/themes/default/img/icons/icon_youtube.ico → searx/static/themes/legacy/img/icons/icon_youtube.icorenamed

Binary file not shown.

searx/static/themes/default/img/preference-icon.png → searx/static/themes/legacy/img/preference-icon.pngrenamed

Binary file not shown.

searx/static/themes/default/img/search-icon.png → searx/static/themes/legacy/img/search-icon.pngrenamed

Binary file not shown.

searx/static/themes/default/img/searx.png → searx/static/themes/legacy/img/searx.pngrenamed

Binary file not shown.

searx/static/themes/default/img/searx_logo.svg → searx/static/themes/legacy/img/searx_logo.svgrenamed

The content is the same.

searx/static/themes/default/js/searx.js → searx/static/themes/legacy/js/searx.jsrenamed

The content is the same.

searx/static/themes/default/less/autocompleter.less → searx/static/themes/legacy/less/autocompleter.lessrenamed

The content is the same.

searx/static/themes/default/less/code.less → searx/static/themes/legacy/less/code.lessrenamed

The content is the same.

searx/static/themes/default/less/definitions.less → searx/static/themes/legacy/less/definitions.lessrenamed

The content is the same.

searx/static/themes/default/less/mixins.less → searx/static/themes/legacy/less/mixins.lessrenamed

The content is the same.

searx/static/themes/default/less/search.less → searx/static/themes/legacy/less/search.lessrenamed

The content is the same.

searx/static/themes/default/less/style-rtl.less → searx/static/themes/legacy/less/style-rtl.lessrenamed

The content is the same.

searx/static/themes/default/less/style.less → searx/static/themes/legacy/less/style.lessrenamed

The content is the same.

searx/templates/courgette/base.html+1−1
@@ -22,7 +22,7 @@
22 {% endblock %}
22 {% endblock %}
23 {% block meta %}{% endblock %}
23 {% block meta %}{% endblock %}
24 {% block head %}
24 {% block head %}
25− <link title="searx" type="application/opensearchdescription+xml" rel="search" href="{{ url_for('opensearch') }}"/>
25+ <link title="{{ instance_name }}" type="application/opensearchdescription+xml" rel="search" href="{{ url_for('opensearch') }}"/>
26 {% endblock %}
26 {% endblock %}
27 <script type="text/javascript">
27 <script type="text/javascript">
28 searx = {};
28 searx = {};
searx/templates/default/404.html → searx/templates/legacy/404.htmlrenamed+1−1
@@ -1,4 +1,4 @@
1−{% extends "default/base.html" %}
1+{% extends "legacy/base.html" %}
2{% block content %}
2{% block content %}
3<div class="center">
3<div class="center">
4 <h1>{{ _('Page not found') }}</h1>
4 <h1>{{ _('Page not found') }}</h1>
searx/templates/default/about.html → searx/templates/legacy/about.htmlrenamed+2−2
@@ -1,6 +1,6 @@
1−{% extends 'default/base.html' %}
1+{% extends 'legacy/base.html' %}
2{% block content %}
2{% block content %}
3−{% include 'default/github_ribbon.html' %}
3+{% include 'legacy/github_ribbon.html' %}
4<div class="row"{% if rtl %} dir="ltr"{% endif %}>
4<div class="row"{% if rtl %} dir="ltr"{% endif %}>
5 <h1>About <a href="{{ url_for('index') }}">searx</a></h1>
5 <h1>About <a href="{{ url_for('index') }}">searx</a></h1>
6
6
searx/templates/default/base.html → searx/templates/legacy/base.htmlrenamed+1−1
@@ -17,7 +17,7 @@
17 {% endblock %}
17 {% endblock %}
18 {% block meta %}{% endblock %}
18 {% block meta %}{% endblock %}
19 {% block head %}
19 {% block head %}
20− <link title="searx" type="application/opensearchdescription+xml" rel="search" href="{{ url_for('opensearch') }}"/>
20+ <link title="{{ instance_name }}" type="application/opensearchdescription+xml" rel="search" href="{{ url_for('opensearch') }}"/>
21 {% endblock %}
21 {% endblock %}
22 </head>
22 </head>
23 <body>
23 <body>
searx/templates/default/categories.html → searx/templates/legacy/categories.htmlrenamed

The content is the same.

searx/templates/default/github_ribbon.html → searx/templates/legacy/github_ribbon.htmlrenamed

The content is the same.

searx/templates/default/index.html → searx/templates/legacy/index.htmlrenamed+3−3
@@ -1,8 +1,8 @@
1−{% extends "default/base.html" %}
1+{% extends "legacy/base.html" %}
2{% block content %}
2{% block content %}
3<div class="center">
3<div class="center">
4 <div class="title"><h1>searx</h1></div>
4 <div class="title"><h1>searx</h1></div>
5− {% include 'default/search.html' %}
5+ {% include 'legacy/search.html' %}
6 <p class="top_margin">
6 <p class="top_margin">
7 {% if rtl %}
7 {% if rtl %}
8 <a href="{{ url_for('preferences') }}" class="hmarg">{{ _('preferences') }}</a>
8 <a href="{{ url_for('preferences') }}" class="hmarg">{{ _('preferences') }}</a>
@@ -13,6 +13,6 @@
13 {% endif %}
13 {% endif %}
14 </p>
14 </p>
15</div>
15</div>
16−{% include 'default/github_ribbon.html' %}
16+{% include 'legacy/github_ribbon.html' %}
17{% endblock %}
17{% endblock %}
18
18
searx/templates/default/infobox.html → searx/templates/legacy/infobox.htmlrenamed

The content is the same.

searx/templates/default/opensearch.xml → searx/templates/legacy/opensearch.xmlrenamed

The content is the same.

searx/templates/default/opensearch_response_rss.xml → searx/templates/legacy/opensearch_response_rss.xmlrenamed

The content is the same.

searx/templates/default/preferences.html → searx/templates/legacy/preferences.htmlrenamed+2−2
@@ -1,4 +1,4 @@
1−{% extends "default/base.html" %}
1+{% extends "legacy/base.html" %}
2{% block head %} {% endblock %}
2{% block head %} {% endblock %}
3{% block content %}
3{% block content %}
4<div class="row">
4<div class="row">
@@ -8,7 +8,7 @@
8 <fieldset>
8 <fieldset>
9 <legend>{{ _('Default categories') }}</legend>
9 <legend>{{ _('Default categories') }}</legend>
10 {% set display_tooltip = false %}
10 {% set display_tooltip = false %}
11− {% include 'default/categories.html' %}
11+ {% include 'legacy/categories.html' %}
12 </fieldset>
12 </fieldset>
13 <fieldset>
13 <fieldset>
14 <legend>{{ _('Search language') }}</legend>
14 <legend>{{ _('Search language') }}</legend>
searx/templates/default/result_templates/code.html → searx/templates/legacy/result_templates/code.htmlrenamed

The content is the same.

searx/templates/default/result_templates/default.html → searx/templates/legacy/result_templates/default.htmlrenamed

The content is the same.

searx/templates/default/result_templates/images.html → searx/templates/legacy/result_templates/images.htmlrenamed

The content is the same.

searx/templates/default/result_templates/map.html → searx/templates/legacy/result_templates/map.htmlrenamed

The content is the same.

searx/templates/default/result_templates/torrent.html → searx/templates/legacy/result_templates/torrent.htmlrenamed

The content is the same.

searx/templates/default/result_templates/videos.html → searx/templates/legacy/result_templates/videos.htmlrenamed

The content is the same.

searx/templates/default/results.html → searx/templates/legacy/results.htmlrenamed+5−5
@@ -1,10 +1,10 @@
1−{% extends "default/base.html" %}
1+{% extends "legacy/base.html" %}
2{% block title %}{{ q }} - {% endblock %}
2{% block title %}{{ q }} - {% endblock %}
3{% block meta %}<link rel="alternate" type="application/rss+xml" title="Searx search: {{ q }}" href="{{ url_for('index') }}?q={{ q|urlencode }}&amp;format=rss&amp;{% for category in selected_categories %}category_{{ category }}=1&amp;{% endfor %}pageno={{ pageno }}">{% endblock %}
3{% block meta %}<link rel="alternate" type="application/rss+xml" title="Searx search: {{ q }}" href="{{ url_for('index') }}?q={{ q|urlencode }}&amp;format=rss&amp;{% for category in selected_categories %}category_{{ category }}=1&amp;{% endfor %}pageno={{ pageno }}">{% endblock %}
4{% block content %}
4{% block content %}
5<div class="preferences_container right"><a href="{{ url_for('preferences') }}" id="preferences"><span>preferences</span></a></div>
5<div class="preferences_container right"><a href="{{ url_for('preferences') }}" id="preferences"><span>preferences</span></a></div>
6<div class="small search center">
6<div class="small search center">
7− {% include 'default/search.html' %}
7+ {% include 'legacy/search.html' %}
8</div>
8</div>
9<div id="results">
9<div id="results">
10 <div id="sidebar">
10 <div id="sidebar">
@@ -55,16 +55,16 @@
55 {% if infoboxes %}
55 {% if infoboxes %}
56 <div id="infoboxes">
56 <div id="infoboxes">
57 {% for infobox in infoboxes %}
57 {% for infobox in infoboxes %}
58− {% include 'default/infobox.html' %}
58+ {% include 'legacy/infobox.html' %}
59 {% endfor %}
59 {% endfor %}
60 </div>
60 </div>
61 {% endif %}
61 {% endif %}
62
62
63 {% for result in results %}
63 {% for result in results %}
64 {% if result['template'] %}
64 {% if result['template'] %}
65− {% include get_result_template('default', result['template']) %}
65+ {% include get_result_template('legacy', result['template']) %}
66 {% else %}
66 {% else %}
67− {% include 'default/result_templates/default.html' %}
67+ {% include 'legacy/result_templates/default.html' %}
68 {% endif %}
68 {% endif %}
69 {% endfor %}
69 {% endfor %}
70
70
searx/templates/default/search.html → searx/templates/legacy/search.htmlrenamed+1−1
@@ -4,5 +4,5 @@
4 <input type="submit" value="search" id="search_submit" />
4 <input type="submit" value="search" id="search_submit" />
5 </div>
5 </div>
6 {% set display_tooltip = true %}
6 {% set display_tooltip = true %}
7− {% include 'default/categories.html' %}
7+ {% include 'legacy/categories.html' %}
8</form>
8</form>
searx/templates/default/stats.html → searx/templates/legacy/stats.htmlrenamed+1−1
@@ -1,4 +1,4 @@
1−{% extends "default/base.html" %}
1+{% extends "legacy/base.html" %}
2{% block head %} {% endblock %}
2{% block head %} {% endblock %}
3{% block content %}
3{% block content %}
4<h2>{{ _('Engine stats') }}</h2>
4<h2>{{ _('Engine stats') }}</h2>
searx/templates/oscar/macros.html+6
@@ -33,6 +33,9 @@
33 <span class="label label-default">{{ engine }}</span>
33 <span class="label label-default">{{ engine }}</span>
34 {% endfor %}
34 {% endfor %}
35 <small>{{ result_link("https://web.archive.org/web/" + result.url, icon('link') + _('cached'), "text-info") }}</small>
35 <small>{{ result_link("https://web.archive.org/web/" + result.url, icon('link') + _('cached'), "text-info") }}</small>
36+ {% if proxify %}
37+ <small>{{ result_link(proxify(result.url), icon('sort') + _('proxied'), "text-info") }}</small>
38+ {% endif %}
36</div>
39</div>
37 <div class="text-muted"><small>{{ result.pretty_url }}</small></div>
40 <div class="text-muted"><small>{{ result.pretty_url }}</small></div>
38{%- endmacro %}
41{%- endmacro %}
@@ -44,6 +47,9 @@
44 <span class="label label-default">{{ engine }}</span>
47 <span class="label label-default">{{ engine }}</span>
45 {% endfor %}
48 {% endfor %}
46 <small>{{ result_link("https://web.archive.org/web/" + result.url, icon('link') + _('cached'), "text-info") }}</small>
49 <small>{{ result_link("https://web.archive.org/web/" + result.url, icon('link') + _('cached'), "text-info") }}</small>
50+ {% if proxify %}
51+ <small>{{ result_link(proxify(result.url), icon('sort') + _('proxied'), "text-info") }}</small>
52+ {% endif %}
47 <div class="text-muted"><small>{{ result.pretty_url }}</small></div>
53 <div class="text-muted"><small>{{ result.pretty_url }}</small></div>
48{%- endmacro %}
54{%- endmacro %}
49
55
searx/templates/pix-art/preferences.html+1−1
@@ -1,4 +1,4 @@
1−{% extends "default/base.html" %}
1+{% extends "legacy/base.html" %}
2{% block head %} {% endblock %}
2{% block head %} {% endblock %}
3{% block content %}
3{% block content %}
4<div class="row">
4<div class="row">
searx/templates/pix-art/stats.html+1−1
@@ -1,4 +1,4 @@
1−{% extends "default/base.html" %}
1+{% extends "legacy/base.html" %}
2{% block head %} {% endblock %}
2{% block head %} {% endblock %}
3{% block content %}
3{% block content %}
4<h2>{{ _('Engine stats') }}</h2>
4<h2>{{ _('Engine stats') }}</h2>
searx/utils.py+15
@@ -252,12 +252,27 @@ def get_torrent_size(filesize, filesize_multiplier):
252 filesize = int(filesize * 1024 * 1024)
252 filesize = int(filesize * 1024 * 1024)
253 elif filesize_multiplier == 'KB':
253 elif filesize_multiplier == 'KB':
254 filesize = int(filesize * 1024)
254 filesize = int(filesize * 1024)
255+ elif filesize_multiplier == 'TiB':
256+ filesize = int(filesize * 1000 * 1000 * 1000 * 1000)
257+ elif filesize_multiplier == 'GiB':
258+ filesize = int(filesize * 1000 * 1000 * 1000)
259+ elif filesize_multiplier == 'MiB':
260+ filesize = int(filesize * 1000 * 1000)
261+ elif filesize_multiplier == 'KiB':
262+ filesize = int(filesize * 1000)
255 except:
263 except:
256 filesize = None
264 filesize = None
257
265
258 return filesize
266 return filesize
259
267
260
268
269+def convert_str_to_int(number_str):
270+ if number_str.isdigit():
271+ return int(number_str)
272+ else:
273+ return 0
274+
275+
261def is_valid_lang(lang):
276def is_valid_lang(lang):
262 is_abbr = (len(lang) == 2)
277 is_abbr = (len(lang) == 2)
263 if is_abbr:
278 if is_abbr:
searx/webapp.py+22−5
@@ -22,10 +22,11 @@ if __name__ == '__main__':
22 from os.path import realpath, dirname
22 from os.path import realpath, dirname
23 path.append(realpath(dirname(realpath(__file__)) + '/../'))
23 path.append(realpath(dirname(realpath(__file__)) + '/../'))
24
24
25−import json
26import cStringIO
25import cStringIO
27−import os
28import hashlib
26import hashlib
27+import hmac
28+import json
29+import os
29import requests
30import requests
30
31
31from searx import logger
32from searx import logger
@@ -245,6 +246,20 @@ def url_for_theme(endpoint, override_theme=None, **values):
245 return url_for(endpoint, **values)
246 return url_for(endpoint, **values)
246
247
247
248
249+def proxify(url):
250+ if url.startswith('//'):
251+ url = 'https:' + url
252+
253+ if not settings.get('result_proxy'):
254+ return url
255+
256+ h = hmac.new(settings['result_proxy']['key'], url.encode('utf-8'), hashlib.sha256).hexdigest()
257+
258+ return '{0}?{1}'.format(settings['result_proxy']['url'],
259+ urlencode(dict(mortyurl=url.encode('utf-8'),
260+ mortyhash=h)))
261+
262+
248def image_proxify(url):
263def image_proxify(url):
249
264
250 if url.startswith('//'):
265 if url.startswith('//'):
@@ -253,8 +268,7 @@ def image_proxify(url):
253 if not request.preferences.get_value('image_proxy'):
268 if not request.preferences.get_value('image_proxy'):
254 return url
269 return url
255
270
256− hash_string = url + settings['server']['secret_key']
271+ h = hmac.new(settings['server']['secret_key'], url.encode('utf-8'), hashlib.sha256).hexdigest()
257− h = hashlib.sha256(hash_string.encode('utf-8')).hexdigest()
258
272
259 return '{0}?{1}'.format(url_for('image_proxy'),
273 return '{0}?{1}'.format(url_for('image_proxy'),
260 urlencode(dict(url=url.encode('utf-8'), h=h)))
274 urlencode(dict(url=url.encode('utf-8'), h=h)))
@@ -313,6 +327,8 @@ def render(template_name, override_theme=None, **kwargs):
313
327
314 kwargs['image_proxify'] = image_proxify
328 kwargs['image_proxify'] = image_proxify
315
329
330+ kwargs['proxify'] = proxify if settings.get('result_proxy') else None
331+
316 kwargs['get_result_template'] = get_result_template
332 kwargs['get_result_template'] = get_result_template
317
333
318 kwargs['theme'] = get_current_theme_name(override=override_theme)
334 kwargs['theme'] = get_current_theme_name(override=override_theme)
@@ -602,7 +618,7 @@ def image_proxy():
602 if not url:
618 if not url:
603 return '', 400
619 return '', 400
604
620
605− h = hashlib.sha256(url + settings['server']['secret_key'].encode('utf-8')).hexdigest()
621+ h = hmac.new(settings['server']['secret_key'], url, hashlib.sha256).hexdigest()
606
622
607 if h != request.args.get('h'):
623 if h != request.args.get('h'):
608 return '', 400
624 return '', 400
@@ -660,6 +676,7 @@ Allow: /
660Allow: /about
676Allow: /about
661Disallow: /stats
677Disallow: /stats
662Disallow: /preferences
678Disallow: /preferences
679+Disallow: /*?*q=*
663""", mimetype='text/plain')
680""", mimetype='text/plain')
664
681
665
682
tests/robot/test_basic.robot+24−28
@@ -4,6 +4,14 @@ Test Setup Open Browser http://localhost:11111/
4Test Teardown Close All Browsers
4Test Teardown Close All Browsers
5
5
6
6
7+*** Keywords ***
8+Submit Preferences
9+ Set Selenium Speed 2 seconds
10+ Submit Form id=search_form
11+ Location Should Be http://localhost:11111/
12+ Set Selenium Speed 0 seconds
13+
14+
7*** Test Cases ***
15*** Test Cases ***
8Front page
16Front page
9 Page Should Contain about
17 Page Should Contain about
@@ -24,8 +32,8 @@ Preferences page
24 Page Should Contain Preferences
32 Page Should Contain Preferences
25 Page Should Contain Default categories
33 Page Should Contain Default categories
26 Page Should Contain Currently used search engines
34 Page Should Contain Currently used search engines
27− Page Should Contain dummy_dummy
35+ Page Should Contain dummy dummy
28− Page Should Contain general_dummy
36+ Page Should Contain general dummy
29
37
30Switch category
38Switch category
31 Go To http://localhost:11111/preferences
39 Go To http://localhost:11111/preferences
@@ -33,8 +41,7 @@ Switch category
33 Page Should Contain Checkbox category_dummy
41 Page Should Contain Checkbox category_dummy
34 Click Element xpath=//*[.="general"]
42 Click Element xpath=//*[.="general"]
35 Click Element xpath=//*[.="dummy"]
43 Click Element xpath=//*[.="dummy"]
36− Submit Form id=search_form
44+ Submit Preferences
37− Location Should Be http://localhost:11111/
38 Checkbox Should Not Be Selected category_general
45 Checkbox Should Not Be Selected category_general
39 Checkbox Should Be Selected category_dummy
46 Checkbox Should Be Selected category_dummy
40
47
@@ -43,8 +50,7 @@ Change language
43 Page Should Contain preferences
50 Page Should Contain preferences
44 Go To http://localhost:11111/preferences
51 Go To http://localhost:11111/preferences
45 Select From List locale hu
52 Select From List locale hu
46− Submit Form id=search_form
53+ Submit Preferences
47− Location Should Be http://localhost:11111/
48 Page Should Contain rólunk
54 Page Should Contain rólunk
49 Page Should Contain beállítások
55 Page Should Contain beállítások
50
56
@@ -53,13 +59,11 @@ Change method
53 Page Should Contain preferences
59 Page Should Contain preferences
54 Go To http://localhost:11111/preferences
60 Go To http://localhost:11111/preferences
55 Select From List method GET
61 Select From List method GET
56− Submit Form id=search_form
62+ Submit Preferences
57− Location Should Be http://localhost:11111/
58 Go To http://localhost:11111/preferences
63 Go To http://localhost:11111/preferences
59 List Selection Should Be method GET
64 List Selection Should Be method GET
60 Select From List method POST
65 Select From List method POST
61− Submit Form id=search_form
66+ Submit Preferences
62− Location Should Be http://localhost:11111/
63 Go To http://localhost:11111/preferences
67 Go To http://localhost:11111/preferences
64 List Selection Should Be method POST
68 List Selection Should Be method POST
65
69
@@ -67,10 +71,9 @@ Change theme
67 Page Should Contain about
71 Page Should Contain about
68 Page Should Contain preferences
72 Page Should Contain preferences
69 Go To http://localhost:11111/preferences
73 Go To http://localhost:11111/preferences
70− List Selection Should Be theme default
74+ List Selection Should Be theme legacy
71 Select From List theme oscar
75 Select From List theme oscar
72− Submit Form id=search_form
76+ Submit Preferences
73− Location Should Be http://localhost:11111/
74 Go To http://localhost:11111/preferences
77 Go To http://localhost:11111/preferences
75 List Selection Should Be theme oscar
78 List Selection Should Be theme oscar
76
79
@@ -80,8 +83,7 @@ Change safesearch
80 Go To http://localhost:11111/preferences
83 Go To http://localhost:11111/preferences
81 List Selection Should Be safesearch None
84 List Selection Should Be safesearch None
82 Select From List safesearch Strict
85 Select From List safesearch Strict
83− Submit Form id=search_form
86+ Submit Preferences
84− Location Should Be http://localhost:11111/
85 Go To http://localhost:11111/preferences
87 Go To http://localhost:11111/preferences
86 List Selection Should Be safesearch Strict
88 List Selection Should Be safesearch Strict
87
89
@@ -91,8 +93,7 @@ Change image proxy
91 Go To http://localhost:11111/preferences
93 Go To http://localhost:11111/preferences
92 List Selection Should Be image_proxy Disabled
94 List Selection Should Be image_proxy Disabled
93 Select From List image_proxy Enabled
95 Select From List image_proxy Enabled
94− Submit Form id=search_form
96+ Submit Preferences
95− Location Should Be http://localhost:11111/
96 Go To http://localhost:11111/preferences
97 Go To http://localhost:11111/preferences
97 List Selection Should Be image_proxy Enabled
98 List Selection Should Be image_proxy Enabled
98
99
@@ -102,8 +103,7 @@ Change search language
102 Go To http://localhost:11111/preferences
103 Go To http://localhost:11111/preferences
103 List Selection Should Be language Automatic
104 List Selection Should Be language Automatic
104 Select From List language Turkish (Turkey) - tr_TR
105 Select From List language Turkish (Turkey) - tr_TR
105− Submit Form id=search_form
106+ Submit Preferences
106− Location Should Be http://localhost:11111/
107 Go To http://localhost:11111/preferences
107 Go To http://localhost:11111/preferences
108 List Selection Should Be language Turkish (Turkey) - tr_TR
108 List Selection Should Be language Turkish (Turkey) - tr_TR
109
109
@@ -113,8 +113,7 @@ Change autocomplete
113 Go To http://localhost:11111/preferences
113 Go To http://localhost:11111/preferences
114 List Selection Should Be autocomplete -
114 List Selection Should Be autocomplete -
115 Select From List autocomplete google
115 Select From List autocomplete google
116− Submit Form id=search_form
116+ Submit Preferences
117− Location Should Be http://localhost:11111/
118 Go To http://localhost:11111/preferences
117 Go To http://localhost:11111/preferences
119 List Selection Should Be autocomplete google
118 List Selection Should Be autocomplete google
120
119
@@ -126,8 +125,7 @@ Change allowed/disabled engines
126 Element Should Contain xpath=//label[@class="deny"][@for='engine_dummy_dummy_dummy'] Block
125 Element Should Contain xpath=//label[@class="deny"][@for='engine_dummy_dummy_dummy'] Block
127 Element Should Contain xpath=//label[@class="deny"][@for='engine_general_general_dummy'] Block
126 Element Should Contain xpath=//label[@class="deny"][@for='engine_general_general_dummy'] Block
128 Click Element xpath=//label[@class="deny"][@for='engine_general_general_dummy']
127 Click Element xpath=//label[@class="deny"][@for='engine_general_general_dummy']
129− Submit Form id=search_form
128+ Submit Preferences
130− Location Should Be http://localhost:11111/
131 Page Should Contain about
129 Page Should Contain about
132 Page Should Contain preferences
130 Page Should Contain preferences
133 Go To http://localhost:11111/preferences
131 Go To http://localhost:11111/preferences
@@ -139,18 +137,16 @@ Block a plugin
139 Page Should Contain about
137 Page Should Contain about
140 Page Should Contain preferences
138 Page Should Contain preferences
141 Go To http://localhost:11111/preferences
139 Go To http://localhost:11111/preferences
142− List Selection Should Be theme default
140+ List Selection Should Be theme legacy
143 Select From List theme oscar
141 Select From List theme oscar
144− Submit Form id=search_form
142+ Submit Preferences
145− Location Should Be http://localhost:11111/
146 Go To http://localhost:11111/preferences
143 Go To http://localhost:11111/preferences
147 List Selection Should Be theme oscar
144 List Selection Should Be theme oscar
148 Page Should Contain Plugins
145 Page Should Contain Plugins
149 Click Link Plugins
146 Click Link Plugins
150 Checkbox Should Not Be Selected id=plugin_HTTPS_rewrite
147 Checkbox Should Not Be Selected id=plugin_HTTPS_rewrite
151 Click Element xpath=//label[@for='plugin_HTTPS_rewrite']
148 Click Element xpath=//label[@for='plugin_HTTPS_rewrite']
152− Submit Form id=search_form
149+ Submit Preferences
153− Location Should Be http://localhost:11111/
154 Go To http://localhost:11111/preferences
150 Go To http://localhost:11111/preferences
155 Page Should Contain Plugins
151 Page Should Contain Plugins
156 Click Link Plugins
152 Click Link Plugins
tests/unit/engines/seedpeer_fixture.htmlnew file+110
@@ -0,0 +1,110 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2+ <html xmlns="http://www.w3.org/1999/xhtml">
3+ <head>
4+ </head>
5+ <body>
6+ <div id="header">
7+ <div id="whoIsYou">
8+ <a href="/lang.php"><small>SeedPeer in your own language?</small></a>&nbsp;&nbsp;&nbsp;<a href="http://www.seedpeer.eu"><img src="/images/flags/uk.gif" width="16px" alt="Torrents EN" /></a> <a href="http://spanish.seedpeer.eu"><img src="/images/flags/es.gif" width="16px" alt="Torrents ES" /></a> <a href="http://german.seedpeer.eu"><img src="/images/flags/de.gif" width="16px" alt="Torrents DE" /></a> <a href="http://french.seedpeer.eu"><img src="/images/flags/fr.gif" width="16px" alt="Torrents FR" /></a> <a href="http://portuguese.seedpeer.eu"><img src="/images/flags/pt.gif" width="16px" alt="Torrents Portuguese" /></a> <a href="http://swedish.seedpeer.eu"><img src="/images/flags/se.gif" width="16px" alt="Torrents Sweden" /></a>
9+ </div>
10+
11+ <script type="text/javascript">
12+ whoIsYou();
13+ </script>
14+ <div id="search">
15+ <form action="/search.php" method="get">
16+ <input id="topsearchbar" name="search" value="narcos season 2" />
17+ <input type="submit" class="searchbutton" value="Torrents" />
18+ <input style="color:#000" type="submit" class="searchbutton" name="usenet" value="Usenet Binaries" />
19+ </form>
20+ <div id="suggestion"></div>
21+ </div>
22+ <div id="logo"><a href="/"><img src="/images/logo2.gif" alt="Seedpeer homepage" width="415" height="143" /></a></div>
23+ <div id="subtext"><a href="/">Home</a> &gt; <a href="/search.html">Torrent search</a> &gt; Narcos season 2 | page 1</div>
24+ </div>
25+ <div id="nav">
26+ <ul>
27+ <!--
28+ <li><font style="color:red;font-size:9px;font-weight:bold;">NEW</font><a title="Download TOP Games for FREE" rel="nofollow" href="http://www.bigrebelads.com/affiliate/index?ref=9301" target="_blank">FREE Games</a></li>
29+
30+ -->
31+ <li style="border-left:none" id="categories"><a title="Browse Torrent Categories" href="/browse.html">Categories</a>
32+ <ul>
33+ <li><a title="Browse Anime Torrents" href="/browse.html#6">Anime</a></li>
34+ <li><a title="Browse Game Torrents" href="/browse.html#4">Games</a></li>
35+ <li><a title="Browse Movie Torrents" href="/browse.html#1">Movies</a></li>
36+ <li><a title="Browse Music Torrents" href="/browse.html#3">Music</a></li>
37+ <li><a title="Browse Software Torrents" href="/browse.html#5">Software</a></li>
38+ <li><a title="Browse TV Torrents" href="/browse.html#2">TV Shows</a></li>
39+ <li><a title="Browse Other Torrents" href="/browse.html#7">Others</a></li>
40+ </ul>
41+ </li>
42+ <li><a title="Upload A Torrents" href="/upload.html">Upload torrent</a></li>
43+ <li id="verified"><a title="Verified Torrents" href="/verified.html">Verified</a></li>
44+ <li id="searchoptions"><a title="Search Torrents" href="/search.html">Torrent search</a></li>
45+ <li id="newsgroups"><a style="color:#212b3e" title="News Groups" href="/usenet.html">Usenet Binaries</a></li>
46+ <li id="about" style="border-right:none"><a rel="nofollow" href="/faq.html">About Us</a>
47+ <ul>
48+ <li><a title="SeedPeer Statistics" href="/stats.html">Statistics</a></li>
49+ <li><a title="Contact Us" href="/contact.html">Contact</a></li>
50+ <li><a title="Frequently Asked Questions" href="/faq.html">FAQ</a></li>
51+ <li><a title="SeedPeer API" href="http://api.seedpeer.eu">Our API</a></li>
52+ <li><a title="SeedPeer Blog" href="/blog">Blog</a></li>
53+ </ul>
54+ </li>
55+ <!--<li><a href="/toolbar.php">Our Toolbar</a></li>-->
56+ </ul>
57+ <div class="clear"></div>
58+ </div>
59+ <div id="body"><div id="pageTop"></div>
60+ <div id="headerbox"><h1>Verified <font class="colored">Narcos season 2</font> torrents</h1></div><table width="100%"><tr><th>
61+ <span style="float:right">
62+ <a href="/search/narcos-season-2/8/1.html"><img style="vertical-align:middle" src="/images/comments.gif" alt="comments" /></a> |
63+ <a href="/search/narcos-season-2/7/1.html"><img style="vertical-align:middle" src="/images/ver.gif" alt="verified" /></a>
64+ </span>
65+ <a href="/search/narcos-season-2/1/1.html">Torrent name</a></th><th class="right"><a href="/search/narcos-season-2/2/1.html">Age</a></th><th class="right"><a href="/search/narcos-season-2/3/1.html">Size</a></th><th class="right"><a href="/search/narcos-season-2/4/1.html">Seeds</a></th><th class="right"><a href="/search/narcos-season-2/5/1.html">Peers</a></th><th class="center"><a href="/search/narcos-season-2/6/1.html">Health</a></th><td class="tableAd" rowspan="6"><iframe src="http://creative.wwwpromoter.com/13689?d=300x250" width="300" height="250" style="border: none;" frameborder="0" scrolling="no"></iframe></td></tr><tr class=""><td><a class="pblink" id="pblink_table_item_1" href="" data-tad="431726" data-last-search="narcos+season+2" target="_blank" rel="nofollow"><strong class='colored'>Narcos season 2</strong> Full Version</a></td><td class="right">20 hours</td><td class="right">681.3 MB</td><td class="right"><font color="green">28</font> </td><td class="right"><font color="navy">654</font> </td><td class="center"><img src="/images/h5.gif" alt="Health" /></td></tr><tr class="tdark"><td><a class="pblink" id="pblink_table_item_2" href="" data-tad="431727" data-url="narcos+season+2" target="_blank" rel="nofollow"><strong class='colored'>Narcos season 2</strong> Trusted Source</a></td><td class="right">12 hours</td><td class="right">787.1 MB</td><td class="right"><font color="green">64</font> </td><td class="right"><font color="navy">220</font> </td><td class="center"><img src="/images/h5.gif" alt="Health" /></td></tr><tr class=""><td><a class="pblink" id="pblink_table_item_3" href="" data-tad="431729" data-last-search="narcos+season+2" target="_blank" rel="nofollow"><strong class='colored'>Full Narcos season 2 Download</strong></a> <small><a class="pblink" id="pblink_table_item_4" href="" data-tad="431729" data-last-search="narcos+season+2" target="_blank" rel="nofollow">Usenet</a></small></td><td class="right">24 hours</td><td class="right">775.5 MB</td><td class="right"><font color="green">60</font> </td><td class="right"><font color="navy">236</font> </td><td class="center"><img src="/images/h5.gif" alt="Health" /></td></tr><tr class="tdark"><td><a class="pblink" id="pblink_table_item_5" href="" data-tad="431730" data-last-search="narcos+season+2" target="_blank" rel="nofollow"><strong class='colored'>Narcos season 2</strong> 2014 - DIRECT STREAMING</a> <small><a class="pblink" id="pblink_table_item_6" href="" data-tad="431729" data-last-search="narcos+season+2" target="_blank" rel="nofollow">Movies</a></small></td><td class="right">17 hours</td><td class="right">654.1 MB</td><td class="right"><font color="green">2</font> </td><td class="right"><font color="navy">391</font> </td><td class="center"><img src="/images/h5.gif" alt="Health" /></td></tr><tr class=""><td><a class="pblink" id="pblink_table_item_7" href="" data-tad="431731" data-last-search="narcos+season+2" target="_blank" rel="nofollow"><strong class='colored'>Narcos season 2</strong> 2014</a> <small><a class="pblink" id="pblink_table_item_8" href="" data-tad="431729" data-last-search="narcos+season+2" target="_blank" rel="nofollow">Movies</a></small></td><td class="right">20 hours</td><td class="right">754.5 MB</td><td class="right"><font color="green">21</font> </td><td class="right"><font color="navy">919</font> </td><td class="center"><img src="/images/h5.gif" alt="Health" /></td></tr></table><br /><br /><center><iframe src='http://creative.wwwpromoter.com/13689?d=728x90' width='728' height='90' style='border: none;' frameborder='0' scrolling='no'></iframe><center><span style="float:right;margin:1em .2em 0 0"><a title="Download at the speed of your connection" href="/usenet.php?search=narcos+season+2"><img src="/images/dlf.gif" alt="Search Binaries" /></a></span><div style="margin-bottom:1em;margin-right:290px" id="headerbox"><h1><a href="/searchfeed/narcos+season+2.xml" target="_blank" title="SeedPeer RSS Torrent Search Feed fornarcos season 2"><img src="/images/feedIcon.png" border="0" /></a>&nbsp;2 <font class="colored">Narcos season 2</font> Torrents were found</h1></div><table width="100%"><tr><th>
66+ <span style="float:right">
67+ <a href="/search/narcos-season-2/8/1.html"><img style="vertical-align:middle" src="/images/comments.gif" alt="comments" /></a> |
68+ <a href="/search/narcos-season-2/7/1.html"><img style="vertical-align:middle" src="/images/ver.gif" alt="verified" /></a>
69+ </span>
70+ <a href="/search/narcos-season-2/1/1.html">Torrent name</a></th><th class="right"><a href="/search/narcos-season-2/2/1.html">Age</a></th><th class="right"><a href="/search/narcos-season-2/3/1.html">Size</a></th><th class="right"><a href="/search/narcos-season-2/4/1.html">Seeds</a></th><th class="right"><a href="/search/narcos-season-2/5/1.html">Peers</a></th><th class="center"><a href="/search/narcos-season-2/6/1.html">Health</a></th></tr><tr class=""><td><small class="comments"><a href="http://www.facebook.com/sharer.php?t=Download%20<strong class='colored'>Narcos</strong> <strong class='colored'>Season</strong> <strong class='colored'>2</strong> Complete 7<strong class='colored'>2</strong>0p WebRip EN-SUB x<strong class='colored'>2</strong>64-[MULVAcoded] S0<strong class='colored'>2</strong>%20 torrent&u=http://seedpeer.seedpeer.eu/details/11686840/Narcos-Season-2-Complete-720p-WebRip-EN-SUB-x264-[MULVAcoded]-S02.html"><img src="/images/facebook.png" alt="Add to Facebook" width="14" height="14" /></a></small><a href="/details/11686840/Narcos-Season-2-Complete-720p-WebRip-EN-SUB-x264-[MULVAcoded]-S02.html"><strong class='colored'>Narcos</strong> <strong class='colored'>Season</strong> <strong class='colored'>2</strong> Complete 7<strong class='colored'>2</strong>0p WebRip EN-SUB x<strong class='colored'>2</strong>64-[MULVAcoded] S0<strong class='colored'>2</strong> <small><a href="/browse.html#11686840"></a></small></a></td><td class="right">19 hours</td><td class="right">4.39 GB</td><td class="right"><font color="green">715</font> </td><td class="right"><font color="navy">183</font> </td><td class="center"><img src="/images/h5.gif" alt="Health" width="40" height="11" /></td></tr><tr class="tdark"><td><small class="comments"><a href="http://www.facebook.com/sharer.php?t=Download%20<strong class='colored'>Narcos</strong> - <strong class='colored'>Season</strong> <strong class='colored'>2</strong> - 7<strong class='colored'>2</strong>0p WEBRiP - x<strong class='colored'>2</strong>65 HEVC - ShAaNiG%20 torrent&u=http://seedpeer.seedpeer.eu/details/11685972/Narcos---Season-2---720p-WEBRiP---x265-HEVC---ShAaNiG.html"><img src="/images/facebook.png" alt="Add to Facebook" width="14" height="14" /></a></small><a href="/details/11685972/Narcos---Season-2---720p-WEBRiP---x265-HEVC---ShAaNiG.html"><strong class='colored'>Narcos</strong> - <strong class='colored'>Season</strong> <strong class='colored'>2</strong> - 7<strong class='colored'>2</strong>0p WEBRiP - x<strong class='colored'>2</strong>65 HEVC - ShAaNiG <small><a href="/browse.html#11685972"></a></small></a></td><td class="right">1 day</td><td class="right">2.48 GB</td><td class="right"><font color="green">861</font> </td><td class="right"><font color="navy">332</font> </td><td class="center"><img src="/images/h5.gif" alt="Health" width="40" height="11" /></td></tr></table><div id="headerbox"><h1>Related searches for: <font class="colored">Narcos season 2</font></h1></div><div id="search_suggestions"><br />Other suggested searches: </div><br /><a href="http://torrentz2.eu/search?f=narcos-season-2">Search for "narcos-season-2" on Torrentz2.eu</a><br /><a href="http://torrent-finder.info/show.php?q=narcos-season-2">Search for "narcos-season-2" on Torrent-Finder</a><br /><center><iframe src='http://creative.wwwpromoter.com/13689?d=300x250' width='300' height='250' style='border: none;' frameborder='0' scrolling='no'></iframe>&nbsp;<iframe src='http://creative.wwwpromoter.com/13689?d=300x250' width='300' height='250' style='border: none;' frameborder='0' scrolling='no'></iframe>&nbsp;<iframe src='http://creative.wwwpromoter.com/13689?d=300x250' width='300' height='250' style='border: none;' frameborder='0' scrolling='no'></iframe></center><div id="footer">
71+ <table width="100%">
72+ <tr>
73+ <td width="30%">
74+ <h2>Torrents Download</h2>
75+ <a href="/">Torrent search</a><br />
76+ <a href="/browse.html">Browse categories</a><br />
77+ <a href="/verified.html">Verified Torrents</a><br />
78+ <a href="/order-date.html">Today's torrents</a><br />
79+ <a href="/yesterday.html">Yesterday's torrents</a><br />
80+ <a href="/stats.html">Statistics</a><br />
81+ <br />
82+ <a href="/faq.html#copyright"><strong>Copyright & Removal</strong></a>
83+ </td>
84+ <td width="30%"><h2>Cool Stuff</h2>
85+ <a href="/promotional.php">Promotional</a><br />
86+ <a href="/contact.html">Advertising Information</a><br />
87+ <strong><a href="/plugins.php" title="Add a search plugin to Firefox or Internet Explorer">Search Plugin <span style="color:red">*</span></a></strong><br />
88+ <a href="http://www.utorrent.com">&micro;Torrent Client</a><br />
89+ <a href="/blog">Seedpeer Blog</a><br />
90+ </td>
91+ <td width="30%"><h2>Links</h2>
92+ <a href="http://www.sumotorrent.com" target="_blank"><strong>SumoTorrent</strong></a><br />
93+ <a href="http://www.torrent-finder.info" target="_blank"><strong>Torrent Finder</strong></a><br />
94+ <a href="http://www.torrentpond.com" target="_blank"><strong>TorrentPond</strong></a><br />
95+ <a href="https://www.limetorrents.cc" target="_blank">LimeTorrents.cc</a><br />
96+ <a href="http://www.torrents.to/" target="_blank">Torrents.to</a><br />
97+ <a href="http://www.torrentfunk.com" target="_blank">TorrentFunk</a><br />
98+ <a href="https://monova.org" target="_blank">Monova</a><br />
99+ <a href="http://www.torrentroom.com" target="_blank">TorrentRoom</a><br />
100+ <a href="http://www.katcr.co/" target="_blank">Kickass Torrents Community</a><br />
101+ </td>
102+ <td width="10%"><div id="bottomlogo"></div></td>
103+ </tr>
104+ </table>
105+ <br />
106+ <br />
107+ </div>
108+ </div>
109+ </body>
110+ </html>
tests/unit/engines/test_digbt.py+3−1
@@ -28,7 +28,9 @@ class TestDigBTEngine(SearxTestCase):
28 <table class="table">
28 <table class="table">
29 <tr><td class="x-item">
29 <tr><td class="x-item">
30 <div>
30 <div>
31− <a title="The Big Bang Theory" class="title" href="/The-Big-Bang-Theory-d2.html">The Big Bang Theory</a>
31+ <a title="The Big Bang Theory" class="title" href="/The-Big-Bang-Theory-d2.html">
32+ The Big <span class="highlight">Bang</span> Theory
33+ </a>
32 <span class="ctime"><span style="color:red;">4 hours ago</span></span>
34 <span class="ctime"><span style="color:red;">4 hours ago</span></span>
33 </div>
35 </div>
34 <div class="files">
36 <div class="files">
tests/unit/engines/test_kickass.py+13−13
@@ -14,7 +14,7 @@ class TestKickassEngine(SearxTestCase):
14 params = kickass.request(query, dicto)
14 params = kickass.request(query, dicto)
15 self.assertIn('url', params)
15 self.assertIn('url', params)
16 self.assertIn(query, params['url'])
16 self.assertIn(query, params['url'])
17− self.assertIn('kickass.to', params['url'])
17+ self.assertIn('kickass.cd', params['url'])
18 self.assertFalse(params['verify'])
18 self.assertFalse(params['verify'])
19
19
20 def test_response(self):
20 def test_response(self):
@@ -84,7 +84,7 @@ class TestKickassEngine(SearxTestCase):
84 </span>
84 </span>
85 </div>
85 </div>
86 </td>
86 </td>
87− <td class="nobr center">449 <span>bytes</span></td>
87+ <td class="nobr center">449 bytes</td>
88 <td class="center">4</td>
88 <td class="center">4</td>
89 <td class="center">2&nbsp;years</td>
89 <td class="center">2&nbsp;years</td>
90 <td class="green center">10</td>
90 <td class="green center">10</td>
@@ -97,7 +97,7 @@ class TestKickassEngine(SearxTestCase):
97 self.assertEqual(type(results), list)
97 self.assertEqual(type(results), list)
98 self.assertEqual(len(results), 1)
98 self.assertEqual(len(results), 1)
99 self.assertEqual(results[0]['title'], 'This should be the title')
99 self.assertEqual(results[0]['title'], 'This should be the title')
100− self.assertEqual(results[0]['url'], 'https://kickass.to/url.html')
100+ self.assertEqual(results[0]['url'], 'https://kickass.cd/url.html')
101 self.assertEqual(results[0]['content'], 'Posted by riri in Other &gt; Unsorted')
101 self.assertEqual(results[0]['content'], 'Posted by riri in Other &gt; Unsorted')
102 self.assertEqual(results[0]['seed'], 10)
102 self.assertEqual(results[0]['seed'], 10)
103 self.assertEqual(results[0]['leech'], 1)
103 self.assertEqual(results[0]['leech'], 1)
@@ -191,7 +191,7 @@ class TestKickassEngine(SearxTestCase):
191 </span>
191 </span>
192 </div>
192 </div>
193 </td>
193 </td>
194− <td class="nobr center">1 <span>KB</span></td>
194+ <td class="nobr center">1 KiB</td>
195 <td class="center">4</td>
195 <td class="center">4</td>
196 <td class="center">2&nbsp;years</td>
196 <td class="center">2&nbsp;years</td>
197 <td class="green center">10</td>
197 <td class="green center">10</td>
@@ -235,7 +235,7 @@ class TestKickassEngine(SearxTestCase):
235 </span>
235 </span>
236 </div>
236 </div>
237 </td>
237 </td>
238− <td class="nobr center">1 <span>MB</span></td>
238+ <td class="nobr center">1 MiB</td>
239 <td class="center">4</td>
239 <td class="center">4</td>
240 <td class="center">2&nbsp;years</td>
240 <td class="center">2&nbsp;years</td>
241 <td class="green center">9</td>
241 <td class="green center">9</td>
@@ -279,7 +279,7 @@ class TestKickassEngine(SearxTestCase):
279 </span>
279 </span>
280 </div>
280 </div>
281 </td>
281 </td>
282− <td class="nobr center">1 <span>GB</span></td>
282+ <td class="nobr center">1 GiB</td>
283 <td class="center">4</td>
283 <td class="center">4</td>
284 <td class="center">2&nbsp;years</td>
284 <td class="center">2&nbsp;years</td>
285 <td class="green center">8</td>
285 <td class="green center">8</td>
@@ -323,7 +323,7 @@ class TestKickassEngine(SearxTestCase):
323 </span>
323 </span>
324 </div>
324 </div>
325 </td>
325 </td>
326− <td class="nobr center">1 <span>TB</span></td>
326+ <td class="nobr center">1 TiB</td>
327 <td class="center">4</td>
327 <td class="center">4</td>
328 <td class="center">2&nbsp;years</td>
328 <td class="center">2&nbsp;years</td>
329 <td class="green center">7</td>
329 <td class="green center">7</td>
@@ -367,7 +367,7 @@ class TestKickassEngine(SearxTestCase):
367 </span>
367 </span>
368 </div>
368 </div>
369 </td>
369 </td>
370− <td class="nobr center">z <span>bytes</span></td>
370+ <td class="nobr center">z bytes</td>
371 <td class="center">r</td>
371 <td class="center">r</td>
372 <td class="center">2&nbsp;years</td>
372 <td class="center">2&nbsp;years</td>
373 <td class="green center">a</td>
373 <td class="green center">a</td>
@@ -380,17 +380,17 @@ class TestKickassEngine(SearxTestCase):
380 self.assertEqual(type(results), list)
380 self.assertEqual(type(results), list)
381 self.assertEqual(len(results), 5)
381 self.assertEqual(len(results), 5)
382 self.assertEqual(results[0]['title'], 'This should be the title')
382 self.assertEqual(results[0]['title'], 'This should be the title')
383− self.assertEqual(results[0]['url'], 'https://kickass.to/url.html')
383+ self.assertEqual(results[0]['url'], 'https://kickass.cd/url.html')
384 self.assertEqual(results[0]['content'], 'Posted by riri in Other &gt; Unsorted')
384 self.assertEqual(results[0]['content'], 'Posted by riri in Other &gt; Unsorted')
385 self.assertEqual(results[0]['seed'], 10)
385 self.assertEqual(results[0]['seed'], 10)
386 self.assertEqual(results[0]['leech'], 1)
386 self.assertEqual(results[0]['leech'], 1)
387 self.assertEqual(results[0]['files'], 4)
387 self.assertEqual(results[0]['files'], 4)
388 self.assertEqual(results[0]['magnetlink'], 'magnet:?xt=urn:btih:MAGNETURL&dn=test')
388 self.assertEqual(results[0]['magnetlink'], 'magnet:?xt=urn:btih:MAGNETURL&dn=test')
389 self.assertEqual(results[0]['torrentfile'], 'http://torcache.net/torrent/53917.torrent?title=test')
389 self.assertEqual(results[0]['torrentfile'], 'http://torcache.net/torrent/53917.torrent?title=test')
390− self.assertEqual(results[0]['filesize'], 1024)
390+ self.assertEqual(results[0]['filesize'], 1000)
391− self.assertEqual(results[1]['filesize'], 1048576)
391+ self.assertEqual(results[1]['filesize'], 1000000)
392− self.assertEqual(results[2]['filesize'], 1073741824)
392+ self.assertEqual(results[2]['filesize'], 1000000000)
393− self.assertEqual(results[3]['filesize'], 1099511627776)
393+ self.assertEqual(results[3]['filesize'], 1000000000000)
394 self.assertEqual(results[4]['seed'], 0)
394 self.assertEqual(results[4]['seed'], 0)
395 self.assertEqual(results[4]['leech'], 0)
395 self.assertEqual(results[4]['leech'], 0)
396 self.assertEqual(results[4]['files'], None)
396 self.assertEqual(results[4]['files'], None)
tests/unit/engines/test_pdbe.pynew file+109
@@ -0,0 +1,109 @@
1+import mock
2+from collections import defaultdict
3+from searx.engines import pdbe
4+from searx.testing import SearxTestCase
5+
6+
7+class TestPdbeEngine(SearxTestCase):
8+ def test_request(self):
9+ query = 'test_query'
10+ dicto = defaultdict(dict)
11+ params = pdbe.request(query, dicto)
12+ self.assertTrue('url' in params)
13+ self.assertTrue('ebi.ac.uk' in params['url'])
14+ self.assertTrue('data' in params)
15+ self.assertTrue('q' in params['data'])
16+ self.assertTrue(query in params['data']['q'])
17+ self.assertTrue('wt' in params['data'])
18+ self.assertTrue('json' in params['data']['wt'])
19+ self.assertTrue('method' in params)
20+ self.assertTrue(params['method'] == 'POST')
21+
22+ def test_response(self):
23+ self.assertRaises(AttributeError, pdbe.response, None)
24+ self.assertRaises(AttributeError, pdbe.response, [])
25+ self.assertRaises(AttributeError, pdbe.response, '')
26+ self.assertRaises(AttributeError, pdbe.response, '[]')
27+
28+ json = """
29+{
30+ "response": {
31+ "docs": [
32+ {
33+ "citation_title": "X-ray crystal structure of ferric Aplysia limacina myoglobin in different liganded states.",
34+ "citation_year": 1993,
35+ "entry_author_list": [
36+ "Conti E, Moser C, Rizzi M, Mattevi A, Lionetti C, Coda A, Ascenzi P, Brunori M, Bolognesi M"
37+ ],
38+ "journal": "J. Mol. Biol.",
39+ "journal_page": "498-508",
40+ "journal_volume": "233",
41+ "pdb_id": "2fal",
42+ "status": "REL",
43+ "title": "X-RAY CRYSTAL STRUCTURE OF FERRIC APLYSIA LIMACINA MYOGLOBIN IN DIFFERENT LIGANDED STATES"
44+ }
45+ ],
46+ "numFound": 1,
47+ "start": 0
48+ },
49+ "responseHeader": {
50+ "QTime": 0,
51+ "params": {
52+ "q": "2fal",
53+ "wt": "json"
54+ },
55+ "status": 0
56+ }
57+}
58+"""
59+
60+ response = mock.Mock(text=json)
61+ results = pdbe.response(response)
62+ self.assertEqual(type(results), list)
63+ self.assertEqual(len(results), 1)
64+ self.assertEqual(results[0]['title'],
65+ 'X-RAY CRYSTAL STRUCTURE OF FERRIC APLYSIA LIMACINA MYOGLOBIN IN DIFFERENT LIGANDED STATES')
66+ self.assertEqual(results[0]['url'], pdbe.pdbe_entry_url.format(pdb_id='2fal'))
67+ self.assertEqual(results[0]['img_src'], pdbe.pdbe_preview_url.format(pdb_id='2fal'))
68+ self.assertTrue('Conti E' in results[0]['content'])
69+ self.assertTrue('X-ray crystal structure of ferric Aplysia limacina myoglobin in different liganded states.' in
70+ results[0]['content'])
71+ self.assertTrue('1993' in results[0]['content'])
72+
73+ # Testing proper handling of PDB entries marked as obsolete
74+ json = """
75+{
76+ "response": {
77+ "docs": [
78+ {
79+ "citation_title": "Obsolete entry test",
80+ "citation_year": 2016,
81+ "entry_author_list": ["Doe J"],
82+ "journal": "J. Obs.",
83+ "journal_page": "1-2",
84+ "journal_volume": "1",
85+ "pdb_id": "xxxx",
86+ "status": "OBS",
87+ "title": "OBSOLETE ENTRY TEST",
88+ "superseded_by": "yyyy"
89+ }
90+ ],
91+ "numFound": 1,
92+ "start": 0
93+ },
94+ "responseHeader": {
95+ "QTime": 0,
96+ "params": {
97+ "q": "xxxx",
98+ "wt": "json"
99+ },
100+ "status": 0
101+ }
102+}
103+"""
104+ response = mock.Mock(text=json)
105+ results = pdbe.response(response)
106+ self.assertEqual(type(results), list)
107+ self.assertEqual(len(results), 1)
108+ self.assertEqual(results[0]['title'], 'OBSOLETE ENTRY TEST&nbsp;(OBSOLETE)')
109+ self.assertTrue(results[0]['content'].startswith('<em>This entry has been superseded by'))
tests/unit/engines/test_seedpeer.pynew file+51
@@ -0,0 +1,51 @@
1+import mock
2+from collections import defaultdict
3+from searx.engines import seedpeer
4+from searx.testing import SearxTestCase
5+from datetime import datetime
6+
7+
8+class TestSeedPeerEngine(SearxTestCase):
9+
10+ html = ''
11+ with open('./tests/unit/engines/seedpeer_fixture.html') as fixture:
12+ html += fixture.read()
13+
14+ def test_request(self):
15+ query = 'test_query'
16+ dicto = defaultdict(dict)
17+ dicto['pageno'] = 1
18+ params = seedpeer.request(query, dicto)
19+ self.assertIn('url', params)
20+ self.assertIn(query, params['url'])
21+ self.assertIn('seedpeer.eu', params['url'])
22+
23+ def test_response_raises_attr_error_on_empty_response(self):
24+ self.assertRaises(AttributeError, seedpeer.response, None)
25+ self.assertRaises(AttributeError, seedpeer.response, [])
26+ self.assertRaises(AttributeError, seedpeer.response, '')
27+ self.assertRaises(AttributeError, seedpeer.response, '[]')
28+
29+ def test_response_returns_empty_list(self):
30+ response = mock.Mock(text='<html></html>')
31+ self.assertEqual(seedpeer.response(response), [])
32+
33+ def test_response_returns_all_results(self):
34+ response = mock.Mock(text=self.html)
35+ results = seedpeer.response(response)
36+ self.assertTrue(isinstance(results, list))
37+ self.assertEqual(len(results), 2)
38+
39+ def test_response_returns_correct_results(self):
40+ response = mock.Mock(text=self.html)
41+ results = seedpeer.response(response)
42+ self.assertEqual(
43+ results[0]['title'], 'Narcos - Season 2 - 720p WEBRiP - x265 HEVC - ShAaNiG '
44+ )
45+ self.assertEqual(
46+ results[0]['url'],
47+ 'http://www.seedpeer.eu/details/11685972/Narcos---Season-2---720p-WEBRiP---x265-HEVC---ShAaNiG.html'
48+ )
49+ self.assertEqual(results[0]['content'], '2.48 GB, 1 day')
50+ self.assertEqual(results[0]['seed'], '861')
51+ self.assertEqual(results[0]['leech'], '332')
tests/unit/test_webapp.py+2−2
@@ -44,7 +44,7 @@ class ViewsTestCase(SearxTestCase):
44 webapp.Search.search = search_mock
44 webapp.Search.search = search_mock
45
45
46 def get_current_theme_name_mock(override=None):
46 def get_current_theme_name_mock(override=None):
47− return 'default'
47+ return 'legacy'
48
48
49 webapp.get_current_theme_name = get_current_theme_name_mock
49 webapp.get_current_theme_name = get_current_theme_name_mock
50
50
@@ -58,7 +58,7 @@ class ViewsTestCase(SearxTestCase):
58 def test_index_html(self):
58 def test_index_html(self):
59 result = self.app.post('/', data={'q': 'test'})
59 result = self.app.post('/', data={'q': 'test'})
60 self.assertIn(
60 self.assertIn(
61− '<h3 class="result_title"><img width="14" height="14" class="favicon" src="/static/themes/default/img/icons/icon_youtube.ico" alt="youtube" /><a href="http://second.test.xyz" rel="noreferrer">Second <span class="highlight">Test</span></a></h3>', # noqa
61+ '<h3 class="result_title"><img width="14" height="14" class="favicon" src="/static/themes/legacy/img/icons/icon_youtube.ico" alt="youtube" /><a href="http://second.test.xyz" rel="noreferrer">Second <span class="highlight">Test</span></a></h3>', # noqa
62 result.data
62 result.data
63 )
63 )
64 self.assertIn(
64 self.assertIn(