logo

searx

My custom branche(s) on searx, a meta-search engine git clone https://hacktivis.me/git/searx.git
commit: a88768efd8ee6b832febda8508cb1ba3c8778b94
parent f90eb428c679d3852d9738f6279d045283340562
Author: Alexandre Flament <alex@al-f.net>
Date:   Sat, 22 Oct 2016 14:25:50 +0200

Merge branch 'master' into http1.1

Diffstat:

M.travis.yml5+++++
MAUTHORS.rst2++
Mmanage.sh4++--
Mrequirements-dev.txt6+++---
Mrequirements.txt2+-
Msearx/engines/__init__.py12+++++++++---
Msearx/engines/digbt.py2+-
Msearx/engines/kickass.py46+++++++++++-----------------------------------
Asearx/engines/pdbe.py109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asearx/engines/seedpeer.py78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msearx/settings.yml27++++++++++++++++++++++++++-
Msearx/settings_robot.yml6+++---
Rsearx/static/themes/default/css/style-rtl.css -> searx/static/themes/legacy/css/style-rtl.css0
Rsearx/static/themes/default/css/style.css -> searx/static/themes/legacy/css/style.css0
Rsearx/static/themes/default/img/favicon.png -> searx/static/themes/legacy/img/favicon.png0
Rsearx/static/themes/default/img/github_ribbon.png -> searx/static/themes/legacy/img/github_ribbon.png0
Rsearx/static/themes/default/img/icons/icon_500px.ico -> searx/static/themes/legacy/img/icons/icon_500px.ico0
Rsearx/static/themes/default/img/icons/icon_bing.ico -> searx/static/themes/legacy/img/icons/icon_bing.ico0
Rsearx/static/themes/default/img/icons/icon_dailymotion.ico -> searx/static/themes/legacy/img/icons/icon_dailymotion.ico0
Rsearx/static/themes/default/img/icons/icon_deezer.ico -> searx/static/themes/legacy/img/icons/icon_deezer.ico0
Rsearx/static/themes/default/img/icons/icon_deviantart.ico -> searx/static/themes/legacy/img/icons/icon_deviantart.ico0
Rsearx/static/themes/default/img/icons/icon_digg.ico -> searx/static/themes/legacy/img/icons/icon_digg.ico0
Rsearx/static/themes/default/img/icons/icon_duckduckgo.ico -> searx/static/themes/legacy/img/icons/icon_duckduckgo.ico0
Rsearx/static/themes/default/img/icons/icon_flickr.ico -> searx/static/themes/legacy/img/icons/icon_flickr.ico0
Rsearx/static/themes/default/img/icons/icon_github.ico -> searx/static/themes/legacy/img/icons/icon_github.ico0
Rsearx/static/themes/default/img/icons/icon_google play apps.ico -> searx/static/themes/legacy/img/icons/icon_google play apps.ico0
Rsearx/static/themes/default/img/icons/icon_google play movies.ico -> searx/static/themes/legacy/img/icons/icon_google play movies.ico0
Rsearx/static/themes/default/img/icons/icon_google play music.ico -> searx/static/themes/legacy/img/icons/icon_google play music.ico0
Rsearx/static/themes/default/img/icons/icon_google.ico -> searx/static/themes/legacy/img/icons/icon_google.ico0
Rsearx/static/themes/default/img/icons/icon_kickass.ico -> searx/static/themes/legacy/img/icons/icon_kickass.ico0
Rsearx/static/themes/default/img/icons/icon_openstreetmap.ico -> searx/static/themes/legacy/img/icons/icon_openstreetmap.ico0
Rsearx/static/themes/default/img/icons/icon_searchcode code.ico -> searx/static/themes/legacy/img/icons/icon_searchcode code.ico0
Rsearx/static/themes/default/img/icons/icon_searchcode doc.ico -> searx/static/themes/legacy/img/icons/icon_searchcode doc.ico0
Rsearx/static/themes/default/img/icons/icon_searchcode.ico -> searx/static/themes/legacy/img/icons/icon_searchcode.ico0
Rsearx/static/themes/default/img/icons/icon_soundcloud.ico -> searx/static/themes/legacy/img/icons/icon_soundcloud.ico0
Rsearx/static/themes/default/img/icons/icon_stackoverflow.ico -> searx/static/themes/legacy/img/icons/icon_stackoverflow.ico0
Rsearx/static/themes/default/img/icons/icon_startpage.ico -> searx/static/themes/legacy/img/icons/icon_startpage.ico0
Rsearx/static/themes/default/img/icons/icon_subtitleseeker.ico -> searx/static/themes/legacy/img/icons/icon_subtitleseeker.ico0
Rsearx/static/themes/default/img/icons/icon_twitter.ico -> searx/static/themes/legacy/img/icons/icon_twitter.ico0
Rsearx/static/themes/default/img/icons/icon_vimeo.ico -> searx/static/themes/legacy/img/icons/icon_vimeo.ico0
Rsearx/static/themes/default/img/icons/icon_wikipedia.ico -> searx/static/themes/legacy/img/icons/icon_wikipedia.ico0
Rsearx/static/themes/default/img/icons/icon_yahoo.ico -> searx/static/themes/legacy/img/icons/icon_yahoo.ico0
Rsearx/static/themes/default/img/icons/icon_youtube.ico -> searx/static/themes/legacy/img/icons/icon_youtube.ico0
Rsearx/static/themes/default/img/preference-icon.png -> searx/static/themes/legacy/img/preference-icon.png0
Rsearx/static/themes/default/img/search-icon.png -> searx/static/themes/legacy/img/search-icon.png0
Rsearx/static/themes/default/img/searx.png -> searx/static/themes/legacy/img/searx.png0
Rsearx/static/themes/default/img/searx_logo.svg -> searx/static/themes/legacy/img/searx_logo.svg0
Rsearx/static/themes/default/js/searx.js -> searx/static/themes/legacy/js/searx.js0
Rsearx/static/themes/default/less/autocompleter.less -> searx/static/themes/legacy/less/autocompleter.less0
Rsearx/static/themes/default/less/code.less -> searx/static/themes/legacy/less/code.less0
Rsearx/static/themes/default/less/definitions.less -> searx/static/themes/legacy/less/definitions.less0
Rsearx/static/themes/default/less/mixins.less -> searx/static/themes/legacy/less/mixins.less0
Rsearx/static/themes/default/less/search.less -> searx/static/themes/legacy/less/search.less0
Rsearx/static/themes/default/less/style-rtl.less -> searx/static/themes/legacy/less/style-rtl.less0
Rsearx/static/themes/default/less/style.less -> searx/static/themes/legacy/less/style.less0
Msearx/templates/courgette/base.html2+-
Dsearx/templates/default/404.html9---------
Dsearx/templates/default/about.html66------------------------------------------------------------------
Dsearx/templates/default/base.html38--------------------------------------
Dsearx/templates/default/index.html18------------------
Dsearx/templates/default/preferences.html129-------------------------------------------------------------------------------
Dsearx/templates/default/results.html100-------------------------------------------------------------------------------
Dsearx/templates/default/search.html8--------
Dsearx/templates/default/stats.html22----------------------
Asearx/templates/legacy/404.html9+++++++++
Asearx/templates/legacy/about.html66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asearx/templates/legacy/base.html38++++++++++++++++++++++++++++++++++++++
Rsearx/templates/default/categories.html -> searx/templates/legacy/categories.html0
Rsearx/templates/default/github_ribbon.html -> searx/templates/legacy/github_ribbon.html0
Asearx/templates/legacy/index.html18++++++++++++++++++
Rsearx/templates/default/infobox.html -> searx/templates/legacy/infobox.html0
Rsearx/templates/default/opensearch.xml -> searx/templates/legacy/opensearch.xml0
Rsearx/templates/default/opensearch_response_rss.xml -> searx/templates/legacy/opensearch_response_rss.xml0
Asearx/templates/legacy/preferences.html129+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rsearx/templates/default/result_templates/code.html -> searx/templates/legacy/result_templates/code.html0
Rsearx/templates/default/result_templates/default.html -> searx/templates/legacy/result_templates/default.html0
Rsearx/templates/default/result_templates/images.html -> searx/templates/legacy/result_templates/images.html0
Rsearx/templates/default/result_templates/map.html -> searx/templates/legacy/result_templates/map.html0
Rsearx/templates/default/result_templates/torrent.html -> searx/templates/legacy/result_templates/torrent.html0
Rsearx/templates/default/result_templates/videos.html -> searx/templates/legacy/result_templates/videos.html0
Asearx/templates/legacy/results.html100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asearx/templates/legacy/search.html8++++++++
Asearx/templates/legacy/stats.html22++++++++++++++++++++++
Msearx/templates/oscar/macros.html6++++++
Msearx/templates/pix-art/preferences.html2+-
Msearx/templates/pix-art/stats.html2+-
Msearx/utils.py15+++++++++++++++
Msearx/webapp.py27++++++++++++++++++++++-----
Mtests/robot/test_basic.robot52++++++++++++++++++++++++----------------------------
Atests/unit/engines/seedpeer_fixture.html111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtests/unit/engines/test_digbt.py4+++-
Mtests/unit/engines/test_kickass.py26+++++++++++++-------------
Atests/unit/engines/test_pdbe.py109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/unit/engines/test_seedpeer.py51+++++++++++++++++++++++++++++++++++++++++++++++++++
Mtests/unit/test_webapp.py4++--
95 files changed, 999 insertions(+), 491 deletions(-)

