on master help sign in
Merge branch 'master' into http1.1
commita88768efd8ee6b832febda8508cb1ba3c8778b94 authorAlexandre Flament <alex@al-f.net> dateSat 22 Oct 2016, 14:25 (10 years ago) parentf90eb4285c7237
87 files changed+624−117
.travis.yml+5 AUTHORS.rst+2 manage.sh+2−2 requirements-dev.txt+3−3 requirements.txt+1−1 searx/engines/__init__.py+9−3 searx/engines/digbt.py+1−1 searx/engines/kickass.py+11−35 searx/engines/pdbe.py+109 searx/engines/seedpeer.py+78 searx/settings.yml+26−1 searx/settings_robot.yml+3−3 searx/static/themes/default/css/style-rtl.css → searx/static/themes/legacy/css/style-rtl.css searx/static/themes/default/css/style.css → searx/static/themes/legacy/css/style.css searx/static/themes/default/img/favicon.png → searx/static/themes/legacy/img/favicon.png searx/static/themes/default/img/github_ribbon.png → searx/static/themes/legacy/img/github_ribbon.png searx/static/themes/default/img/icons/icon_500px.ico → searx/static/themes/legacy/img/icons/icon_500px.ico searx/static/themes/default/img/icons/icon_bing.ico → searx/static/themes/legacy/img/icons/icon_bing.ico searx/static/themes/default/img/icons/icon_dailymotion.ico → searx/static/themes/legacy/img/icons/icon_dailymotion.ico searx/static/themes/default/img/icons/icon_deezer.ico → searx/static/themes/legacy/img/icons/icon_deezer.ico searx/static/themes/default/img/icons/icon_deviantart.ico → searx/static/themes/legacy/img/icons/icon_deviantart.ico searx/static/themes/default/img/icons/icon_digg.ico → searx/static/themes/legacy/img/icons/icon_digg.ico searx/static/themes/default/img/icons/icon_duckduckgo.ico → searx/static/themes/legacy/img/icons/icon_duckduckgo.ico searx/static/themes/default/img/icons/icon_flickr.ico → searx/static/themes/legacy/img/icons/icon_flickr.ico searx/static/themes/default/img/icons/icon_github.ico → searx/static/themes/legacy/img/icons/icon_github.ico searx/static/themes/default/img/icons/icon_google play apps.ico → searx/static/themes/legacy/img/icons/icon_google play apps.ico searx/static/themes/default/img/icons/icon_google play movies.ico → searx/static/themes/legacy/img/icons/icon_google play movies.ico searx/static/themes/default/img/icons/icon_google play music.ico → searx/static/themes/legacy/img/icons/icon_google play music.ico searx/static/themes/default/img/icons/icon_google.ico → searx/static/themes/legacy/img/icons/icon_google.ico searx/static/themes/default/img/icons/icon_kickass.ico → searx/static/themes/legacy/img/icons/icon_kickass.ico searx/static/themes/default/img/icons/icon_openstreetmap.ico → searx/static/themes/legacy/img/icons/icon_openstreetmap.ico searx/static/themes/default/img/icons/icon_searchcode code.ico → searx/static/themes/legacy/img/icons/icon_searchcode code.ico searx/static/themes/default/img/icons/icon_searchcode doc.ico → searx/static/themes/legacy/img/icons/icon_searchcode doc.ico searx/static/themes/default/img/icons/icon_searchcode.ico → searx/static/themes/legacy/img/icons/icon_searchcode.ico searx/static/themes/default/img/icons/icon_soundcloud.ico → searx/static/themes/legacy/img/icons/icon_soundcloud.ico searx/static/themes/default/img/icons/icon_stackoverflow.ico → searx/static/themes/legacy/img/icons/icon_stackoverflow.ico searx/static/themes/default/img/icons/icon_startpage.ico → searx/static/themes/legacy/img/icons/icon_startpage.ico searx/static/themes/default/img/icons/icon_subtitleseeker.ico → searx/static/themes/legacy/img/icons/icon_subtitleseeker.ico searx/static/themes/default/img/icons/icon_twitter.ico → searx/static/themes/legacy/img/icons/icon_twitter.ico searx/static/themes/default/img/icons/icon_vimeo.ico → searx/static/themes/legacy/img/icons/icon_vimeo.ico searx/static/themes/default/img/icons/icon_wikipedia.ico → searx/static/themes/legacy/img/icons/icon_wikipedia.ico searx/static/themes/default/img/icons/icon_yahoo.ico → searx/static/themes/legacy/img/icons/icon_yahoo.ico searx/static/themes/default/img/icons/icon_youtube.ico → searx/static/themes/legacy/img/icons/icon_youtube.ico searx/static/themes/default/img/preference-icon.png → searx/static/themes/legacy/img/preference-icon.png searx/static/themes/default/img/search-icon.png → searx/static/themes/legacy/img/search-icon.png searx/static/themes/default/img/searx.png → searx/static/themes/legacy/img/searx.png searx/static/themes/default/img/searx_logo.svg → searx/static/themes/legacy/img/searx_logo.svg searx/static/themes/default/js/searx.js → searx/static/themes/legacy/js/searx.js searx/static/themes/default/less/autocompleter.less → searx/static/themes/legacy/less/autocompleter.less searx/static/themes/default/less/code.less → searx/static/themes/legacy/less/code.less searx/static/themes/default/less/definitions.less → searx/static/themes/legacy/less/definitions.less searx/static/themes/default/less/mixins.less → searx/static/themes/legacy/less/mixins.less searx/static/themes/default/less/search.less → searx/static/themes/legacy/less/search.less searx/static/themes/default/less/style-rtl.less → searx/static/themes/legacy/less/style-rtl.less searx/static/themes/default/less/style.less → searx/static/themes/legacy/less/style.less searx/templates/courgette/base.html+1−1 searx/templates/default/404.html → searx/templates/legacy/404.html+1−1 searx/templates/default/about.html → searx/templates/legacy/about.html+2−2 searx/templates/default/base.html → searx/templates/legacy/base.html+1−1 searx/templates/default/categories.html → searx/templates/legacy/categories.html searx/templates/default/github_ribbon.html → searx/templates/legacy/github_ribbon.html searx/templates/default/index.html → searx/templates/legacy/index.html+3−3 searx/templates/default/infobox.html → searx/templates/legacy/infobox.html searx/templates/default/opensearch.xml → searx/templates/legacy/opensearch.xml searx/templates/default/opensearch_response_rss.xml → searx/templates/legacy/opensearch_response_rss.xml searx/templates/default/preferences.html → searx/templates/legacy/preferences.html+2−2 searx/templates/default/result_templates/code.html → searx/templates/legacy/result_templates/code.html searx/templates/default/result_templates/default.html → searx/templates/legacy/result_templates/default.html searx/templates/default/result_templates/images.html → searx/templates/legacy/result_templates/images.html searx/templates/default/result_templates/map.html → searx/templates/legacy/result_templates/map.html searx/templates/default/result_templates/torrent.html → searx/templates/legacy/result_templates/torrent.html searx/templates/default/result_templates/videos.html → searx/templates/legacy/result_templates/videos.html searx/templates/default/results.html → searx/templates/legacy/results.html+5−5 searx/templates/default/search.html → searx/templates/legacy/search.html+1−1 searx/templates/default/stats.html → searx/templates/legacy/stats.html+1−1 searx/templates/oscar/macros.html+6 searx/templates/pix-art/preferences.html+1−1 searx/templates/pix-art/stats.html+1−1 searx/utils.py+15 searx/webapp.py+22−5 tests/robot/test_basic.robot+24−28 tests/unit/engines/seedpeer_fixture.html+110 tests/unit/engines/test_digbt.py+3−1 tests/unit/engines/test_kickass.py+13−13 tests/unit/engines/test_pdbe.py+109 tests/unit/engines/test_seedpeer.py+51 tests/unit/test_webapp.py+2−2
.travis.yml+5
@@ -4,6 +4,8 @@ cache:
44 - npm
55 - directories:
66 - $HOME/.cache/pip
7+addons:
8+ firefox: "latest"
79language: python
810python:
911 - "2.7"
@@ -12,6 +14,9 @@ before_install:
1214 - "sh -e /etc/init.d/xvfb start"
1315 - npm install less grunt-cli
1416 - ( 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;
1520install:
1621 - ./manage.sh update_dev_packages
1722 - pip install coveralls
AUTHORS.rst+2
@@ -58,3 +58,5 @@ generally made searx better:
5858- marc @a01200356
5959- Harry Wood @harry-wood
6060- 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() {
5353
5454styles() {
5555 echo '[!] Building styles'
56− build_style themes/default/less/style.less themes/default/css/style.css
57− build_style themes/default/less/style-rtl.less themes/default/css/style-rtl.css
56+ build_style themes/legacy/less/style.less themes/legacy/css/style.css
57+ build_style themes/legacy/less/style-rtl.less themes/legacy/css/style-rtl.css
5858 build_style themes/courgette/less/style.less themes/courgette/css/style.css
5959 build_style themes/courgette/less/style-rtl.less themes/courgette/css/style-rtl.css
6060 build_style less/bootstrap/bootstrap.less css/bootstrap.min.css
requirements-dev.txt+3−3
@@ -3,8 +3,8 @@ mock==2.0.0
33nose2[coverage-plugin]
44pep8==1.7.0
55plone.testing==5.0.0
6−robotframework-selenium2library==1.7.4
6+robotframework-selenium2library==1.8.0
77robotsuite==1.7.0
8−transifex-client==0.11
8+transifex-client==0.12.2
99unittest2==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
22flask==0.11.1
33flask-babel==0.11.1
44lxml==3.6.0
searx/engines/__init__.py+9−3
@@ -57,11 +57,17 @@ def load_module(filename):
5757
5858
5959def load_engine(engine_data):
60− engine_name = engine_data['engine']
60+
61+ if '_' in engine_data['name']:
62+ logger.error('Engine name conains underscore: "{}"'.format(engine_data['name']))
63+ sys.exit(1)
64+
65+ engine_module = engine_data['engine']
66+
6167 try:
62− engine = load_module(engine_name + '.py')
68+ engine = load_module(engine_module + '.py')
6369 except:
64− logger.exception('Cannot load engine "{}"'.format(engine_name))
70+ logger.exception('Cannot load engine "{}"'.format(engine_module))
6571 return None
6672
6773 for param_name in engine_data:
searx/engines/digbt.py+1−1
@@ -40,7 +40,7 @@ def response(resp):
4040 results = list()
4141 for result in search_res:
4242 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]'))
4444 content = extract_text(result.xpath('.//div[@class="files"]'))
4545 files_data = extract_text(result.xpath('.//div[@class="tail"]')).split()
4646 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
1616from lxml import html
1717from operator import itemgetter
1818from searx.engines.xpath import extract_text
19+from searx.utils import get_torrent_size, convert_str_to_int
1920
2021# engine dependent config
2122categories = ['videos', 'music', 'files']
2223paging = True
2324
2425# search-url
25−url = 'https://kickass.to/'
26+url = 'https://kickass.cd/'
2627search_url = url + 'search/{search_term}/{pageno}/'
2728
2829# specific xpath variables
@@ -57,41 +58,16 @@ def response(resp):
5758 href = urljoin(url, link.attrib['href'])
5859 title = extract_text(link)
5960 content = escape(extract_text(result.xpath(content_xpath)))
60− seed = result.xpath('.//td[contains(@class, "green")]/text()')[0]
61− leech = result.xpath('.//td[contains(@class, "red")]/text()')[0]
62− filesize = result.xpath('.//td[contains(@class, "nobr")]/text()')[0]
63− filesize_multiplier = result.xpath('.//td[contains(@class, "nobr")]//span/text()')[0]
64− files = result.xpath('.//td[contains(@class, "center")][2]/text()')[0]
65−
66− # convert seed to int if possible
67− if seed.isdigit():
68− seed = int(seed)
69− else:
70− seed = 0
61+ seed = extract_text(result.xpath('.//td[contains(@class, "green")]'))
62+ leech = extract_text(result.xpath('.//td[contains(@class, "red")]'))
63+ filesize_info = extract_text(result.xpath('.//td[contains(@class, "nobr")]'))
64+ files = extract_text(result.xpath('.//td[contains(@class, "center")][2]'))
7165
72− # convert leech to int if possible
73− if leech.isdigit():
74− leech = int(leech)
75− else:
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':
90− filesize = int(filesize * 1024)
91− except:
92− filesize = None
93−
94− # convert files to int if possible
66+ seed = convert_str_to_int(seed)
67+ leech = convert_str_to_int(leech)
68+
69+ filesize, filesize_multiplier = filesize_info.split()
70+ filesize = get_torrent_size(filesize, filesize_multiplier)
9571 if files.isdigit():
9672 files = int(files)
9773 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:
1818 default_theme : oscar # ui theme
1919 default_locale : "" # Default interface locale - leave blank to detect from browser information or use codes from the 'locales' config section
2020
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+
2127outgoing: # communication with search engines
2228 request_timeout : 2.0 # seconds
2329 useragent_suffix : "" # suffix of searx_useragent, could contain informations like an email address to the administrator
@@ -301,6 +307,12 @@ engines:
301307 timeout : 6.0
302308 disabled : True
303309
310+ - name: kickass
311+ engine : kickass
312+ shortcut : kc
313+ timeout : 4.0
314+ disabled : True
315+
304316 - name : microsoft academic
305317 engine : json_engine
306318 paging : True
@@ -339,6 +351,13 @@ engines:
339351 disabled : True
340352 shortcut : or
341353
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+
342361 - name : photon
343362 engine : photon
344363 shortcut : ph
@@ -377,7 +396,7 @@ engines:
377396 timeout : 10.0
378397 disabled : True
379398
380− - name : scanr_structures
399+ - name : scanr structures
381400 shortcut: scs
382401 engine : scanr_structures
383402 disabled : True
@@ -495,6 +514,12 @@ engines:
495514 timeout: 6.0
496515 categories : science
497516
517+ - name : seedpeer
518+ engine : seedpeer
519+ shortcut: speu
520+ categories: files, music, videos
521+ disabled: True
522+
498523 - name : dictzone
499524 engine : dictzone
500525 shortcut : dc
searx/settings_robot.yml+3−3
@@ -15,7 +15,7 @@ server:
1515
1616ui:
1717 themes_path : ""
18− default_theme : default
18+ default_theme : legacy
1919 default_locale : ""
2020
2121outgoing:
@@ -23,12 +23,12 @@ outgoing:
2323 useragent_suffix : ""
2424
2525engines:
26− - name : general_dummy
26+ - name : general dummy
2727 engine : dummy
2828 categories : general
2929 shortcut : gd
3030
31− - name : dummy_dummy
31+ - name : dummy dummy
3232 engine : dummy
3333 categories : dummy
3434 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 @@
2222 {% endblock %}
2323 {% block meta %}{% endblock %}
2424 {% 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') }}"/>
2626 {% endblock %}
2727 <script type="text/javascript">
2828 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" %}
22{% block content %}
33<div class="center">
44 <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' %}
22{% block content %}
3−{% include 'default/github_ribbon.html' %}
3+{% include 'legacy/github_ribbon.html' %}
44<div class="row"{% if rtl %} dir="ltr"{% endif %}>
55 <h1>About <a href="{{ url_for('index') }}">searx</a></h1>
66
searx/templates/default/base.html → searx/templates/legacy/base.htmlrenamed+1−1
@@ -17,7 +17,7 @@
1717 {% endblock %}
1818 {% block meta %}{% endblock %}
1919 {% 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') }}"/>
2121 {% endblock %}
2222 </head>
2323 <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" %}
22{% block content %}
33<div class="center">
44 <div class="title"><h1>searx</h1></div>
5− {% include 'default/search.html' %}
5+ {% include 'legacy/search.html' %}
66 <p class="top_margin">
77 {% if rtl %}
88 <a href="{{ url_for('preferences') }}" class="hmarg">{{ _('preferences') }}</a>
@@ -13,6 +13,6 @@
1313 {% endif %}
1414 </p>
1515</div>
16−{% include 'default/github_ribbon.html' %}
16+{% include 'legacy/github_ribbon.html' %}
1717{% endblock %}
1818
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" %}
22{% block head %} {% endblock %}
33{% block content %}
44<div class="row">
@@ -8,7 +8,7 @@
88 <fieldset>
99 <legend>{{ _('Default categories') }}</legend>
1010 {% set display_tooltip = false %}
11− {% include 'default/categories.html' %}
11+ {% include 'legacy/categories.html' %}
1212 </fieldset>
1313 <fieldset>
1414 <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" %}
22{% block title %}{{ q }} - {% endblock %}
33{% 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 %}
44{% block content %}
55<div class="preferences_container right"><a href="{{ url_for('preferences') }}" id="preferences"><span>preferences</span></a></div>
66<div class="small search center">
7− {% include 'default/search.html' %}
7+ {% include 'legacy/search.html' %}
88</div>
99<div id="results">
1010 <div id="sidebar">
@@ -55,16 +55,16 @@
5555 {% if infoboxes %}
5656 <div id="infoboxes">
5757 {% for infobox in infoboxes %}
58− {% include 'default/infobox.html' %}
58+ {% include 'legacy/infobox.html' %}
5959 {% endfor %}
6060 </div>
6161 {% endif %}
6262
6363 {% for result in results %}
6464 {% if result['template'] %}
65− {% include get_result_template('default', result['template']) %}
65+ {% include get_result_template('legacy', result['template']) %}
6666 {% else %}
67− {% include 'default/result_templates/default.html' %}
67+ {% include 'legacy/result_templates/default.html' %}
6868 {% endif %}
6969 {% endfor %}
7070
searx/templates/default/search.html → searx/templates/legacy/search.htmlrenamed+1−1
@@ -4,5 +4,5 @@
44 <input type="submit" value="search" id="search_submit" />
55 </div>
66 {% set display_tooltip = true %}
7− {% include 'default/categories.html' %}
7+ {% include 'legacy/categories.html' %}
88</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" %}
22{% block head %} {% endblock %}
33{% block content %}
44<h2>{{ _('Engine stats') }}</h2>
searx/templates/oscar/macros.html+6
@@ -33,6 +33,9 @@
3333 <span class="label label-default">{{ engine }}</span>
3434 {% endfor %}
3535 <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 %}
3639</div>
3740 <div class="text-muted"><small>{{ result.pretty_url }}</small></div>
3841{%- endmacro %}
@@ -44,6 +47,9 @@
4447 <span class="label label-default">{{ engine }}</span>
4548 {% endfor %}
4649 <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 %}
4753 <div class="text-muted"><small>{{ result.pretty_url }}</small></div>
4854{%- endmacro %}
4955
searx/templates/pix-art/preferences.html+1−1
@@ -1,4 +1,4 @@
1−{% extends "default/base.html" %}
1+{% extends "legacy/base.html" %}
22{% block head %} {% endblock %}
33{% block content %}
44<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" %}
22{% block head %} {% endblock %}
33{% block content %}
44<h2>{{ _('Engine stats') }}</h2>
searx/utils.py+15
@@ -252,12 +252,27 @@ def get_torrent_size(filesize, filesize_multiplier):
252252 filesize = int(filesize * 1024 * 1024)
253253 elif filesize_multiplier == 'KB':
254254 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)
255263 except:
256264 filesize = None
257265
258266 return filesize
259267
260268
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+
261276def is_valid_lang(lang):
262277 is_abbr = (len(lang) == 2)
263278 if is_abbr:
searx/webapp.py+22−5
@@ -22,10 +22,11 @@ if __name__ == '__main__':
2222 from os.path import realpath, dirname
2323 path.append(realpath(dirname(realpath(__file__)) + '/../'))
2424
25−import json
2625import cStringIO
27−import os
2826import hashlib
27+import hmac
28+import json
29+import os
2930import requests
3031
3132from searx import logger
@@ -245,6 +246,20 @@ def url_for_theme(endpoint, override_theme=None, **values):
245246 return url_for(endpoint, **values)
246247
247248
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+
248263def image_proxify(url):
249264
250265 if url.startswith('//'):
@@ -253,8 +268,7 @@ def image_proxify(url):
253268 if not request.preferences.get_value('image_proxy'):
254269 return url
255270
256− hash_string = url + settings['server']['secret_key']
257− h = hashlib.sha256(hash_string.encode('utf-8')).hexdigest()
271+ h = hmac.new(settings['server']['secret_key'], url.encode('utf-8'), hashlib.sha256).hexdigest()
258272
259273 return '{0}?{1}'.format(url_for('image_proxy'),
260274 urlencode(dict(url=url.encode('utf-8'), h=h)))
@@ -313,6 +327,8 @@ def render(template_name, override_theme=None, **kwargs):
313327
314328 kwargs['image_proxify'] = image_proxify
315329
330+ kwargs['proxify'] = proxify if settings.get('result_proxy') else None
331+
316332 kwargs['get_result_template'] = get_result_template
317333
318334 kwargs['theme'] = get_current_theme_name(override=override_theme)
@@ -602,7 +618,7 @@ def image_proxy():
602618 if not url:
603619 return '', 400
604620
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()
606622
607623 if h != request.args.get('h'):
608624 return '', 400
@@ -660,6 +676,7 @@ Allow: /
660676Allow: /about
661677Disallow: /stats
662678Disallow: /preferences
679+Disallow: /*?*q=*
663680""", mimetype='text/plain')
664681
665682
tests/robot/test_basic.robot+24−28
@@ -4,6 +4,14 @@ Test Setup Open Browser http://localhost:11111/
44Test Teardown Close All Browsers
55
66
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+
715*** Test Cases ***
816Front page
917 Page Should Contain about
@@ -24,8 +32,8 @@ Preferences page
2432 Page Should Contain Preferences
2533 Page Should Contain Default categories
2634 Page Should Contain Currently used search engines
27− Page Should Contain dummy_dummy
28− Page Should Contain general_dummy
35+ Page Should Contain dummy dummy
36+ Page Should Contain general dummy
2937
3038Switch category
3139 Go To http://localhost:11111/preferences
@@ -33,8 +41,7 @@ Switch category
3341 Page Should Contain Checkbox category_dummy
3442 Click Element xpath=//*[.="general"]
3543 Click Element xpath=//*[.="dummy"]
36− Submit Form id=search_form
37− Location Should Be http://localhost:11111/
44+ Submit Preferences
3845 Checkbox Should Not Be Selected category_general
3946 Checkbox Should Be Selected category_dummy
4047
@@ -43,8 +50,7 @@ Change language
4350 Page Should Contain preferences
4451 Go To http://localhost:11111/preferences
4552 Select From List locale hu
46− Submit Form id=search_form
47− Location Should Be http://localhost:11111/
53+ Submit Preferences
4854 Page Should Contain rólunk
4955 Page Should Contain beállítások
5056
@@ -53,13 +59,11 @@ Change method
5359 Page Should Contain preferences
5460 Go To http://localhost:11111/preferences
5561 Select From List method GET
56− Submit Form id=search_form
57− Location Should Be http://localhost:11111/
62+ Submit Preferences
5863 Go To http://localhost:11111/preferences
5964 List Selection Should Be method GET
6065 Select From List method POST
61− Submit Form id=search_form
62− Location Should Be http://localhost:11111/
66+ Submit Preferences
6367 Go To http://localhost:11111/preferences
6468 List Selection Should Be method POST
6569
@@ -67,10 +71,9 @@ Change theme
6771 Page Should Contain about
6872 Page Should Contain preferences
6973 Go To http://localhost:11111/preferences
70− List Selection Should Be theme default
74+ List Selection Should Be theme legacy
7175 Select From List theme oscar
72− Submit Form id=search_form
73− Location Should Be http://localhost:11111/
76+ Submit Preferences
7477 Go To http://localhost:11111/preferences
7578 List Selection Should Be theme oscar
7679
@@ -80,8 +83,7 @@ Change safesearch
8083 Go To http://localhost:11111/preferences
8184 List Selection Should Be safesearch None
8285 Select From List safesearch Strict
83− Submit Form id=search_form
84− Location Should Be http://localhost:11111/
86+ Submit Preferences
8587 Go To http://localhost:11111/preferences
8688 List Selection Should Be safesearch Strict
8789
@@ -91,8 +93,7 @@ Change image proxy
9193 Go To http://localhost:11111/preferences
9294 List Selection Should Be image_proxy Disabled
9395 Select From List image_proxy Enabled
94− Submit Form id=search_form
95− Location Should Be http://localhost:11111/
96+ Submit Preferences
9697 Go To http://localhost:11111/preferences
9798 List Selection Should Be image_proxy Enabled
9899
@@ -102,8 +103,7 @@ Change search language
102103 Go To http://localhost:11111/preferences
103104 List Selection Should Be language Automatic
104105 Select From List language Turkish (Turkey) - tr_TR
105− Submit Form id=search_form
106− Location Should Be http://localhost:11111/
106+ Submit Preferences
107107 Go To http://localhost:11111/preferences
108108 List Selection Should Be language Turkish (Turkey) - tr_TR
109109
@@ -113,8 +113,7 @@ Change autocomplete
113113 Go To http://localhost:11111/preferences
114114 List Selection Should Be autocomplete -
115115 Select From List autocomplete google
116− Submit Form id=search_form
117− Location Should Be http://localhost:11111/
116+ Submit Preferences
118117 Go To http://localhost:11111/preferences
119118 List Selection Should Be autocomplete google
120119
@@ -126,8 +125,7 @@ Change allowed/disabled engines
126125 Element Should Contain xpath=//label[@class="deny"][@for='engine_dummy_dummy_dummy'] Block
127126 Element Should Contain xpath=//label[@class="deny"][@for='engine_general_general_dummy'] Block
128127 Click Element xpath=//label[@class="deny"][@for='engine_general_general_dummy']
129− Submit Form id=search_form
130− Location Should Be http://localhost:11111/
128+ Submit Preferences
131129 Page Should Contain about
132130 Page Should Contain preferences
133131 Go To http://localhost:11111/preferences
@@ -139,18 +137,16 @@ Block a plugin
139137 Page Should Contain about
140138 Page Should Contain preferences
141139 Go To http://localhost:11111/preferences
142− List Selection Should Be theme default
140+ List Selection Should Be theme legacy
143141 Select From List theme oscar
144− Submit Form id=search_form
145− Location Should Be http://localhost:11111/
142+ Submit Preferences
146143 Go To http://localhost:11111/preferences
147144 List Selection Should Be theme oscar
148145 Page Should Contain Plugins
149146 Click Link Plugins
150147 Checkbox Should Not Be Selected id=plugin_HTTPS_rewrite
151148 Click Element xpath=//label[@for='plugin_HTTPS_rewrite']
152− Submit Form id=search_form
153− Location Should Be http://localhost:11111/
149+ Submit Preferences
154150 Go To http://localhost:11111/preferences
155151 Page Should Contain Plugins
156152 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):
2828 <table class="table">
2929 <tr><td class="x-item">
3030 <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>
3234 <span class="ctime"><span style="color:red;">4 hours ago</span></span>
3335 </div>
3436 <div class="files">
tests/unit/engines/test_kickass.py+13−13
@@ -14,7 +14,7 @@ class TestKickassEngine(SearxTestCase):
1414 params = kickass.request(query, dicto)
1515 self.assertIn('url', params)
1616 self.assertIn(query, params['url'])
17− self.assertIn('kickass.to', params['url'])
17+ self.assertIn('kickass.cd', params['url'])
1818 self.assertFalse(params['verify'])
1919
2020 def test_response(self):
@@ -84,7 +84,7 @@ class TestKickassEngine(SearxTestCase):
8484 </span>
8585 </div>
8686 </td>
87− <td class="nobr center">449 <span>bytes</span></td>
87+ <td class="nobr center">449 bytes</td>
8888 <td class="center">4</td>
8989 <td class="center">2&nbsp;years</td>
9090 <td class="green center">10</td>
@@ -97,7 +97,7 @@ class TestKickassEngine(SearxTestCase):
9797 self.assertEqual(type(results), list)
9898 self.assertEqual(len(results), 1)
9999 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')
101101 self.assertEqual(results[0]['content'], 'Posted by riri in Other &gt; Unsorted')
102102 self.assertEqual(results[0]['seed'], 10)
103103 self.assertEqual(results[0]['leech'], 1)
@@ -191,7 +191,7 @@ class TestKickassEngine(SearxTestCase):
191191 </span>
192192 </div>
193193 </td>
194− <td class="nobr center">1 <span>KB</span></td>
194+ <td class="nobr center">1 KiB</td>
195195 <td class="center">4</td>
196196 <td class="center">2&nbsp;years</td>
197197 <td class="green center">10</td>
@@ -235,7 +235,7 @@ class TestKickassEngine(SearxTestCase):
235235 </span>
236236 </div>
237237 </td>
238− <td class="nobr center">1 <span>MB</span></td>
238+ <td class="nobr center">1 MiB</td>
239239 <td class="center">4</td>
240240 <td class="center">2&nbsp;years</td>
241241 <td class="green center">9</td>
@@ -279,7 +279,7 @@ class TestKickassEngine(SearxTestCase):
279279 </span>
280280 </div>
281281 </td>
282− <td class="nobr center">1 <span>GB</span></td>
282+ <td class="nobr center">1 GiB</td>
283283 <td class="center">4</td>
284284 <td class="center">2&nbsp;years</td>
285285 <td class="green center">8</td>
@@ -323,7 +323,7 @@ class TestKickassEngine(SearxTestCase):
323323 </span>
324324 </div>
325325 </td>
326− <td class="nobr center">1 <span>TB</span></td>
326+ <td class="nobr center">1 TiB</td>
327327 <td class="center">4</td>
328328 <td class="center">2&nbsp;years</td>
329329 <td class="green center">7</td>
@@ -367,7 +367,7 @@ class TestKickassEngine(SearxTestCase):
367367 </span>
368368 </div>
369369 </td>
370− <td class="nobr center">z <span>bytes</span></td>
370+ <td class="nobr center">z bytes</td>
371371 <td class="center">r</td>
372372 <td class="center">2&nbsp;years</td>
373373 <td class="green center">a</td>
@@ -380,17 +380,17 @@ class TestKickassEngine(SearxTestCase):
380380 self.assertEqual(type(results), list)
381381 self.assertEqual(len(results), 5)
382382 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')
384384 self.assertEqual(results[0]['content'], 'Posted by riri in Other &gt; Unsorted')
385385 self.assertEqual(results[0]['seed'], 10)
386386 self.assertEqual(results[0]['leech'], 1)
387387 self.assertEqual(results[0]['files'], 4)
388388 self.assertEqual(results[0]['magnetlink'], 'magnet:?xt=urn:btih:MAGNETURL&dn=test')
389389 self.assertEqual(results[0]['torrentfile'], 'http://torcache.net/torrent/53917.torrent?title=test')
390− self.assertEqual(results[0]['filesize'], 1024)
391− self.assertEqual(results[1]['filesize'], 1048576)
392− self.assertEqual(results[2]['filesize'], 1073741824)
393− self.assertEqual(results[3]['filesize'], 1099511627776)
390+ self.assertEqual(results[0]['filesize'], 1000)
391+ self.assertEqual(results[1]['filesize'], 1000000)
392+ self.assertEqual(results[2]['filesize'], 1000000000)
393+ self.assertEqual(results[3]['filesize'], 1000000000000)
394394 self.assertEqual(results[4]['seed'], 0)
395395 self.assertEqual(results[4]['leech'], 0)
396396 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):
4444 webapp.Search.search = search_mock
4545
4646 def get_current_theme_name_mock(override=None):
47− return 'default'
47+ return 'legacy'
4848
4949 webapp.get_current_theme_name = get_current_theme_name_mock
5050
@@ -58,7 +58,7 @@ class ViewsTestCase(SearxTestCase):
5858 def test_index_html(self):
5959 result = self.app.post('/', data={'q': 'test'})
6060 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
6262 result.data
6363 )
6464 self.assertIn(