diff --git a/.travis.yml b/.travis.yml @@ -4,6 +4,8 @@ cache: - npm - directories: - $HOME/.cache/pip +addons: + firefox: "latest" language: python python: - "2.7" @@ -12,6 +14,9 @@ before_install: - "sh -e /etc/init.d/xvfb start" - npm install less grunt-cli - ( cd searx/static/themes/oscar;npm install; cd - ) + - mkdir -p ~/drivers; export PATH=~/drivers:$PATH; + - GECKODRIVER_URL="https://github.com/mozilla/geckodriver/releases/download/v0.11.1/geckodriver-v0.11.1-linux64.tar.gz"; + - FILE=`mktemp`; wget "$GECKODRIVER_URL" -qO $FILE && tar xz -C ~/drivers -f $FILE geckodriver; rm $FILE; chmod 777 ~/drivers/geckodriver; install: - ./manage.sh update_dev_packages - pip install coveralls diff --git a/AUTHORS.rst b/AUTHORS.rst @@ -58,3 +58,5 @@ generally made searx better: - marc @a01200356 - Harry Wood @harry-wood - Thomas Renard @threnard +- Pydo `<https://github.com/pydo>`_ +- Athemis `<https://github.com/Athemis>`_ diff --git a/manage.sh b/manage.sh @@ -53,8 +53,8 @@ build_style() { styles() { echo '[!] Building styles' - build_style themes/default/less/style.less themes/default/css/style.css - build_style themes/default/less/style-rtl.less themes/default/css/style-rtl.css + build_style themes/legacy/less/style.less themes/legacy/css/style.css + build_style themes/legacy/less/style-rtl.less themes/legacy/css/style-rtl.css build_style themes/courgette/less/style.less themes/courgette/css/style.css build_style themes/courgette/less/style-rtl.less themes/courgette/css/style-rtl.css build_style less/bootstrap/bootstrap.less css/bootstrap.min.css diff --git a/requirements-dev.txt b/requirements-dev.txt @@ -3,8 +3,8 @@ mock==2.0.0 nose2[coverage-plugin] pep8==1.7.0 plone.testing==5.0.0 -robotframework-selenium2library==1.7.4 +robotframework-selenium2library==1.8.0 robotsuite==1.7.0 -transifex-client==0.11 +transifex-client==0.12.2 unittest2==1.1.0 -zope.testrunner==4.4.10 +zope.testrunner==4.5.1 diff --git a/requirements.txt b/requirements.txt @@ -1,4 +1,4 @@ -certifi==2016.2.28 +certifi==2016.9.26 flask==0.11.1 flask-babel==0.11.1 lxml==3.6.0 diff --git a/searx/engines/__init__.py b/searx/engines/__init__.py @@ -57,11 +57,17 @@ def load_module(filename): def load_engine(engine_data): - engine_name = engine_data['engine'] + + if '_' in engine_data['name']: + logger.error('Engine name conains underscore: "{}"'.format(engine_data['name'])) + sys.exit(1) + + engine_module = engine_data['engine'] + try: - engine = load_module(engine_name + '.py') + engine = load_module(engine_module + '.py') except: - logger.exception('Cannot load engine "{}"'.format(engine_name)) + logger.exception('Cannot load engine "{}"'.format(engine_module)) return None for param_name in engine_data: diff --git a/searx/engines/digbt.py b/searx/engines/digbt.py @@ -40,7 +40,7 @@ def response(resp): results = list() for result in search_res: url = urljoin(URL, result.xpath('.//a[@title]/@href')[0]) - title = result.xpath('.//a[@title]/text()')[0] + title = extract_text(result.xpath('.//a[@title]')) content = extract_text(result.xpath('.//div[@class="files"]')) files_data = extract_text(result.xpath('.//div[@class="tail"]')).split() filesize = get_torrent_size(files_data[FILESIZE], files_data[FILESIZE_MULTIPLIER]) diff --git a/searx/engines/kickass.py b/searx/engines/kickass.py @@ -16,13 +16,14 @@ from urllib import quote from lxml import html from operator import itemgetter from searx.engines.xpath import extract_text +from searx.utils import get_torrent_size, convert_str_to_int # engine dependent config categories = ['videos', 'music', 'files'] paging = True # search-url -url = 'https://kickass.to/' +url = 'https://kickass.cd/' search_url = url + 'search/{search_term}/{pageno}/' # specific xpath variables @@ -57,41 +58,16 @@ def response(resp): href = urljoin(url, link.attrib['href']) title = extract_text(link) content = escape(extract_text(result.xpath(content_xpath))) - seed = result.xpath('.//td[contains(@class, "green")]/text()')[0] - leech = result.xpath('.//td[contains(@class, "red")]/text()')[0] - filesize = result.xpath('.//td[contains(@class, "nobr")]/text()')[0] - filesize_multiplier = result.xpath('.//td[contains(@class, "nobr")]//span/text()')[0] - files = result.xpath('.//td[contains(@class, "center")][2]/text()')[0] - - # convert seed to int if possible - if seed.isdigit(): - seed = int(seed) - else: - seed = 0 + seed = extract_text(result.xpath('.//td[contains(@class, "green")]')) + leech = extract_text(result.xpath('.//td[contains(@class, "red")]')) + filesize_info = extract_text(result.xpath('.//td[contains(@class, "nobr")]')) + files = extract_text(result.xpath('.//td[contains(@class, "center")][2]')) - # convert leech to int if possible - if leech.isdigit(): - leech = int(leech) - else: - leech = 0 - - # convert filesize to byte if possible - try: - filesize = float(filesize) - - # convert filesize to byte - if filesize_multiplier == 'TB': - filesize = int(filesize * 1024 * 1024 * 1024 * 1024) - elif filesize_multiplier == 'GB': - filesize = int(filesize * 1024 * 1024 * 1024) - elif filesize_multiplier == 'MB': - filesize = int(filesize * 1024 * 1024) - elif filesize_multiplier == 'KB': - filesize = int(filesize * 1024) - except: - filesize = None - - # convert files to int if possible + seed = convert_str_to_int(seed) + leech = convert_str_to_int(leech) + + filesize, filesize_multiplier = filesize_info.split() + filesize = get_torrent_size(filesize, filesize_multiplier) if files.isdigit(): files = int(files) else: diff --git a/searx/engines/pdbe.py b/searx/engines/pdbe.py @@ -0,0 +1,109 @@ +""" + PDBe (Protein Data Bank in Europe) + + @website https://www.ebi.ac.uk/pdbe + @provide-api yes (https://www.ebi.ac.uk/pdbe/api/doc/search.html), + unlimited + @using-api yes + @results python dictionary (from json) + @stable yes + @parse url, title, content, img_src +""" + +from json import loads +from flask_babel import gettext + +categories = ['science'] + +hide_obsolete = False + +# status codes of unpublished entries +pdb_unpublished_codes = ['HPUB', 'HOLD', 'PROC', 'WAIT', 'AUTH', 'AUCO', 'REPL', 'POLC', 'REFI', 'TRSF', 'WDRN'] +# url for api query +pdbe_solr_url = 'https://www.ebi.ac.uk/pdbe/search/pdb/select?' +# base url for results +pdbe_entry_url = 'https://www.ebi.ac.uk/pdbe/entry/pdb/{pdb_id}' +# link to preview image of structure +pdbe_preview_url = 'https://www.ebi.ac.uk/pdbe/static/entry/{pdb_id}_deposited_chain_front_image-200x200.png' + + +def request(query, params): + + params['url'] = pdbe_solr_url + params['method'] = 'POST' + params['data'] = { + 'q': query, + 'wt': "json" # request response in parsable format + } + return params + + +def construct_body(result): + # set title + title = result['title'] + + # construct content body + content = """{title}<br />{authors} {journal} <strong>{volume}</strong>&nbsp;{page} ({year})""" + + # replace placeholders with actual content + try: + if result['journal']: + content = content.format( + title=result['citation_title'], + authors=result['entry_author_list'][0], journal=result['journal'], volume=result['journal_volume'], + page=result['journal_page'], year=result['citation_year']) + else: + content = content.format( + title=result['citation_title'], + authors=result['entry_author_list'][0], journal='', volume='', page='', year=result['release_year']) + img_src = pdbe_preview_url.format(pdb_id=result['pdb_id']) + except (KeyError): + content = None + img_src = None + + # construct url for preview image + try: + img_src = pdbe_preview_url.format(pdb_id=result['pdb_id']) + except (KeyError): + img_src = None + + return [title, content, img_src] + + +def response(resp): + + results = [] + json = loads(resp.text)['response']['docs'] + + # parse results + for result in json: + # catch obsolete entries and mark them accordingly + if result['status'] in pdb_unpublished_codes: + continue + if hide_obsolete: + continue + if result['status'] == 'OBS': + # expand title to add some sort of warning message + title = gettext('{title}&nbsp;(OBSOLETE)').format(title=result['title']) + superseded_url = pdbe_entry_url.format(pdb_id=result['superseded_by']) + + # since we can't construct a proper body from the response, we'll make up our own + msg_superseded = gettext("This entry has been superseded by") + content = '<em>{msg_superseded} \<a href="{url}">{pdb_id}</a></em>'.format( + msg_superseded=msg_superseded, + url=superseded_url, + pdb_id=result['superseded_by'], ) + + # obsoleted entries don't have preview images + img_src = None + else: + title, content, img_src = construct_body(result) + + results.append({ + 'url': pdbe_entry_url.format(pdb_id=result['pdb_id']), + 'title': title, + 'content': content, + 'img_src': img_src + }) + + return results diff --git a/searx/engines/seedpeer.py b/searx/engines/seedpeer.py @@ -0,0 +1,78 @@ +# Seedpeer (Videos, Music, Files) +# +# @website http://seedpeer.eu +# @provide-api no (nothing found) +# +# @using-api no +# @results HTML (using search portal) +# @stable yes (HTML can change) +# @parse url, title, content, seed, leech, magnetlink + +from urlparse import urljoin +from cgi import escape +from urllib import quote +from lxml import html +from operator import itemgetter +from searx.engines.xpath import extract_text + + +url = 'http://www.seedpeer.eu/' +search_url = url + 'search/{search_term}/7/{page_no}.html' +# specific xpath variables +torrent_xpath = '//*[@id="body"]/center/center/table[2]/tr/td/a' +alternative_torrent_xpath = '//*[@id="body"]/center/center/table[1]/tr/td/a' +title_xpath = '//*[@id="body"]/center/center/table[2]/tr/td/a/text()' +alternative_title_xpath = '//*[@id="body"]/center/center/table/tr/td/a' +seeds_xpath = '//*[@id="body"]/center/center/table[2]/tr/td[4]/font/text()' +alternative_seeds_xpath = '//*[@id="body"]/center/center/table/tr/td[4]/font/text()' +peers_xpath = '//*[@id="body"]/center/center/table[2]/tr/td[5]/font/text()' +alternative_peers_xpath = '//*[@id="body"]/center/center/table/tr/td[5]/font/text()' +age_xpath = '//*[@id="body"]/center/center/table[2]/tr/td[2]/text()' +alternative_age_xpath = '//*[@id="body"]/center/center/table/tr/td[2]/text()' +size_xpath = '//*[@id="body"]/center/center/table[2]/tr/td[3]/text()' +alternative_size_xpath = '//*[@id="body"]/center/center/table/tr/td[3]/text()' + + +# do search-request +def request(query, params): + params['url'] = search_url.format(search_term=quote(query), + page_no=params['pageno'] - 1) + return params + + +# get response from search-request +def response(resp): + results = [] + dom = html.fromstring(resp.text) + torrent_links = dom.xpath(torrent_xpath) + if len(torrent_links) > 0: + seeds = dom.xpath(seeds_xpath) + peers = dom.xpath(peers_xpath) + titles = dom.xpath(title_xpath) + sizes = dom.xpath(size_xpath) + ages = dom.xpath(age_xpath) + else: # under ~5 results uses a different xpath + torrent_links = dom.xpath(alternative_torrent_xpath) + seeds = dom.xpath(alternative_seeds_xpath) + peers = dom.xpath(alternative_peers_xpath) + titles = dom.xpath(alternative_title_xpath) + sizes = dom.xpath(alternative_size_xpath) + ages = dom.xpath(alternative_age_xpath) + # return empty array if nothing is found + if not torrent_links: + return [] + + # parse results + for index, result in enumerate(torrent_links): + link = result.attrib.get('href') + href = urljoin(url, link) + results.append({'url': href, + 'title': titles[index].text_content(), + 'content': '{}, {}'.format(sizes[index], ages[index]), + 'seed': seeds[index], + 'leech': peers[index], + + 'template': 'torrent.html'}) + + # return results sorted by seeder + return sorted(results, key=itemgetter('seed'), reverse=True) diff --git a/searx/settings.yml b/searx/settings.yml @@ -18,6 +18,12 @@ ui: default_theme : oscar # ui theme default_locale : "" # Default interface locale - leave blank to detect from browser information or use codes from the 'locales' config section +# searx supports result proxification using an external service: https://github.com/asciimoo/morty +# uncomment below section if you have running morty proxy +#result_proxy: +# url : http://127.0.0.1:3000/ +# key : your_morty_proxy_key + outgoing: # communication with search engines request_timeout : 2.0 # seconds useragent_suffix : "" # suffix of searx_useragent, could contain informations like an email address to the administrator @@ -301,6 +307,12 @@ engines: timeout : 6.0 disabled : True + - name: kickass + engine : kickass + shortcut : kc + timeout : 4.0 + disabled : True + - name : microsoft academic engine : json_engine paging : True @@ -339,6 +351,13 @@ engines: disabled : True shortcut : or + - name : pdbe + engine : pdbe + shortcut : pdb +# Hide obsolete PDB entries. +# Default is not to hide obsolete structures +# hide_obsolete : False + - name : photon engine : photon shortcut : ph @@ -377,7 +396,7 @@ engines: timeout : 10.0 disabled : True - - name : scanr_structures + - name : scanr structures shortcut: scs engine : scanr_structures disabled : True @@ -495,6 +514,12 @@ engines: timeout: 6.0 categories : science + - name : seedpeer + engine : seedpeer + shortcut: speu + categories: files, music, videos + disabled: True + - name : dictzone engine : dictzone shortcut : dc diff --git a/searx/settings_robot.yml b/searx/settings_robot.yml @@ -15,7 +15,7 @@ server: ui: themes_path : "" - default_theme : default + default_theme : legacy default_locale : "" outgoing: @@ -23,12 +23,12 @@ outgoing: useragent_suffix : "" engines: - - name : general_dummy + - name : general dummy engine : dummy categories : general shortcut : gd - - name : dummy_dummy + - name : dummy dummy engine : dummy categories : dummy shortcut : dd diff --git a/searx/static/themes/default/css/style-rtl.css b/searx/static/themes/legacy/css/style-rtl.css diff --git a/searx/static/themes/default/css/style.css b/searx/static/themes/legacy/css/style.css diff --git a/searx/static/themes/default/img/favicon.png b/searx/static/themes/legacy/img/favicon.png Binary files differ. diff --git a/searx/static/themes/default/img/github_ribbon.png b/searx/static/themes/legacy/img/github_ribbon.png Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_500px.ico b/searx/static/themes/legacy/img/icons/icon_500px.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_bing.ico b/searx/static/themes/legacy/img/icons/icon_bing.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_dailymotion.ico b/searx/static/themes/legacy/img/icons/icon_dailymotion.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_deezer.ico b/searx/static/themes/legacy/img/icons/icon_deezer.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_deviantart.ico b/searx/static/themes/legacy/img/icons/icon_deviantart.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_digg.ico b/searx/static/themes/legacy/img/icons/icon_digg.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_duckduckgo.ico b/searx/static/themes/legacy/img/icons/icon_duckduckgo.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_flickr.ico b/searx/static/themes/legacy/img/icons/icon_flickr.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_github.ico b/searx/static/themes/legacy/img/icons/icon_github.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_google play apps.ico b/searx/static/themes/legacy/img/icons/icon_google play apps.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_google play movies.ico b/searx/static/themes/legacy/img/icons/icon_google play movies.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_google play music.ico b/searx/static/themes/legacy/img/icons/icon_google play music.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_google.ico b/searx/static/themes/legacy/img/icons/icon_google.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_kickass.ico b/searx/static/themes/legacy/img/icons/icon_kickass.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_openstreetmap.ico b/searx/static/themes/legacy/img/icons/icon_openstreetmap.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_searchcode code.ico b/searx/static/themes/legacy/img/icons/icon_searchcode code.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_searchcode doc.ico b/searx/static/themes/legacy/img/icons/icon_searchcode doc.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_searchcode.ico b/searx/static/themes/legacy/img/icons/icon_searchcode.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_soundcloud.ico b/searx/static/themes/legacy/img/icons/icon_soundcloud.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_stackoverflow.ico b/searx/static/themes/legacy/img/icons/icon_stackoverflow.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_startpage.ico b/searx/static/themes/legacy/img/icons/icon_startpage.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_subtitleseeker.ico b/searx/static/themes/legacy/img/icons/icon_subtitleseeker.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_twitter.ico b/searx/static/themes/legacy/img/icons/icon_twitter.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_vimeo.ico b/searx/static/themes/legacy/img/icons/icon_vimeo.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_wikipedia.ico b/searx/static/themes/legacy/img/icons/icon_wikipedia.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_yahoo.ico b/searx/static/themes/legacy/img/icons/icon_yahoo.ico Binary files differ. diff --git a/searx/static/themes/default/img/icons/icon_youtube.ico b/searx/static/themes/legacy/img/icons/icon_youtube.ico Binary files differ. diff --git a/searx/static/themes/default/img/preference-icon.png b/searx/static/themes/legacy/img/preference-icon.png Binary files differ. diff --git a/searx/static/themes/default/img/search-icon.png b/searx/static/themes/legacy/img/search-icon.png Binary files differ. diff --git a/searx/static/themes/default/img/searx.png b/searx/static/themes/legacy/img/searx.png Binary files differ. diff --git a/searx/static/themes/default/img/searx_logo.svg b/searx/static/themes/legacy/img/searx_logo.svg diff --git a/searx/static/themes/default/js/searx.js b/searx/static/themes/legacy/js/searx.js diff --git a/searx/static/themes/default/less/autocompleter.less b/searx/static/themes/legacy/less/autocompleter.less diff --git a/searx/static/themes/default/less/code.less b/searx/static/themes/legacy/less/code.less diff --git a/searx/static/themes/default/less/definitions.less b/searx/static/themes/legacy/less/definitions.less diff --git a/searx/static/themes/default/less/mixins.less b/searx/static/themes/legacy/less/mixins.less diff --git a/searx/static/themes/default/less/search.less b/searx/static/themes/legacy/less/search.less diff --git a/searx/static/themes/default/less/style-rtl.less b/searx/static/themes/legacy/less/style-rtl.less diff --git a/searx/static/themes/default/less/style.less b/searx/static/themes/legacy/less/style.less diff --git a/searx/templates/courgette/base.html b/searx/templates/courgette/base.html @@ -22,7 +22,7 @@ {% endblock %} {% block meta %}{% endblock %} {% block head %} - <link title="searx" type="application/opensearchdescription+xml" rel="search" href="{{ url_for('opensearch') }}"/> + <link title="{{ instance_name }}" type="application/opensearchdescription+xml" rel="search" href="{{ url_for('opensearch') }}"/> {% endblock %} <script type="text/javascript"> searx = {}; diff --git a/searx/templates/default/404.html b/searx/templates/default/404.html @@ -1,9 +0,0 @@ -{% extends "default/base.html" %} -{% block content %} -<div class="center"> - <h1>{{ _('Page not found') }}</h1> - {% autoescape false %} - <p>{{ _('Go to %(search_page)s.', search_page='<a href="{}">{}</a>'.decode('utf-8').format(url_for('index'), _('search page'))) }}</p> - {% endautoescape %} -</div> -{% endblock %} diff --git a/searx/templates/default/about.html b/searx/templates/default/about.html @@ -1,66 +0,0 @@ -{% extends 'default/base.html' %} -{% block content %} -{% include 'default/github_ribbon.html' %} -<div class="row"{% if rtl %} dir="ltr"{% endif %}> - <h1>About <a href="{{ url_for('index') }}">searx</a></h1> - - <p>Searx is a <a href="https://en.wikipedia.org/wiki/Metasearch_engine">metasearch engine</a>, aggregating the results of other <a href="{{ url_for('preferences') }}">search engines</a> while not storing information about its users. - </p> - <h2>Why use searx?</h2> - <ul> - <li>searx may not offer you as personalised results as Google, but it doesn't generate a profile about you</li> - <li>searx doesn't care about what you search for, never shares anything with a third party, and it can't be used to compromise you</li> - <li>searx is free software, the code is 100% open and you can help to make it better. See more on <a href="https://github.com/asciimoo/searx">github</a></li> - </ul> - <p>If you do care about privacy, want to be a conscious user, or otherwise believe - in digital freedom, make searx your default search engine or run it on your own server</p> - -<h2>Technical details - How does it work?</h2> - -<p>Searx is a <a href="https://en.wikipedia.org/wiki/Metasearch_engine">metasearch engine</a>, -inspired by the <a href="http://seeks-project.info/">seeks project</a>.<br /> -It provides basic privacy by mixing your queries with searches on other platforms without storing search data. Queries are made using a POST request on every browser (except chrome*). Therefore they show up in neither our logs, nor your url history. In case of Chrome* users there is an exception, if searx used from the search bar it performs GET requests.<br /> -Searx can be added to your browser's search bar; moreover, it can be set as the default search engine. -</p> - -<h2>How can I make it my own?</h2> - -<p>Searx appreciates your concern regarding logs, so take the <a href="https://github.com/asciimoo/searx">code</a> and run it yourself! <br />Add your Searx to this <a href="https://github.com/asciimoo/searx/wiki/Searx-instances">list</a> to help other people reclaim their privacy and make the Internet freer! -<br />The more decentralized Internet is the more freedom we have!</p> - - -<h2>More about searx</h2> - -<ul> - <li><a href="https://github.com/asciimoo/searx">github</a></li> - <li><a href="https://www.ohloh.net/p/searx/">ohloh</a></li> - <li><a href="https://twitter.com/Searx_engine">twitter</a></li> - <li>IRC: #searx @ freenode (<a href="https://kiwiirc.com/client/irc.freenode.com/searx">webclient</a>)</li> - <li><a href="https://www.transifex.com/projects/p/searx/">transifex</a></li> -</ul> - - -<hr /> - -<h2 id="faq">FAQ</h2> - -<h3>How to add to firefox?</h3> -<p><a href="#" onclick="window.external.AddSearchProvider(window.location.protocol + '//' + window.location.host + '{{ url_for('opensearch') }}');">Install</a> searx as a search engine on any version of Firefox! (javascript required)</p> - -<h2 id="dev_faq">Developer FAQ</h2> - -<h3>New engines?</h3> -<ul> - <li>Edit your <a href="https://raw.github.com/asciimoo/searx/master/searx/settings.yml">settings.yml</a></li> - <li>Create your custom engine module, check the <a href="https://github.com/asciimoo/searx/blob/master/examples/basic_engine.py">example engine</a></li> -</ul> -<p>Don't forget to restart searx after config edit!</p> - -<h3>Installation/WSGI support?</h3> -<p>See the <a href="https://github.com/asciimoo/searx/wiki/Installation">installation and setup</a> wiki page</p> - -<h3>How to debug engines?</h3> -<p><a href="{{ url_for('stats') }}">Stats page</a> contains some useful data about the engines used.</p> - -</div> -{% endblock %} diff --git a/searx/templates/default/base.html b/searx/templates/default/base.html @@ -1,38 +0,0 @@ -<!DOCTYPE html> -<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"{% if rtl %} dir="rtl"{% endif %}> - <head> - <meta charset="UTF-8" /> - <meta name="description" content="searx - a privacy-respecting, hackable metasearch engine" /> - <meta name="keywords" content="searx, search, search engine, metasearch, meta search" /> - <meta name="generator" content="searx/{{ searx_version }}"> - <meta name="referrer" content="no-referrer"> - <meta name="viewport" content="width=device-width, maximum-scale=1.0, user-scalable=1" /> - <title>{% block title %}{% endblock %}searx</title> - <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}" type="text/css" media="screen" /> - {% if rtl %} - <link rel="stylesheet" href="{{ url_for('static', filename='css/style-rtl.css') }}" type="text/css" media="screen" /> - {% endif %} - <link rel="shortcut icon" href="{{ url_for('static', filename='img/favicon.png') }}?v=2" /> - {% block styles %} - {% endblock %} - {% block meta %}{% endblock %} - {% block head %} - <link title="searx" type="application/opensearchdescription+xml" rel="search" href="{{ url_for('opensearch') }}"/> - {% endblock %} - </head> - <body> - <div id="container"> - {% block content %} - {% endblock %} - {% if autocomplete %} - <script src="{{ url_for('static', filename='js/mootools-core-1.4.5-min.js') }}" ></script> - <script src="{{ url_for('static', filename='js/mootools-autocompleter-1.1.2-min.js') }}" ></script> - {% endif %} - <script type="text/javascript"> - searx = {}; - searx.autocompleter = {% if autocomplete %}true{% else %}false{% endif %}; - </script> - <script src="{{ url_for('static', filename='js/searx.js') }}" ></script> - </div> - </body> -</html> diff --git a/searx/templates/default/index.html b/searx/templates/default/index.html @@ -1,18 +0,0 @@ -{% extends "default/base.html" %} -{% block content %} -<div class="center"> - <div class="title"><h1>searx</h1></div> - {% include 'default/search.html' %} - <p class="top_margin"> - {% if rtl %} - <a href="{{ url_for('preferences') }}" class="hmarg">{{ _('preferences') }}</a> - {% endif %} - <a href="{{ url_for('about') }}" class="hmarg">{{ _('about') }}</a> - {% if not rtl %} - <a href="{{ url_for('preferences') }}" class="hmarg">{{ _('preferences') }}</a> - {% endif %} - </p> -</div> -{% include 'default/github_ribbon.html' %} -{% endblock %} - diff --git a/searx/templates/default/preferences.html b/searx/templates/default/preferences.html @@ -1,129 +0,0 @@ -{% extends "default/base.html" %} -{% block head %} {% endblock %} -{% block content %} -<div class="row"> - <h2>{{ _('Preferences') }}</h2> - - <form method="post" action="{{ url_for('preferences') }}" id="search_form"> - <fieldset> - <legend>{{ _('Default categories') }}</legend> - {% set display_tooltip = false %} - {% include 'default/categories.html' %} - </fieldset> - <fieldset> - <legend>{{ _('Search language') }}</legend> - <p> - <select name='language'> - <option value="all" {% if current_language == 'all' %}selected="selected"{% endif %}>{{ _('Automatic') }}</option> - {% for lang_id,lang_name,country_name in language_codes | sort(attribute=1) %} - <option value="{{ lang_id }}" {% if lang_id == current_language %}selected="selected"{% endif %}>{{ lang_name }} ({{ country_name }}) - {{ lang_id }}</option> - {% endfor %} - </select> - </p> - </fieldset> - <fieldset> - <legend>{{ _('Interface language') }}</legend> - <p> - <select name='locale'> - {% for locale_id,locale_name in locales.items() | sort %} - <option value="{{ locale_id }}" {% if locale_id == current_locale %}selected="selected"{% endif %}>{{ locale_name }}</option> - {% endfor %} - </select> - </p> - </fieldset> - <fieldset> - <legend>{{ _('Autocomplete') }}</legend> - <p> - <select name="autocomplete"> - <option value=""> - </option> - {% for backend in autocomplete_backends %} - <option value="{{ backend }}" {% if backend == autocomplete %}selected="selected"{% endif %}>{{ backend }}</option> - {% endfor %} - </select> - </p> - </fieldset> - <fieldset> - <legend>{{ _('Image proxy') }}</legend> - <p> - <select name='image_proxy'> - <option value="1" {% if image_proxy %}selected="selected"{% endif %}>{{ _('Enabled') }}</option> - <option value="" {% if not image_proxy %}selected="selected"{% endif %}>{{ _('Disabled') }}</option> - </select> - </p> - </fieldset> - <fieldset> - <legend>{{ _('Method') }}</legend> - <p> - <select name='method'> - <option value="POST" {% if method == 'POST' %}selected="selected"{% endif %}>POST</option> - <option value="GET" {% if method == 'GET' %}selected="selected"{% endif %}>GET</option> - </select> - </p> - </fieldset> - <fieldset> - <legend>{{ _('SafeSearch') }}</legend> - <p> - <select name='safesearch'> - <option value="2" {% if safesearch == '2' %}selected="selected"{% endif %}>{{ _('Strict') }}</option> - <option value="1" {% if safesearch == '1' %}selected="selected"{% endif %}>{{ _('Moderate') }}</option> - <option value="0" {% if safesearch == '0' %}selected="selected"{% endif %}>{{ _('None') }}</option> - </select> - </p> - </fieldset> - <fieldset> - <legend>{{ _('Themes') }}</legend> - <p> - <select name="theme"> - {% for name in themes %} - <option value="{{ name }}" {% if name == theme %}selected="selected"{% endif %}>{{ name }}</option> - {% endfor %} - </select> - </p> - </fieldset> - <fieldset> - <legend>{{ _('Results on new tabs') }}</legend> - <p> - <select name='results_on_new_tab'> - <option value="1" {% if results_on_new_tab %}selected="selected"{% endif %}>{{ _('On') }}</option> - <option value="0" {% if not results_on_new_tab %}selected="selected"{% endif %}>{{ _('Off')}}</option> - </select> - </p> - </fieldset> - <fieldset> - <legend>{{ _('Currently used search engines') }}</legend> - - <table> - <tr> - <th>{{ _('Engine name') }}</th> - <th>{{ _('Category') }}</th> - <th>{{ _('Allow') }} / {{ _('Block') }}</th> - </tr> - {% for categ in all_categories %} - {% for search_engine in engines_by_category[categ] %} - - {% if not search_engine.private %} - <tr> - <td>{{ search_engine.name }} ({{ shortcuts[search_engine.name] }})&lrm;</td> - <td>{{ _(categ) }}</td> - <td class="engine_checkbox"> - <input type="checkbox" id="engine_{{ categ|replace(' ', '_') }}_{{ search_engine.name|replace(' ', '_') }}" name="engine_{{ search_engine.name }}__{{ categ }}"{% if (search_engine.name, categ) in disabled_engines %} checked="checked"{% endif %} /> - <label class="allow" for="engine_{{ categ|replace(' ', '_') }}_{{ search_engine.name|replace(' ', '_') }}">{{ _('Allow') }}</label> - <label class="deny" for="engine_{{ categ|replace(' ', '_') }}_{{ search_engine.name|replace(' ', '_') }}">{{ _('Block') }}</label> - </td> - </tr> - {% endif %} - {% endfor %} - {% endfor %} - </table> - </fieldset> - <p class="small_font">{{ _('These settings are stored in your cookies, this allows us not to store this data about you.') }} - <br /> - {{ _("These cookies serve your sole convenience, we don't use these cookies to track you.") }} - </p> - - <input type="submit" value="{{ _('save') }}" /> - <div class="{% if rtl %}left{% else %}right{% endif %} preferences_back"><a href="{{ url_for('clear_cookies') }}">{{ _('Reset defaults') }}</a></div> - <div class="{% if rtl %}left{% else %}right{% endif %} preferences_back"><a href="{{ url_for('index') }}">{{ _('back') }}</a></div> - </form> -</div> -{% endblock %} diff --git a/searx/templates/default/results.html b/searx/templates/default/results.html @@ -1,100 +0,0 @@ -{% extends "default/base.html" %} -{% block title %}{{ q }} - {% endblock %} -{% 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 %} -{% block content %} -<div class="preferences_container right"><a href="{{ url_for('preferences') }}" id="preferences"><span>preferences</span></a></div> -<div class="small search center"> - {% include 'default/search.html' %} -</div> -<div id="results"> - <div id="sidebar"> - - <div id="search_url"> - {{ _('Search URL') }}: - <input type="text" value="{{ base_url }}?q={{ q|urlencode }}{% if selected_categories %}&amp;categories={{ selected_categories|join(",") | replace(' ','+') }}{% endif %}{% if pageno > 1 %}&amp;pageno={{ pageno }}{% endif %}" readonly /> - </div> - <div id="apis"> - {{ _('Download results') }} - {% for output_type in ('csv', 'json', 'rss') %} - <form method="{{ method or 'POST' }}" action="{{ url_for('index') }}"> - <div class="left"> - <input type="hidden" name="q" value="{{ q }}" /> - <input type="hidden" name="format" value="{{ output_type }}" /> - {% for category in selected_categories %} - <input type="hidden" name="category_{{ category }}" value="1"/> - {% endfor %} - <input type="hidden" name="pageno" value="{{ pageno }}" /> - <input type="submit" value="{{ output_type }}" /> - </div> - </form> - {% endfor %} - </div> - </div> - - {% if answers %} - <div id="answers"><span>{{ _('Answers') }}</span> - {% for answer in answers %} - <span>{{ answer }}</span> - {% endfor %} - </div> - {% endif %} - - {% if suggestions %} - <div id="suggestions"><span id="suggestions-title">{{ _('Suggestions') }} : </span> - {% set first = true %} - {% for suggestion in suggestions %} - {% if not first %} &bull; {% endif %}<form method="{{ method or 'POST' }}" action="{{ url_for('index') }}"> - <input type="hidden" name="q" value="{{ suggestion }}"> - <input type="submit" class="suggestion" value="{{ suggestion }}" /> - </form> - {% set first = false %} - {% endfor %} - </div> - {% endif %} - - {% if infoboxes %} - <div id="infoboxes"> - {% for infobox in infoboxes %} - {% include 'default/infobox.html' %} - {% endfor %} - </div> - {% endif %} - - {% for result in results %} - {% if result['template'] %} - {% include get_result_template('default', result['template']) %} - {% else %} - {% include 'default/result_templates/default.html' %} - {% endif %} - {% endfor %} - - {% if paging %} - <div id="pagination"> - {% if pageno > 1 %} - <form method="{{ method or 'POST' }}" action="{{ url_for('index') }}"> - <div class="{% if rtl %}right{% else %}left{% endif %}"> - <input type="hidden" name="q" value="{{ q }}" /> - {% for category in selected_categories %} - <input type="hidden" name="category_{{ category }}" value="1"/> - {% endfor %} - <input type="hidden" name="pageno" value="{{ pageno-1 }}" /> - <input type="submit" value="<< {{ _('previous page') }}" /> - </div> - </form> - {% endif %} - <form method="{{ method or 'POST' }}" action="{{ url_for('index') }}"> - <div class="{% if rtl %}left{% else %}right{% endif %}"> - {% for category in selected_categories %} - <input type="hidden" name="category_{{ category }}" value="1"/> - {% endfor %} - <input type="hidden" name="q" value="{{ q }}" /> - <input type="hidden" name="pageno" value="{{ pageno+1 }}" /> - <input type="submit" value="{{ _('next page') }} >>" /> - </div> - </form> - - <br /> - </div> - {% endif %} -</div> -{% endblock %} diff --git a/searx/templates/default/search.html b/searx/templates/default/search.html @@ -1,8 +0,0 @@ -<form method="{{ method or 'POST' }}" action="{{ url_for('index') }}" id="search_form"> - <div id="search_wrapper"> - <input type="text" placeholder="{{ _('Search for...') }}" id="q" class="q" name="q" tabindex="1" autocomplete="off" size="100" {% if q %}value="{{ q }}"{% endif %}/> - <input type="submit" value="search" id="search_submit" /> - </div> - {% set display_tooltip = true %} - {% include 'default/categories.html' %} -</form> diff --git a/searx/templates/default/stats.html b/searx/templates/default/stats.html @@ -1,22 +0,0 @@ -{% extends "default/base.html" %} -{% block head %} {% endblock %} -{% block content %} -<h2>{{ _('Engine stats') }}</h2> - -{% for stat_name,stat_category in stats %} -<div class="left"> - <table> - <tr colspan="3"> - <th>{{ stat_name }}</th> - </tr> - {% for engine in stat_category %} - <tr> - <td>{{ engine.name }}</td> - <td>{{ '%.02f'|format(engine.avg) }}</td> - <td class="percentage"><div style="width: {{ engine.percentage }}%">&nbsp;</div></td> - </tr> - {% endfor %} - </table> -</div> -{% endfor %} -{% endblock %} diff --git a/searx/templates/legacy/404.html b/searx/templates/legacy/404.html @@ -0,0 +1,9 @@ +{% extends "legacy/base.html" %} +{% block content %} +<div class="center"> + <h1>{{ _('Page not found') }}</h1> + {% autoescape false %} + <p>{{ _('Go to %(search_page)s.', search_page='<a href="{}">{}</a>'.decode('utf-8').format(url_for('index'), _('search page'))) }}</p> + {% endautoescape %} +</div> +{% endblock %} diff --git a/searx/templates/legacy/about.html b/searx/templates/legacy/about.html @@ -0,0 +1,66 @@ +{% extends 'legacy/base.html' %} +{% block content %} +{% include 'legacy/github_ribbon.html' %} +<div class="row"{% if rtl %} dir="ltr"{% endif %}> + <h1>About <a href="{{ url_for('index') }}">searx</a></h1> + + <p>Searx is a <a href="https://en.wikipedia.org/wiki/Metasearch_engine">metasearch engine</a>, aggregating the results of other <a href="{{ url_for('preferences') }}">search engines</a> while not storing information about its users. + </p> + <h2>Why use searx?</h2> + <ul> + <li>searx may not offer you as personalised results as Google, but it doesn't generate a profile about you</li> + <li>searx doesn't care about what you search for, never shares anything with a third party, and it can't be used to compromise you</li> + <li>searx is free software, the code is 100% open and you can help to make it better. See more on <a href="https://github.com/asciimoo/searx">github</a></li> + </ul> + <p>If you do care about privacy, want to be a conscious user, or otherwise believe + in digital freedom, make searx your default search engine or run it on your own server</p> + +<h2>Technical details - How does it work?</h2> + +<p>Searx is a <a href="https://en.wikipedia.org/wiki/Metasearch_engine">metasearch engine</a>, +inspired by the <a href="http://seeks-project.info/">seeks project</a>.<br /> +It provides basic privacy by mixing your queries with searches on other platforms without storing search data. Queries are made using a POST request on every browser (except chrome*). Therefore they show up in neither our logs, nor your url history. In case of Chrome* users there is an exception, if searx used from the search bar it performs GET requests.<br /> +Searx can be added to your browser's search bar; moreover, it can be set as the default search engine. +</p> + +<h2>How can I make it my own?</h2> + +<p>Searx appreciates your concern regarding logs, so take the <a href="https://github.com/asciimoo/searx">code</a> and run it yourself! <br />Add your Searx to this <a href="https://github.com/asciimoo/searx/wiki/Searx-instances">list</a> to help other people reclaim their privacy and make the Internet freer! +<br />The more decentralized Internet is the more freedom we have!</p> + + +<h2>More about searx</h2> + +<ul> + <li><a href="https://github.com/asciimoo/searx">github</a></li> + <li><a href="https://www.ohloh.net/p/searx/">ohloh</a></li> + <li><a href="https://twitter.com/Searx_engine">twitter</a></li> + <li>IRC: #searx @ freenode (<a href="https://kiwiirc.com/client/irc.freenode.com/searx">webclient</a>)</li> + <li><a href="https://www.transifex.com/projects/p/searx/">transifex</a></li> +</ul> + + +<hr /> + +<h2 id="faq">FAQ</h2> + +<h3>How to add to firefox?</h3> +<p><a href="#" onclick="window.external.AddSearchProvider(window.location.protocol + '//' + window.location.host + '{{ url_for('opensearch') }}');">Install</a> searx as a search engine on any version of Firefox! (javascript required)</p> + +<h2 id="dev_faq">Developer FAQ</h2> + +<h3>New engines?</h3> +<ul> + <li>Edit your <a href="https://raw.github.com/asciimoo/searx/master/searx/settings.yml">settings.yml</a></li> + <li>Create your custom engine module, check the <a href="https://github.com/asciimoo/searx/blob/master/examples/basic_engine.py">example engine</a></li> +</ul> +<p>Don't forget to restart searx after config edit!</p> + +<h3>Installation/WSGI support?</h3> +<p>See the <a href="https://github.com/asciimoo/searx/wiki/Installation">installation and setup</a> wiki page</p> + +<h3>How to debug engines?</h3> +<p><a href="{{ url_for('stats') }}">Stats page</a> contains some useful data about the engines used.</p> + +</div> +{% endblock %} diff --git a/searx/templates/legacy/base.html b/searx/templates/legacy/base.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"{% if rtl %} dir="rtl"{% endif %}> + <head> + <meta charset="UTF-8" /> + <meta name="description" content="searx - a privacy-respecting, hackable metasearch engine" /> + <meta name="keywords" content="searx, search, search engine, metasearch, meta search" /> + <meta name="generator" content="searx/{{ searx_version }}"> + <meta name="referrer" content="no-referrer"> + <meta name="viewport" content="width=device-width, maximum-scale=1.0, user-scalable=1" /> + <title>{% block title %}{% endblock %}searx</title> + <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}" type="text/css" media="screen" /> + {% if rtl %} + <link rel="stylesheet" href="{{ url_for('static', filename='css/style-rtl.css') }}" type="text/css" media="screen" /> + {% endif %} + <link rel="shortcut icon" href="{{ url_for('static', filename='img/favicon.png') }}?v=2" /> + {% block styles %} + {% endblock %} + {% block meta %}{% endblock %} + {% block head %} + <link title="{{ instance_name }}" type="application/opensearchdescription+xml" rel="search" href="{{ url_for('opensearch') }}"/> + {% endblock %} + </head> + <body> + <div id="container"> + {% block content %} + {% endblock %} + {% if autocomplete %} + <script src="{{ url_for('static', filename='js/mootools-core-1.4.5-min.js') }}" ></script> + <script src="{{ url_for('static', filename='js/mootools-autocompleter-1.1.2-min.js') }}" ></script> + {% endif %} + <script type="text/javascript"> + searx = {}; + searx.autocompleter = {% if autocomplete %}true{% else %}false{% endif %}; + </script> + <script src="{{ url_for('static', filename='js/searx.js') }}" ></script> + </div> + </body> +</html> diff --git a/searx/templates/default/categories.html b/searx/templates/legacy/categories.html diff --git a/searx/templates/default/github_ribbon.html b/searx/templates/legacy/github_ribbon.html diff --git a/searx/templates/legacy/index.html b/searx/templates/legacy/index.html @@ -0,0 +1,18 @@ +{% extends "legacy/base.html" %} +{% block content %} +<div class="center"> + <div class="title"><h1>searx</h1></div> + {% include 'legacy/search.html' %} + <p class="top_margin"> + {% if rtl %} + <a href="{{ url_for('preferences') }}" class="hmarg">{{ _('preferences') }}</a> + {% endif %} + <a href="{{ url_for('about') }}" class="hmarg">{{ _('about') }}</a> + {% if not rtl %} + <a href="{{ url_for('preferences') }}" class="hmarg">{{ _('preferences') }}</a> + {% endif %} + </p> +</div> +{% include 'legacy/github_ribbon.html' %} +{% endblock %} + diff --git a/searx/templates/default/infobox.html b/searx/templates/legacy/infobox.html diff --git a/searx/templates/default/opensearch.xml b/searx/templates/legacy/opensearch.xml diff --git a/searx/templates/default/opensearch_response_rss.xml b/searx/templates/legacy/opensearch_response_rss.xml diff --git a/searx/templates/legacy/preferences.html b/searx/templates/legacy/preferences.html @@ -0,0 +1,129 @@ +{% extends "legacy/base.html" %} +{% block head %} {% endblock %} +{% block content %} +<div class="row"> + <h2>{{ _('Preferences') }}</h2> + + <form method="post" action="{{ url_for('preferences') }}" id="search_form"> + <fieldset> + <legend>{{ _('Default categories') }}</legend> + {% set display_tooltip = false %} + {% include 'legacy/categories.html' %} + </fieldset> + <fieldset> + <legend>{{ _('Search language') }}</legend> + <p> + <select name='language'> + <option value="all" {% if current_language == 'all' %}selected="selected"{% endif %}>{{ _('Automatic') }}</option> + {% for lang_id,lang_name,country_name in language_codes | sort(attribute=1) %} + <option value="{{ lang_id }}" {% if lang_id == current_language %}selected="selected"{% endif %}>{{ lang_name }} ({{ country_name }}) - {{ lang_id }}</option> + {% endfor %} + </select> + </p> + </fieldset> + <fieldset> + <legend>{{ _('Interface language') }}</legend> + <p> + <select name='locale'> + {% for locale_id,locale_name in locales.items() | sort %} + <option value="{{ locale_id }}" {% if locale_id == current_locale %}selected="selected"{% endif %}>{{ locale_name }}</option> + {% endfor %} + </select> + </p> + </fieldset> + <fieldset> + <legend>{{ _('Autocomplete') }}</legend> + <p> + <select name="autocomplete"> + <option value=""> - </option> + {% for backend in autocomplete_backends %} + <option value="{{ backend }}" {% if backend == autocomplete %}selected="selected"{% endif %}>{{ backend }}</option> + {% endfor %} + </select> + </p> + </fieldset> + <fieldset> + <legend>{{ _('Image proxy') }}</legend> + <p> + <select name='image_proxy'> + <option value="1" {% if image_proxy %}selected="selected"{% endif %}>{{ _('Enabled') }}</option> + <option value="" {% if not image_proxy %}selected="selected"{% endif %}>{{ _('Disabled') }}</option> + </select> + </p> + </fieldset> + <fieldset> + <legend>{{ _('Method') }}</legend> + <p> + <select name='method'> + <option value="POST" {% if method == 'POST' %}selected="selected"{% endif %}>POST</option> + <option value="GET" {% if method == 'GET' %}selected="selected"{% endif %}>GET</option> + </select> + </p> + </fieldset> + <fieldset> + <legend>{{ _('SafeSearch') }}</legend> + <p> + <select name='safesearch'> + <option value="2" {% if safesearch == '2' %}selected="selected"{% endif %}>{{ _('Strict') }}</option> + <option value="1" {% if safesearch == '1' %}selected="selected"{% endif %}>{{ _('Moderate') }}</option> + <option value="0" {% if safesearch == '0' %}selected="selected"{% endif %}>{{ _('None') }}</option> + </select> + </p> + </fieldset> + <fieldset> + <legend>{{ _('Themes') }}</legend> + <p> + <select name="theme"> + {% for name in themes %} + <option value="{{ name }}" {% if name == theme %}selected="selected"{% endif %}>{{ name }}</option> + {% endfor %} + </select> + </p> + </fieldset> + <fieldset> + <legend>{{ _('Results on new tabs') }}</legend> + <p> + <select name='results_on_new_tab'> + <option value="1" {% if results_on_new_tab %}selected="selected"{% endif %}>{{ _('On') }}</option> + <option value="0" {% if not results_on_new_tab %}selected="selected"{% endif %}>{{ _('Off')}}</option> + </select> + </p> + </fieldset> + <fieldset> + <legend>{{ _('Currently used search engines') }}</legend> + + <table> + <tr> + <th>{{ _('Engine name') }}</th> + <th>{{ _('Category') }}</th> + <th>{{ _('Allow') }} / {{ _('Block') }}</th> + </tr> + {% for categ in all_categories %} + {% for search_engine in engines_by_category[categ] %} + + {% if not search_engine.private %} + <tr> + <td>{{ search_engine.name }} ({{ shortcuts[search_engine.name] }})&lrm;</td> + <td>{{ _(categ) }}</td> + <td class="engine_checkbox"> + <input type="checkbox" id="engine_{{ categ|replace(' ', '_') }}_{{ search_engine.name|replace(' ', '_') }}" name="engine_{{ search_engine.name }}__{{ categ }}"{% if (search_engine.name, categ) in disabled_engines %} checked="checked"{% endif %} /> + <label class="allow" for="engine_{{ categ|replace(' ', '_') }}_{{ search_engine.name|replace(' ', '_') }}">{{ _('Allow') }}</label> + <label class="deny" for="engine_{{ categ|replace(' ', '_') }}_{{ search_engine.name|replace(' ', '_') }}">{{ _('Block') }}</label> + </td> + </tr> + {% endif %} + {% endfor %} + {% endfor %} + </table> + </fieldset> + <p class="small_font">{{ _('These settings are stored in your cookies, this allows us not to store this data about you.') }} + <br /> + {{ _("These cookies serve your sole convenience, we don't use these cookies to track you.") }} + </p> + + <input type="submit" value="{{ _('save') }}" /> + <div class="{% if rtl %}left{% else %}right{% endif %} preferences_back"><a href="{{ url_for('clear_cookies') }}">{{ _('Reset defaults') }}</a></div> + <div class="{% if rtl %}left{% else %}right{% endif %} preferences_back"><a href="{{ url_for('index') }}">{{ _('back') }}</a></div> + </form> +</div> +{% endblock %} diff --git a/searx/templates/default/result_templates/code.html b/searx/templates/legacy/result_templates/code.html diff --git a/searx/templates/default/result_templates/default.html b/searx/templates/legacy/result_templates/default.html diff --git a/searx/templates/default/result_templates/images.html b/searx/templates/legacy/result_templates/images.html diff --git a/searx/templates/default/result_templates/map.html b/searx/templates/legacy/result_templates/map.html diff --git a/searx/templates/default/result_templates/torrent.html b/searx/templates/legacy/result_templates/torrent.html diff --git a/searx/templates/default/result_templates/videos.html b/searx/templates/legacy/result_templates/videos.html diff --git a/searx/templates/legacy/results.html b/searx/templates/legacy/results.html @@ -0,0 +1,100 @@ +{% extends "legacy/base.html" %} +{% block title %}{{ q }} - {% endblock %} +{% 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 %} +{% block content %} +<div class="preferences_container right"><a href="{{ url_for('preferences') }}" id="preferences"><span>preferences</span></a></div> +<div class="small search center"> + {% include 'legacy/search.html' %} +</div> +<div id="results"> + <div id="sidebar"> + + <div id="search_url"> + {{ _('Search URL') }}: + <input type="text" value="{{ base_url }}?q={{ q|urlencode }}{% if selected_categories %}&amp;categories={{ selected_categories|join(",") | replace(' ','+') }}{% endif %}{% if pageno > 1 %}&amp;pageno={{ pageno }}{% endif %}" readonly /> + </div> + <div id="apis"> + {{ _('Download results') }} + {% for output_type in ('csv', 'json', 'rss') %} + <form method="{{ method or 'POST' }}" action="{{ url_for('index') }}"> + <div class="left"> + <input type="hidden" name="q" value="{{ q }}" /> + <input type="hidden" name="format" value="{{ output_type }}" /> + {% for category in selected_categories %} + <input type="hidden" name="category_{{ category }}" value="1"/> + {% endfor %} + <input type="hidden" name="pageno" value="{{ pageno }}" /> + <input type="submit" value="{{ output_type }}" /> + </div> + </form> + {% endfor %} + </div> + </div> + + {% if answers %} + <div id="answers"><span>{{ _('Answers') }}</span> + {% for answer in answers %} + <span>{{ answer }}</span> + {% endfor %} + </div> + {% endif %} + + {% if suggestions %} + <div id="suggestions"><span id="suggestions-title">{{ _('Suggestions') }} : </span> + {% set first = true %} + {% for suggestion in suggestions %} + {% if not first %} &bull; {% endif %}<form method="{{ method or 'POST' }}" action="{{ url_for('index') }}"> + <input type="hidden" name="q" value="{{ suggestion }}"> + <input type="submit" class="suggestion" value="{{ suggestion }}" /> + </form> + {% set first = false %} + {% endfor %} + </div> + {% endif %} + + {% if infoboxes %} + <div id="infoboxes"> + {% for infobox in infoboxes %} + {% include 'legacy/infobox.html' %} + {% endfor %} + </div> + {% endif %} + + {% for result in results %} + {% if result['template'] %} + {% include get_result_template('legacy', result['template']) %} + {% else %} + {% include 'legacy/result_templates/default.html' %} + {% endif %} + {% endfor %} + + {% if paging %} + <div id="pagination"> + {% if pageno > 1 %} + <form method="{{ method or 'POST' }}" action="{{ url_for('index') }}"> + <div class="{% if rtl %}right{% else %}left{% endif %}"> + <input type="hidden" name="q" value="{{ q }}" /> + {% for category in selected_categories %} + <input type="hidden" name="category_{{ category }}" value="1"/> + {% endfor %} + <input type="hidden" name="pageno" value="{{ pageno-1 }}" /> + <input type="submit" value="<< {{ _('previous page') }}" /> + </div> + </form> + {% endif %} + <form method="{{ method or 'POST' }}" action="{{ url_for('index') }}"> + <div class="{% if rtl %}left{% else %}right{% endif %}"> + {% for category in selected_categories %} + <input type="hidden" name="category_{{ category }}" value="1"/> + {% endfor %} + <input type="hidden" name="q" value="{{ q }}" /> + <input type="hidden" name="pageno" value="{{ pageno+1 }}" /> + <input type="submit" value="{{ _('next page') }} >>" /> + </div> + </form> + + <br /> + </div> + {% endif %} +</div> +{% endblock %} diff --git a/searx/templates/legacy/search.html b/searx/templates/legacy/search.html @@ -0,0 +1,8 @@ +<form method="{{ method or 'POST' }}" action="{{ url_for('index') }}" id="search_form"> + <div id="search_wrapper"> + <input type="text" placeholder="{{ _('Search for...') }}" id="q" class="q" name="q" tabindex="1" autocomplete="off" size="100" {% if q %}value="{{ q }}"{% endif %}/> + <input type="submit" value="search" id="search_submit" /> + </div> + {% set display_tooltip = true %} + {% include 'legacy/categories.html' %} +</form> diff --git a/searx/templates/legacy/stats.html b/searx/templates/legacy/stats.html @@ -0,0 +1,22 @@ +{% extends "legacy/base.html" %} +{% block head %} {% endblock %} +{% block content %} +<h2>{{ _('Engine stats') }}</h2> + +{% for stat_name,stat_category in stats %} +<div class="left"> + <table> + <tr colspan="3"> + <th>{{ stat_name }}</th> + </tr> + {% for engine in stat_category %} + <tr> + <td>{{ engine.name }}</td> + <td>{{ '%.02f'|format(engine.avg) }}</td> + <td class="percentage"><div style="width: {{ engine.percentage }}%">&nbsp;</div></td> + </tr> + {% endfor %} + </table> +</div> +{% endfor %} +{% endblock %} diff --git a/searx/templates/oscar/macros.html b/searx/templates/oscar/macros.html @@ -33,6 +33,9 @@ <span class="label label-default">{{ engine }}</span> {% endfor %} <small>{{ result_link("https://web.archive.org/web/" + result.url, icon('link') + _('cached'), "text-info") }}</small> + {% if proxify %} + <small>{{ result_link(proxify(result.url), icon('sort') + _('proxied'), "text-info") }}</small> + {% endif %} </div> <div class="text-muted"><small>{{ result.pretty_url }}</small></div> {%- endmacro %} @@ -44,6 +47,9 @@ <span class="label label-default">{{ engine }}</span> {% endfor %} <small>{{ result_link("https://web.archive.org/web/" + result.url, icon('link') + _('cached'), "text-info") }}</small> + {% if proxify %} + <small>{{ result_link(proxify(result.url), icon('sort') + _('proxied'), "text-info") }}</small> + {% endif %} <div class="text-muted"><small>{{ result.pretty_url }}</small></div> {%- endmacro %} diff --git a/searx/templates/pix-art/preferences.html b/searx/templates/pix-art/preferences.html @@ -1,4 +1,4 @@ -{% extends "default/base.html" %} +{% extends "legacy/base.html" %} {% block head %} {% endblock %} {% block content %} <div class="row"> diff --git a/searx/templates/pix-art/stats.html b/searx/templates/pix-art/stats.html @@ -1,4 +1,4 @@ -{% extends "default/base.html" %} +{% extends "legacy/base.html" %} {% block head %} {% endblock %} {% block content %} <h2>{{ _('Engine stats') }}</h2> diff --git a/searx/utils.py b/searx/utils.py @@ -252,12 +252,27 @@ def get_torrent_size(filesize, filesize_multiplier): filesize = int(filesize * 1024 * 1024) elif filesize_multiplier == 'KB': filesize = int(filesize * 1024) + elif filesize_multiplier == 'TiB': + filesize = int(filesize * 1000 * 1000 * 1000 * 1000) + elif filesize_multiplier == 'GiB': + filesize = int(filesize * 1000 * 1000 * 1000) + elif filesize_multiplier == 'MiB': + filesize = int(filesize * 1000 * 1000) + elif filesize_multiplier == 'KiB': + filesize = int(filesize * 1000) except: filesize = None return filesize +def convert_str_to_int(number_str): + if number_str.isdigit(): + return int(number_str) + else: + return 0 + + def is_valid_lang(lang): is_abbr = (len(lang) == 2) if is_abbr: diff --git a/searx/webapp.py b/searx/webapp.py @@ -22,10 +22,11 @@ if __name__ == '__main__': from os.path import realpath, dirname path.append(realpath(dirname(realpath(__file__)) + '/../')) -import json import cStringIO -import os import hashlib +import hmac +import json +import os import requests from searx import logger @@ -245,6 +246,20 @@ def url_for_theme(endpoint, override_theme=None, **values): return url_for(endpoint, **values) +def proxify(url): + if url.startswith('//'): + url = 'https:' + url + + if not settings.get('result_proxy'): + return url + + h = hmac.new(settings['result_proxy']['key'], url.encode('utf-8'), hashlib.sha256).hexdigest() + + return '{0}?{1}'.format(settings['result_proxy']['url'], + urlencode(dict(mortyurl=url.encode('utf-8'), + mortyhash=h))) + + def image_proxify(url): if url.startswith('//'): @@ -253,8 +268,7 @@ def image_proxify(url): if not request.preferences.get_value('image_proxy'): return url - hash_string = url + settings['server']['secret_key'] - h = hashlib.sha256(hash_string.encode('utf-8')).hexdigest() + h = hmac.new(settings['server']['secret_key'], url.encode('utf-8'), hashlib.sha256).hexdigest() return '{0}?{1}'.format(url_for('image_proxy'), urlencode(dict(url=url.encode('utf-8'), h=h))) @@ -313,6 +327,8 @@ def render(template_name, override_theme=None, **kwargs): kwargs['image_proxify'] = image_proxify + kwargs['proxify'] = proxify if settings.get('result_proxy') else None + kwargs['get_result_template'] = get_result_template kwargs['theme'] = get_current_theme_name(override=override_theme) @@ -602,7 +618,7 @@ def image_proxy(): if not url: return '', 400 - h = hashlib.sha256(url + settings['server']['secret_key'].encode('utf-8')).hexdigest() + h = hmac.new(settings['server']['secret_key'], url, hashlib.sha256).hexdigest() if h != request.args.get('h'): return '', 400 @@ -660,6 +676,7 @@ Allow: / Allow: /about Disallow: /stats Disallow: /preferences +Disallow: /*?*q=* """, mimetype='text/plain') diff --git a/tests/robot/test_basic.robot b/tests/robot/test_basic.robot @@ -4,6 +4,14 @@ Test Setup Open Browser http://localhost:11111/ Test Teardown Close All Browsers +*** Keywords *** +Submit Preferences + Set Selenium Speed 2 seconds + Submit Form id=search_form + Location Should Be http://localhost:11111/ + Set Selenium Speed 0 seconds + + *** Test Cases *** Front page Page Should Contain about @@ -24,8 +32,8 @@ Preferences page Page Should Contain Preferences Page Should Contain Default categories Page Should Contain Currently used search engines - Page Should Contain dummy_dummy - Page Should Contain general_dummy + Page Should Contain dummy dummy + Page Should Contain general dummy Switch category Go To http://localhost:11111/preferences @@ -33,8 +41,7 @@ Switch category Page Should Contain Checkbox category_dummy Click Element xpath=//*[.="general"] Click Element xpath=//*[.="dummy"] - Submit Form id=search_form - Location Should Be http://localhost:11111/ + Submit Preferences Checkbox Should Not Be Selected category_general Checkbox Should Be Selected category_dummy @@ -43,8 +50,7 @@ Change language Page Should Contain preferences Go To http://localhost:11111/preferences Select From List locale hu - Submit Form id=search_form - Location Should Be http://localhost:11111/ + Submit Preferences Page Should Contain rólunk Page Should Contain beállítások @@ -53,13 +59,11 @@ Change method Page Should Contain preferences Go To http://localhost:11111/preferences Select From List method GET - Submit Form id=search_form - Location Should Be http://localhost:11111/ + Submit Preferences Go To http://localhost:11111/preferences List Selection Should Be method GET Select From List method POST - Submit Form id=search_form - Location Should Be http://localhost:11111/ + Submit Preferences Go To http://localhost:11111/preferences List Selection Should Be method POST @@ -67,10 +71,9 @@ Change theme Page Should Contain about Page Should Contain preferences Go To http://localhost:11111/preferences - List Selection Should Be theme default + List Selection Should Be theme legacy Select From List theme oscar - Submit Form id=search_form - Location Should Be http://localhost:11111/ + Submit Preferences Go To http://localhost:11111/preferences List Selection Should Be theme oscar @@ -80,8 +83,7 @@ Change safesearch Go To http://localhost:11111/preferences List Selection Should Be safesearch None Select From List safesearch Strict - Submit Form id=search_form - Location Should Be http://localhost:11111/ + Submit Preferences Go To http://localhost:11111/preferences List Selection Should Be safesearch Strict @@ -91,8 +93,7 @@ Change image proxy Go To http://localhost:11111/preferences List Selection Should Be image_proxy Disabled Select From List image_proxy Enabled - Submit Form id=search_form - Location Should Be http://localhost:11111/ + Submit Preferences Go To http://localhost:11111/preferences List Selection Should Be image_proxy Enabled @@ -102,8 +103,7 @@ Change search language Go To http://localhost:11111/preferences List Selection Should Be language Automatic Select From List language Turkish (Turkey) - tr_TR - Submit Form id=search_form - Location Should Be http://localhost:11111/ + Submit Preferences Go To http://localhost:11111/preferences List Selection Should Be language Turkish (Turkey) - tr_TR @@ -113,8 +113,7 @@ Change autocomplete Go To http://localhost:11111/preferences List Selection Should Be autocomplete - Select From List autocomplete google - Submit Form id=search_form - Location Should Be http://localhost:11111/ + Submit Preferences Go To http://localhost:11111/preferences List Selection Should Be autocomplete google @@ -126,8 +125,7 @@ Change allowed/disabled engines Element Should Contain xpath=//label[@class="deny"][@for='engine_dummy_dummy_dummy'] Block Element Should Contain xpath=//label[@class="deny"][@for='engine_general_general_dummy'] Block Click Element xpath=//label[@class="deny"][@for='engine_general_general_dummy'] - Submit Form id=search_form - Location Should Be http://localhost:11111/ + Submit Preferences Page Should Contain about Page Should Contain preferences Go To http://localhost:11111/preferences @@ -139,18 +137,16 @@ Block a plugin Page Should Contain about Page Should Contain preferences Go To http://localhost:11111/preferences - List Selection Should Be theme default + List Selection Should Be theme legacy Select From List theme oscar - Submit Form id=search_form - Location Should Be http://localhost:11111/ + Submit Preferences Go To http://localhost:11111/preferences List Selection Should Be theme oscar Page Should Contain Plugins Click Link Plugins Checkbox Should Not Be Selected id=plugin_HTTPS_rewrite Click Element xpath=//label[@for='plugin_HTTPS_rewrite'] - Submit Form id=search_form - Location Should Be http://localhost:11111/ + Submit Preferences Go To http://localhost:11111/preferences Page Should Contain Plugins Click Link Plugins diff --git a/tests/unit/engines/seedpeer_fixture.html b/tests/unit/engines/seedpeer_fixture.html @@ -0,0 +1,110 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + <html xmlns="http://www.w3.org/1999/xhtml"> + <head> + </head> + <body> + <div id="header"> + <div id="whoIsYou"> + <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> + </div> + + <script type="text/javascript"> + whoIsYou(); + </script> + <div id="search"> + <form action="/search.php" method="get"> + <input id="topsearchbar" name="search" value="narcos season 2" /> + <input type="submit" class="searchbutton" value="Torrents" /> + <input style="color:#000" type="submit" class="searchbutton" name="usenet" value="Usenet Binaries" /> + </form> + <div id="suggestion"></div> + </div> + <div id="logo"><a href="/"><img src="/images/logo2.gif" alt="Seedpeer homepage" width="415" height="143" /></a></div> + <div id="subtext"><a href="/">Home</a> &gt; <a href="/search.html">Torrent search</a> &gt; Narcos season 2 | page 1</div> + </div> + <div id="nav"> + <ul> + <!-- + <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> + + --> + <li style="border-left:none" id="categories"><a title="Browse Torrent Categories" href="/browse.html">Categories</a> + <ul> + <li><a title="Browse Anime Torrents" href="/browse.html#6">Anime</a></li> + <li><a title="Browse Game Torrents" href="/browse.html#4">Games</a></li> + <li><a title="Browse Movie Torrents" href="/browse.html#1">Movies</a></li> + <li><a title="Browse Music Torrents" href="/browse.html#3">Music</a></li> + <li><a title="Browse Software Torrents" href="/browse.html#5">Software</a></li> + <li><a title="Browse TV Torrents" href="/browse.html#2">TV Shows</a></li> + <li><a title="Browse Other Torrents" href="/browse.html#7">Others</a></li> + </ul> + </li> + <li><a title="Upload A Torrents" href="/upload.html">Upload torrent</a></li> + <li id="verified"><a title="Verified Torrents" href="/verified.html">Verified</a></li> + <li id="searchoptions"><a title="Search Torrents" href="/search.html">Torrent search</a></li> + <li id="newsgroups"><a style="color:#212b3e" title="News Groups" href="/usenet.html">Usenet Binaries</a></li> + <li id="about" style="border-right:none"><a rel="nofollow" href="/faq.html">About Us</a> + <ul> + <li><a title="SeedPeer Statistics" href="/stats.html">Statistics</a></li> + <li><a title="Contact Us" href="/contact.html">Contact</a></li> + <li><a title="Frequently Asked Questions" href="/faq.html">FAQ</a></li> + <li><a title="SeedPeer API" href="http://api.seedpeer.eu">Our API</a></li> + <li><a title="SeedPeer Blog" href="/blog">Blog</a></li> + </ul> + </li> + <!--<li><a href="/toolbar.php">Our Toolbar</a></li>--> + </ul> + <div class="clear"></div> + </div> + <div id="body"><div id="pageTop"></div> + <div id="headerbox"><h1>Verified <font class="colored">Narcos season 2</font> torrents</h1></div><table width="100%"><tr><th> + <span style="float:right"> + <a href="/search/narcos-season-2/8/1.html"><img style="vertical-align:middle" src="/images/comments.gif" alt="comments" /></a> | + <a href="/search/narcos-season-2/7/1.html"><img style="vertical-align:middle" src="/images/ver.gif" alt="verified" /></a> + </span> + <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> + <span style="float:right"> + <a href="/search/narcos-season-2/8/1.html"><img style="vertical-align:middle" src="/images/comments.gif" alt="comments" /></a> | + <a href="/search/narcos-season-2/7/1.html"><img style="vertical-align:middle" src="/images/ver.gif" alt="verified" /></a> + </span> + <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"> + <table width="100%"> + <tr> + <td width="30%"> + <h2>Torrents Download</h2> + <a href="/">Torrent search</a><br /> + <a href="/browse.html">Browse categories</a><br /> + <a href="/verified.html">Verified Torrents</a><br /> + <a href="/order-date.html">Today's torrents</a><br /> + <a href="/yesterday.html">Yesterday's torrents</a><br /> + <a href="/stats.html">Statistics</a><br /> + <br /> + <a href="/faq.html#copyright"><strong>Copyright & Removal</strong></a> + </td> + <td width="30%"><h2>Cool Stuff</h2> + <a href="/promotional.php">Promotional</a><br /> + <a href="/contact.html">Advertising Information</a><br /> + <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 /> + <a href="http://www.utorrent.com">&micro;Torrent Client</a><br /> + <a href="/blog">Seedpeer Blog</a><br /> + </td> + <td width="30%"><h2>Links</h2> + <a href="http://www.sumotorrent.com" target="_blank"><strong>SumoTorrent</strong></a><br /> + <a href="http://www.torrent-finder.info" target="_blank"><strong>Torrent Finder</strong></a><br /> + <a href="http://www.torrentpond.com" target="_blank"><strong>TorrentPond</strong></a><br /> + <a href="https://www.limetorrents.cc" target="_blank">LimeTorrents.cc</a><br /> + <a href="http://www.torrents.to/" target="_blank">Torrents.to</a><br /> + <a href="http://www.torrentfunk.com" target="_blank">TorrentFunk</a><br /> + <a href="https://monova.org" target="_blank">Monova</a><br /> + <a href="http://www.torrentroom.com" target="_blank">TorrentRoom</a><br /> + <a href="http://www.katcr.co/" target="_blank">Kickass Torrents Community</a><br /> + </td> + <td width="10%"><div id="bottomlogo"></div></td> + </tr> + </table> + <br /> + <br /> + </div> + </div> + </body> + </html> +\ No newline at end of file diff --git a/tests/unit/engines/test_digbt.py b/tests/unit/engines/test_digbt.py @@ -28,7 +28,9 @@ class TestDigBTEngine(SearxTestCase): <table class="table"> <tr><td class="x-item"> <div> - <a title="The Big Bang Theory" class="title" href="/The-Big-Bang-Theory-d2.html">The Big Bang Theory</a> + <a title="The Big Bang Theory" class="title" href="/The-Big-Bang-Theory-d2.html"> + The Big <span class="highlight">Bang</span> Theory + </a> <span class="ctime"><span style="color:red;">4 hours ago</span></span> </div> <div class="files"> diff --git a/tests/unit/engines/test_kickass.py b/tests/unit/engines/test_kickass.py @@ -14,7 +14,7 @@ class TestKickassEngine(SearxTestCase): params = kickass.request(query, dicto) self.assertIn('url', params) self.assertIn(query, params['url']) - self.assertIn('kickass.to', params['url']) + self.assertIn('kickass.cd', params['url']) self.assertFalse(params['verify']) def test_response(self): @@ -84,7 +84,7 @@ class TestKickassEngine(SearxTestCase): </span> </div> </td> - <td class="nobr center">449 <span>bytes</span></td> + <td class="nobr center">449 bytes</td> <td class="center">4</td> <td class="center">2&nbsp;years</td> <td class="green center">10</td> @@ -97,7 +97,7 @@ class TestKickassEngine(SearxTestCase): self.assertEqual(type(results), list) self.assertEqual(len(results), 1) self.assertEqual(results[0]['title'], 'This should be the title') - self.assertEqual(results[0]['url'], 'https://kickass.to/url.html') + self.assertEqual(results[0]['url'], 'https://kickass.cd/url.html') self.assertEqual(results[0]['content'], 'Posted by riri in Other &gt; Unsorted') self.assertEqual(results[0]['seed'], 10) self.assertEqual(results[0]['leech'], 1) @@ -191,7 +191,7 @@ class TestKickassEngine(SearxTestCase): </span> </div> </td> - <td class="nobr center">1 <span>KB</span></td> + <td class="nobr center">1 KiB</td> <td class="center">4</td> <td class="center">2&nbsp;years</td> <td class="green center">10</td> @@ -235,7 +235,7 @@ class TestKickassEngine(SearxTestCase): </span> </div> </td> - <td class="nobr center">1 <span>MB</span></td> + <td class="nobr center">1 MiB</td> <td class="center">4</td> <td class="center">2&nbsp;years</td> <td class="green center">9</td> @@ -279,7 +279,7 @@ class TestKickassEngine(SearxTestCase): </span> </div> </td> - <td class="nobr center">1 <span>GB</span></td> + <td class="nobr center">1 GiB</td> <td class="center">4</td> <td class="center">2&nbsp;years</td> <td class="green center">8</td> @@ -323,7 +323,7 @@ class TestKickassEngine(SearxTestCase): </span> </div> </td> - <td class="nobr center">1 <span>TB</span></td> + <td class="nobr center">1 TiB</td> <td class="center">4</td> <td class="center">2&nbsp;years</td> <td class="green center">7</td> @@ -367,7 +367,7 @@ class TestKickassEngine(SearxTestCase): </span> </div> </td> - <td class="nobr center">z <span>bytes</span></td> + <td class="nobr center">z bytes</td> <td class="center">r</td> <td class="center">2&nbsp;years</td> <td class="green center">a</td> @@ -380,17 +380,17 @@ class TestKickassEngine(SearxTestCase): self.assertEqual(type(results), list) self.assertEqual(len(results), 5) self.assertEqual(results[0]['title'], 'This should be the title') - self.assertEqual(results[0]['url'], 'https://kickass.to/url.html') + self.assertEqual(results[0]['url'], 'https://kickass.cd/url.html') self.assertEqual(results[0]['content'], 'Posted by riri in Other &gt; Unsorted') self.assertEqual(results[0]['seed'], 10) self.assertEqual(results[0]['leech'], 1) self.assertEqual(results[0]['files'], 4) self.assertEqual(results[0]['magnetlink'], 'magnet:?xt=urn:btih:MAGNETURL&dn=test') self.assertEqual(results[0]['torrentfile'], 'http://torcache.net/torrent/53917.torrent?title=test') - self.assertEqual(results[0]['filesize'], 1024) - self.assertEqual(results[1]['filesize'], 1048576) - self.assertEqual(results[2]['filesize'], 1073741824) - self.assertEqual(results[3]['filesize'], 1099511627776) + self.assertEqual(results[0]['filesize'], 1000) + self.assertEqual(results[1]['filesize'], 1000000) + self.assertEqual(results[2]['filesize'], 1000000000) + self.assertEqual(results[3]['filesize'], 1000000000000) self.assertEqual(results[4]['seed'], 0) self.assertEqual(results[4]['leech'], 0) self.assertEqual(results[4]['files'], None) diff --git a/tests/unit/engines/test_pdbe.py b/tests/unit/engines/test_pdbe.py @@ -0,0 +1,109 @@ +import mock +from collections import defaultdict +from searx.engines import pdbe +from searx.testing import SearxTestCase + + +class TestPdbeEngine(SearxTestCase): + def test_request(self): + query = 'test_query' + dicto = defaultdict(dict) + params = pdbe.request(query, dicto) + self.assertTrue('url' in params) + self.assertTrue('ebi.ac.uk' in params['url']) + self.assertTrue('data' in params) + self.assertTrue('q' in params['data']) + self.assertTrue(query in params['data']['q']) + self.assertTrue('wt' in params['data']) + self.assertTrue('json' in params['data']['wt']) + self.assertTrue('method' in params) + self.assertTrue(params['method'] == 'POST') + + def test_response(self): + self.assertRaises(AttributeError, pdbe.response, None) + self.assertRaises(AttributeError, pdbe.response, []) + self.assertRaises(AttributeError, pdbe.response, '') + self.assertRaises(AttributeError, pdbe.response, '[]') + + json = """ +{ + "response": { + "docs": [ + { + "citation_title": "X-ray crystal structure of ferric Aplysia limacina myoglobin in different liganded states.", + "citation_year": 1993, + "entry_author_list": [ + "Conti E, Moser C, Rizzi M, Mattevi A, Lionetti C, Coda A, Ascenzi P, Brunori M, Bolognesi M" + ], + "journal": "J. Mol. Biol.", + "journal_page": "498-508", + "journal_volume": "233", + "pdb_id": "2fal", + "status": "REL", + "title": "X-RAY CRYSTAL STRUCTURE OF FERRIC APLYSIA LIMACINA MYOGLOBIN IN DIFFERENT LIGANDED STATES" + } + ], + "numFound": 1, + "start": 0 + }, + "responseHeader": { + "QTime": 0, + "params": { + "q": "2fal", + "wt": "json" + }, + "status": 0 + } +} +""" + + response = mock.Mock(text=json) + results = pdbe.response(response) + self.assertEqual(type(results), list) + self.assertEqual(len(results), 1) + self.assertEqual(results[0]['title'], + 'X-RAY CRYSTAL STRUCTURE OF FERRIC APLYSIA LIMACINA MYOGLOBIN IN DIFFERENT LIGANDED STATES') + self.assertEqual(results[0]['url'], pdbe.pdbe_entry_url.format(pdb_id='2fal')) + self.assertEqual(results[0]['img_src'], pdbe.pdbe_preview_url.format(pdb_id='2fal')) + self.assertTrue('Conti E' in results[0]['content']) + self.assertTrue('X-ray crystal structure of ferric Aplysia limacina myoglobin in different liganded states.' in + results[0]['content']) + self.assertTrue('1993' in results[0]['content']) + + # Testing proper handling of PDB entries marked as obsolete + json = """ +{ + "response": { + "docs": [ + { + "citation_title": "Obsolete entry test", + "citation_year": 2016, + "entry_author_list": ["Doe J"], + "journal": "J. Obs.", + "journal_page": "1-2", + "journal_volume": "1", + "pdb_id": "xxxx", + "status": "OBS", + "title": "OBSOLETE ENTRY TEST", + "superseded_by": "yyyy" + } + ], + "numFound": 1, + "start": 0 + }, + "responseHeader": { + "QTime": 0, + "params": { + "q": "xxxx", + "wt": "json" + }, + "status": 0 + } +} +""" + response = mock.Mock(text=json) + results = pdbe.response(response) + self.assertEqual(type(results), list) + self.assertEqual(len(results), 1) + self.assertEqual(results[0]['title'], 'OBSOLETE ENTRY TEST&nbsp;(OBSOLETE)') + self.assertTrue(results[0]['content'].startswith('<em>This entry has been superseded by')) diff --git a/tests/unit/engines/test_seedpeer.py b/tests/unit/engines/test_seedpeer.py @@ -0,0 +1,51 @@ +import mock +from collections import defaultdict +from searx.engines import seedpeer +from searx.testing import SearxTestCase +from datetime import datetime + + +class TestSeedPeerEngine(SearxTestCase): + + html = '' + with open('./tests/unit/engines/seedpeer_fixture.html') as fixture: + html += fixture.read() + + def test_request(self): + query = 'test_query' + dicto = defaultdict(dict) + dicto['pageno'] = 1 + params = seedpeer.request(query, dicto) + self.assertIn('url', params) + self.assertIn(query, params['url']) + self.assertIn('seedpeer.eu', params['url']) + + def test_response_raises_attr_error_on_empty_response(self): + self.assertRaises(AttributeError, seedpeer.response, None) + self.assertRaises(AttributeError, seedpeer.response, []) + self.assertRaises(AttributeError, seedpeer.response, '') + self.assertRaises(AttributeError, seedpeer.response, '[]') + + def test_response_returns_empty_list(self): + response = mock.Mock(text='<html></html>') + self.assertEqual(seedpeer.response(response), []) + + def test_response_returns_all_results(self): + response = mock.Mock(text=self.html) + results = seedpeer.response(response) + self.assertTrue(isinstance(results, list)) + self.assertEqual(len(results), 2) + + def test_response_returns_correct_results(self): + response = mock.Mock(text=self.html) + results = seedpeer.response(response) + self.assertEqual( + results[0]['title'], 'Narcos - Season 2 - 720p WEBRiP - x265 HEVC - ShAaNiG ' + ) + self.assertEqual( + results[0]['url'], + 'http://www.seedpeer.eu/details/11685972/Narcos---Season-2---720p-WEBRiP---x265-HEVC---ShAaNiG.html' + ) + self.assertEqual(results[0]['content'], '2.48 GB, 1 day') + self.assertEqual(results[0]['seed'], '861') + self.assertEqual(results[0]['leech'], '332') diff --git a/tests/unit/test_webapp.py b/tests/unit/test_webapp.py @@ -44,7 +44,7 @@ class ViewsTestCase(SearxTestCase): webapp.Search.search = search_mock def get_current_theme_name_mock(override=None): - return 'default' + return 'legacy' webapp.get_current_theme_name = get_current_theme_name_mock @@ -58,7 +58,7 @@ class ViewsTestCase(SearxTestCase): def test_index_html(self): result = self.app.post('/', data={'q': 'test'}) self.assertIn( - '<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 + '<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 result.data ) self.assertIn(