mirror of
				https://github.com/searxng/searxng.git
				synced 2025-11-03 19:17:07 -05:00 
			
		
		
		
	
						commit
						d800e3fcfa
					
				
							
								
								
									
										31
									
								
								.codecov.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								.codecov.yml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					comment: false
 | 
				
			||||||
 | 
					coverage:
 | 
				
			||||||
 | 
					  status:
 | 
				
			||||||
 | 
					    project:
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        # basic
 | 
				
			||||||
 | 
					        target: auto
 | 
				
			||||||
 | 
					        threshold: null
 | 
				
			||||||
 | 
					        base: auto 
 | 
				
			||||||
 | 
					        # advanced
 | 
				
			||||||
 | 
					        branches: null
 | 
				
			||||||
 | 
					        if_no_uploads: error
 | 
				
			||||||
 | 
					        if_not_found: success
 | 
				
			||||||
 | 
					        if_ci_failed: error
 | 
				
			||||||
 | 
					        only_pulls: false
 | 
				
			||||||
 | 
					        flags: null
 | 
				
			||||||
 | 
					        paths: null
 | 
				
			||||||
 | 
					    patch:
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        # basic
 | 
				
			||||||
 | 
					        target: auto
 | 
				
			||||||
 | 
					        threshold: null
 | 
				
			||||||
 | 
					        base: auto 
 | 
				
			||||||
 | 
					        # advanced
 | 
				
			||||||
 | 
					        branches: null
 | 
				
			||||||
 | 
					        if_no_uploads: error
 | 
				
			||||||
 | 
					        if_not_found: success
 | 
				
			||||||
 | 
					        if_ci_failed: error
 | 
				
			||||||
 | 
					        only_pulls: false
 | 
				
			||||||
 | 
					        flags: null
 | 
				
			||||||
 | 
					        paths: null
 | 
				
			||||||
@ -13,21 +13,21 @@ python:
 | 
				
			|||||||
before_install:
 | 
					before_install:
 | 
				
			||||||
  - "export DISPLAY=:99.0"
 | 
					  - "export DISPLAY=:99.0"
 | 
				
			||||||
  - "sh -e /etc/init.d/xvfb start"
 | 
					  - "sh -e /etc/init.d/xvfb start"
 | 
				
			||||||
  - npm install less less-plugin-clean-css grunt-cli
 | 
					  - npm install less@2.7 less-plugin-clean-css grunt-cli
 | 
				
			||||||
  - export PATH=`pwd`/node_modules/.bin:$PATH
 | 
					  - export PATH=`pwd`/node_modules/.bin:$PATH
 | 
				
			||||||
  - ./manage.sh install_geckodriver ~/drivers
 | 
					  - ./manage.sh install_geckodriver ~/drivers
 | 
				
			||||||
  - export PATH=~/drivers:$PATH
 | 
					  - export PATH=~/drivers:$PATH
 | 
				
			||||||
install:
 | 
					install:
 | 
				
			||||||
  - ./manage.sh npm_packages
 | 
					  - ./manage.sh npm_packages
 | 
				
			||||||
  - ./manage.sh update_dev_packages
 | 
					  - ./manage.sh update_dev_packages
 | 
				
			||||||
  - pip install coveralls
 | 
					  - pip install codecov
 | 
				
			||||||
script:
 | 
					script:
 | 
				
			||||||
  - ./manage.sh styles
 | 
					  - ./manage.sh styles
 | 
				
			||||||
  - ./manage.sh grunt_build
 | 
					  - ./manage.sh grunt_build
 | 
				
			||||||
  - ./manage.sh tests
 | 
					  - ./manage.sh tests
 | 
				
			||||||
after_success:
 | 
					after_success:
 | 
				
			||||||
  - ./manage.sh py_test_coverage
 | 
					  - ./manage.sh py_test_coverage
 | 
				
			||||||
  - coveralls
 | 
					  - codecov
 | 
				
			||||||
notifications:
 | 
					notifications:
 | 
				
			||||||
  irc:
 | 
					  irc:
 | 
				
			||||||
    channels:
 | 
					    channels:
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										12
									
								
								README.rst
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								README.rst
									
									
									
									
									
								
							@ -9,7 +9,8 @@ instances <https://github.com/asciimoo/searx/wiki/Searx-instances>`__.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
See the `documentation <https://asciimoo.github.io/searx>`__ and the `wiki <https://github.com/asciimoo/searx/wiki>`__ for more information.
 | 
					See the `documentation <https://asciimoo.github.io/searx>`__ and the `wiki <https://github.com/asciimoo/searx/wiki>`__ for more information.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
|Flattr searx|
 | 
					|OpenCollective searx backers|
 | 
				
			||||||
 | 
					|OpenCollective searx sponsors|
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Installation
 | 
					Installation
 | 
				
			||||||
~~~~~~~~~~~~
 | 
					~~~~~~~~~~~~
 | 
				
			||||||
@ -41,5 +42,10 @@ More about searx
 | 
				
			|||||||
-  `twitter <https://twitter.com/Searx_engine>`__
 | 
					-  `twitter <https://twitter.com/Searx_engine>`__
 | 
				
			||||||
-  IRC: #searx @ freenode
 | 
					-  IRC: #searx @ freenode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. |Flattr searx| image:: http://api.flattr.com/button/flattr-badge-large.png
 | 
					
 | 
				
			||||||
   :target: https://flattr.com/submit/auto?user_id=asciimoo&url=https://github.com/asciimoo/searx&title=searx&language=&tags=github&category=software
 | 
					.. |OpenCollective searx backers| image:: https://opencollective.com/searx/backers/badge.svg
 | 
				
			||||||
 | 
					   :target: https://opencollective.com/searx#backer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. |OpenCollective searx sponsors| image:: https://opencollective.com/searx/sponsors/badge.svg
 | 
				
			||||||
 | 
					   :target: https://opencollective.com/searx#sponsor
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										74
									
								
								manage.sh
									
									
									
									
									
								
							
							
						
						
									
										74
									
								
								manage.sh
									
									
									
									
									
								
							@ -1,11 +1,11 @@
 | 
				
			|||||||
#!/bin/sh
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BASE_DIR=$(dirname "`readlink -f "$0"`")
 | 
					BASE_DIR="$(dirname -- "`readlink -f -- "$0"`")"
 | 
				
			||||||
PYTHONPATH=$BASE_DIR
 | 
					PYTHONPATH="$BASE_DIR"
 | 
				
			||||||
SEARX_DIR="$BASE_DIR/searx"
 | 
					SEARX_DIR="$BASE_DIR/searx"
 | 
				
			||||||
ACTION=$1
 | 
					ACTION="$1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cd "$BASE_DIR"
 | 
					cd -- "$BASE_DIR"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
update_packages() {
 | 
					update_packages() {
 | 
				
			||||||
    pip install --upgrade pip
 | 
					    pip install --upgrade pip
 | 
				
			||||||
@ -22,40 +22,40 @@ install_geckodriver() {
 | 
				
			|||||||
    echo '[!] Checking geckodriver'
 | 
					    echo '[!] Checking geckodriver'
 | 
				
			||||||
    # TODO : check the current geckodriver version
 | 
					    # TODO : check the current geckodriver version
 | 
				
			||||||
    set -e
 | 
					    set -e
 | 
				
			||||||
    geckodriver -V 2>1 > /dev/null || NOTFOUND=1
 | 
					    geckodriver -V > /dev/null 2>&1 || NOTFOUND=1
 | 
				
			||||||
    set +e
 | 
					    set +e
 | 
				
			||||||
    if [ -z $NOTFOUND ]; then
 | 
					    if [ -z "$NOTFOUND" ]; then
 | 
				
			||||||
	return
 | 
					        return
 | 
				
			||||||
    fi
 | 
					    fi
 | 
				
			||||||
    GECKODRIVER_VERSION="v0.18.0"
 | 
					    GECKODRIVER_VERSION="v0.18.0"
 | 
				
			||||||
    PLATFORM=`python -c "import six; import platform; six.print_(platform.system().lower(), platform.architecture()[0])"`
 | 
					    PLATFORM="`python -c "import six; import platform; six.print_(platform.system().lower(), platform.architecture()[0])"`"
 | 
				
			||||||
    case $PLATFORM in
 | 
					    case "$PLATFORM" in
 | 
				
			||||||
	"linux 32bit" | "linux2 32bit") ARCH="linux32";;
 | 
					        "linux 32bit" | "linux2 32bit") ARCH="linux32";;
 | 
				
			||||||
	"linux 64bit" | "linux2 64bit") ARCH="linux64";;
 | 
					        "linux 64bit" | "linux2 64bit") ARCH="linux64";;
 | 
				
			||||||
	"windows 32 bit") ARCH="win32";;
 | 
					        "windows 32 bit") ARCH="win32";;
 | 
				
			||||||
	"windows 64 bit") ARCH="win64";;
 | 
					        "windows 64 bit") ARCH="win64";;
 | 
				
			||||||
	"mac 64bit") ARCH="macos";;
 | 
					        "mac 64bit") ARCH="macos";;
 | 
				
			||||||
    esac
 | 
					    esac
 | 
				
			||||||
    GECKODRIVER_URL="https://github.com/mozilla/geckodriver/releases/download/$GECKODRIVER_VERSION/geckodriver-$GECKODRIVER_VERSION-$ARCH.tar.gz";
 | 
					    GECKODRIVER_URL="https://github.com/mozilla/geckodriver/releases/download/$GECKODRIVER_VERSION/geckodriver-$GECKODRIVER_VERSION-$ARCH.tar.gz";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if [ -z "$1" ]; then
 | 
					    if [ -z "$1" ]; then
 | 
				
			||||||
	if [ -z "$VIRTUAL_ENV" ]; then
 | 
					        if [ -z "$VIRTUAL_ENV" ]; then
 | 
				
			||||||
	    echo "geckodriver can't be installed because VIRTUAL_ENV is not set, you should download it from\n  $GECKODRIVER_URL"
 | 
					            echo "geckodriver can't be installed because VIRTUAL_ENV is not set, you should download it from\n  $GECKODRIVER_URL"
 | 
				
			||||||
	    exit    
 | 
					            exit
 | 
				
			||||||
	else
 | 
					        else
 | 
				
			||||||
	    GECKODRIVER_DIR="$VIRTUAL_ENV/bin"
 | 
					            GECKODRIVER_DIR="$VIRTUAL_ENV/bin"
 | 
				
			||||||
	fi
 | 
					        fi
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
	GECKODRIVER_DIR="$1"
 | 
					        GECKODRIVER_DIR="$1"
 | 
				
			||||||
	mkdir -p "$GECKODRIVER_DIR"
 | 
					        mkdir -p -- "$GECKODRIVER_DIR"
 | 
				
			||||||
    fi
 | 
					    fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    echo "Installing $GECKODRIVER_DIR/geckodriver from\n  $GECKODRIVER_URL"
 | 
					    echo "Installing $GECKODRIVER_DIR/geckodriver from\n  $GECKODRIVER_URL"
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    FILE=`mktemp`
 | 
					    FILE="`mktemp`"
 | 
				
			||||||
    wget "$GECKODRIVER_URL" -qO $FILE && tar xz -C "$GECKODRIVER_DIR" -f $FILE geckodriver
 | 
					    wget -qO "$FILE" -- "$GECKODRIVER_URL" && tar xz -C "$GECKODRIVER_DIR" -f "$FILE" geckodriver
 | 
				
			||||||
    rm $FILE
 | 
					    rm -- "$FILE"
 | 
				
			||||||
    chmod 777 "$GECKODRIVER_DIR/geckodriver"
 | 
					    chmod 777 -- "$GECKODRIVER_DIR/geckodriver"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pep8_check() {
 | 
					pep8_check() {
 | 
				
			||||||
@ -73,14 +73,14 @@ unit_tests() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
py_test_coverage() {
 | 
					py_test_coverage() {
 | 
				
			||||||
    echo '[!] Running python test coverage'
 | 
					    echo '[!] Running python test coverage'
 | 
				
			||||||
    PYTHONPATH=`pwd` python -m nose2 -C --coverage "$SEARX_DIR" -s "$BASE_DIR/tests/unit"
 | 
					    PYTHONPATH="`pwd`" python -m nose2 -C --log-capture --with-coverage --coverage "$SEARX_DIR" -s "$BASE_DIR/tests/unit" \
 | 
				
			||||||
    coverage report
 | 
					    && coverage report \
 | 
				
			||||||
    coverage html
 | 
					    && coverage html
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
robot_tests() {
 | 
					robot_tests() {
 | 
				
			||||||
    echo '[!] Running robot tests'
 | 
					    echo '[!] Running robot tests'
 | 
				
			||||||
    PYTHONPATH=`pwd` python "$SEARX_DIR/testing.py" robot
 | 
					    PYTHONPATH="`pwd`" python "$SEARX_DIR/testing.py" robot
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
tests() {
 | 
					tests() {
 | 
				
			||||||
@ -113,18 +113,18 @@ styles() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
npm_packages() {
 | 
					npm_packages() {
 | 
				
			||||||
    echo '[!] install NPM packages for oscar theme'
 | 
					    echo '[!] install NPM packages for oscar theme'
 | 
				
			||||||
    cd $BASE_DIR/searx/static/themes/oscar
 | 
					    cd -- "$BASE_DIR/searx/static/themes/oscar"
 | 
				
			||||||
    npm install
 | 
					    npm install
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    echo '[!] install NPM packages for simple theme'    
 | 
					    echo '[!] install NPM packages for simple theme'
 | 
				
			||||||
    cd $BASE_DIR/searx/static/themes/simple
 | 
					    cd -- "$BASE_DIR/searx/static/themes/simple"
 | 
				
			||||||
    npm install
 | 
					    npm install
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
grunt_build() {
 | 
					grunt_build() {
 | 
				
			||||||
    echo '[!] Grunt build : oscar theme'
 | 
					    echo '[!] Grunt build : oscar theme'
 | 
				
			||||||
    grunt --gruntfile "$SEARX_DIR/static/themes/oscar/gruntfile.js"
 | 
					    grunt --gruntfile "$SEARX_DIR/static/themes/oscar/gruntfile.js"
 | 
				
			||||||
    echo '[!] Grunt build : simple theme'    
 | 
					    echo '[!] Grunt build : simple theme'
 | 
				
			||||||
    grunt --gruntfile "$SEARX_DIR/static/themes/simple/gruntfile.js"
 | 
					    grunt --gruntfile "$SEARX_DIR/static/themes/simple/gruntfile.js"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -133,7 +133,7 @@ locales() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
help() {
 | 
					help() {
 | 
				
			||||||
    [ -z "$1" ] || printf "Error: $1\n"
 | 
					    [ -z "$1" ] || printf 'Error: %s\n' "$1"
 | 
				
			||||||
    echo "Searx manage.sh help
 | 
					    echo "Searx manage.sh help
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Commands
 | 
					Commands
 | 
				
			||||||
@ -156,4 +156,4 @@ Commands
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[ "$(command -V "$ACTION" | grep ' function$')" = "" ] \
 | 
					[ "$(command -V "$ACTION" | grep ' function$')" = "" ] \
 | 
				
			||||||
    && help "action not found" \
 | 
					    && help "action not found" \
 | 
				
			||||||
    || $ACTION "$2"
 | 
					    || "$ACTION" "$2"
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
babel==2.3.4
 | 
					babel==2.3.4
 | 
				
			||||||
mock==2.0.0
 | 
					mock==2.0.0
 | 
				
			||||||
nose2[coverage-plugin]
 | 
					nose2[coverage-plugin]
 | 
				
			||||||
 | 
					cov-core==1.15.0
 | 
				
			||||||
pep8==1.7.0
 | 
					pep8==1.7.0
 | 
				
			||||||
plone.testing==5.0.0
 | 
					plone.testing==5.0.0
 | 
				
			||||||
splinter==0.7.5
 | 
					splinter==0.7.5
 | 
				
			||||||
 | 
				
			|||||||
@ -7,4 +7,4 @@ pygments==2.1.3
 | 
				
			|||||||
pyopenssl==17.2.0
 | 
					pyopenssl==17.2.0
 | 
				
			||||||
python-dateutil==2.6.1
 | 
					python-dateutil==2.6.1
 | 
				
			||||||
pyyaml==3.12
 | 
					pyyaml==3.12
 | 
				
			||||||
requests[socks]==2.14.2
 | 
					requests[socks]==2.18.4
 | 
				
			||||||
 | 
				
			|||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@ -18,7 +18,6 @@
 | 
				
			|||||||
from lxml import html
 | 
					from lxml import html
 | 
				
			||||||
from json import loads
 | 
					from json import loads
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
from searx.engines.bing import _fetch_supported_languages, supported_languages_url
 | 
					 | 
				
			||||||
from searx.url_utils import urlencode
 | 
					from searx.url_utils import urlencode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# engine dependent config
 | 
					# engine dependent config
 | 
				
			||||||
@ -26,6 +25,8 @@ categories = ['images']
 | 
				
			|||||||
paging = True
 | 
					paging = True
 | 
				
			||||||
safesearch = True
 | 
					safesearch = True
 | 
				
			||||||
time_range_support = True
 | 
					time_range_support = True
 | 
				
			||||||
 | 
					language_support = True
 | 
				
			||||||
 | 
					supported_languages_url = 'https://www.bing.com/account/general'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# search-url
 | 
					# search-url
 | 
				
			||||||
base_url = 'https://www.bing.com/'
 | 
					base_url = 'https://www.bing.com/'
 | 
				
			||||||
@ -45,23 +46,41 @@ safesearch_types = {2: 'STRICT',
 | 
				
			|||||||
_quote_keys_regex = re.compile('({|,)([a-z][a-z0-9]*):(")', re.I | re.U)
 | 
					_quote_keys_regex = re.compile('({|,)([a-z][a-z0-9]*):(")', re.I | re.U)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# get supported region code
 | 
				
			||||||
 | 
					def get_region_code(lang, lang_list=None):
 | 
				
			||||||
 | 
					    region = None
 | 
				
			||||||
 | 
					    if lang in (lang_list or supported_languages):
 | 
				
			||||||
 | 
					        region = lang
 | 
				
			||||||
 | 
					    elif lang.startswith('no'):
 | 
				
			||||||
 | 
					        region = 'nb-NO'
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        # try to get a supported country code with language
 | 
				
			||||||
 | 
					        lang = lang.split('-')[0]
 | 
				
			||||||
 | 
					        for lc in (lang_list or supported_languages):
 | 
				
			||||||
 | 
					            if lang == lc.split('-')[0]:
 | 
				
			||||||
 | 
					                region = lc
 | 
				
			||||||
 | 
					                break
 | 
				
			||||||
 | 
					    if region:
 | 
				
			||||||
 | 
					        return region.lower()
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        return 'en-us'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# do search-request
 | 
					# do search-request
 | 
				
			||||||
def request(query, params):
 | 
					def request(query, params):
 | 
				
			||||||
    offset = (params['pageno'] - 1) * 10 + 1
 | 
					    offset = (params['pageno'] - 1) * 10 + 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # required for cookie
 | 
					 | 
				
			||||||
    if params['language'] == 'all':
 | 
					 | 
				
			||||||
        language = 'en-US'
 | 
					 | 
				
			||||||
    else:
 | 
					 | 
				
			||||||
        language = params['language']
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    search_path = search_string.format(
 | 
					    search_path = search_string.format(
 | 
				
			||||||
        query=urlencode({'q': query}),
 | 
					        query=urlencode({'q': query}),
 | 
				
			||||||
        offset=offset)
 | 
					        offset=offset)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    language = get_region_code(params['language'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    params['cookies']['SRCHHPGUSR'] = \
 | 
					    params['cookies']['SRCHHPGUSR'] = \
 | 
				
			||||||
        'NEWWND=0&NRSLT=-1&SRCHLANG=' + language.split('-')[0] +\
 | 
					        'ADLT=' + safesearch_types.get(params['safesearch'], 'DEMOTE')
 | 
				
			||||||
        '&ADLT=' + safesearch_types.get(params['safesearch'], 'DEMOTE')
 | 
					
 | 
				
			||||||
 | 
					    params['cookies']['_EDGE_S'] = 'mkt=' + language +\
 | 
				
			||||||
 | 
					        '&ui=' + language + '&F=1'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    params['url'] = base_url + search_path
 | 
					    params['url'] = base_url + search_path
 | 
				
			||||||
    if params['time_range'] in time_range_dict:
 | 
					    if params['time_range'] in time_range_dict:
 | 
				
			||||||
@ -106,3 +125,22 @@ def response(resp):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    # return results
 | 
					    # return results
 | 
				
			||||||
    return results
 | 
					    return results
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# get supported languages from their site
 | 
				
			||||||
 | 
					def _fetch_supported_languages(resp):
 | 
				
			||||||
 | 
					    supported_languages = []
 | 
				
			||||||
 | 
					    dom = html.fromstring(resp.text)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    regions_xpath = '//div[@id="region-section-content"]' \
 | 
				
			||||||
 | 
					                    + '//ul[@class="b_vList"]/li/a/@href'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    regions = dom.xpath(regions_xpath)
 | 
				
			||||||
 | 
					    for region in regions:
 | 
				
			||||||
 | 
					        code = re.search('setmkt=[^\&]+', region).group()[7:]
 | 
				
			||||||
 | 
					        if code == 'nb-NO':
 | 
				
			||||||
 | 
					            code = 'no-NO'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        supported_languages.append(code)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return supported_languages
 | 
				
			||||||
 | 
				
			|||||||
@ -12,6 +12,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from json import loads
 | 
					from json import loads
 | 
				
			||||||
from lxml import html
 | 
					from lxml import html
 | 
				
			||||||
 | 
					from searx.engines.bing_images import _fetch_supported_languages, supported_languages_url, get_region_code
 | 
				
			||||||
from searx.engines.xpath import extract_text
 | 
					from searx.engines.xpath import extract_text
 | 
				
			||||||
from searx.url_utils import urlencode
 | 
					from searx.url_utils import urlencode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -21,6 +22,7 @@ paging = True
 | 
				
			|||||||
safesearch = True
 | 
					safesearch = True
 | 
				
			||||||
time_range_support = True
 | 
					time_range_support = True
 | 
				
			||||||
number_of_results = 10
 | 
					number_of_results = 10
 | 
				
			||||||
 | 
					language_support = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
search_url = 'https://www.bing.com/videos/asyncv2?{query}&async=content&'\
 | 
					search_url = 'https://www.bing.com/videos/asyncv2?{query}&async=content&'\
 | 
				
			||||||
             'first={offset}&count={number_of_results}&CW=1366&CH=25&FORM=R5VR5'
 | 
					             'first={offset}&count={number_of_results}&CW=1366&CH=25&FORM=R5VR5'
 | 
				
			||||||
@ -45,7 +47,8 @@ def request(query, params):
 | 
				
			|||||||
        'ADLT=' + safesearch_types.get(params['safesearch'], 'DEMOTE')
 | 
					        'ADLT=' + safesearch_types.get(params['safesearch'], 'DEMOTE')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # language cookie
 | 
					    # language cookie
 | 
				
			||||||
    params['cookies']['_EDGE_S'] = 'mkt=' + params['language'].lower() + '&F=1'
 | 
					    region = get_region_code(params['language'], lang_list=supported_languages)
 | 
				
			||||||
 | 
					    params['cookies']['_EDGE_S'] = 'mkt=' + region + '&F=1'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # query and paging
 | 
					    # query and paging
 | 
				
			||||||
    params['url'] = search_url.format(query=urlencode({'q': query}),
 | 
					    params['url'] = search_url.format(query=urlencode({'q': query}),
 | 
				
			||||||
 | 
				
			|||||||
@ -1,70 +0,0 @@
 | 
				
			|||||||
"""
 | 
					 | 
				
			||||||
 Blekko (Images)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 @website     https://blekko.com
 | 
					 | 
				
			||||||
 @provide-api yes (inofficial)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 @using-api   yes
 | 
					 | 
				
			||||||
 @results     JSON
 | 
					 | 
				
			||||||
 @stable      yes
 | 
					 | 
				
			||||||
 @parse       url, title, img_src
 | 
					 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from json import loads
 | 
					 | 
				
			||||||
from searx.url_utils import urlencode
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# engine dependent config
 | 
					 | 
				
			||||||
categories = ['images']
 | 
					 | 
				
			||||||
paging = True
 | 
					 | 
				
			||||||
safesearch = True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# search-url
 | 
					 | 
				
			||||||
base_url = 'https://blekko.com'
 | 
					 | 
				
			||||||
search_url = '/api/images?{query}&c={c}'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# safesearch definitions
 | 
					 | 
				
			||||||
safesearch_types = {2: '1',
 | 
					 | 
				
			||||||
                    1: '',
 | 
					 | 
				
			||||||
                    0: '0'}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# do search-request
 | 
					 | 
				
			||||||
def request(query, params):
 | 
					 | 
				
			||||||
    c = (params['pageno'] - 1) * 48
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    params['url'] = base_url +\
 | 
					 | 
				
			||||||
        search_url.format(query=urlencode({'q': query}),
 | 
					 | 
				
			||||||
                          c=c)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if params['pageno'] != 1:
 | 
					 | 
				
			||||||
        params['url'] += '&page={pageno}'.format(pageno=(params['pageno'] - 1))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # let Blekko know we wan't have profiling
 | 
					 | 
				
			||||||
    params['cookies']['tag_lesslogging'] = '1'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # parse safesearch argument
 | 
					 | 
				
			||||||
    params['cookies']['safesearch'] = safesearch_types.get(params['safesearch'], '')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return params
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# get response from search-request
 | 
					 | 
				
			||||||
def response(resp):
 | 
					 | 
				
			||||||
    results = []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    search_results = loads(resp.text)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # return empty array if there are no results
 | 
					 | 
				
			||||||
    if not search_results:
 | 
					 | 
				
			||||||
        return []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for result in search_results:
 | 
					 | 
				
			||||||
        # append result
 | 
					 | 
				
			||||||
        results.append({'url': result['page_url'],
 | 
					 | 
				
			||||||
                        'title': result['title'],
 | 
					 | 
				
			||||||
                        'content': '',
 | 
					 | 
				
			||||||
                        'img_src': result['url'],
 | 
					 | 
				
			||||||
                        'template': 'images.html'})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # return results
 | 
					 | 
				
			||||||
    return results
 | 
					 | 
				
			||||||
@ -10,6 +10,8 @@
 | 
				
			|||||||
 @parse       url, title, content, publishedDate, thumbnail
 | 
					 @parse       url, title, content, publishedDate, thumbnail
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import random
 | 
				
			||||||
 | 
					import string
 | 
				
			||||||
from dateutil import parser
 | 
					from dateutil import parser
 | 
				
			||||||
from json import loads
 | 
					from json import loads
 | 
				
			||||||
from lxml import html
 | 
					from lxml import html
 | 
				
			||||||
@ -30,12 +32,17 @@ title_xpath = './/h2//a//text()'
 | 
				
			|||||||
content_xpath = './/p//text()'
 | 
					content_xpath = './/p//text()'
 | 
				
			||||||
pubdate_xpath = './/time'
 | 
					pubdate_xpath = './/time'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					digg_cookie_chars = string.ascii_uppercase + string.ascii_lowercase +\
 | 
				
			||||||
 | 
					    string.digits + "+_"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# do search-request
 | 
					# do search-request
 | 
				
			||||||
def request(query, params):
 | 
					def request(query, params):
 | 
				
			||||||
    offset = (params['pageno'] - 1) * 10
 | 
					    offset = (params['pageno'] - 1) * 10
 | 
				
			||||||
    params['url'] = search_url.format(position=offset,
 | 
					    params['url'] = search_url.format(position=offset,
 | 
				
			||||||
                                      query=quote_plus(query))
 | 
					                                      query=quote_plus(query))
 | 
				
			||||||
 | 
					    params['cookies']['frontend.auid'] = ''.join(random.choice(
 | 
				
			||||||
 | 
					        digg_cookie_chars) for _ in range(22))
 | 
				
			||||||
    return params
 | 
					    return params
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -134,4 +134,4 @@ def _fetch_supported_languages(resp):
 | 
				
			|||||||
    regions_json = loads(response_page)
 | 
					    regions_json = loads(response_page)
 | 
				
			||||||
    supported_languages = map((lambda x: x[3:] + '-' + x[:2].upper()), regions_json.keys())
 | 
					    supported_languages = map((lambda x: x[3:] + '-' + x[:2].upper()), regions_json.keys())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return supported_languages
 | 
					    return list(supported_languages)
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@
 | 
				
			|||||||
 @website     http://www.faroo.com
 | 
					 @website     http://www.faroo.com
 | 
				
			||||||
 @provide-api yes (http://www.faroo.com/hp/api/api.html), require API-key
 | 
					 @provide-api yes (http://www.faroo.com/hp/api/api.html), require API-key
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 @using-api   yes
 | 
					 @using-api   no
 | 
				
			||||||
 @results     JSON
 | 
					 @results     JSON
 | 
				
			||||||
 @stable      yes
 | 
					 @stable      yes
 | 
				
			||||||
 @parse       url, title, content, publishedDate, img_src
 | 
					 @parse       url, title, content, publishedDate, img_src
 | 
				
			||||||
@ -20,18 +20,16 @@ categories = ['general', 'news']
 | 
				
			|||||||
paging = True
 | 
					paging = True
 | 
				
			||||||
language_support = True
 | 
					language_support = True
 | 
				
			||||||
number_of_results = 10
 | 
					number_of_results = 10
 | 
				
			||||||
api_key = None
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# search-url
 | 
					# search-url
 | 
				
			||||||
url = 'http://www.faroo.com/'
 | 
					url = 'http://www.faroo.com/'
 | 
				
			||||||
search_url = url + 'api?{query}'\
 | 
					search_url = url + 'instant.json?{query}'\
 | 
				
			||||||
                      '&start={offset}'\
 | 
					    '&start={offset}'\
 | 
				
			||||||
                      '&length={number_of_results}'\
 | 
					    '&length={number_of_results}'\
 | 
				
			||||||
                      '&l={language}'\
 | 
					    '&l={language}'\
 | 
				
			||||||
                      '&src={categorie}'\
 | 
					    '&src={categorie}'\
 | 
				
			||||||
                      '&i=false'\
 | 
					    '&i=false'\
 | 
				
			||||||
                      '&f=json'\
 | 
					    '&c=false'
 | 
				
			||||||
                      '&key={api_key}'  # noqa
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
search_category = {'general': 'web',
 | 
					search_category = {'general': 'web',
 | 
				
			||||||
                   'news': 'news'}
 | 
					                   'news': 'news'}
 | 
				
			||||||
@ -57,21 +55,15 @@ def request(query, params):
 | 
				
			|||||||
                                      number_of_results=number_of_results,
 | 
					                                      number_of_results=number_of_results,
 | 
				
			||||||
                                      query=urlencode({'q': query}),
 | 
					                                      query=urlencode({'q': query}),
 | 
				
			||||||
                                      language=language,
 | 
					                                      language=language,
 | 
				
			||||||
                                      categorie=categorie,
 | 
					                                      categorie=categorie)
 | 
				
			||||||
                                      api_key=api_key)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # using searx User-Agent
 | 
					    params['headers']['Referer'] = url
 | 
				
			||||||
    params['headers']['User-Agent'] = searx_useragent()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return params
 | 
					    return params
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# get response from search-request
 | 
					# get response from search-request
 | 
				
			||||||
def response(resp):
 | 
					def response(resp):
 | 
				
			||||||
    # HTTP-Code 401: api-key is not valide
 | 
					 | 
				
			||||||
    if resp.status_code == 401:
 | 
					 | 
				
			||||||
        raise Exception("API key is not valide")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # HTTP-Code 429: rate limit exceeded
 | 
					    # HTTP-Code 429: rate limit exceeded
 | 
				
			||||||
    if resp.status_code == 429:
 | 
					    if resp.status_code == 429:
 | 
				
			||||||
        raise Exception("rate limit has been exceeded!")
 | 
					        raise Exception("rate limit has been exceeded!")
 | 
				
			||||||
@ -86,31 +78,19 @@ def response(resp):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    # parse results
 | 
					    # parse results
 | 
				
			||||||
    for result in search_res['results']:
 | 
					    for result in search_res['results']:
 | 
				
			||||||
 | 
					        publishedDate = None
 | 
				
			||||||
 | 
					        result_json = {'url': result['url'], 'title': result['title'],
 | 
				
			||||||
 | 
					                       'content': result['kwic']}
 | 
				
			||||||
        if result['news']:
 | 
					        if result['news']:
 | 
				
			||||||
            # timestamp (milliseconds since 1970)
 | 
					            result_json['publishedDate'] = \
 | 
				
			||||||
            publishedDate = datetime.datetime.fromtimestamp(result['date'] / 1000.0)  # noqa
 | 
					                datetime.datetime.fromtimestamp(result['date'] / 1000.0)
 | 
				
			||||||
 | 
					 | 
				
			||||||
            # append news result
 | 
					 | 
				
			||||||
            results.append({'url': result['url'],
 | 
					 | 
				
			||||||
                            'title': result['title'],
 | 
					 | 
				
			||||||
                            'publishedDate': publishedDate,
 | 
					 | 
				
			||||||
                            'content': result['kwic']})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            # append general result
 | 
					 | 
				
			||||||
            # TODO, publishedDate correct?
 | 
					 | 
				
			||||||
            results.append({'url': result['url'],
 | 
					 | 
				
			||||||
                            'title': result['title'],
 | 
					 | 
				
			||||||
                            'content': result['kwic']})
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # append image result if image url is set
 | 
					        # append image result if image url is set
 | 
				
			||||||
        # TODO, show results with an image like in faroo
 | 
					 | 
				
			||||||
        if result['iurl']:
 | 
					        if result['iurl']:
 | 
				
			||||||
            results.append({'template': 'images.html',
 | 
					            result_json['template'] = 'videos.html'
 | 
				
			||||||
                            'url': result['url'],
 | 
					            result_json['thumbnail'] = result['iurl']
 | 
				
			||||||
                            'title': result['title'],
 | 
					
 | 
				
			||||||
                            'content': result['kwic'],
 | 
					        results.append(result_json)
 | 
				
			||||||
                            'img_src': result['iurl']})
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # return results
 | 
					    # return results
 | 
				
			||||||
    return results
 | 
					    return results
 | 
				
			||||||
 | 
				
			|||||||
@ -1,62 +0,0 @@
 | 
				
			|||||||
"""
 | 
					 | 
				
			||||||
 General Files (Files)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 @website     http://www.general-files.org
 | 
					 | 
				
			||||||
 @provide-api no (nothing found)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 @using-api   no (because nothing found)
 | 
					 | 
				
			||||||
 @results     HTML (using search portal)
 | 
					 | 
				
			||||||
 @stable      no (HTML can change)
 | 
					 | 
				
			||||||
 @parse       url, title, content
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 @todo        detect torrents?
 | 
					 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from lxml import html
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# engine dependent config
 | 
					 | 
				
			||||||
categories = ['files']
 | 
					 | 
				
			||||||
paging = True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# search-url
 | 
					 | 
				
			||||||
base_url = 'http://www.general-file.com'
 | 
					 | 
				
			||||||
search_url = base_url + '/files-{letter}/{query}/{pageno}'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# specific xpath variables
 | 
					 | 
				
			||||||
result_xpath = '//table[@class="block-file"]'
 | 
					 | 
				
			||||||
title_xpath = './/h2/a//text()'
 | 
					 | 
				
			||||||
url_xpath = './/h2/a/@href'
 | 
					 | 
				
			||||||
content_xpath = './/p//text()'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# do search-request
 | 
					 | 
				
			||||||
def request(query, params):
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    params['url'] = search_url.format(query=query,
 | 
					 | 
				
			||||||
                                      letter=query[0],
 | 
					 | 
				
			||||||
                                      pageno=params['pageno'])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return params
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# get response from search-request
 | 
					 | 
				
			||||||
def response(resp):
 | 
					 | 
				
			||||||
    results = []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    dom = html.fromstring(resp.text)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # parse results
 | 
					 | 
				
			||||||
    for result in dom.xpath(result_xpath):
 | 
					 | 
				
			||||||
        url = result.xpath(url_xpath)[0]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # skip fast download links
 | 
					 | 
				
			||||||
        if not url.startswith('/'):
 | 
					 | 
				
			||||||
            continue
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # append result
 | 
					 | 
				
			||||||
        results.append({'url': base_url + url,
 | 
					 | 
				
			||||||
                        'title': ''.join(result.xpath(title_xpath)),
 | 
					 | 
				
			||||||
                        'content': ''.join(result.xpath(content_xpath))})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # return results
 | 
					 | 
				
			||||||
    return results
 | 
					 | 
				
			||||||
@ -10,6 +10,7 @@
 | 
				
			|||||||
 @parse       url, title, content
 | 
					 @parse       url, title, content
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import random
 | 
				
			||||||
from json import loads
 | 
					from json import loads
 | 
				
			||||||
from time import time
 | 
					from time import time
 | 
				
			||||||
from lxml.html import fromstring
 | 
					from lxml.html import fromstring
 | 
				
			||||||
@ -32,7 +33,8 @@ search_string = 'search?{query}'\
 | 
				
			|||||||
    '&qh=0'\
 | 
					    '&qh=0'\
 | 
				
			||||||
    '&qlang={lang}'\
 | 
					    '&qlang={lang}'\
 | 
				
			||||||
    '&ff={safesearch}'\
 | 
					    '&ff={safesearch}'\
 | 
				
			||||||
    '&rxikd={rxikd}'  # random number - 9 digits
 | 
					    '&rxieu={rxieu}'\
 | 
				
			||||||
 | 
					    '&rand={rxikd}'  # current unix timestamp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# specific xpath variables
 | 
					# specific xpath variables
 | 
				
			||||||
results_xpath = '//response//result'
 | 
					results_xpath = '//response//result'
 | 
				
			||||||
@ -59,10 +61,12 @@ def request(query, params):
 | 
				
			|||||||
    else:
 | 
					    else:
 | 
				
			||||||
        safesearch = 0
 | 
					        safesearch = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # rxieu is some kind of hash from the search query, but accepts random atm
 | 
				
			||||||
    search_path = search_string.format(query=urlencode({'q': query}),
 | 
					    search_path = search_string.format(query=urlencode({'q': query}),
 | 
				
			||||||
                                       offset=offset,
 | 
					                                       offset=offset,
 | 
				
			||||||
                                       number_of_results=number_of_results,
 | 
					                                       number_of_results=number_of_results,
 | 
				
			||||||
                                       rxikd=str(time())[:9],
 | 
					                                       rxikd=int(time() * 1000),
 | 
				
			||||||
 | 
					                                       rxieu=random.randint(1000000000, 9999999999),
 | 
				
			||||||
                                       lang=language,
 | 
					                                       lang=language,
 | 
				
			||||||
                                       safesearch=safesearch)
 | 
					                                       safesearch=safesearch)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -67,8 +67,8 @@ def response(resp):
 | 
				
			|||||||
    for result in dom.xpath('//div[@class="g"]|//div[@class="g _cy"]'):
 | 
					    for result in dom.xpath('//div[@class="g"]|//div[@class="g _cy"]'):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            r = {
 | 
					            r = {
 | 
				
			||||||
                'url': result.xpath('.//div[@class="_cnc"]//a/@href')[0],
 | 
					                'url': result.xpath('.//a[@class="l _PMs"]')[0].attrib.get("href"),
 | 
				
			||||||
                'title': ''.join(result.xpath('.//div[@class="_cnc"]//h3//text()')),
 | 
					                'title': ''.join(result.xpath('.//a[@class="l _PMs"]//text()')),
 | 
				
			||||||
                'content': ''.join(result.xpath('.//div[@class="st"]//text()')),
 | 
					                'content': ''.join(result.xpath('.//div[@class="st"]//text()')),
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        except:
 | 
					        except:
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
"""
 | 
					"""
 | 
				
			||||||
 Nyaa.se (Anime Bittorrent tracker)
 | 
					 Nyaa.si (Anime Bittorrent tracker)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 @website      http://www.nyaa.se/
 | 
					 @website      http://www.nyaa.si/
 | 
				
			||||||
 @provide-api  no
 | 
					 @provide-api  no
 | 
				
			||||||
 @using-api    no
 | 
					 @using-api    no
 | 
				
			||||||
 @results      HTML
 | 
					 @results      HTML
 | 
				
			||||||
@ -12,50 +12,25 @@
 | 
				
			|||||||
from lxml import html
 | 
					from lxml import html
 | 
				
			||||||
from searx.engines.xpath import extract_text
 | 
					from searx.engines.xpath import extract_text
 | 
				
			||||||
from searx.url_utils import urlencode
 | 
					from searx.url_utils import urlencode
 | 
				
			||||||
 | 
					from searx.utils import get_torrent_size, int_or_zero
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# engine dependent config
 | 
					# engine dependent config
 | 
				
			||||||
categories = ['files', 'images', 'videos', 'music']
 | 
					categories = ['files', 'images', 'videos', 'music']
 | 
				
			||||||
paging = True
 | 
					paging = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# search-url
 | 
					# search-url
 | 
				
			||||||
base_url = 'http://www.nyaa.se/'
 | 
					base_url = 'http://www.nyaa.si/'
 | 
				
			||||||
search_url = base_url + '?page=search&{query}&offset={offset}'
 | 
					search_url = base_url + '?page=search&{query}&offset={offset}'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# xpath queries
 | 
					# xpath queries
 | 
				
			||||||
xpath_results = '//table[@class="tlist"]//tr[contains(@class, "tlistrow")]'
 | 
					xpath_results = '//table[contains(@class, "torrent-list")]//tr[not(th)]'
 | 
				
			||||||
xpath_category = './/td[@class="tlisticon"]/a'
 | 
					xpath_category = './/td[1]/a[1]'
 | 
				
			||||||
xpath_title = './/td[@class="tlistname"]/a'
 | 
					xpath_title = './/td[2]/a[last()]'
 | 
				
			||||||
xpath_torrent_file = './/td[@class="tlistdownload"]/a'
 | 
					xpath_torrent_links = './/td[3]/a'
 | 
				
			||||||
xpath_filesize = './/td[@class="tlistsize"]/text()'
 | 
					xpath_filesize = './/td[4]/text()'
 | 
				
			||||||
xpath_seeds = './/td[@class="tlistsn"]/text()'
 | 
					xpath_seeds = './/td[6]/text()'
 | 
				
			||||||
xpath_leeches = './/td[@class="tlistln"]/text()'
 | 
					xpath_leeches = './/td[7]/text()'
 | 
				
			||||||
xpath_downloads = './/td[@class="tlistdn"]/text()'
 | 
					xpath_downloads = './/td[8]/text()'
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# convert a variable to integer or return 0 if it's not a number
 | 
					 | 
				
			||||||
def int_or_zero(num):
 | 
					 | 
				
			||||||
    if isinstance(num, list):
 | 
					 | 
				
			||||||
        if len(num) < 1:
 | 
					 | 
				
			||||||
            return 0
 | 
					 | 
				
			||||||
        num = num[0]
 | 
					 | 
				
			||||||
    if num.isdigit():
 | 
					 | 
				
			||||||
        return int(num)
 | 
					 | 
				
			||||||
    return 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# get multiplier to convert torrent size to bytes
 | 
					 | 
				
			||||||
def get_filesize_mul(suffix):
 | 
					 | 
				
			||||||
    return {
 | 
					 | 
				
			||||||
        'KB': 1024,
 | 
					 | 
				
			||||||
        'MB': 1024 ** 2,
 | 
					 | 
				
			||||||
        'GB': 1024 ** 3,
 | 
					 | 
				
			||||||
        'TB': 1024 ** 4,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        'KIB': 1024,
 | 
					 | 
				
			||||||
        'MIB': 1024 ** 2,
 | 
					 | 
				
			||||||
        'GIB': 1024 ** 3,
 | 
					 | 
				
			||||||
        'TIB': 1024 ** 4
 | 
					 | 
				
			||||||
    }[str(suffix).upper()]
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# do search-request
 | 
					# do search-request
 | 
				
			||||||
@ -72,25 +47,32 @@ def response(resp):
 | 
				
			|||||||
    dom = html.fromstring(resp.text)
 | 
					    dom = html.fromstring(resp.text)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for result in dom.xpath(xpath_results):
 | 
					    for result in dom.xpath(xpath_results):
 | 
				
			||||||
 | 
					        # defaults
 | 
				
			||||||
 | 
					        filesize = 0
 | 
				
			||||||
 | 
					        magnet_link = ""
 | 
				
			||||||
 | 
					        torrent_link = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # category in which our torrent belongs
 | 
					        # category in which our torrent belongs
 | 
				
			||||||
        category = result.xpath(xpath_category)[0].attrib.get('title')
 | 
					        try:
 | 
				
			||||||
 | 
					            category = result.xpath(xpath_category)[0].attrib.get('title')
 | 
				
			||||||
 | 
					        except:
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # torrent title
 | 
					        # torrent title
 | 
				
			||||||
        page_a = result.xpath(xpath_title)[0]
 | 
					        page_a = result.xpath(xpath_title)[0]
 | 
				
			||||||
        title = extract_text(page_a)
 | 
					        title = extract_text(page_a)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # link to the page
 | 
					        # link to the page
 | 
				
			||||||
        href = page_a.attrib.get('href')
 | 
					        href = base_url + page_a.attrib.get('href')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # link to the torrent file
 | 
					        for link in result.xpath(xpath_torrent_links):
 | 
				
			||||||
        torrent_link = result.xpath(xpath_torrent_file)[0].attrib.get('href')
 | 
					            url = link.attrib.get('href')
 | 
				
			||||||
 | 
					            if 'magnet' in url:
 | 
				
			||||||
        # torrent size
 | 
					                # link to the magnet
 | 
				
			||||||
        try:
 | 
					                magnet_link = url
 | 
				
			||||||
            file_size, suffix = result.xpath(xpath_filesize)[0].split(' ')
 | 
					            else:
 | 
				
			||||||
            file_size = int(float(file_size) * get_filesize_mul(suffix))
 | 
					                # link to the torrent file
 | 
				
			||||||
        except:
 | 
					                torrent_link = url
 | 
				
			||||||
            file_size = None
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # seed count
 | 
					        # seed count
 | 
				
			||||||
        seed = int_or_zero(result.xpath(xpath_seeds))
 | 
					        seed = int_or_zero(result.xpath(xpath_seeds))
 | 
				
			||||||
@ -101,6 +83,14 @@ def response(resp):
 | 
				
			|||||||
        # torrent downloads count
 | 
					        # torrent downloads count
 | 
				
			||||||
        downloads = int_or_zero(result.xpath(xpath_downloads))
 | 
					        downloads = int_or_zero(result.xpath(xpath_downloads))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # let's try to calculate the torrent size
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            filesize_info = result.xpath(xpath_filesize)[0]
 | 
				
			||||||
 | 
					            filesize, filesize_multiplier = filesize_info.split()
 | 
				
			||||||
 | 
					            filesize = get_torrent_size(filesize, filesize_multiplier)
 | 
				
			||||||
 | 
					        except:
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # content string contains all information not included into template
 | 
					        # content string contains all information not included into template
 | 
				
			||||||
        content = 'Category: "{category}". Downloaded {downloads} times.'
 | 
					        content = 'Category: "{category}". Downloaded {downloads} times.'
 | 
				
			||||||
        content = content.format(category=category, downloads=downloads)
 | 
					        content = content.format(category=category, downloads=downloads)
 | 
				
			||||||
@ -110,8 +100,9 @@ def response(resp):
 | 
				
			|||||||
                        'content': content,
 | 
					                        'content': content,
 | 
				
			||||||
                        'seed': seed,
 | 
					                        'seed': seed,
 | 
				
			||||||
                        'leech': leech,
 | 
					                        'leech': leech,
 | 
				
			||||||
                        'filesize': file_size,
 | 
					                        'filesize': filesize,
 | 
				
			||||||
                        'torrentfile': torrent_link,
 | 
					                        'torrentfile': torrent_link,
 | 
				
			||||||
 | 
					                        'magnetlink': magnet_link,
 | 
				
			||||||
                        'template': 'torrent.html'})
 | 
					                        'template': 'torrent.html'})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return results
 | 
					    return results
 | 
				
			||||||
 | 
				
			|||||||
@ -118,7 +118,7 @@ def _fetch_supported_languages(resp):
 | 
				
			|||||||
    dom = fromstring(resp.text)
 | 
					    dom = fromstring(resp.text)
 | 
				
			||||||
    options = dom.xpath('//div[@id="regions-popup"]//ul/li/a')
 | 
					    options = dom.xpath('//div[@id="regions-popup"]//ul/li/a')
 | 
				
			||||||
    for option in options:
 | 
					    for option in options:
 | 
				
			||||||
        code = option.xpath('./@data-val')[0]
 | 
					        code = option.xpath('./@data-search-language')[0]
 | 
				
			||||||
        if code.startswith('nb-'):
 | 
					        if code.startswith('nb-'):
 | 
				
			||||||
            code = code.replace('nb', 'no', 1)
 | 
					            code = code.replace('nb', 'no', 1)
 | 
				
			||||||
        supported_languages.append(code)
 | 
					        supported_languages.append(code)
 | 
				
			||||||
 | 
				
			|||||||
@ -14,8 +14,8 @@ import re
 | 
				
			|||||||
from lxml import html
 | 
					from lxml import html
 | 
				
			||||||
from searx.engines.xpath import extract_text
 | 
					from searx.engines.xpath import extract_text
 | 
				
			||||||
from datetime import datetime
 | 
					from datetime import datetime
 | 
				
			||||||
from searx.engines.nyaa import int_or_zero, get_filesize_mul
 | 
					 | 
				
			||||||
from searx.url_utils import urlencode
 | 
					from searx.url_utils import urlencode
 | 
				
			||||||
 | 
					from searx.utils import get_torrent_size, int_or_zero
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# engine dependent config
 | 
					# engine dependent config
 | 
				
			||||||
categories = ['files', 'videos', 'music']
 | 
					categories = ['files', 'videos', 'music']
 | 
				
			||||||
@ -76,8 +76,7 @@ def response(resp):
 | 
				
			|||||||
                try:
 | 
					                try:
 | 
				
			||||||
                    # ('1.228', 'GB')
 | 
					                    # ('1.228', 'GB')
 | 
				
			||||||
                    groups = size_re.match(item).groups()
 | 
					                    groups = size_re.match(item).groups()
 | 
				
			||||||
                    multiplier = get_filesize_mul(groups[1])
 | 
					                    params['filesize'] = get_torrent_size(groups[0], groups[1])
 | 
				
			||||||
                    params['filesize'] = int(multiplier * float(groups[0]))
 | 
					 | 
				
			||||||
                except:
 | 
					                except:
 | 
				
			||||||
                    pass
 | 
					                    pass
 | 
				
			||||||
            elif item.startswith('Date:'):
 | 
					            elif item.startswith('Date:'):
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
"""
 | 
					"""
 | 
				
			||||||
 Torrentz.eu (BitTorrent meta-search engine)
 | 
					 Torrentz2.eu (BitTorrent meta-search engine)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 @website      https://torrentz.eu/
 | 
					 @website      https://torrentz2.eu/
 | 
				
			||||||
 @provide-api  no
 | 
					 @provide-api  no
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 @using-api    no
 | 
					 @using-api    no
 | 
				
			||||||
@ -14,24 +14,24 @@
 | 
				
			|||||||
import re
 | 
					import re
 | 
				
			||||||
from lxml import html
 | 
					from lxml import html
 | 
				
			||||||
from datetime import datetime
 | 
					from datetime import datetime
 | 
				
			||||||
from searx.engines.nyaa import int_or_zero, get_filesize_mul
 | 
					 | 
				
			||||||
from searx.engines.xpath import extract_text
 | 
					from searx.engines.xpath import extract_text
 | 
				
			||||||
from searx.url_utils import urlencode
 | 
					from searx.url_utils import urlencode
 | 
				
			||||||
 | 
					from searx.utils import get_torrent_size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# engine dependent config
 | 
					# engine dependent config
 | 
				
			||||||
categories = ['files', 'videos', 'music']
 | 
					categories = ['files', 'videos', 'music']
 | 
				
			||||||
paging = True
 | 
					paging = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# search-url
 | 
					# search-url
 | 
				
			||||||
# https://torrentz.eu/search?f=EXAMPLE&p=6
 | 
					# https://torrentz2.eu/search?f=EXAMPLE&p=6
 | 
				
			||||||
base_url = 'https://torrentz.eu/'
 | 
					base_url = 'https://torrentz2.eu/'
 | 
				
			||||||
search_url = base_url + 'search?{query}'
 | 
					search_url = base_url + 'search?{query}'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# do search-request
 | 
					# do search-request
 | 
				
			||||||
def request(query, params):
 | 
					def request(query, params):
 | 
				
			||||||
    page = params['pageno'] - 1
 | 
					    page = params['pageno'] - 1
 | 
				
			||||||
    query = urlencode({'q': query, 'p': page})
 | 
					    query = urlencode({'f': query, 'p': page})
 | 
				
			||||||
    params['url'] = search_url.format(query=query)
 | 
					    params['url'] = search_url.format(query=query)
 | 
				
			||||||
    return params
 | 
					    return params
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -54,22 +54,29 @@ def response(resp):
 | 
				
			|||||||
        # extract url and remove a slash in the beginning
 | 
					        # extract url and remove a slash in the beginning
 | 
				
			||||||
        link = links[0].attrib.get('href').lstrip('/')
 | 
					        link = links[0].attrib.get('href').lstrip('/')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        seed = result.xpath('./dd/span[@class="u"]/text()')[0].replace(',', '')
 | 
					        seed = 0
 | 
				
			||||||
        leech = result.xpath('./dd/span[@class="d"]/text()')[0].replace(',', '')
 | 
					        leech = 0
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            seed = int(result.xpath('./dd/span[4]/text()')[0].replace(',', ''))
 | 
				
			||||||
 | 
					            leech = int(result.xpath('./dd/span[5]/text()')[0].replace(',', ''))
 | 
				
			||||||
 | 
					        except:
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        params = {
 | 
					        params = {
 | 
				
			||||||
            'url': base_url + link,
 | 
					            'url': base_url + link,
 | 
				
			||||||
            'title': title,
 | 
					            'title': title,
 | 
				
			||||||
            'seed': int_or_zero(seed),
 | 
					            'seed': seed,
 | 
				
			||||||
            'leech': int_or_zero(leech),
 | 
					            'leech': leech,
 | 
				
			||||||
            'template': 'torrent.html'
 | 
					            'template': 'torrent.html'
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # let's try to calculate the torrent size
 | 
					        # let's try to calculate the torrent size
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            size_str = result.xpath('./dd/span[@class="s"]/text()')[0]
 | 
					            filesize_info = result.xpath('./dd/span[3]/text()')[0]
 | 
				
			||||||
            size, suffix = size_str.split()
 | 
					            filesize, filesize_multiplier = filesize_info.split()
 | 
				
			||||||
            params['filesize'] = int(size) * get_filesize_mul(suffix)
 | 
					            filesize = get_torrent_size(filesize, filesize_multiplier)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            params['filesize'] = filesize
 | 
				
			||||||
        except:
 | 
					        except:
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -80,9 +87,8 @@ def response(resp):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        # extract and convert creation date
 | 
					        # extract and convert creation date
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            date_str = result.xpath('./dd/span[@class="a"]/span')[0].attrib.get('title')
 | 
					            date_ts = result.xpath('./dd/span[2]')[0].attrib.get('title')
 | 
				
			||||||
            # Fri, 25 Mar 2016 16:29:01
 | 
					            date = datetime.fromtimestamp(float(date_ts))
 | 
				
			||||||
            date = datetime.strptime(date_str, '%a, %d %b %Y %H:%M:%S')
 | 
					 | 
				
			||||||
            params['publishedDate'] = date
 | 
					            params['publishedDate'] = date
 | 
				
			||||||
        except:
 | 
					        except:
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
				
			|||||||
@ -5,6 +5,11 @@
 | 
				
			|||||||
language_codes = (
 | 
					language_codes = (
 | 
				
			||||||
    (u"ar-SA", u"العربية", u"", u"Arabic"),
 | 
					    (u"ar-SA", u"العربية", u"", u"Arabic"),
 | 
				
			||||||
    (u"bg-BG", u"Български", u"", u"Bulgarian"),
 | 
					    (u"bg-BG", u"Български", u"", u"Bulgarian"),
 | 
				
			||||||
 | 
					    (u"ca", u"Català", u"", u"Catalan"),
 | 
				
			||||||
 | 
					    (u"ca-AD", u"Català", u"Andorra", u"Catalan"),
 | 
				
			||||||
 | 
					    (u"ca-CT", u"Català", u"", u"Catalan"),
 | 
				
			||||||
 | 
					    (u"ca-ES", u"Català", u"Espanya", u"Catalan"),
 | 
				
			||||||
 | 
					    (u"ca-FR", u"Català", u"França", u"Catalan"),
 | 
				
			||||||
    (u"cs-CZ", u"Čeština", u"", u"Czech"),
 | 
					    (u"cs-CZ", u"Čeština", u"", u"Czech"),
 | 
				
			||||||
    (u"da-DK", u"Dansk", u"", u"Danish"),
 | 
					    (u"da-DK", u"Dansk", u"", u"Danish"),
 | 
				
			||||||
    (u"de", u"Deutsch", u"", u"German"),
 | 
					    (u"de", u"Deutsch", u"", u"German"),
 | 
				
			||||||
@ -15,9 +20,7 @@ language_codes = (
 | 
				
			|||||||
    (u"en", u"English", u"", u"English"),
 | 
					    (u"en", u"English", u"", u"English"),
 | 
				
			||||||
    (u"en-AU", u"English", u"Australia", u"English"),
 | 
					    (u"en-AU", u"English", u"Australia", u"English"),
 | 
				
			||||||
    (u"en-CA", u"English", u"Canada", u"English"),
 | 
					    (u"en-CA", u"English", u"Canada", u"English"),
 | 
				
			||||||
    (u"en-CY", u"English", u"Cyprus", u"English"),
 | 
					 | 
				
			||||||
    (u"en-GB", u"English", u"United Kingdom", u"English"),
 | 
					    (u"en-GB", u"English", u"United Kingdom", u"English"),
 | 
				
			||||||
    (u"en-GD", u"English", u"Grenada", u"English"),
 | 
					 | 
				
			||||||
    (u"en-ID", u"English", u"Indonesia", u"English"),
 | 
					    (u"en-ID", u"English", u"Indonesia", u"English"),
 | 
				
			||||||
    (u"en-IE", u"English", u"Ireland", u"English"),
 | 
					    (u"en-IE", u"English", u"Ireland", u"English"),
 | 
				
			||||||
    (u"en-IN", u"English", u"India", u"English"),
 | 
					    (u"en-IN", u"English", u"India", u"English"),
 | 
				
			||||||
@ -28,6 +31,7 @@ language_codes = (
 | 
				
			|||||||
    (u"en-US", u"English", u"United States", u"English"),
 | 
					    (u"en-US", u"English", u"United States", u"English"),
 | 
				
			||||||
    (u"en-ZA", u"English", u"South Africa", u"English"),
 | 
					    (u"en-ZA", u"English", u"South Africa", u"English"),
 | 
				
			||||||
    (u"es", u"Español", u"", u"Spanish"),
 | 
					    (u"es", u"Español", u"", u"Spanish"),
 | 
				
			||||||
 | 
					    (u"es-AD", u"Español", u"Andorra", u"Spanish"),
 | 
				
			||||||
    (u"es-AR", u"Español", u"Argentina", u"Spanish"),
 | 
					    (u"es-AR", u"Español", u"Argentina", u"Spanish"),
 | 
				
			||||||
    (u"es-CL", u"Español", u"Chile", u"Spanish"),
 | 
					    (u"es-CL", u"Español", u"Chile", u"Spanish"),
 | 
				
			||||||
    (u"es-CO", u"Español", u"Colombia", u"Spanish"),
 | 
					    (u"es-CO", u"Español", u"Colombia", u"Spanish"),
 | 
				
			||||||
@ -38,38 +42,32 @@ language_codes = (
 | 
				
			|||||||
    (u"et-EE", u"Eesti", u"", u"Estonian"),
 | 
					    (u"et-EE", u"Eesti", u"", u"Estonian"),
 | 
				
			||||||
    (u"fi-FI", u"Suomi", u"", u"Finnish"),
 | 
					    (u"fi-FI", u"Suomi", u"", u"Finnish"),
 | 
				
			||||||
    (u"fr", u"Français", u"", u"French"),
 | 
					    (u"fr", u"Français", u"", u"French"),
 | 
				
			||||||
 | 
					    (u"fr-AD", u"Français", u"Andorre", u"French"),
 | 
				
			||||||
    (u"fr-BE", u"Français", u"Belgique", u"French"),
 | 
					    (u"fr-BE", u"Français", u"Belgique", u"French"),
 | 
				
			||||||
    (u"fr-CA", u"Français", u"Canada", u"French"),
 | 
					    (u"fr-CA", u"Français", u"Canada", u"French"),
 | 
				
			||||||
    (u"fr-CH", u"Français", u"Suisse", u"French"),
 | 
					    (u"fr-CH", u"Français", u"Suisse", u"French"),
 | 
				
			||||||
    (u"fr-FR", u"Français", u"France", u"French"),
 | 
					    (u"fr-FR", u"Français", u"France", u"French"),
 | 
				
			||||||
    (u"he-IL", u"עברית", u"", u"Hebrew"),
 | 
					    (u"he-IL", u"עברית", u"", u"Hebrew"),
 | 
				
			||||||
    (u"hr-HR", u"Hrvatski", u"", u"Croatian"),
 | 
					 | 
				
			||||||
    (u"hu-HU", u"Magyar", u"", u"Hungarian"),
 | 
					    (u"hu-HU", u"Magyar", u"", u"Hungarian"),
 | 
				
			||||||
    (u"id-ID", u"Bahasa Indonesia", u"", u"Indonesian"),
 | 
					 | 
				
			||||||
    (u"it", u"Italiano", u"", u"Italian"),
 | 
					    (u"it", u"Italiano", u"", u"Italian"),
 | 
				
			||||||
    (u"it-CH", u"Italiano", u"Svizzera", u"Italian"),
 | 
					    (u"it-CH", u"Italiano", u"Svizzera", u"Italian"),
 | 
				
			||||||
    (u"it-IT", u"Italiano", u"Italia", u"Italian"),
 | 
					    (u"it-IT", u"Italiano", u"Italia", u"Italian"),
 | 
				
			||||||
    (u"ja-JP", u"日本語", u"", u"Japanese"),
 | 
					    (u"ja-JP", u"日本語", u"", u"Japanese"),
 | 
				
			||||||
    (u"ko-KR", u"한국어", u"", u"Korean"),
 | 
					    (u"ko-KR", u"한국어", u"", u"Korean"),
 | 
				
			||||||
    (u"lt-LT", u"Lietuvių", u"", u"Lithuanian"),
 | 
					 | 
				
			||||||
    (u"lv-LV", u"Latviešu", u"", u"Latvian"),
 | 
					 | 
				
			||||||
    (u"ms-MY", u"Bahasa Melayu", u"", u"Malay"),
 | 
					 | 
				
			||||||
    (u"nl", u"Nederlands", u"", u"Dutch"),
 | 
					    (u"nl", u"Nederlands", u"", u"Dutch"),
 | 
				
			||||||
    (u"nl-BE", u"Nederlands", u"België", u"Dutch"),
 | 
					    (u"nl-BE", u"Nederlands", u"België", u"Dutch"),
 | 
				
			||||||
    (u"nl-NL", u"Nederlands", u"Nederland", u"Dutch"),
 | 
					    (u"nl-NL", u"Nederlands", u"Nederland", u"Dutch"),
 | 
				
			||||||
    (u"no-NO", u"Norsk", u"", u"Norwegian"),
 | 
					    (u"no-NO", u"Norsk", u"", u"Norwegian"),
 | 
				
			||||||
    (u"pl-PL", u"Polski", u"", u"Polish"),
 | 
					    (u"pl-PL", u"Polski", u"", u"Polish"),
 | 
				
			||||||
    (u"pt", u"Português", u"", u"Portuguese"),
 | 
					    (u"pt", u"Português", u"", u"Portuguese"),
 | 
				
			||||||
 | 
					    (u"pt-AD", u"Português", u"Andorra", u"Portuguese"),
 | 
				
			||||||
    (u"pt-BR", u"Português", u"Brasil", u"Portuguese"),
 | 
					    (u"pt-BR", u"Português", u"Brasil", u"Portuguese"),
 | 
				
			||||||
    (u"pt-PT", u"Português", u"Portugal", u"Portuguese"),
 | 
					    (u"pt-PT", u"Português", u"Portugal", u"Portuguese"),
 | 
				
			||||||
    (u"ro-RO", u"Română", u"", u"Romanian"),
 | 
					    (u"ro-RO", u"Română", u"", u"Romanian"),
 | 
				
			||||||
    (u"ru-RU", u"Русский", u"", u"Russian"),
 | 
					    (u"ru-RU", u"Русский", u"", u"Russian"),
 | 
				
			||||||
    (u"sk-SK", u"Slovenčina", u"", u"Slovak"),
 | 
					 | 
				
			||||||
    (u"sl", u"Slovenščina", u"", u"Slovenian"),
 | 
					 | 
				
			||||||
    (u"sv-SE", u"Svenska", u"", u"Swedish"),
 | 
					    (u"sv-SE", u"Svenska", u"", u"Swedish"),
 | 
				
			||||||
    (u"th-TH", u"ไทย", u"", u"Thai"),
 | 
					    (u"th-TH", u"ไทย", u"", u"Thai"),
 | 
				
			||||||
    (u"tr-TR", u"Türkçe", u"", u"Turkish"),
 | 
					    (u"tr-TR", u"Türkçe", u"", u"Turkish"),
 | 
				
			||||||
    (u"vi-VN", u"Tiếng Việt", u"", u"Vietnamese"),
 | 
					 | 
				
			||||||
    (u"zh", u"中文", u"", u"Chinese"),
 | 
					    (u"zh", u"中文", u"", u"Chinese"),
 | 
				
			||||||
    (u"zh-CN", u"中文", u"中国", u"Chinese"),
 | 
					    (u"zh-CN", u"中文", u"中国", u"Chinese"),
 | 
				
			||||||
    (u"zh-HK", u"中文", u"香港", u"Chinese"),
 | 
					    (u"zh-HK", u"中文", u"香港", u"Chinese"),
 | 
				
			||||||
 | 
				
			|||||||
@ -189,11 +189,10 @@ engines:
 | 
				
			|||||||
    shortcut : et
 | 
					    shortcut : et
 | 
				
			||||||
    disabled : True
 | 
					    disabled : True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# api-key required: http://www.faroo.com/hp/api/api.html#key
 | 
					  - name : faroo
 | 
				
			||||||
#  - name : faroo
 | 
					    engine : faroo
 | 
				
			||||||
#    engine : faroo
 | 
					    shortcut : fa
 | 
				
			||||||
#    shortcut : fa
 | 
					    disabled : True
 | 
				
			||||||
#    api_key : 'apikey' # required!
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  - name : 500px
 | 
					  - name : 500px
 | 
				
			||||||
    engine : www500px
 | 
					    engine : www500px
 | 
				
			||||||
@ -247,15 +246,16 @@ engines:
 | 
				
			|||||||
    disabled: True
 | 
					    disabled: True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  - name : gitlab
 | 
					  - name : gitlab
 | 
				
			||||||
    engine : xpath
 | 
					    engine : json_engine
 | 
				
			||||||
    paging : True
 | 
					    paging : True
 | 
				
			||||||
    search_url : https://gitlab.com/search?page={pageno}&search={query}
 | 
					    search_url : https://gitlab.com/api/v4/projects?search={query}&page={pageno}
 | 
				
			||||||
    url_xpath : //li[@class="project-row"]//a[@class="project"]/@href
 | 
					    url_query : web_url
 | 
				
			||||||
    title_xpath : //li[@class="project-row"]//span[contains(@class, "project-full-name")]
 | 
					    title_query : name_with_namespace
 | 
				
			||||||
    content_xpath : //li[@class="project-row"]//div[@class="description"]/p
 | 
					    content_query : description
 | 
				
			||||||
 | 
					    page_size : 20
 | 
				
			||||||
    categories : it
 | 
					    categories : it
 | 
				
			||||||
    shortcut : gl
 | 
					    shortcut : gl
 | 
				
			||||||
    timeout : 5.0
 | 
					    timeout : 10.0
 | 
				
			||||||
    disabled : True
 | 
					    disabled : True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  - name : github
 | 
					  - name : github
 | 
				
			||||||
@ -326,9 +326,9 @@ engines:
 | 
				
			|||||||
    engine : xpath
 | 
					    engine : xpath
 | 
				
			||||||
    paging : True
 | 
					    paging : True
 | 
				
			||||||
    search_url : https://geektimes.ru/search/page{pageno}/?q={query}
 | 
					    search_url : https://geektimes.ru/search/page{pageno}/?q={query}
 | 
				
			||||||
    url_xpath : //div[@class="search_results"]//a[@class="post__title_link"]/@href
 | 
					    url_xpath : //article[contains(@class, "post")]//a[@class="post__title_link"]/@href
 | 
				
			||||||
    title_xpath : //div[@class="search_results"]//a[@class="post__title_link"]
 | 
					    title_xpath : //article[contains(@class, "post")]//a[@class="post__title_link"]
 | 
				
			||||||
    content_xpath : //div[@class="search_results"]//div[contains(@class, "content")]
 | 
					    content_xpath : //article[contains(@class, "post")]//div[contains(@class, "post__text")]
 | 
				
			||||||
    categories : it
 | 
					    categories : it
 | 
				
			||||||
    timeout : 4.0
 | 
					    timeout : 4.0
 | 
				
			||||||
    disabled : True
 | 
					    disabled : True
 | 
				
			||||||
@ -338,9 +338,9 @@ engines:
 | 
				
			|||||||
    engine : xpath
 | 
					    engine : xpath
 | 
				
			||||||
    paging : True
 | 
					    paging : True
 | 
				
			||||||
    search_url : https://habrahabr.ru/search/page{pageno}/?q={query}
 | 
					    search_url : https://habrahabr.ru/search/page{pageno}/?q={query}
 | 
				
			||||||
    url_xpath : //div[@class="search_results"]//a[contains(@class, "post__title_link")]/@href
 | 
					    url_xpath : //article[contains(@class, "post")]//a[@class="post__title_link"]/@href
 | 
				
			||||||
    title_xpath : //div[@class="search_results"]//a[contains(@class, "post__title_link")]
 | 
					    title_xpath : //article[contains(@class, "post")]//a[@class="post__title_link"]
 | 
				
			||||||
    content_xpath : //div[@class="search_results"]//div[contains(@class, "content")]
 | 
					    content_xpath : //article[contains(@class, "post")]//div[contains(@class, "post__text")]
 | 
				
			||||||
    categories : it
 | 
					    categories : it
 | 
				
			||||||
    timeout : 4.0
 | 
					    timeout : 4.0
 | 
				
			||||||
    disabled : True
 | 
					    disabled : True
 | 
				
			||||||
@ -556,6 +556,12 @@ engines:
 | 
				
			|||||||
    timeout : 6.0
 | 
					    timeout : 6.0
 | 
				
			||||||
    disabled : True
 | 
					    disabled : True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - name : torrentz
 | 
				
			||||||
 | 
					    engine : torrentz
 | 
				
			||||||
 | 
					    shortcut : tor
 | 
				
			||||||
 | 
					    url: https://torrentz2.eu/
 | 
				
			||||||
 | 
					    timeout : 3.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  - name : twitter
 | 
					  - name : twitter
 | 
				
			||||||
    engine : twitter
 | 
					    engine : twitter
 | 
				
			||||||
    shortcut : tw
 | 
					    shortcut : tw
 | 
				
			||||||
@ -579,6 +585,7 @@ engines:
 | 
				
			|||||||
  - name : yahoo
 | 
					  - name : yahoo
 | 
				
			||||||
    engine : yahoo
 | 
					    engine : yahoo
 | 
				
			||||||
    shortcut : yh
 | 
					    shortcut : yh
 | 
				
			||||||
 | 
					    disabled : True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  - name : yandex
 | 
					  - name : yandex
 | 
				
			||||||
    engine : yandex
 | 
					    engine : yandex
 | 
				
			||||||
@ -639,10 +646,10 @@ engines:
 | 
				
			|||||||
    engine: xpath
 | 
					    engine: xpath
 | 
				
			||||||
    shortcut: vo
 | 
					    shortcut: vo
 | 
				
			||||||
    categories: social media
 | 
					    categories: social media
 | 
				
			||||||
    search_url : https://voat.co/search?q={query}
 | 
					    search_url : https://searchvoat.co/?t={query}
 | 
				
			||||||
    url_xpath : //p[contains(@class, "title")]/a/@href
 | 
					    url_xpath : //div[@class="entry"]/p/a[@class="title"]/@href
 | 
				
			||||||
    title_xpath : //p[contains(@class, "title")]/a
 | 
					    title_xpath : //div[@class="entry"]/p/a[@class="title"]
 | 
				
			||||||
    content_xpath : //span[@class="domain"]
 | 
					    content_xpath : //div[@class="entry"]/p/span[@class="domain"]
 | 
				
			||||||
    timeout : 10.0
 | 
					    timeout : 10.0
 | 
				
			||||||
    disabled : True
 | 
					    disabled : True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -651,12 +658,6 @@ engines:
 | 
				
			|||||||
    shortcut : 1337x
 | 
					    shortcut : 1337x
 | 
				
			||||||
    disabled : True
 | 
					    disabled : True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#The blekko technology and team have joined IBM Watson! -> https://blekko.com/
 | 
					 | 
				
			||||||
#  - name : blekko images
 | 
					 | 
				
			||||||
#    engine : blekko_images
 | 
					 | 
				
			||||||
#    locale : en-US
 | 
					 | 
				
			||||||
#    shortcut : bli
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#  - name : yacy
 | 
					#  - name : yacy
 | 
				
			||||||
#    engine : yacy
 | 
					#    engine : yacy
 | 
				
			||||||
#    shortcut : ya
 | 
					#    shortcut : ya
 | 
				
			||||||
@ -676,7 +677,6 @@ locales:
 | 
				
			|||||||
    bg : Български (Bulgarian)
 | 
					    bg : Български (Bulgarian)
 | 
				
			||||||
    cs : Čeština (Czech)
 | 
					    cs : Čeština (Czech)
 | 
				
			||||||
    de : Deutsch (German)
 | 
					    de : Deutsch (German)
 | 
				
			||||||
    de_DE : Deutsch (German_Germany)
 | 
					 | 
				
			||||||
    el_GR : Ελληνικά (Greek_Greece)
 | 
					    el_GR : Ελληνικά (Greek_Greece)
 | 
				
			||||||
    eo : Esperanto (Esperanto)
 | 
					    eo : Esperanto (Esperanto)
 | 
				
			||||||
    es : Español (Spanish)
 | 
					    es : Español (Spanish)
 | 
				
			||||||
 | 
				
			|||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								searx/static/themes/oscar/js/searx.min.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								searx/static/themes/oscar/js/searx.min.js
									
									
									
									
										vendored
									
									
								
							@ -1,2 +1,2 @@
 | 
				
			|||||||
/*! oscar/searx.min.js | 25-07-2016 | https://github.com/asciimoo/searx */
 | 
					/*! oscar/searx.min.js | 06-10-2017 | https://github.com/asciimoo/searx */
 | 
				
			||||||
requirejs.config({baseUrl:"./static/themes/oscar/js",paths:{app:"../app"}}),searx.autocompleter&&(searx.searchResults=new Bloodhound({datumTokenizer:Bloodhound.tokenizers.obj.whitespace("value"),queryTokenizer:Bloodhound.tokenizers.whitespace,remote:"./autocompleter?q=%QUERY"}),searx.searchResults.initialize()),$(document).ready(function(){searx.autocompleter&&$("#q").typeahead(null,{name:"search-results",displayKey:function(a){return a},source:searx.searchResults.ttAdapter()})}),$(document).ready(function(){$("#q.autofocus").focus(),$(".select-all-on-click").click(function(){$(this).select()}),$(".btn-collapse").click(function(){var a=$(this).data("btn-text-collapsed"),b=$(this).data("btn-text-not-collapsed");""!==a&&""!==b&&($(this).hasClass("collapsed")?new_html=$(this).html().replace(a,b):new_html=$(this).html().replace(b,a),$(this).html(new_html))}),$(".btn-toggle .btn").click(function(){var a="btn-"+$(this).data("btn-class"),b=$(this).data("btn-label-default"),c=$(this).data("btn-label-toggled");""!==c&&($(this).hasClass("btn-default")?new_html=$(this).html().replace(b,c):new_html=$(this).html().replace(c,b),$(this).html(new_html)),$(this).toggleClass(a),$(this).toggleClass("btn-default")}),$(".media-loader").click(function(){var a=$(this).data("target"),b=$(a+" > iframe"),c=b.attr("src");void 0!==c&&c!==!1||b.attr("src",b.data("src"))}),$(".btn-sm").dblclick(function(){var a="btn-"+$(this).data("btn-class");$(this).hasClass("btn-default")?($(".btn-sm > input").attr("checked","checked"),$(".btn-sm > input").prop("checked",!0),$(".btn-sm").addClass(a),$(".btn-sm").addClass("active"),$(".btn-sm").removeClass("btn-default")):($(".btn-sm > input").attr("checked",""),$(".btn-sm > input").removeAttr("checked"),$(".btn-sm > input").checked=!1,$(".btn-sm").removeClass(a),$(".btn-sm").removeClass("active"),$(".btn-sm").addClass("btn-default"))})}),$(document).ready(function(){$(".searx_overpass_request").on("click",function(a){var b="https://overpass-api.de/api/interpreter?data=",c=b+"[out:json][timeout:25];(",d=");out meta;",e=$(this).data("osm-id"),f=$(this).data("osm-type"),g=$(this).data("result-table"),h="#"+$(this).data("result-table-loadicon"),i=["addr:city","addr:country","addr:housenumber","addr:postcode","addr:street"];if(e&&f&&g){g="#"+g;var j=null;switch(f){case"node":j=c+"node("+e+");"+d;break;case"way":j=c+"way("+e+");"+d;break;case"relation":j=c+"relation("+e+");"+d}if(j){$.ajax(j).done(function(a){if(a&&a.elements&&a.elements[0]){var b=a.elements[0],c=$(g).html();for(var d in b.tags)if(null===b.tags.name||i.indexOf(d)==-1){switch(c+="<tr><td>"+d+"</td><td>",d){case"phone":case"fax":c+='<a href="tel:'+b.tags[d].replace(/ /g,"")+'">'+b.tags[d]+"</a>";break;case"email":c+='<a href="mailto:'+b.tags[d]+'">'+b.tags[d]+"</a>";break;case"website":case"url":c+='<a href="'+b.tags[d]+'">'+b.tags[d]+"</a>";break;case"wikidata":c+='<a href="https://www.wikidata.org/wiki/'+b.tags[d]+'">'+b.tags[d]+"</a>";break;case"wikipedia":if(b.tags[d].indexOf(":")!=-1){c+='<a href="https://'+b.tags[d].substring(0,b.tags[d].indexOf(":"))+".wikipedia.org/wiki/"+b.tags[d].substring(b.tags[d].indexOf(":")+1)+'">'+b.tags[d]+"</a>";break}default:c+=b.tags[d]}c+="</td></tr>"}$(g).html(c),$(g).removeClass("hidden"),$(h).addClass("hidden")}}).fail(function(){$(h).html($(h).html()+'<p class="text-muted">could not load data!</p>')})}}$(this).off(a)}),$(".searx_init_map").on("click",function(a){var b=$(this).data("leaflet-target"),c=$(this).data("map-lon"),d=$(this).data("map-lat"),e=$(this).data("map-zoom"),f=$(this).data("map-boundingbox"),g=$(this).data("map-geojson");require(["leaflet-0.7.3.min"],function(a){f&&(southWest=L.latLng(f[0],f[2]),northEast=L.latLng(f[1],f[3]),map_bounds=L.latLngBounds(southWest,northEast)),L.Icon.Default.imagePath="./static/themes/oscar/img/map";var h=L.map(b),i="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",j='Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors',k=new L.TileLayer(i,{minZoom:1,maxZoom:19,attribution:j}),l="https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png",m='Wikimedia maps beta | Maps data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors';new L.TileLayer(l,{minZoom:1,maxZoom:19,attribution:m});map_bounds?setTimeout(function(){h.fitBounds(map_bounds,{maxZoom:17})},0):c&&d&&(e?h.setView(new L.LatLng(d,c),e):h.setView(new L.LatLng(d,c),8)),h.addLayer(k);var n={"OSM Mapnik":k};L.control.layers(n).addTo(h),g&&L.geoJson(g).addTo(h)}),$(this).off(a)})});
 | 
					requirejs.config({baseUrl:"./static/themes/oscar/js",paths:{app:"../app"}}),searx.autocompleter&&(searx.searchResults=new Bloodhound({datumTokenizer:Bloodhound.tokenizers.obj.whitespace("value"),queryTokenizer:Bloodhound.tokenizers.whitespace,remote:"./autocompleter?q=%QUERY"}),searx.searchResults.initialize()),$(document).ready(function(){searx.autocompleter&&$("#q").typeahead(null,{name:"search-results",displayKey:function(a){return a},source:searx.searchResults.ttAdapter()})}),$(document).ready(function(){$("#q.autofocus").focus(),$(".select-all-on-click").click(function(){$(this).select()}),$(".btn-collapse").click(function(){var a=$(this).data("btn-text-collapsed"),b=$(this).data("btn-text-not-collapsed");""!==a&&""!==b&&($(this).hasClass("collapsed")?new_html=$(this).html().replace(a,b):new_html=$(this).html().replace(b,a),$(this).html(new_html))}),$(".btn-toggle .btn").click(function(){var a="btn-"+$(this).data("btn-class"),b=$(this).data("btn-label-default"),c=$(this).data("btn-label-toggled");""!==c&&($(this).hasClass("btn-default")?new_html=$(this).html().replace(b,c):new_html=$(this).html().replace(c,b),$(this).html(new_html)),$(this).toggleClass(a),$(this).toggleClass("btn-default")}),$(".media-loader").click(function(){var a=$(this).data("target"),b=$(a+" > iframe"),c=b.attr("src");void 0!==c&&c!==!1||b.attr("src",b.data("src"))}),$(".btn-sm").dblclick(function(){var a="btn-"+$(this).data("btn-class");$(this).hasClass("btn-default")?($(".btn-sm > input").attr("checked","checked"),$(".btn-sm > input").prop("checked",!0),$(".btn-sm").addClass(a),$(".btn-sm").addClass("active"),$(".btn-sm").removeClass("btn-default")):($(".btn-sm > input").attr("checked",""),$(".btn-sm > input").removeAttr("checked"),$(".btn-sm > input").checked=!1,$(".btn-sm").removeClass(a),$(".btn-sm").removeClass("active"),$(".btn-sm").addClass("btn-default"))})}),$(document).ready(function(){$(".searx_overpass_request").on("click",function(a){var b="https://overpass-api.de/api/interpreter?data=",c=b+"[out:json][timeout:25];(",d=");out meta;",e=$(this).data("osm-id"),f=$(this).data("osm-type"),g=$(this).data("result-table"),h="#"+$(this).data("result-table-loadicon"),i=["addr:city","addr:country","addr:housenumber","addr:postcode","addr:street"];if(e&&f&&g){g="#"+g;var j=null;switch(f){case"node":j=c+"node("+e+");"+d;break;case"way":j=c+"way("+e+");"+d;break;case"relation":j=c+"relation("+e+");"+d}if(j){$.ajax(j).done(function(a){if(a&&a.elements&&a.elements[0]){var b=a.elements[0],c=$(g).html();for(var d in b.tags)if(null===b.tags.name||i.indexOf(d)==-1){switch(c+="<tr><td>"+d+"</td><td>",d){case"phone":case"fax":c+='<a href="tel:'+b.tags[d].replace(/ /g,"")+'">'+b.tags[d]+"</a>";break;case"email":c+='<a href="mailto:'+b.tags[d]+'">'+b.tags[d]+"</a>";break;case"website":case"url":c+='<a href="'+b.tags[d]+'">'+b.tags[d]+"</a>";break;case"wikidata":c+='<a href="https://www.wikidata.org/wiki/'+b.tags[d]+'">'+b.tags[d]+"</a>";break;case"wikipedia":if(b.tags[d].indexOf(":")!=-1){c+='<a href="https://'+b.tags[d].substring(0,b.tags[d].indexOf(":"))+".wikipedia.org/wiki/"+b.tags[d].substring(b.tags[d].indexOf(":")+1)+'">'+b.tags[d]+"</a>";break}default:c+=b.tags[d]}c+="</td></tr>"}$(g).html(c),$(g).removeClass("hidden"),$(h).addClass("hidden")}}).fail(function(){$(h).html($(h).html()+'<p class="text-muted">could not load data!</p>')})}}$(this).off(a)}),$(".searx_init_map").on("click",function(a){var b=$(this).data("leaflet-target"),c=$(this).data("map-lon"),d=$(this).data("map-lat"),e=$(this).data("map-zoom"),f=$(this).data("map-boundingbox"),g=$(this).data("map-geojson");require(["leaflet-0.7.3.min"],function(a){f&&(southWest=L.latLng(f[0],f[2]),northEast=L.latLng(f[1],f[3]),map_bounds=L.latLngBounds(southWest,northEast)),L.Icon.Default.imagePath="./static/themes/oscar/img/map";var h=L.map(b),i="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",j='Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors',k=new L.TileLayer(i,{minZoom:1,maxZoom:19,attribution:j}),l="https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png",m='Wikimedia maps beta | Maps data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors';new L.TileLayer(l,{minZoom:1,maxZoom:19,attribution:m});map_bounds?setTimeout(function(){h.fitBounds(map_bounds,{maxZoom:17})},0):c&&d&&(e?h.setView(new L.LatLng(d,c),e):h.setView(new L.LatLng(d,c),8)),h.addLayer(k);var n={"OSM Mapnik":k};L.control.layers(n).addTo(h),g&&L.geoJson(g).addTo(h)}),$(this).off(a)})});
 | 
				
			||||||
@ -19,3 +19,5 @@
 | 
				
			|||||||
@import "cursor.less";
 | 
					@import "cursor.less";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@import "code.less";
 | 
					@import "code.less";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@import "preferences.less";
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					.table > tbody > tr > td, .table > tbody > tr > th {
 | 
				
			||||||
 | 
					    vertical-align: middle !important;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -17,3 +17,5 @@
 | 
				
			|||||||
@import "code.less";
 | 
					@import "code.less";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@import "navbar.less";
 | 
					@import "navbar.less";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@import "preferences.less";
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										3
									
								
								searx/static/themes/oscar/less/pointhi/preferences.less
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								searx/static/themes/oscar/less/pointhi/preferences.less
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					.table > tbody > tr > td, .table > tbody > tr > th {
 | 
				
			||||||
 | 
					    vertical-align: middle !important;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,11 +1,11 @@
 | 
				
			|||||||
<div class="result {{ result.class }}">
 | 
					<div class="result {{ result.class }}">
 | 
				
			||||||
    <h3 class="result_title">{% if result['favicon'] %}<img width="14" height="14" class="favicon" src="static/{{theme}}/img/icon_{{result['favicon']}}.ico" alt="{{result['favicon']}}" />{% endif %}<a href="{{ result.url }}" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}>{{ result.title|safe }}</a></h3>
 | 
					    <h3 class="result_title"><a href="{{ result.url }}" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}>{{ result.title|safe }}</a></h3>
 | 
				
			||||||
    {% if result.publishedDate %}<span class="published_date">{{ result.publishedDate }}</span>{% endif %}
 | 
					    {% if result.publishedDate %}<span class="published_date">{{ result.publishedDate }}</span>{% endif %}
 | 
				
			||||||
    <p class="content">{% if result.img_src %}<img src="{{ image_proxify(result.img_src) }}" class="image" />{% endif %}{% if result.content %}{{ result.content|safe }}<br class="last"/>{% endif %}</p>
 | 
					    <p class="content">{% if result.img_src %}<img src="{{ image_proxify(result.img_src) }}" class="image" />{% endif %}{% if result.content %}{{ result.content|safe }}<br class="last"/>{% endif %}</p>
 | 
				
			||||||
    {% if result.repository %}<p class="content"><a href="{{ result.repository|safe }}" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}>{{ result.repository }}</a></p>{% endif %}
 | 
					    {% if result.repository %}<p class="content"><a href="{{ result.repository|safe }}" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}>{{ result.repository }}</a></p>{% endif %}
 | 
				
			||||||
    <div dir="ltr">
 | 
					    <div dir="ltr">
 | 
				
			||||||
    {{ result.codelines|code_highlighter(result.code_language)|safe }}
 | 
					    {{ result.codelines|code_highlighter(result.code_language)|safe }}
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <p class="url">{{ result.pretty_url }}‎</p>
 | 
					    <p class="url">{{ result.pretty_url }}‎</p>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,11 +1,11 @@
 | 
				
			|||||||
<div class="result {{ result.class }}">
 | 
					<div class="result {{ result.class }}">
 | 
				
			||||||
    <h3 class="result_title"> {% if result['favicon'] %}<img width="14" height="14" class="favicon" src="static/{{theme}}/img/icon_{{result['favicon']}}.ico" alt="{{result['favicon']}}" />{% endif %}<a href="{{ result.url }}" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}>{{ result.title|safe }}</a></h3>
 | 
					    <h3 class="result_title"><a href="{{ result.url }}" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}>{{ result.title|safe }}</a></h3>
 | 
				
			||||||
    <p class="url">{{ result.pretty_url }}‎ <a class="cache_link" href="https://web.archive.org/web/{{ result.url }}" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}>{{ _('cached') }}</a></p>
 | 
					    <p class="url">{{ result.pretty_url }}‎ <a class="cache_link" href="https://web.archive.org/web/{{ result.url }}" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}>{{ _('cached') }}</a></p>
 | 
				
			||||||
    {% if result.publishedDate %}<p class="published_date">{{ result.publishedDate }}</p>{% endif %}
 | 
					    {% if result.publishedDate %}<p class="published_date">{{ result.publishedDate }}</p>{% endif %}
 | 
				
			||||||
    <p class="content">{% if result.img_src %}<img src="{{ image_proxify(result.img_src) }}" class="image" />{% endif %}{% if result.content %}{{ result.content|safe }}<br class="last"/>{% endif %}</p>
 | 
					    <p class="content">{% if result.img_src %}<img src="{{ image_proxify(result.img_src) }}" class="image" />{% endif %}{% if result.content %}{{ result.content|safe }}<br class="last"/>{% endif %}</p>
 | 
				
			||||||
    {% if result.repository %}<p class="result-content"><a href="{{ result.repository|safe }}" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}>{{ result.repository }}</a></p>{% endif %}
 | 
					    {% if result.repository %}<p class="result-content"><a href="{{ result.repository|safe }}" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}>{{ result.repository }}</a></p>{% endif %}
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    <div dir="ltr">
 | 
					    <div dir="ltr">
 | 
				
			||||||
    {{ result.codelines|code_highlighter(result.code_language)|safe }}
 | 
					    {{ result.codelines|code_highlighter(result.code_language)|safe }}
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,88 +1,99 @@
 | 
				
			|||||||
<!-- Draw glyphicon icon from bootstrap-theme -->
 | 
					<!-- Draw glyphicon icon from bootstrap-theme -->
 | 
				
			||||||
{% macro icon(action) -%}
 | 
					{% macro icon(action) -%}
 | 
				
			||||||
    <span class="glyphicon glyphicon-{{ action }}"></span>
 | 
					    <span class="glyphicon glyphicon-{{ action }}"></span>
 | 
				
			||||||
{%- endmacro %}
 | 
					{%- endmacro %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<!-- Draw favicon -->
 | 
					<!-- Draw favicon -->
 | 
				
			||||||
<!-- TODO: using url_for methode -->
 | 
					{% macro draw_favicon(favicon) -%}
 | 
				
			||||||
{% macro draw_favicon(favicon) -%}
 | 
					    <img width="32" height="32" class="favicon" src="{{ url_for('static', filename='themes/oscar/img/icons/' + favicon + '.png') }}" alt="{{ favicon }}" />
 | 
				
			||||||
    <img width="32" height="32" class="favicon" src="static/themes/oscar/img/icons/{{ favicon }}.png" alt="{{ favicon }}" />
 | 
					{%- endmacro %}
 | 
				
			||||||
{%- endmacro %}
 | 
					
 | 
				
			||||||
 | 
					{%- macro result_link(url, title, classes='') -%}
 | 
				
			||||||
{%- macro result_link(url, title, classes='') -%}
 | 
					<a href="{{ url }}" {% if classes %}class="{{ classes }}" {% endif %}{% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}>{{ title }}</a>
 | 
				
			||||||
<a href="{{ url }}" {% if classes %}class="{{ classes }}" {% endif %}{% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}>{{ title }}</a>
 | 
					{%- endmacro -%}
 | 
				
			||||||
{%- endmacro -%}
 | 
					
 | 
				
			||||||
 | 
					<!-- Draw result header -->
 | 
				
			||||||
<!-- Draw result header -->
 | 
					{% macro result_header(result, favicons) -%}
 | 
				
			||||||
{% macro result_header(result, favicons) -%}
 | 
					<h4 class="result_header">{% if result.engine~".png" in favicons %}{{ draw_favicon(result.engine) }} {% endif %}{{ result_link(result.url, result.title|safe) }}</h4>
 | 
				
			||||||
<h4 class="result_header">{% if result.engine~".png" in favicons %}{{ draw_favicon(result.engine) }} {% endif %}{{ result_link(result.url, result.title|safe) }}</h4>
 | 
					{%- endmacro %}
 | 
				
			||||||
{%- endmacro %}
 | 
					
 | 
				
			||||||
 | 
					<!-- Draw result sub header -->
 | 
				
			||||||
<!-- Draw result sub header -->
 | 
					{% macro result_sub_header(result) -%}
 | 
				
			||||||
{% macro result_sub_header(result) -%}
 | 
					    {% if result.publishedDate %}<time class="text-muted" datetime="{{ result.pubdate }}" >{{ result.publishedDate }}</time>{% endif %}
 | 
				
			||||||
    {% if result.publishedDate %}<time class="text-muted" datetime="{{ result.pubdate }}" >{{ result.publishedDate }}</time>{% endif %}
 | 
					    {% if result.magnetlink %}<small> • {{ result_link(result.magnetlink, icon('magnet') + _('magnet link'), "magnetlink") }}</small>{% endif %}
 | 
				
			||||||
    {% if result.magnetlink %}<small> • {{ result_link(result.magnetlink, icon('magnet') + _('magnet link'), "magnetlink") }}</small>{% endif %}
 | 
					    {% if result.torrentfile %}<small> • {{ result_link(result.torrentfile, icon('download-alt') + _('torrent file'), "torrentfile") }}</small>{% endif %}
 | 
				
			||||||
    {% if result.torrentfile %}<small> • {{ result_link(result.torrentfile, icon('download-alt') + _('torrent file'), "torrentfile") }}</small>{% endif %}
 | 
					{%- endmacro %}
 | 
				
			||||||
{%- endmacro %}
 | 
					
 | 
				
			||||||
 | 
					<!-- Draw result footer -->
 | 
				
			||||||
<!-- Draw result footer -->
 | 
					{% macro result_footer(result) -%}
 | 
				
			||||||
{% macro result_footer(result) -%}
 | 
					    <div class="clearfix"></div>
 | 
				
			||||||
    <div class="clearfix"></div>
 | 
					    <div class="pull-right">
 | 
				
			||||||
    <div class="pull-right">
 | 
					    {% for engine in result.engines %}
 | 
				
			||||||
    {% for engine in result.engines %}
 | 
					        <span class="label label-default">{{ engine }}</span>
 | 
				
			||||||
        <span class="label label-default">{{ engine }}</span>
 | 
					    {% endfor %}
 | 
				
			||||||
    {% endfor %}
 | 
					    <small>{{ result_link("https://web.archive.org/web/" + result.url, icon('link') + _('cached'), "text-info") }}</small>
 | 
				
			||||||
    <small>{{ result_link("https://web.archive.org/web/" + result.url, icon('link') + _('cached'), "text-info") }}</small>
 | 
					    {% if proxify %}
 | 
				
			||||||
    {% if proxify %}
 | 
					    <small>{{ result_link(proxify(result.url), icon('sort') + _('proxied'), "text-info") }}</small>
 | 
				
			||||||
    <small>{{ result_link(proxify(result.url), icon('sort') + _('proxied'), "text-info") }}</small>
 | 
					    {% endif %}
 | 
				
			||||||
    {% endif %}
 | 
					</div>
 | 
				
			||||||
</div>
 | 
					<div class="external-link">{{ result.pretty_url }}</div>
 | 
				
			||||||
<div class="external-link">{{ result.pretty_url }}</div>
 | 
					{%- endmacro %}
 | 
				
			||||||
{%- endmacro %}
 | 
					
 | 
				
			||||||
 | 
					<!-- Draw result footer -->
 | 
				
			||||||
<!-- Draw result footer -->
 | 
					{% macro result_footer_rtl(result) -%}
 | 
				
			||||||
{% macro result_footer_rtl(result) -%}
 | 
					    <div class="clearfix"></div>
 | 
				
			||||||
    <div class="clearfix"></div>
 | 
					    {% for engine in result.engines %}
 | 
				
			||||||
    {% for engine in result.engines %}
 | 
					        <span class="label label-default">{{ engine }}</span>
 | 
				
			||||||
        <span class="label label-default">{{ engine }}</span>
 | 
					    {% endfor %}
 | 
				
			||||||
    {% endfor %}
 | 
					    <small>{{ result_link("https://web.archive.org/web/" + result.url, icon('link') + _('cached'), "text-info") }}</small>
 | 
				
			||||||
    <small>{{ result_link("https://web.archive.org/web/" + result.url, icon('link') + _('cached'), "text-info") }}</small>
 | 
					    {% if proxify %}
 | 
				
			||||||
    {% if proxify %}
 | 
					    <small>{{ result_link(proxify(result.url), icon('sort') + _('proxied'), "text-info") }}</small>
 | 
				
			||||||
    <small>{{ result_link(proxify(result.url), icon('sort') + _('proxied'), "text-info") }}</small>
 | 
					    {% endif %}
 | 
				
			||||||
    {% endif %}
 | 
					    <div class="external-link">{{ result.pretty_url }}</div>
 | 
				
			||||||
    <div class="external-link">{{ result.pretty_url }}</div>
 | 
					{%- endmacro %}
 | 
				
			||||||
{%- endmacro %}
 | 
					
 | 
				
			||||||
 | 
					{% macro preferences_item_header(info, label, rtl) -%}
 | 
				
			||||||
{% macro preferences_item_header(info, label, rtl) -%}
 | 
					    {% if rtl %}
 | 
				
			||||||
    {% if rtl %}
 | 
					    <div class="row form-group">
 | 
				
			||||||
    <div class="row form-group">
 | 
					        <label class="col-sm-3 col-md-2 pull-right">{{ label }}</label>
 | 
				
			||||||
        <label class="col-sm-3 col-md-2 pull-right">{{ label }}</label>
 | 
					        <span class="col-sm-5 col-md-6 help-block pull-left">{{ info }}</span>
 | 
				
			||||||
        <span class="col-sm-5 col-md-6 help-block pull-left">{{ info }}</span>
 | 
					        <div class="col-sm-4 col-md-4">
 | 
				
			||||||
        <div class="col-sm-4 col-md-4">
 | 
					    {% else %}
 | 
				
			||||||
    {% else %}
 | 
					    <div class="row form-group">
 | 
				
			||||||
    <div class="row form-group">
 | 
					        <label class="col-sm-3 col-md-2">{{ label }}</label>
 | 
				
			||||||
        <label class="col-sm-3 col-md-2">{{ label }}</label>
 | 
					        <div class="col-sm-4 col-md-4">
 | 
				
			||||||
        <div class="col-sm-4 col-md-4">
 | 
					    {% endif %}
 | 
				
			||||||
    {% endif %}
 | 
					{%- endmacro %}
 | 
				
			||||||
{%- endmacro %}
 | 
					
 | 
				
			||||||
 | 
					{% macro preferences_item_footer(info, label, rtl) -%}
 | 
				
			||||||
{% macro preferences_item_footer(info, label, rtl) -%}
 | 
					    {% if rtl %}
 | 
				
			||||||
    {% if rtl %}
 | 
					        </div>
 | 
				
			||||||
        </div>
 | 
					    </div>
 | 
				
			||||||
    </div>
 | 
					    {% else %}
 | 
				
			||||||
    {% else %}
 | 
					        </div>
 | 
				
			||||||
        </div>
 | 
					        <span class="col-sm-5 col-md-6 help-block">{{ info }}</span>
 | 
				
			||||||
        <span class="col-sm-5 col-md-6 help-block">{{ info }}</span>
 | 
					    </div>
 | 
				
			||||||
    </div>
 | 
					    {% endif %}
 | 
				
			||||||
    {% endif %}
 | 
					{%- endmacro %}
 | 
				
			||||||
{%- endmacro %}
 | 
					
 | 
				
			||||||
 | 
					{% macro checkbox_toggle(id, blocked) -%}
 | 
				
			||||||
{% macro checkbox_toggle(id, blocked) -%}
 | 
					    <div class="onoffswitch">
 | 
				
			||||||
    <div class="onoffswitch">
 | 
					        <input type="checkbox" id="{{ id }}" name="{{ id }}"{% if blocked %} checked="checked"{% endif %} class="onoffswitch-checkbox">
 | 
				
			||||||
        <input type="checkbox" id="{{ id }}" name="{{ id }}"{% if blocked %} checked="checked"{% endif %} class="onoffswitch-checkbox">
 | 
					        <label class="onoffswitch-label" for="{{ id }}">
 | 
				
			||||||
        <label class="onoffswitch-label" for="{{ id }}">
 | 
					            <span class="onoffswitch-inner"></span>
 | 
				
			||||||
            <span class="onoffswitch-inner"></span>
 | 
					            <span class="onoffswitch-switch"></span>
 | 
				
			||||||
            <span class="onoffswitch-switch"></span>
 | 
					        </label>
 | 
				
			||||||
        </label>
 | 
					    </div>
 | 
				
			||||||
    </div>
 | 
					{%- endmacro %}
 | 
				
			||||||
{%- endmacro %}
 | 
					
 | 
				
			||||||
 | 
					{% macro support_toggle(supports) -%}
 | 
				
			||||||
 | 
					    {% if supports %}
 | 
				
			||||||
 | 
					    <span class="label label-success">
 | 
				
			||||||
 | 
					        {{ _("supported") }}
 | 
				
			||||||
 | 
					    </span>
 | 
				
			||||||
 | 
					    {% else %}
 | 
				
			||||||
 | 
					    <span class="label label-danger">
 | 
				
			||||||
 | 
					        {{ _("not supported") }}
 | 
				
			||||||
 | 
					    </span>
 | 
				
			||||||
 | 
					    {% endif %}
 | 
				
			||||||
 | 
					{%- endmacro %}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,8 @@
 | 
				
			|||||||
{% from 'oscar/macros.html' import preferences_item_header, preferences_item_header_rtl, preferences_item_footer, preferences_item_footer_rtl, checkbox_toggle %}
 | 
					{% from 'oscar/macros.html' import preferences_item_header, preferences_item_header_rtl, preferences_item_footer, preferences_item_footer_rtl, checkbox_toggle, support_toggle %}
 | 
				
			||||||
{% extends "oscar/base.html" %}
 | 
					{% extends "oscar/base.html" %}
 | 
				
			||||||
{% block title %}{{ _('preferences') }} - {% endblock %}
 | 
					{% block title %}{{ _('preferences') }} - {% endblock %}
 | 
				
			||||||
{% block content %}
 | 
					{% block content %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div>
 | 
					<div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <h1>{{ _('Preferences') }}</h1>
 | 
					    <h1>{{ _('Preferences') }}</h1>
 | 
				
			||||||
@ -148,7 +149,7 @@
 | 
				
			|||||||
				    <th>{{ _("Allow") }}</th>
 | 
									    <th>{{ _("Allow") }}</th>
 | 
				
			||||||
				    <th>{{ _("Engine name") }}</th>
 | 
									    <th>{{ _("Engine name") }}</th>
 | 
				
			||||||
				    <th>{{ _("Shortcut") }}</th>
 | 
									    <th>{{ _("Shortcut") }}</th>
 | 
				
			||||||
				    <th>{{ _("Supports selected language") }}</th>
 | 
									    <th>{{ _("Selected language") }}</th>
 | 
				
			||||||
				    <th>{{ _("SafeSearch") }}</th>
 | 
									    <th>{{ _("SafeSearch") }}</th>
 | 
				
			||||||
				    <th>{{ _("Time range") }}</th>
 | 
									    <th>{{ _("Time range") }}</th>
 | 
				
			||||||
				    <th>{{ _("Avg. time") }}</th>
 | 
									    <th>{{ _("Avg. time") }}</th>
 | 
				
			||||||
@ -156,8 +157,9 @@
 | 
				
			|||||||
                                    {% else %}
 | 
					                                    {% else %}
 | 
				
			||||||
				    <th>{{ _("Max time") }}</th>
 | 
									    <th>{{ _("Max time") }}</th>
 | 
				
			||||||
				    <th>{{ _("Avg. time") }}</th>
 | 
									    <th>{{ _("Avg. time") }}</th>
 | 
				
			||||||
 | 
									    <th>{{ _("Time range") }}</th>
 | 
				
			||||||
				    <th>{{ _("SafeSearch") }}</th>
 | 
									    <th>{{ _("SafeSearch") }}</th>
 | 
				
			||||||
				    <th>{{ _("Supports selected language") }}</th>
 | 
									    <th>{{ _("Selected language") }}</th>
 | 
				
			||||||
				    <th>{{ _("Shortcut") }}</th>
 | 
									    <th>{{ _("Shortcut") }}</th>
 | 
				
			||||||
				    <th>{{ _("Engine name") }}</th>
 | 
									    <th>{{ _("Engine name") }}</th>
 | 
				
			||||||
				    <th>{{ _("Allow") }}</th>
 | 
									    <th>{{ _("Allow") }}</th>
 | 
				
			||||||
@ -172,17 +174,18 @@
 | 
				
			|||||||
                                    </td>
 | 
					                                    </td>
 | 
				
			||||||
                                    <th>{{ search_engine.name }}</th>
 | 
					                                    <th>{{ search_engine.name }}</th>
 | 
				
			||||||
				    <td class="name">{{ shortcuts[search_engine.name] }}</td>
 | 
									    <td class="name">{{ shortcuts[search_engine.name] }}</td>
 | 
				
			||||||
				    <td><input type="checkbox" {{ "checked" if current_language == 'all' or current_language in search_engine.supported_languages or current_language.split('-')[0] in search_engine.supported_languages else ""}} readonly="readonly" disabled="disabled"></td>
 | 
										<td>{{ support_toggle(current_language == 'all' or current_language in search_engine.supported_languages or current_language.split('-')[0] in search_engine.supported_languages) }}</td>
 | 
				
			||||||
				    <td><input type="checkbox" {{ "checked" if search_engine.safesearch==True else ""}} readonly="readonly" disabled="disabled"></td>
 | 
										<td>{{ support_toggle(search_engine.safesearch==True) }}</td>
 | 
				
			||||||
				    <td><input type="checkbox" {{ "checked" if search_engine.time_range_support==True else ""}} readonly="readonly" disabled="disabled"></td>
 | 
										<td>{{ support_toggle(search_engine.time_range_support==True) }}</td>
 | 
				
			||||||
				    <td class="{{ 'danger' if stats[search_engine.name]['warn_time'] else '' }}">{{ 'N/A' if stats[search_engine.name].time==None else stats[search_engine.name].time }}</td>
 | 
										<td class="{{ 'danger' if stats[search_engine.name]['warn_time'] else '' }}">{{ 'N/A' if stats[search_engine.name].time==None else stats[search_engine.name].time }}</td>
 | 
				
			||||||
				    <td class="{{ 'danger' if stats[search_engine.name]['warn_timeout'] else '' }}">{{ search_engine.timeout }}</td>
 | 
										<td class="{{ 'danger' if stats[search_engine.name]['warn_timeout'] else '' }}">{{ search_engine.timeout }}</td>
 | 
				
			||||||
                                    {% else %}
 | 
														{% else %}
 | 
				
			||||||
				    <td class="{{ 'danger' if stats[search_engine.name]['warn_timeout'] else '' }}">{{ search_engine.timeout }}</td>
 | 
										<td class="{{ 'danger' if stats[search_engine.name]['warn_timeout'] else '' }}">{{ search_engine.timeout }}</td>
 | 
				
			||||||
				    <td class="{{ 'danger' if stats[search_engine.name]['warn_time'] else '' }}">{{ 'N/A' if stats[search_engine.name].time==None else stats[search_engine.name].time }}</td>
 | 
										<td class="{{ 'danger' if stats[search_engine.name]['warn_time'] else '' }}">{{ 'N/A' if stats[search_engine.name].time==None else stats[search_engine.name].time }}</td>
 | 
				
			||||||
				    <td><input type="checkbox" {{ "checked" if search_engine.safesearch==True else ""}} readonly="readonly" disabled="disabled"></td>
 | 
										<td>{{ support_toggle(search_engine.time_range_support==True) }}</td>
 | 
				
			||||||
				    <td><input type="checkbox" {{ "checked" if current_language == 'all' or current_language in search_engine.supported_languages or current_language.split('-')[0] in search_engine.supported_languages else ""}} readonly="readonly" disabled="disabled"></td>
 | 
										<td>{{ support_toggle(search_engine.safesearch==True) }}</td>
 | 
				
			||||||
				    <td>{{ shortcuts[search_engine.name] }}</td>
 | 
										<td>{{ support_toggle(current_language == 'all' or current_language in search_engine.supported_languages or current_language.split('-')[0] in search_engine.supported_languages) }}</td>
 | 
				
			||||||
 | 
										<td>{{ shortcuts[search_engine.name] }}</td>
 | 
				
			||||||
                                    <th>{{ search_engine.name }}</th>
 | 
					                                    <th>{{ search_engine.name }}</th>
 | 
				
			||||||
                                    <td class="onoff-checkbox">
 | 
					                                    <td class="onoff-checkbox">
 | 
				
			||||||
                                        {{ checkbox_toggle('engine_' + search_engine.name|replace(' ', '_') + '__' + categ|replace(' ', '_'), (search_engine.name, categ) in disabled_engines) }}
 | 
					                                        {{ checkbox_toggle('engine_' + search_engine.name|replace(' ', '_') + '__' + categ|replace(' ', '_'), (search_engine.name, categ) in disabled_engines) }}
 | 
				
			||||||
 | 
				
			|||||||
@ -8,9 +8,8 @@
 | 
				
			|||||||
{%- endmacro %}
 | 
					{%- endmacro %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<!-- Draw favicon -->
 | 
					<!-- Draw favicon -->
 | 
				
			||||||
<!-- TODO: using url_for methode -->
 | 
					 | 
				
			||||||
{% macro draw_favicon(favicon) -%}
 | 
					{% macro draw_favicon(favicon) -%}
 | 
				
			||||||
    <img width="14" height="14" class="favicon" src="static/themes/simple/img/icons/{{ favicon }}.png" alt="{{ favicon }}" />
 | 
					    <img width="14" height="14" class="favicon" src="{{ url_for('static', filename='themes/simple/img/icons/' + favicon + '.png') }}" alt="{{ favicon }}" />
 | 
				
			||||||
{%- endmacro %}
 | 
					{%- endmacro %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% macro result_open_link(url, classes='') -%}
 | 
					{% macro result_open_link(url, classes='') -%}
 | 
				
			||||||
 | 
				
			|||||||
										
											Binary file not shown.
										
									
								
							@ -1,844 +0,0 @@
 | 
				
			|||||||
# Translations template for PROJECT.
 | 
					 | 
				
			||||||
# Copyright (C) 2016 ORGANIZATION
 | 
					 | 
				
			||||||
# This file is distributed under the same license as the PROJECT project.
 | 
					 | 
				
			||||||
# 
 | 
					 | 
				
			||||||
# Translators:
 | 
					 | 
				
			||||||
# Bamstam, 2016-2017
 | 
					 | 
				
			||||||
# Benjamin Richter <benjamin@hacktherack.de>, 2015
 | 
					 | 
				
			||||||
# cy8aer <cybaer42@web.de>, 2016-2017
 | 
					 | 
				
			||||||
msgid ""
 | 
					 | 
				
			||||||
msgstr ""
 | 
					 | 
				
			||||||
"Project-Id-Version: searx\n"
 | 
					 | 
				
			||||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
 | 
					 | 
				
			||||||
"POT-Creation-Date: 2016-12-29 10:42+0100\n"
 | 
					 | 
				
			||||||
"PO-Revision-Date: 2017-05-19 20:17+0000\n"
 | 
					 | 
				
			||||||
"Last-Translator: cy8aer <cybaer42@web.de>\n"
 | 
					 | 
				
			||||||
"Language-Team: German (Germany) (http://www.transifex.com/asciimoo/searx/language/de_DE/)\n"
 | 
					 | 
				
			||||||
"MIME-Version: 1.0\n"
 | 
					 | 
				
			||||||
"Content-Type: text/plain; charset=UTF-8\n"
 | 
					 | 
				
			||||||
"Content-Transfer-Encoding: 8bit\n"
 | 
					 | 
				
			||||||
"Generated-By: Babel 2.3.4\n"
 | 
					 | 
				
			||||||
"Language: de_DE\n"
 | 
					 | 
				
			||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/webapp.py:123
 | 
					 | 
				
			||||||
msgid "files"
 | 
					 | 
				
			||||||
msgstr "Dateien"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/webapp.py:124
 | 
					 | 
				
			||||||
msgid "general"
 | 
					 | 
				
			||||||
msgstr "Allgemein"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/webapp.py:125
 | 
					 | 
				
			||||||
msgid "music"
 | 
					 | 
				
			||||||
msgstr "Musik"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/webapp.py:126
 | 
					 | 
				
			||||||
msgid "social media"
 | 
					 | 
				
			||||||
msgstr "Soziale Medien"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/webapp.py:127
 | 
					 | 
				
			||||||
msgid "images"
 | 
					 | 
				
			||||||
msgstr "Fotos"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/webapp.py:128
 | 
					 | 
				
			||||||
msgid "videos"
 | 
					 | 
				
			||||||
msgstr "Videos"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/webapp.py:129
 | 
					 | 
				
			||||||
msgid "it"
 | 
					 | 
				
			||||||
msgstr "IT"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/webapp.py:130
 | 
					 | 
				
			||||||
msgid "news"
 | 
					 | 
				
			||||||
msgstr "Nachrichten"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/webapp.py:131
 | 
					 | 
				
			||||||
msgid "map"
 | 
					 | 
				
			||||||
msgstr "Karten"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/webapp.py:132
 | 
					 | 
				
			||||||
msgid "science"
 | 
					 | 
				
			||||||
msgstr "Wissenschaft"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/webapp.py:384 searx/webapp.py:594
 | 
					 | 
				
			||||||
msgid "Invalid settings, please edit your preferences"
 | 
					 | 
				
			||||||
msgstr "Ungültige Auswahl, bitte überprüfen Sie die Einstellungen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/webapp.py:425
 | 
					 | 
				
			||||||
msgid "search error"
 | 
					 | 
				
			||||||
msgstr "Fehler bei der Suche"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/webapp.py:467
 | 
					 | 
				
			||||||
msgid "{minutes} minute(s) ago"
 | 
					 | 
				
			||||||
msgstr "vor {minutes} Minute(n)"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/webapp.py:469
 | 
					 | 
				
			||||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
 | 
					 | 
				
			||||||
msgstr "vor {hours} Stunde(n). {minutes} Minute(n)"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/answerers/random/answerer.py:48
 | 
					 | 
				
			||||||
msgid "Random value generator"
 | 
					 | 
				
			||||||
msgstr "Zufallswertgenerator"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/answerers/random/answerer.py:49
 | 
					 | 
				
			||||||
msgid "Generate different random values"
 | 
					 | 
				
			||||||
msgstr "Zufallswerte generieren"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/answerers/statistics/answerer.py:49
 | 
					 | 
				
			||||||
msgid "Statistics functions"
 | 
					 | 
				
			||||||
msgstr "Statistik-Funktionen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/answerers/statistics/answerer.py:50
 | 
					 | 
				
			||||||
msgid "Compute {functions} of the arguments"
 | 
					 | 
				
			||||||
msgstr "{functions} der Argumente berechnen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/engines/__init__.py:192
 | 
					 | 
				
			||||||
msgid "Engine time (sec)"
 | 
					 | 
				
			||||||
msgstr "Zeitbedarf (s)"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/engines/__init__.py:196
 | 
					 | 
				
			||||||
msgid "Page loads (sec)"
 | 
					 | 
				
			||||||
msgstr "Ladezeit (s)"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/engines/__init__.py:200 searx/templates/oscar/results.html:88
 | 
					 | 
				
			||||||
msgid "Number of results"
 | 
					 | 
				
			||||||
msgstr "Anzahl Ergebnisse"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/engines/__init__.py:204
 | 
					 | 
				
			||||||
msgid "Scores"
 | 
					 | 
				
			||||||
msgstr "Punktwerte"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/engines/__init__.py:208
 | 
					 | 
				
			||||||
msgid "Scores per result"
 | 
					 | 
				
			||||||
msgstr "Punktwerte pro Ergebnis"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/engines/__init__.py:212
 | 
					 | 
				
			||||||
msgid "Errors"
 | 
					 | 
				
			||||||
msgstr "Fehler"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/engines/pdbe.py:87
 | 
					 | 
				
			||||||
msgid "{title} (OBSOLETE)"
 | 
					 | 
				
			||||||
msgstr "{title} (OBSOLET)"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/engines/pdbe.py:91
 | 
					 | 
				
			||||||
msgid "This entry has been superseded by"
 | 
					 | 
				
			||||||
msgstr "Dieser Eintrag wurde ersetzt durch"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/plugins/doai_rewrite.py:7
 | 
					 | 
				
			||||||
msgid "DOAI rewrite"
 | 
					 | 
				
			||||||
msgstr "DOAI-Umgehung"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/plugins/doai_rewrite.py:8
 | 
					 | 
				
			||||||
msgid ""
 | 
					 | 
				
			||||||
"Avoid paywalls by redirecting to open-access versions of publications when "
 | 
					 | 
				
			||||||
"available"
 | 
					 | 
				
			||||||
msgstr "Paywalls umgehen, indem wenn möglich auf Open-Access-Versionen von Publikationen umgeleitet wird"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/plugins/https_rewrite.py:29
 | 
					 | 
				
			||||||
msgid "Rewrite HTTP links to HTTPS if possible"
 | 
					 | 
				
			||||||
msgstr "Umschreiben von HTTP-Links nach HTTPS, wenn möglich"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/plugins/infinite_scroll.py:3
 | 
					 | 
				
			||||||
msgid "Infinite scroll"
 | 
					 | 
				
			||||||
msgstr "Unbegrenztes Scrollen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/plugins/infinite_scroll.py:4
 | 
					 | 
				
			||||||
msgid "Automatically load next page when scrolling to bottom of current page"
 | 
					 | 
				
			||||||
msgstr "Nächste Seite automatisch laden, wenn zum Seitenende gescrollt wird"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/plugins/open_results_on_new_tab.py:18
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:113
 | 
					 | 
				
			||||||
msgid "Open result links on new browser tabs"
 | 
					 | 
				
			||||||
msgstr "Öffne Links in einem neuen Browser-Tab"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/plugins/open_results_on_new_tab.py:19
 | 
					 | 
				
			||||||
msgid ""
 | 
					 | 
				
			||||||
"Results are opened in the same window by default. This plugin overwrites the"
 | 
					 | 
				
			||||||
" default behaviour to open links on new tabs/windows. (JavaScript required)"
 | 
					 | 
				
			||||||
msgstr "Suchergebnisse werden standardmäßig im gleichen Fenster geöffnet. Dieses Plug-in überschreibt dieses Standardverhalten und öffnet Links in neuen Tabs/Fenstern (benötigt JavaScript)."
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/plugins/search_on_category_select.py:18
 | 
					 | 
				
			||||||
msgid "Search on category select"
 | 
					 | 
				
			||||||
msgstr "Suchen nach Kategorie"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/plugins/search_on_category_select.py:19
 | 
					 | 
				
			||||||
msgid ""
 | 
					 | 
				
			||||||
"Perform search immediately if a category selected. Disable to select "
 | 
					 | 
				
			||||||
"multiple categories. (JavaScript required)"
 | 
					 | 
				
			||||||
msgstr "Suche sofort durchführen, wenn eine Kategorie ausgewählt wird. Deaktivieren Sie diese Option, um mehrere Kategorien auswählen zu können (benötigt JavaScript)."
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/plugins/self_info.py:20
 | 
					 | 
				
			||||||
msgid ""
 | 
					 | 
				
			||||||
"Displays your IP if the query is \"ip\" and your user agent if the query "
 | 
					 | 
				
			||||||
"contains \"user agent\"."
 | 
					 | 
				
			||||||
msgstr "Zeigt Ihre IP-Adresse an, wenn \"ip\" als Suchanfrage eingegeben wird und den User Agent bzw. das verwendete Client-Programm, wenn die Suchanfrage den Ausdruck \"user agent\" enthält."
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/plugins/tracker_url_remover.py:26
 | 
					 | 
				
			||||||
msgid "Tracker URL remover"
 | 
					 | 
				
			||||||
msgstr "Tracking-URLs bereinigen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/plugins/tracker_url_remover.py:27
 | 
					 | 
				
			||||||
msgid "Remove trackers arguments from the returned URL"
 | 
					 | 
				
			||||||
msgstr "Tracker-Argumente der erhaltenen URL entfernen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/plugins/vim_hotkeys.py:3
 | 
					 | 
				
			||||||
msgid "Vim-like hotkeys"
 | 
					 | 
				
			||||||
msgstr "Vim-ähnliche Hotkeys"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/plugins/vim_hotkeys.py:4
 | 
					 | 
				
			||||||
msgid ""
 | 
					 | 
				
			||||||
"Navigate search results with Vim-like hotkeys (JavaScript required). Press "
 | 
					 | 
				
			||||||
"\"h\" key on main or result page to get help."
 | 
					 | 
				
			||||||
msgstr "Durch Suchergebnisse navigieren mit Vim-ähnlichen Hotkeys (benötigt JavaScript). \"h\" drücken auf der Hauptseite oder der Ergebnisseite, um Hilfe zu erhalten."
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/404.html:4 searx/templates/legacy/404.html:4
 | 
					 | 
				
			||||||
#: searx/templates/oscar/404.html:4 searx/templates/pix-art/404.html:4
 | 
					 | 
				
			||||||
msgid "Page not found"
 | 
					 | 
				
			||||||
msgstr "Seite nicht gefunden"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/404.html:6 searx/templates/legacy/404.html:6
 | 
					 | 
				
			||||||
#: searx/templates/oscar/404.html:6 searx/templates/pix-art/404.html:6
 | 
					 | 
				
			||||||
#, python-format
 | 
					 | 
				
			||||||
msgid "Go to %(search_page)s."
 | 
					 | 
				
			||||||
msgstr "Gehe zu %(search_page)s."
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/404.html:6 searx/templates/legacy/404.html:6
 | 
					 | 
				
			||||||
#: searx/templates/oscar/404.html:6 searx/templates/pix-art/404.html:6
 | 
					 | 
				
			||||||
msgid "search page"
 | 
					 | 
				
			||||||
msgstr "Seite durchsuchen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/index.html:9
 | 
					 | 
				
			||||||
#: searx/templates/courgette/index.html:13
 | 
					 | 
				
			||||||
#: searx/templates/courgette/results.html:5
 | 
					 | 
				
			||||||
#: searx/templates/legacy/index.html:8 searx/templates/legacy/index.html:12
 | 
					 | 
				
			||||||
#: searx/templates/oscar/navbar.html:12
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:3
 | 
					 | 
				
			||||||
#: searx/templates/pix-art/index.html:8
 | 
					 | 
				
			||||||
msgid "preferences"
 | 
					 | 
				
			||||||
msgstr "Einstellungen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/index.html:11
 | 
					 | 
				
			||||||
#: searx/templates/legacy/index.html:10 searx/templates/oscar/about.html:2
 | 
					 | 
				
			||||||
#: searx/templates/oscar/navbar.html:11 searx/templates/pix-art/index.html:7
 | 
					 | 
				
			||||||
msgid "about"
 | 
					 | 
				
			||||||
msgstr "Über uns"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:5
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:5
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:7
 | 
					 | 
				
			||||||
#: searx/templates/pix-art/preferences.html:5
 | 
					 | 
				
			||||||
msgid "Preferences"
 | 
					 | 
				
			||||||
msgstr "Einstellungen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:9
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:9
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:32
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:34
 | 
					 | 
				
			||||||
msgid "Default categories"
 | 
					 | 
				
			||||||
msgstr "Standardkategorien"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:13
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:14
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:40
 | 
					 | 
				
			||||||
#: searx/templates/pix-art/preferences.html:9
 | 
					 | 
				
			||||||
msgid "Search language"
 | 
					 | 
				
			||||||
msgstr "Suchsprache"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:16
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:17
 | 
					 | 
				
			||||||
#: searx/templates/oscar/languages.html:6
 | 
					 | 
				
			||||||
#: searx/templates/pix-art/preferences.html:12
 | 
					 | 
				
			||||||
msgid "Default language"
 | 
					 | 
				
			||||||
msgstr "Standardsprache"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:24
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:25
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:46
 | 
					 | 
				
			||||||
#: searx/templates/pix-art/preferences.html:20
 | 
					 | 
				
			||||||
msgid "Interface language"
 | 
					 | 
				
			||||||
msgstr "Sprache der Benutzeroberfläche"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:34
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:35
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:56
 | 
					 | 
				
			||||||
msgid "Autocomplete"
 | 
					 | 
				
			||||||
msgstr "Autovervollständigen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:45
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:46
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:67
 | 
					 | 
				
			||||||
msgid "Image proxy"
 | 
					 | 
				
			||||||
msgstr "Proxy-Server für Bilder"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:48
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:49
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:71
 | 
					 | 
				
			||||||
msgid "Enabled"
 | 
					 | 
				
			||||||
msgstr "Aktiviert"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:49
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:50
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:72
 | 
					 | 
				
			||||||
msgid "Disabled"
 | 
					 | 
				
			||||||
msgstr "Deaktiviert"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:54
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:55
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:76
 | 
					 | 
				
			||||||
#: searx/templates/pix-art/preferences.html:30
 | 
					 | 
				
			||||||
msgid "Method"
 | 
					 | 
				
			||||||
msgstr "Methode"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:63
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:64
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:85
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:152
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:159
 | 
					 | 
				
			||||||
msgid "SafeSearch"
 | 
					 | 
				
			||||||
msgstr "SafeSearch"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:66
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:67
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:89
 | 
					 | 
				
			||||||
msgid "Strict"
 | 
					 | 
				
			||||||
msgstr "Streng"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:67
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:68
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:90
 | 
					 | 
				
			||||||
msgid "Moderate"
 | 
					 | 
				
			||||||
msgstr "Moderat"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:68
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:69
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:91
 | 
					 | 
				
			||||||
msgid "None"
 | 
					 | 
				
			||||||
msgstr "Keine"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:73
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:74
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:95
 | 
					 | 
				
			||||||
#: searx/templates/pix-art/preferences.html:39
 | 
					 | 
				
			||||||
msgid "Themes"
 | 
					 | 
				
			||||||
msgstr "Oberflächen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:83
 | 
					 | 
				
			||||||
msgid "Color"
 | 
					 | 
				
			||||||
msgstr "Farbe"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:86
 | 
					 | 
				
			||||||
msgid "Blue (default)"
 | 
					 | 
				
			||||||
msgstr "Blau (Standard)"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:87
 | 
					 | 
				
			||||||
msgid "Violet"
 | 
					 | 
				
			||||||
msgstr "Violett"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:88
 | 
					 | 
				
			||||||
msgid "Green"
 | 
					 | 
				
			||||||
msgstr "Grün"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:89
 | 
					 | 
				
			||||||
msgid "Cyan"
 | 
					 | 
				
			||||||
msgstr "Türkis"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:90
 | 
					 | 
				
			||||||
msgid "Orange"
 | 
					 | 
				
			||||||
msgstr "Orange"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:91
 | 
					 | 
				
			||||||
msgid "Red"
 | 
					 | 
				
			||||||
msgstr "Rot"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:96
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:93
 | 
					 | 
				
			||||||
#: searx/templates/pix-art/preferences.html:49
 | 
					 | 
				
			||||||
msgid "Currently used search engines"
 | 
					 | 
				
			||||||
msgstr "Momentan genutzte Suchmaschinen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:100
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:97
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:149
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:162
 | 
					 | 
				
			||||||
#: searx/templates/pix-art/preferences.html:53
 | 
					 | 
				
			||||||
msgid "Engine name"
 | 
					 | 
				
			||||||
msgstr "Suchmaschinen-Name"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:101
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:98
 | 
					 | 
				
			||||||
msgid "Category"
 | 
					 | 
				
			||||||
msgstr "Kategorie"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:102
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:113
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:99
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:110
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:148
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:163
 | 
					 | 
				
			||||||
#: searx/templates/pix-art/preferences.html:54
 | 
					 | 
				
			||||||
#: searx/templates/pix-art/preferences.html:64
 | 
					 | 
				
			||||||
msgid "Allow"
 | 
					 | 
				
			||||||
msgstr "Zulassen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:102
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:114
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:99
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:111
 | 
					 | 
				
			||||||
#: searx/templates/pix-art/preferences.html:54
 | 
					 | 
				
			||||||
#: searx/templates/pix-art/preferences.html:65
 | 
					 | 
				
			||||||
msgid "Block"
 | 
					 | 
				
			||||||
msgstr "Blockieren"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:122
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:119
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:282
 | 
					 | 
				
			||||||
#: searx/templates/pix-art/preferences.html:73
 | 
					 | 
				
			||||||
msgid ""
 | 
					 | 
				
			||||||
"These settings are stored in your cookies, this allows us not to store this "
 | 
					 | 
				
			||||||
"data about you."
 | 
					 | 
				
			||||||
msgstr "Diese Einstellungen werden in Ihren Cookies gespeichert, deshalb müssen wir diese persönlichen Daten nicht bei uns speichern."
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:124
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:121
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:284
 | 
					 | 
				
			||||||
#: searx/templates/pix-art/preferences.html:75
 | 
					 | 
				
			||||||
msgid ""
 | 
					 | 
				
			||||||
"These cookies serve your sole convenience, we don't use these cookies to "
 | 
					 | 
				
			||||||
"track you."
 | 
					 | 
				
			||||||
msgstr "Diese Cookies ermöglichen lediglich eine komfortablere Nutzung, wir verwenden diese Cookies nicht, um Sie zu tracken."
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:127
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:124
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:287
 | 
					 | 
				
			||||||
#: searx/templates/pix-art/preferences.html:78
 | 
					 | 
				
			||||||
msgid "save"
 | 
					 | 
				
			||||||
msgstr "speichern"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:128
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:125
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:289
 | 
					 | 
				
			||||||
msgid "Reset defaults"
 | 
					 | 
				
			||||||
msgstr "Voreinstellungen wiederherstellen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/preferences.html:129
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:126
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:288
 | 
					 | 
				
			||||||
#: searx/templates/pix-art/preferences.html:79
 | 
					 | 
				
			||||||
msgid "back"
 | 
					 | 
				
			||||||
msgstr "zurück"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/results.html:12
 | 
					 | 
				
			||||||
#: searx/templates/legacy/results.html:13
 | 
					 | 
				
			||||||
#: searx/templates/oscar/results.html:124
 | 
					 | 
				
			||||||
msgid "Search URL"
 | 
					 | 
				
			||||||
msgstr "Such-URL"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/results.html:16
 | 
					 | 
				
			||||||
#: searx/templates/legacy/results.html:17
 | 
					 | 
				
			||||||
#: searx/templates/oscar/results.html:129
 | 
					 | 
				
			||||||
msgid "Download results"
 | 
					 | 
				
			||||||
msgstr "Suchergebnisse herunterladen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/results.html:34
 | 
					 | 
				
			||||||
#: searx/templates/legacy/results.html:35
 | 
					 | 
				
			||||||
msgid "Answers"
 | 
					 | 
				
			||||||
msgstr "Antworten"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/results.html:42
 | 
					 | 
				
			||||||
#: searx/templates/legacy/results.html:43
 | 
					 | 
				
			||||||
#: searx/templates/oscar/results.html:104
 | 
					 | 
				
			||||||
msgid "Suggestions"
 | 
					 | 
				
			||||||
msgstr "Vorschläge"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/results.html:70
 | 
					 | 
				
			||||||
#: searx/templates/legacy/results.html:81
 | 
					 | 
				
			||||||
#: searx/templates/oscar/results.html:53 searx/templates/oscar/results.html:66
 | 
					 | 
				
			||||||
msgid "previous page"
 | 
					 | 
				
			||||||
msgstr "vorherige Seite"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/results.html:81
 | 
					 | 
				
			||||||
#: searx/templates/legacy/results.html:92
 | 
					 | 
				
			||||||
#: searx/templates/oscar/results.html:45 searx/templates/oscar/results.html:75
 | 
					 | 
				
			||||||
msgid "next page"
 | 
					 | 
				
			||||||
msgstr "nächste Seite"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/search.html:3
 | 
					 | 
				
			||||||
#: searx/templates/legacy/search.html:3 searx/templates/oscar/search.html:4
 | 
					 | 
				
			||||||
#: searx/templates/oscar/search_full.html:9
 | 
					 | 
				
			||||||
#: searx/templates/pix-art/search.html:3
 | 
					 | 
				
			||||||
msgid "Search for..."
 | 
					 | 
				
			||||||
msgstr "Suchen nach ..."
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/stats.html:4 searx/templates/legacy/stats.html:4
 | 
					 | 
				
			||||||
#: searx/templates/oscar/stats.html:5 searx/templates/pix-art/stats.html:4
 | 
					 | 
				
			||||||
msgid "Engine stats"
 | 
					 | 
				
			||||||
msgstr "Suchmaschinen-Statistiken"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/result_templates/images.html:4
 | 
					 | 
				
			||||||
#: searx/templates/legacy/result_templates/images.html:4
 | 
					 | 
				
			||||||
#: searx/templates/pix-art/result_templates/images.html:4
 | 
					 | 
				
			||||||
msgid "original context"
 | 
					 | 
				
			||||||
msgstr "Ursprünglicher Kontext"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/result_templates/torrent.html:7
 | 
					 | 
				
			||||||
#: searx/templates/legacy/result_templates/torrent.html:11
 | 
					 | 
				
			||||||
#: searx/templates/oscar/result_templates/torrent.html:6
 | 
					 | 
				
			||||||
msgid "Seeder"
 | 
					 | 
				
			||||||
msgstr "Seeder"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/result_templates/torrent.html:7
 | 
					 | 
				
			||||||
#: searx/templates/legacy/result_templates/torrent.html:11
 | 
					 | 
				
			||||||
#: searx/templates/oscar/result_templates/torrent.html:6
 | 
					 | 
				
			||||||
msgid "Leecher"
 | 
					 | 
				
			||||||
msgstr "Leecher"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/result_templates/torrent.html:9
 | 
					 | 
				
			||||||
#: searx/templates/legacy/result_templates/torrent.html:9
 | 
					 | 
				
			||||||
#: searx/templates/oscar/macros.html:24
 | 
					 | 
				
			||||||
msgid "magnet link"
 | 
					 | 
				
			||||||
msgstr "Magnet-Link"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/courgette/result_templates/torrent.html:10
 | 
					 | 
				
			||||||
#: searx/templates/legacy/result_templates/torrent.html:10
 | 
					 | 
				
			||||||
#: searx/templates/oscar/macros.html:25
 | 
					 | 
				
			||||||
msgid "torrent file"
 | 
					 | 
				
			||||||
msgstr "Torrent-Datei"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/legacy/categories.html:8
 | 
					 | 
				
			||||||
msgid "Click on the magnifier to perform search"
 | 
					 | 
				
			||||||
msgstr "Klicken Sie auf das Vergrößerungsglas, um die Suche zu starten"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:84
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:112
 | 
					 | 
				
			||||||
msgid "Results on new tabs"
 | 
					 | 
				
			||||||
msgstr "Ergebnisse in neuen Tabs"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:87
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:116
 | 
					 | 
				
			||||||
msgid "On"
 | 
					 | 
				
			||||||
msgstr "An"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/legacy/preferences.html:88
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:117
 | 
					 | 
				
			||||||
msgid "Off"
 | 
					 | 
				
			||||||
msgstr "Aus"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/legacy/result_templates/code.html:3
 | 
					 | 
				
			||||||
#: searx/templates/legacy/result_templates/default.html:3
 | 
					 | 
				
			||||||
#: searx/templates/legacy/result_templates/map.html:9
 | 
					 | 
				
			||||||
#: searx/templates/oscar/macros.html:35 searx/templates/oscar/macros.html:49
 | 
					 | 
				
			||||||
msgid "cached"
 | 
					 | 
				
			||||||
msgstr "im Cache"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/advanced.html:4
 | 
					 | 
				
			||||||
msgid "Advanced settings"
 | 
					 | 
				
			||||||
msgstr "Erweiterte Einstellungen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/base.html:62
 | 
					 | 
				
			||||||
#: searx/templates/oscar/messages/first_time.html:4
 | 
					 | 
				
			||||||
#: searx/templates/oscar/messages/no_results.html:5
 | 
					 | 
				
			||||||
#: searx/templates/oscar/messages/save_settings_successfull.html:5
 | 
					 | 
				
			||||||
#: searx/templates/oscar/messages/unknow_error.html:5
 | 
					 | 
				
			||||||
msgid "Close"
 | 
					 | 
				
			||||||
msgstr "Schließen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/base.html:64
 | 
					 | 
				
			||||||
msgid "Error!"
 | 
					 | 
				
			||||||
msgstr "Fehler!"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/base.html:90
 | 
					 | 
				
			||||||
msgid "Powered by"
 | 
					 | 
				
			||||||
msgstr "Bereitgestellt von"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/base.html:90
 | 
					 | 
				
			||||||
msgid "a privacy-respecting, hackable metasearch engine"
 | 
					 | 
				
			||||||
msgstr "eine die Privatsphäre respektierende, hackbare Meta-Suchmaschine"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/macros.html:37 searx/templates/oscar/macros.html:51
 | 
					 | 
				
			||||||
msgid "proxied"
 | 
					 | 
				
			||||||
msgstr "via Proxy-Server"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:12
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:21
 | 
					 | 
				
			||||||
msgid "General"
 | 
					 | 
				
			||||||
msgstr "Allgemein"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:13
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:133
 | 
					 | 
				
			||||||
msgid "Engines"
 | 
					 | 
				
			||||||
msgstr "Suchmaschinen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:14
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:204
 | 
					 | 
				
			||||||
msgid "Plugins"
 | 
					 | 
				
			||||||
msgstr "Plug-ins"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:15
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:230
 | 
					 | 
				
			||||||
msgid "Answerers"
 | 
					 | 
				
			||||||
msgstr "Instant Answers/Sofortantworten"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:16
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:257
 | 
					 | 
				
			||||||
msgid "Cookies"
 | 
					 | 
				
			||||||
msgstr "Cookies"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:41
 | 
					 | 
				
			||||||
msgid "What language do you prefer for search?"
 | 
					 | 
				
			||||||
msgstr "Welche Sprache möchten Sie für die Suche verwenden?"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:47
 | 
					 | 
				
			||||||
msgid "Change the language of the layout"
 | 
					 | 
				
			||||||
msgstr "Sprache des Layouts ändern"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:57
 | 
					 | 
				
			||||||
msgid "Find stuff as you type"
 | 
					 | 
				
			||||||
msgstr "Bereits während der Eingabe suchen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:68
 | 
					 | 
				
			||||||
msgid "Proxying image results through searx"
 | 
					 | 
				
			||||||
msgstr "Bilder-Suchergebnisse über den searx-Proxy-Server laden"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:77
 | 
					 | 
				
			||||||
msgid ""
 | 
					 | 
				
			||||||
"Change how forms are submited, <a "
 | 
					 | 
				
			||||||
"href=\"http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods\""
 | 
					 | 
				
			||||||
" rel=\"external\">learn more about request methods</a>"
 | 
					 | 
				
			||||||
msgstr "HTTP-Anfragemethode ändern <a href=\"https://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol#HTTP-Anfragemethoden\" rel=\"external\">(weiterführende Informationen zu HTTP-Anfragemethoden)</a>"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:86
 | 
					 | 
				
			||||||
msgid "Filter content"
 | 
					 | 
				
			||||||
msgstr "Inhalte filtern"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:96
 | 
					 | 
				
			||||||
msgid "Change searx layout"
 | 
					 | 
				
			||||||
msgstr "searx-Layout ändern"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:105
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:110
 | 
					 | 
				
			||||||
msgid "Choose style for this theme"
 | 
					 | 
				
			||||||
msgstr "Stilrichtung für diese Benutzeroberfläche auswählen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:105
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:110
 | 
					 | 
				
			||||||
msgid "Style"
 | 
					 | 
				
			||||||
msgstr "Stilrichtung"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:150
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:161
 | 
					 | 
				
			||||||
msgid "Shortcut"
 | 
					 | 
				
			||||||
msgstr "Kürzel"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:151
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:160
 | 
					 | 
				
			||||||
msgid "Supports selected language"
 | 
					 | 
				
			||||||
msgstr "Unterstützt die ausgewähle Sprache"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:153
 | 
					 | 
				
			||||||
msgid "Time range"
 | 
					 | 
				
			||||||
msgstr "Zeitraum"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:154
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:158
 | 
					 | 
				
			||||||
msgid "Avg. time"
 | 
					 | 
				
			||||||
msgstr "Durchschn. Zeit"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:155
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:157
 | 
					 | 
				
			||||||
msgid "Max time"
 | 
					 | 
				
			||||||
msgstr "Maximale Zeit"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:233
 | 
					 | 
				
			||||||
msgid "This is the list of searx's instant answering modules."
 | 
					 | 
				
			||||||
msgstr "Auflistung der searx-Module für Sofortantworten:"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:237
 | 
					 | 
				
			||||||
msgid "Name"
 | 
					 | 
				
			||||||
msgstr "Name"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:238
 | 
					 | 
				
			||||||
msgid "Keywords"
 | 
					 | 
				
			||||||
msgstr "Schlüsselwörter"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:239
 | 
					 | 
				
			||||||
msgid "Description"
 | 
					 | 
				
			||||||
msgstr "Beschreibung"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:240
 | 
					 | 
				
			||||||
msgid "Examples"
 | 
					 | 
				
			||||||
msgstr "Beispiele"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:260
 | 
					 | 
				
			||||||
msgid ""
 | 
					 | 
				
			||||||
"This is the list of cookies and their values searx is storing on your "
 | 
					 | 
				
			||||||
"computer."
 | 
					 | 
				
			||||||
msgstr "Hier werden die Cookies und die gespeicherten Cookie-Informationen aufgelistet, die searx auf Ihrem Computer speichert."
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:261
 | 
					 | 
				
			||||||
msgid "With that list, you can assess searx transparency."
 | 
					 | 
				
			||||||
msgstr "Mit Hilfe dieser Auflistung können Sie die Transparenz der searx-Suche einschätzen."
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:266
 | 
					 | 
				
			||||||
msgid "Cookie name"
 | 
					 | 
				
			||||||
msgstr "Cookie-Name"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/preferences.html:267
 | 
					 | 
				
			||||||
msgid "Value"
 | 
					 | 
				
			||||||
msgstr "Wert"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/results.html:7
 | 
					 | 
				
			||||||
msgid "Search results"
 | 
					 | 
				
			||||||
msgstr "Durchsuche Ergebnisse"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/results.html:119
 | 
					 | 
				
			||||||
msgid "Links"
 | 
					 | 
				
			||||||
msgstr "Links"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/search.html:6
 | 
					 | 
				
			||||||
#: searx/templates/oscar/search_full.html:11
 | 
					 | 
				
			||||||
msgid "Start search"
 | 
					 | 
				
			||||||
msgstr "Suche starten"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/stats.html:2
 | 
					 | 
				
			||||||
msgid "stats"
 | 
					 | 
				
			||||||
msgstr "Statistiken"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/time-range.html:3
 | 
					 | 
				
			||||||
msgid "Anytime"
 | 
					 | 
				
			||||||
msgstr "Beliebiger Zeitunkt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/time-range.html:6
 | 
					 | 
				
			||||||
msgid "Last day"
 | 
					 | 
				
			||||||
msgstr "Gestern"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/time-range.html:9
 | 
					 | 
				
			||||||
msgid "Last week"
 | 
					 | 
				
			||||||
msgstr "Letzte Woche"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/time-range.html:12
 | 
					 | 
				
			||||||
msgid "Last month"
 | 
					 | 
				
			||||||
msgstr "Letzter Monat"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/time-range.html:15
 | 
					 | 
				
			||||||
msgid "Last year"
 | 
					 | 
				
			||||||
msgstr "Letztes Jahr"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/messages/first_time.html:6
 | 
					 | 
				
			||||||
#: searx/templates/oscar/messages/no_data_available.html:3
 | 
					 | 
				
			||||||
msgid "Heads up!"
 | 
					 | 
				
			||||||
msgstr "Aufgepasst!"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/messages/first_time.html:7
 | 
					 | 
				
			||||||
msgid "It look like you are using searx first time."
 | 
					 | 
				
			||||||
msgstr "Anscheinend benutzen Sie searx zum ersten Mal."
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/messages/no_cookies.html:3
 | 
					 | 
				
			||||||
msgid "Information!"
 | 
					 | 
				
			||||||
msgstr "Zur Information!"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/messages/no_cookies.html:4
 | 
					 | 
				
			||||||
msgid "currently, there are no cookies defined."
 | 
					 | 
				
			||||||
msgstr "Zur Zeit sind keine Cookies definiert."
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/messages/no_data_available.html:4
 | 
					 | 
				
			||||||
msgid "There is currently no data available. "
 | 
					 | 
				
			||||||
msgstr "Zur Zeit sind keine Daten verfügbar."
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/messages/no_results.html:7
 | 
					 | 
				
			||||||
msgid "Sorry!"
 | 
					 | 
				
			||||||
msgstr "Entschuldigung!"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/messages/no_results.html:8
 | 
					 | 
				
			||||||
msgid ""
 | 
					 | 
				
			||||||
"we didn't find any results. Please use another query or search in more "
 | 
					 | 
				
			||||||
"categories."
 | 
					 | 
				
			||||||
msgstr "Leider konnten wir keine Suchergebnisse finden. Bitte verwenden Sie eine andere Suchabfrage oder erweitern Sie die Suche auf mehr Kategorien."
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/messages/save_settings_successfull.html:7
 | 
					 | 
				
			||||||
msgid "Well done!"
 | 
					 | 
				
			||||||
msgstr "Gut gemacht!"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/messages/save_settings_successfull.html:8
 | 
					 | 
				
			||||||
msgid "Settings saved successfully."
 | 
					 | 
				
			||||||
msgstr "Einstellungen erfolgreich gespeichert."
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/messages/unknow_error.html:7
 | 
					 | 
				
			||||||
msgid "Oh snap!"
 | 
					 | 
				
			||||||
msgstr "Hoppla!"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/messages/unknow_error.html:8
 | 
					 | 
				
			||||||
msgid "Something went wrong."
 | 
					 | 
				
			||||||
msgstr "Ein Fehler ist aufgetreten."
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/result_templates/default.html:7
 | 
					 | 
				
			||||||
msgid "show media"
 | 
					 | 
				
			||||||
msgstr "Medien anzeigen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/result_templates/default.html:7
 | 
					 | 
				
			||||||
msgid "hide media"
 | 
					 | 
				
			||||||
msgstr "Medien verbergen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/result_templates/images.html:30
 | 
					 | 
				
			||||||
msgid "Get image"
 | 
					 | 
				
			||||||
msgstr "Bild herunterladen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/result_templates/images.html:33
 | 
					 | 
				
			||||||
msgid "View source"
 | 
					 | 
				
			||||||
msgstr "Quelle anzeigen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/result_templates/map.html:7
 | 
					 | 
				
			||||||
msgid "show map"
 | 
					 | 
				
			||||||
msgstr "Karte anzeigen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/result_templates/map.html:7
 | 
					 | 
				
			||||||
msgid "hide map"
 | 
					 | 
				
			||||||
msgstr "Karte verbergen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/result_templates/map.html:11
 | 
					 | 
				
			||||||
msgid "show details"
 | 
					 | 
				
			||||||
msgstr "Details anzeigen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/result_templates/map.html:11
 | 
					 | 
				
			||||||
msgid "hide details"
 | 
					 | 
				
			||||||
msgstr "Details verbergen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/result_templates/torrent.html:7
 | 
					 | 
				
			||||||
msgid "Filesize"
 | 
					 | 
				
			||||||
msgstr "Dateigröße"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/result_templates/torrent.html:9
 | 
					 | 
				
			||||||
msgid "Bytes"
 | 
					 | 
				
			||||||
msgstr "Bytes"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/result_templates/torrent.html:10
 | 
					 | 
				
			||||||
msgid "kiB"
 | 
					 | 
				
			||||||
msgstr "kiB"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/result_templates/torrent.html:11
 | 
					 | 
				
			||||||
msgid "MiB"
 | 
					 | 
				
			||||||
msgstr "MiB"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/result_templates/torrent.html:12
 | 
					 | 
				
			||||||
msgid "GiB"
 | 
					 | 
				
			||||||
msgstr "GiB"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/result_templates/torrent.html:13
 | 
					 | 
				
			||||||
msgid "TiB"
 | 
					 | 
				
			||||||
msgstr "TiB"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/result_templates/torrent.html:15
 | 
					 | 
				
			||||||
msgid "Number of Files"
 | 
					 | 
				
			||||||
msgstr "Anzahl Dateien"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/result_templates/videos.html:7
 | 
					 | 
				
			||||||
msgid "show video"
 | 
					 | 
				
			||||||
msgstr "Video anzeigen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/oscar/result_templates/videos.html:7
 | 
					 | 
				
			||||||
msgid "hide video"
 | 
					 | 
				
			||||||
msgstr "Video verbergen"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#: searx/templates/pix-art/results.html:28
 | 
					 | 
				
			||||||
msgid "Load more..."
 | 
					 | 
				
			||||||
msgstr "Mehr anzeigen ..."
 | 
					 | 
				
			||||||
@ -1,4 +1,6 @@
 | 
				
			|||||||
import csv
 | 
					import csv
 | 
				
			||||||
 | 
					import hashlib
 | 
				
			||||||
 | 
					import hmac
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -290,6 +292,15 @@ def convert_str_to_int(number_str):
 | 
				
			|||||||
        return 0
 | 
					        return 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# convert a variable to integer or return 0 if it's not a number
 | 
				
			||||||
 | 
					def int_or_zero(num):
 | 
				
			||||||
 | 
					    if isinstance(num, list):
 | 
				
			||||||
 | 
					        if len(num) < 1:
 | 
				
			||||||
 | 
					            return 0
 | 
				
			||||||
 | 
					        num = num[0]
 | 
				
			||||||
 | 
					    return convert_str_to_int(num)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def is_valid_lang(lang):
 | 
					def is_valid_lang(lang):
 | 
				
			||||||
    is_abbr = (len(lang) == 2)
 | 
					    is_abbr = (len(lang) == 2)
 | 
				
			||||||
    if is_abbr:
 | 
					    if is_abbr:
 | 
				
			||||||
@ -312,3 +323,10 @@ def load_module(filename, module_dir):
 | 
				
			|||||||
    module = load_source(modname, filepath)
 | 
					    module = load_source(modname, filepath)
 | 
				
			||||||
    module.name = modname
 | 
					    module.name = modname
 | 
				
			||||||
    return module
 | 
					    return module
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def new_hmac(secret_key, url):
 | 
				
			||||||
 | 
					    if sys.version_info[0] == 2:
 | 
				
			||||||
 | 
					        return hmac.new(bytes(secret_key), url, hashlib.sha256).hexdigest()
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        return hmac.new(bytes(secret_key, 'utf-8'), url, hashlib.sha256).hexdigest()
 | 
				
			||||||
 | 
				
			|||||||
@ -69,6 +69,7 @@ from searx.plugins import plugins
 | 
				
			|||||||
from searx.preferences import Preferences, ValidationException
 | 
					from searx.preferences import Preferences, ValidationException
 | 
				
			||||||
from searx.answerers import answerers
 | 
					from searx.answerers import answerers
 | 
				
			||||||
from searx.url_utils import urlencode, urlparse, urljoin
 | 
					from searx.url_utils import urlencode, urlparse, urljoin
 | 
				
			||||||
 | 
					from searx.utils import new_hmac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# check if the pyopenssl package is installed.
 | 
					# check if the pyopenssl package is installed.
 | 
				
			||||||
# It is needed for SSL connection without trouble, see #298
 | 
					# It is needed for SSL connection without trouble, see #298
 | 
				
			||||||
@ -290,7 +291,7 @@ def image_proxify(url):
 | 
				
			|||||||
    if settings.get('result_proxy'):
 | 
					    if settings.get('result_proxy'):
 | 
				
			||||||
        return proxify(url)
 | 
					        return proxify(url)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    h = hmac.new(settings['server']['secret_key'], url.encode('utf-8'), hashlib.sha256).hexdigest()
 | 
					    h = new_hmac(settings['server']['secret_key'], url.encode('utf-8'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return '{0}?{1}'.format(url_for('image_proxy'),
 | 
					    return '{0}?{1}'.format(url_for('image_proxy'),
 | 
				
			||||||
                            urlencode(dict(url=url.encode('utf-8'), h=h)))
 | 
					                            urlencode(dict(url=url.encode('utf-8'), h=h)))
 | 
				
			||||||
@ -704,7 +705,7 @@ def image_proxy():
 | 
				
			|||||||
    if not url:
 | 
					    if not url:
 | 
				
			||||||
        return '', 400
 | 
					        return '', 400
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    h = hmac.new(settings['server']['secret_key'], url, hashlib.sha256).hexdigest()
 | 
					    h = new_hmac(settings['server']['secret_key'], url)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if h != request.args.get('h'):
 | 
					    if h != request.args.get('h'):
 | 
				
			||||||
        return '', 400
 | 
					        return '', 400
 | 
				
			||||||
@ -731,7 +732,7 @@ def image_proxy():
 | 
				
			|||||||
        logger.debug('image-proxy: wrong content-type: {0}'.format(resp.headers.get('content-type')))
 | 
					        logger.debug('image-proxy: wrong content-type: {0}'.format(resp.headers.get('content-type')))
 | 
				
			||||||
        return '', 400
 | 
					        return '', 400
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    img = ''
 | 
					    img = b''
 | 
				
			||||||
    chunk_counter = 0
 | 
					    chunk_counter = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for chunk in resp.iter_content(1024 * 1024):
 | 
					    for chunk in resp.iter_content(1024 * 1024):
 | 
				
			||||||
@ -792,7 +793,8 @@ def opensearch():
 | 
				
			|||||||
@app.route('/favicon.ico')
 | 
					@app.route('/favicon.ico')
 | 
				
			||||||
def favicon():
 | 
					def favicon():
 | 
				
			||||||
    return send_from_directory(os.path.join(app.root_path,
 | 
					    return send_from_directory(os.path.join(app.root_path,
 | 
				
			||||||
                                            'static/themes',
 | 
					                                            static_path,
 | 
				
			||||||
 | 
					                                            'themes',
 | 
				
			||||||
                                            get_current_theme_name(),
 | 
					                                            get_current_theme_name(),
 | 
				
			||||||
                                            'img'),
 | 
					                                            'img'),
 | 
				
			||||||
                               'favicon.png',
 | 
					                               'favicon.png',
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										91
									
								
								tests/unit/engines/test_base.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								tests/unit/engines/test_base.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,91 @@
 | 
				
			|||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					from collections import defaultdict
 | 
				
			||||||
 | 
					import mock
 | 
				
			||||||
 | 
					from searx.engines import base
 | 
				
			||||||
 | 
					from searx.testing import SearxTestCase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TestBaseEngine(SearxTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_request(self):
 | 
				
			||||||
 | 
					        query = 'test_query'
 | 
				
			||||||
 | 
					        dicto = defaultdict(dict)
 | 
				
			||||||
 | 
					        dicto['pageno'] = 1
 | 
				
			||||||
 | 
					        params = base.request(query, dicto)
 | 
				
			||||||
 | 
					        self.assertIn('url', params)
 | 
				
			||||||
 | 
					        self.assertIn('base-search.net', params['url'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_response(self):
 | 
				
			||||||
 | 
					        self.assertRaises(AttributeError, base.response, None)
 | 
				
			||||||
 | 
					        self.assertRaises(AttributeError, base.response, [])
 | 
				
			||||||
 | 
					        self.assertRaises(AttributeError, base.response, '')
 | 
				
			||||||
 | 
					        self.assertRaises(AttributeError, base.response, '[]')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        response = mock.Mock(text='<response></response>')
 | 
				
			||||||
 | 
					        self.assertEqual(base.response(response), [])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        xml_mock = """<?xml version="1.0"?>
 | 
				
			||||||
 | 
					<response>
 | 
				
			||||||
 | 
					  <lst name="responseHeader">
 | 
				
			||||||
 | 
					    <int name="status">0</int>
 | 
				
			||||||
 | 
					    <int name="QTime">1</int>
 | 
				
			||||||
 | 
					  </lst>
 | 
				
			||||||
 | 
					  <result name="response" numFound="1" start="0">
 | 
				
			||||||
 | 
					    <doc>
 | 
				
			||||||
 | 
					      <date name="dchdate">2000-01-01T01:01:01Z</date>
 | 
				
			||||||
 | 
					      <str name="dcdocid">1</str>
 | 
				
			||||||
 | 
					      <str name="dccontinent">cna</str>
 | 
				
			||||||
 | 
					      <str name="dccountry">us</str>
 | 
				
			||||||
 | 
					      <str name="dccollection">ftciteseerx</str>
 | 
				
			||||||
 | 
					      <str name="dcprovider">CiteSeerX</str>
 | 
				
			||||||
 | 
					      <str name="dctitle">Science and more</str>
 | 
				
			||||||
 | 
					      <arr name="dccreator">
 | 
				
			||||||
 | 
					        <str>Someone</str>
 | 
				
			||||||
 | 
					      </arr>
 | 
				
			||||||
 | 
					      <arr name="dcperson">
 | 
				
			||||||
 | 
					        <str>Someone</str>
 | 
				
			||||||
 | 
					      </arr>
 | 
				
			||||||
 | 
					      <arr name="dcsubject">
 | 
				
			||||||
 | 
					        <str>Science and more</str>
 | 
				
			||||||
 | 
					      </arr>
 | 
				
			||||||
 | 
					      <str name="dcdescription">Science, and even more.</str>
 | 
				
			||||||
 | 
					      <arr name="dccontributor">
 | 
				
			||||||
 | 
					        <str>The neighbour</str>
 | 
				
			||||||
 | 
					      </arr>
 | 
				
			||||||
 | 
					      <str name="dcdate">2001</str>
 | 
				
			||||||
 | 
					      <int name="dcyear">2001</int>
 | 
				
			||||||
 | 
					      <arr name="dctype">
 | 
				
			||||||
 | 
					        <str>text</str>
 | 
				
			||||||
 | 
					      </arr>
 | 
				
			||||||
 | 
					      <arr name="dctypenorm">
 | 
				
			||||||
 | 
					        <str>1</str>
 | 
				
			||||||
 | 
					      </arr>
 | 
				
			||||||
 | 
					      <arr name="dcformat">
 | 
				
			||||||
 | 
					        <str>application/pdf</str>
 | 
				
			||||||
 | 
					      </arr>
 | 
				
			||||||
 | 
					      <arr name="dccontenttype">
 | 
				
			||||||
 | 
					        <str>application/pdf</str>
 | 
				
			||||||
 | 
					      </arr>
 | 
				
			||||||
 | 
					      <arr name="dcidentifier">
 | 
				
			||||||
 | 
					        <str>http://example.org/</str>
 | 
				
			||||||
 | 
					      </arr>
 | 
				
			||||||
 | 
					      <str name="dclink">http://example.org</str>
 | 
				
			||||||
 | 
					      <str name="dcsource">http://example.org</str>
 | 
				
			||||||
 | 
					      <arr name="dclanguage">
 | 
				
			||||||
 | 
					        <str>en</str>
 | 
				
			||||||
 | 
					      </arr>
 | 
				
			||||||
 | 
					      <str name="dcrights">Under the example.org licence</str>
 | 
				
			||||||
 | 
					      <int name="dcoa">1</int>
 | 
				
			||||||
 | 
					      <arr name="dclang">
 | 
				
			||||||
 | 
					        <str>eng</str>
 | 
				
			||||||
 | 
					      </arr>
 | 
				
			||||||
 | 
					    </doc>
 | 
				
			||||||
 | 
					  </result>
 | 
				
			||||||
 | 
					</response>"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        response = mock.Mock(text=xml_mock.encode('utf-8'))
 | 
				
			||||||
 | 
					        results = base.response(response)
 | 
				
			||||||
 | 
					        self.assertEqual(type(results), list)
 | 
				
			||||||
 | 
					        self.assertEqual(len(results), 1)
 | 
				
			||||||
 | 
					        self.assertEqual(results[0]['title'], 'Science and more')
 | 
				
			||||||
 | 
					        self.assertEqual(results[0]['content'], 'Science, and even more.')
 | 
				
			||||||
@ -8,10 +8,12 @@ from searx.testing import SearxTestCase
 | 
				
			|||||||
class TestBingImagesEngine(SearxTestCase):
 | 
					class TestBingImagesEngine(SearxTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_request(self):
 | 
					    def test_request(self):
 | 
				
			||||||
 | 
					        bing_images.supported_languages = ['fr-FR', 'en-US']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        query = 'test_query'
 | 
					        query = 'test_query'
 | 
				
			||||||
        dicto = defaultdict(dict)
 | 
					        dicto = defaultdict(dict)
 | 
				
			||||||
        dicto['pageno'] = 1
 | 
					        dicto['pageno'] = 1
 | 
				
			||||||
        dicto['language'] = 'fr_FR'
 | 
					        dicto['language'] = 'fr-FR'
 | 
				
			||||||
        dicto['safesearch'] = 1
 | 
					        dicto['safesearch'] = 1
 | 
				
			||||||
        dicto['time_range'] = ''
 | 
					        dicto['time_range'] = ''
 | 
				
			||||||
        params = bing_images.request(query, dicto)
 | 
					        params = bing_images.request(query, dicto)
 | 
				
			||||||
@ -19,12 +21,19 @@ class TestBingImagesEngine(SearxTestCase):
 | 
				
			|||||||
        self.assertTrue(query in params['url'])
 | 
					        self.assertTrue(query in params['url'])
 | 
				
			||||||
        self.assertTrue('bing.com' in params['url'])
 | 
					        self.assertTrue('bing.com' in params['url'])
 | 
				
			||||||
        self.assertTrue('SRCHHPGUSR' in params['cookies'])
 | 
					        self.assertTrue('SRCHHPGUSR' in params['cookies'])
 | 
				
			||||||
        self.assertTrue('fr' in params['cookies']['SRCHHPGUSR'])
 | 
					        self.assertTrue('DEMOTE' in params['cookies']['SRCHHPGUSR'])
 | 
				
			||||||
 | 
					        self.assertTrue('_EDGE_S' in params['cookies'])
 | 
				
			||||||
 | 
					        self.assertTrue('fr-fr' in params['cookies']['_EDGE_S'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        dicto['language'] = 'fr'
 | 
				
			||||||
 | 
					        params = bing_images.request(query, dicto)
 | 
				
			||||||
 | 
					        self.assertTrue('_EDGE_S' in params['cookies'])
 | 
				
			||||||
 | 
					        self.assertTrue('fr-fr' in params['cookies']['_EDGE_S'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        dicto['language'] = 'all'
 | 
					        dicto['language'] = 'all'
 | 
				
			||||||
        params = bing_images.request(query, dicto)
 | 
					        params = bing_images.request(query, dicto)
 | 
				
			||||||
        self.assertIn('SRCHHPGUSR', params['cookies'])
 | 
					        self.assertTrue('_EDGE_S' in params['cookies'])
 | 
				
			||||||
        self.assertIn('en', params['cookies']['SRCHHPGUSR'])
 | 
					        self.assertTrue('en-us' in params['cookies']['_EDGE_S'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_response(self):
 | 
					    def test_response(self):
 | 
				
			||||||
        self.assertRaises(AttributeError, bing_images.response, None)
 | 
					        self.assertRaises(AttributeError, bing_images.response, None)
 | 
				
			||||||
@ -82,3 +91,28 @@ class TestBingImagesEngine(SearxTestCase):
 | 
				
			|||||||
        self.assertEqual(results[0]['content'], '')
 | 
					        self.assertEqual(results[0]['content'], '')
 | 
				
			||||||
        self.assertEqual(results[0]['thumbnail_src'], 'thumb_url')
 | 
					        self.assertEqual(results[0]['thumbnail_src'], 'thumb_url')
 | 
				
			||||||
        self.assertEqual(results[0]['img_src'], 'img_url')
 | 
					        self.assertEqual(results[0]['img_src'], 'img_url')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_fetch_supported_languages(self):
 | 
				
			||||||
 | 
					        html = """
 | 
				
			||||||
 | 
					        <div>
 | 
				
			||||||
 | 
					            <div id="region-section-content">
 | 
				
			||||||
 | 
					                <ul class="b_vList">
 | 
				
			||||||
 | 
					                    <li>
 | 
				
			||||||
 | 
					                        <a href="https://bing...&setmkt=de-DE&s...">Germany</a>
 | 
				
			||||||
 | 
					                        <a href="https://bing...&setmkt=nb-NO&s...">Norway</a>
 | 
				
			||||||
 | 
					                    </li>
 | 
				
			||||||
 | 
					                </ul>
 | 
				
			||||||
 | 
					                <ul class="b_vList">
 | 
				
			||||||
 | 
					                    <li>
 | 
				
			||||||
 | 
					                        <a href="https://bing...&setmkt=es-AR&s...">Argentina</a>
 | 
				
			||||||
 | 
					                    </li>
 | 
				
			||||||
 | 
					                </ul>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        response = mock.Mock(text=html)
 | 
				
			||||||
 | 
					        languages = list(bing_images._fetch_supported_languages(response))
 | 
				
			||||||
 | 
					        self.assertEqual(len(languages), 3)
 | 
				
			||||||
 | 
					        self.assertIn('de-DE', languages)
 | 
				
			||||||
 | 
					        self.assertIn('no-NO', languages)
 | 
				
			||||||
 | 
					        self.assertIn('es-AR', languages)
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,8 @@ from searx.testing import SearxTestCase
 | 
				
			|||||||
class TestBingVideosEngine(SearxTestCase):
 | 
					class TestBingVideosEngine(SearxTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_request(self):
 | 
					    def test_request(self):
 | 
				
			||||||
 | 
					        bing_videos.supported_languages = ['fr-FR', 'en-US']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        query = 'test_query'
 | 
					        query = 'test_query'
 | 
				
			||||||
        dicto = defaultdict(dict)
 | 
					        dicto = defaultdict(dict)
 | 
				
			||||||
        dicto['pageno'] = 1
 | 
					        dicto['pageno'] = 1
 | 
				
			||||||
 | 
				
			|||||||
@ -1,71 +0,0 @@
 | 
				
			|||||||
from collections import defaultdict
 | 
					 | 
				
			||||||
import mock
 | 
					 | 
				
			||||||
from searx.engines import blekko_images
 | 
					 | 
				
			||||||
from searx.testing import SearxTestCase
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class TestBlekkoImagesEngine(SearxTestCase):
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_request(self):
 | 
					 | 
				
			||||||
        query = 'test_query'
 | 
					 | 
				
			||||||
        dicto = defaultdict(dict)
 | 
					 | 
				
			||||||
        dicto['pageno'] = 0
 | 
					 | 
				
			||||||
        dicto['safesearch'] = 1
 | 
					 | 
				
			||||||
        params = blekko_images.request(query, dicto)
 | 
					 | 
				
			||||||
        self.assertIn('url', params)
 | 
					 | 
				
			||||||
        self.assertIn(query, params['url'])
 | 
					 | 
				
			||||||
        self.assertIn('blekko.com', params['url'])
 | 
					 | 
				
			||||||
        self.assertIn('page', params['url'])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        dicto['pageno'] = 1
 | 
					 | 
				
			||||||
        params = blekko_images.request(query, dicto)
 | 
					 | 
				
			||||||
        self.assertNotIn('page', params['url'])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_response(self):
 | 
					 | 
				
			||||||
        self.assertRaises(AttributeError, blekko_images.response, None)
 | 
					 | 
				
			||||||
        self.assertRaises(AttributeError, blekko_images.response, [])
 | 
					 | 
				
			||||||
        self.assertRaises(AttributeError, blekko_images.response, '')
 | 
					 | 
				
			||||||
        self.assertRaises(AttributeError, blekko_images.response, '[]')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        response = mock.Mock(text='[]')
 | 
					 | 
				
			||||||
        self.assertEqual(blekko_images.response(response), [])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        json = """
 | 
					 | 
				
			||||||
        [
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                "c": 1,
 | 
					 | 
				
			||||||
                "page_url": "http://result_url.html",
 | 
					 | 
				
			||||||
                "title": "Photo title",
 | 
					 | 
				
			||||||
                "tn_url": "http://ts1.mm.bing.net/th?id=HN.608050619474382748&pid=15.1",
 | 
					 | 
				
			||||||
                "url": "http://result_image.jpg"
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                "c": 2,
 | 
					 | 
				
			||||||
                "page_url": "http://companyorange.simpsite.nl/OSM",
 | 
					 | 
				
			||||||
                "title": "OSM",
 | 
					 | 
				
			||||||
                "tn_url": "http://ts2.mm.bing.net/th?id=HN.608048068264919461&pid=15.1",
 | 
					 | 
				
			||||||
                "url": "http://simpsite.nl/userdata2/58985/Home/OSM.bmp"
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                "c": 3,
 | 
					 | 
				
			||||||
                "page_url": "http://invincible.webklik.nl/page/osm",
 | 
					 | 
				
			||||||
                "title": "OSM",
 | 
					 | 
				
			||||||
                "tn_url": "http://ts1.mm.bing.net/th?id=HN.608024514657649476&pid=15.1",
 | 
					 | 
				
			||||||
                "url": "http://www.webklik.nl/user_files/2009_09/65324/osm.gif"
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                "c": 4,
 | 
					 | 
				
			||||||
                "page_url": "http://www.offshorenorway.no/event/companyDetail/id/12492",
 | 
					 | 
				
			||||||
                "title": "Go to OSM Offshore AS homepage",
 | 
					 | 
				
			||||||
                "tn_url": "http://ts2.mm.bing.net/th?id=HN.608054265899847285&pid=15.1",
 | 
					 | 
				
			||||||
                "url": "http://www.offshorenorway.no/firmalogo/OSM-logo.png"
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        response = mock.Mock(text=json)
 | 
					 | 
				
			||||||
        results = blekko_images.response(response)
 | 
					 | 
				
			||||||
        self.assertEqual(type(results), list)
 | 
					 | 
				
			||||||
        self.assertEqual(len(results), 4)
 | 
					 | 
				
			||||||
        self.assertEqual(results[0]['title'], 'Photo title')
 | 
					 | 
				
			||||||
        self.assertEqual(results[0]['url'], 'http://result_url.html')
 | 
					 | 
				
			||||||
        self.assertEqual(results[0]['img_src'], 'http://result_image.jpg')
 | 
					 | 
				
			||||||
@ -40,9 +40,6 @@ class TestFarooEngine(SearxTestCase):
 | 
				
			|||||||
        response = mock.Mock(text='{"data": []}')
 | 
					        response = mock.Mock(text='{"data": []}')
 | 
				
			||||||
        self.assertEqual(faroo.response(response), [])
 | 
					        self.assertEqual(faroo.response(response), [])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        response = mock.Mock(text='{"data": []}', status_code=401)
 | 
					 | 
				
			||||||
        self.assertRaises(Exception, faroo.response, response)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        response = mock.Mock(text='{"data": []}', status_code=429)
 | 
					        response = mock.Mock(text='{"data": []}', status_code=429)
 | 
				
			||||||
        self.assertRaises(Exception, faroo.response, response)
 | 
					        self.assertRaises(Exception, faroo.response, response)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -98,14 +95,14 @@ class TestFarooEngine(SearxTestCase):
 | 
				
			|||||||
        response = mock.Mock(text=json)
 | 
					        response = mock.Mock(text=json)
 | 
				
			||||||
        results = faroo.response(response)
 | 
					        results = faroo.response(response)
 | 
				
			||||||
        self.assertEqual(type(results), list)
 | 
					        self.assertEqual(type(results), list)
 | 
				
			||||||
        self.assertEqual(len(results), 4)
 | 
					        self.assertEqual(len(results), 3)
 | 
				
			||||||
        self.assertEqual(results[0]['title'], 'This is the title')
 | 
					        self.assertEqual(results[0]['title'], 'This is the title')
 | 
				
			||||||
        self.assertEqual(results[0]['url'], 'http://this.is.the.url/')
 | 
					        self.assertEqual(results[0]['url'], 'http://this.is.the.url/')
 | 
				
			||||||
        self.assertEqual(results[0]['content'], 'This is the content')
 | 
					        self.assertEqual(results[0]['content'], 'This is the content')
 | 
				
			||||||
        self.assertEqual(results[1]['title'], 'This is the title2')
 | 
					        self.assertEqual(results[1]['title'], 'This is the title2')
 | 
				
			||||||
        self.assertEqual(results[1]['url'], 'http://this.is.the.url2/')
 | 
					        self.assertEqual(results[1]['url'], 'http://this.is.the.url2/')
 | 
				
			||||||
        self.assertEqual(results[1]['content'], 'This is the content2')
 | 
					        self.assertEqual(results[1]['content'], 'This is the content2')
 | 
				
			||||||
        self.assertEqual(results[3]['img_src'], 'http://upload.wikimedia.org/optimized.jpg')
 | 
					        self.assertEqual(results[2]['thumbnail'], 'http://upload.wikimedia.org/optimized.jpg')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        json = """
 | 
					        json = """
 | 
				
			||||||
        {}
 | 
					        {}
 | 
				
			||||||
 | 
				
			|||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@ -13,38 +13,92 @@ class TestNyaaEngine(SearxTestCase):
 | 
				
			|||||||
        params = nyaa.request(query, dic)
 | 
					        params = nyaa.request(query, dic)
 | 
				
			||||||
        self.assertTrue('url' in params)
 | 
					        self.assertTrue('url' in params)
 | 
				
			||||||
        self.assertTrue(query in params['url'])
 | 
					        self.assertTrue(query in params['url'])
 | 
				
			||||||
        self.assertTrue('nyaa.se' in params['url'])
 | 
					        self.assertTrue('nyaa.si' in params['url'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_response(self):
 | 
					    def test_response(self):
 | 
				
			||||||
        resp = mock.Mock(text='<html></html>')
 | 
					        resp = mock.Mock(text='<html></html>')
 | 
				
			||||||
        self.assertEqual(nyaa.response(resp), [])
 | 
					        self.assertEqual(nyaa.response(resp), [])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        html = """
 | 
					        html = """
 | 
				
			||||||
        <table class="tlist">
 | 
					        <table class="table table-bordered table-hover table-striped torrent-list">
 | 
				
			||||||
          <tbody>
 | 
					        <thead>
 | 
				
			||||||
            <tr class="trusted tlistrow">
 | 
					        <tr>
 | 
				
			||||||
              <td class="tlisticon">
 | 
					        <th class="hdr-category text-center" style="width:80px;">
 | 
				
			||||||
                <a href="//www.nyaa.se" title="English-translated Anime">
 | 
					        <div>Category</div>
 | 
				
			||||||
                   <img src="//files.nyaa.se" alt="English-translated Anime">
 | 
					        </th>
 | 
				
			||||||
                </a>
 | 
					        <th class="hdr-name" style="width:auto;">
 | 
				
			||||||
              </td>
 | 
					        <div>Name</div>
 | 
				
			||||||
              <td class="tlistname">
 | 
					        </th>
 | 
				
			||||||
                <a href="//www.nyaa.se/?page3">
 | 
					        <th class="hdr-comments sorting text-center" title="Comments" style="width:50px;">
 | 
				
			||||||
                  Sample torrent title
 | 
					        <a href="/?f=0&c=0_0&q=Death+Parade&s=comments&o=desc"></a>
 | 
				
			||||||
                </a>
 | 
					        <i class="fa fa-comments-o"></i>
 | 
				
			||||||
              </td>
 | 
					        </th>
 | 
				
			||||||
              <td class="tlistdownload">
 | 
					        <th class="hdr-link text-center" style="width:70px;">
 | 
				
			||||||
                <a href="//www.nyaa.se/?page_dl" title="Download">
 | 
					        <div>Link</div>
 | 
				
			||||||
                  <img src="//files.nyaa.se/www-dl.png" alt="DL">
 | 
					        </th>
 | 
				
			||||||
                </a>
 | 
					        <th class="hdr-size sorting text-center" style="width:100px;">
 | 
				
			||||||
              </td>
 | 
					        <a href="/?f=0&c=0_0&q=Death+Parade&s=size&o=desc"></a>
 | 
				
			||||||
              <td class="tlistsize">10 MiB</td>
 | 
					        <div>Size</div>
 | 
				
			||||||
              <td class="tlistsn">1</td>
 | 
					        </th>
 | 
				
			||||||
              <td class="tlistln">3</td>
 | 
					        <th class="hdr-date sorting_desc text-center" title="In local time" style="width:140px;">
 | 
				
			||||||
              <td class="tlistdn">666</td>
 | 
					        <a href="/?f=0&c=0_0&q=Death+Parade&s=id&o=asc"></a>
 | 
				
			||||||
              <td class="tlistmn">0</td>
 | 
					        <div>Date</div>
 | 
				
			||||||
            </tr>
 | 
					        </th>
 | 
				
			||||||
          </tbody>
 | 
					        <th class="hdr-seeders sorting text-center" title="Seeders" style="width:50px;">
 | 
				
			||||||
 | 
					        <a href="/?f=0&c=0_0&q=Death+Parade&s=seeders&o=desc"></a>
 | 
				
			||||||
 | 
					        <i class="fa fa-arrow-up" aria-hidden="true"></i>
 | 
				
			||||||
 | 
					        </th>
 | 
				
			||||||
 | 
					        <th class="hdr-leechers sorting text-center" title="Leechers" style="width:50px;">
 | 
				
			||||||
 | 
					        <a href="/?f=0&c=0_0&q=Death+Parade&s=leechers&o=desc"></a>
 | 
				
			||||||
 | 
					        <i class="fa fa-arrow-down" aria-hidden="true"></i>
 | 
				
			||||||
 | 
					        </th>
 | 
				
			||||||
 | 
					        <th class="hdr-downloads sorting text-center" title="Completed downloads" style="width:50px;">
 | 
				
			||||||
 | 
					        <a href="/?f=0&c=0_0&q=Death+Parade&s=downloads&o=desc"></a>
 | 
				
			||||||
 | 
					        <i class="fa fa-check" aria-hidden="true"></i>
 | 
				
			||||||
 | 
					        </th>
 | 
				
			||||||
 | 
					        </tr>
 | 
				
			||||||
 | 
					        </thead>
 | 
				
			||||||
 | 
					        <tbody>
 | 
				
			||||||
 | 
					        <tr class="default">
 | 
				
			||||||
 | 
					        <td style="padding:0 4px;">
 | 
				
			||||||
 | 
					        <a href="/?c=1_2" title="Anime - English-translated">
 | 
				
			||||||
 | 
					        <img src="/static/img/icons/nyaa/1_2.png" alt="Anime - English-translated">
 | 
				
			||||||
 | 
					        </a>
 | 
				
			||||||
 | 
					        </td>
 | 
				
			||||||
 | 
					        <td colspan="2">
 | 
				
			||||||
 | 
					        <a href="/view/1" title="Sample title 1">Sample title 1</a>
 | 
				
			||||||
 | 
					        </td>
 | 
				
			||||||
 | 
					        <td class="text-center" style="white-space: nowrap;">
 | 
				
			||||||
 | 
					        <a href="/download/1.torrent"><i class="fa fa-fw fa-download"></i></a>
 | 
				
			||||||
 | 
					        <a href="magnet:?xt=urn:btih:2"><i class="fa fa-fw fa-magnet"></i></a>
 | 
				
			||||||
 | 
					        </td>
 | 
				
			||||||
 | 
					        <td class="text-center">723.7 MiB</td>
 | 
				
			||||||
 | 
					        <td class="text-center" data-timestamp="1503307456" title="1 week 3
 | 
				
			||||||
 | 
					        days 9 hours 44 minutes 39 seconds ago">2017-08-21 11:24</td>
 | 
				
			||||||
 | 
					        <td class="text-center" style="color: green;">1</td>
 | 
				
			||||||
 | 
					        <td class="text-center" style="color: red;">3</td>
 | 
				
			||||||
 | 
					        <td class="text-center">12</td>
 | 
				
			||||||
 | 
					        </tr>
 | 
				
			||||||
 | 
					        <tr class="default">
 | 
				
			||||||
 | 
					        <td style="padding:0 4px;">
 | 
				
			||||||
 | 
					        <a href="/?c=1_2" title="Anime - English-translated">
 | 
				
			||||||
 | 
					        <img src="/static/img/icons/nyaa/1_2.png" alt="Anime - English-translated">
 | 
				
			||||||
 | 
					        </a>
 | 
				
			||||||
 | 
					        </td>
 | 
				
			||||||
 | 
					        <td colspan="2">
 | 
				
			||||||
 | 
					        <a href="/view/2" title="Sample title 2">Sample title 2</a>
 | 
				
			||||||
 | 
					        </td>
 | 
				
			||||||
 | 
					        <td class="text-center" style="white-space: nowrap;">
 | 
				
			||||||
 | 
					        <a href="magnet:?xt=urn:btih:2"><i class="fa fa-fw fa-magnet"></i></a>
 | 
				
			||||||
 | 
					        </td>
 | 
				
			||||||
 | 
					        <td class="text-center">8.2 GiB</td>
 | 
				
			||||||
 | 
					        <td class="text-center" data-timestamp="1491608400" title="4 months 3
 | 
				
			||||||
 | 
					        weeks 4 days 19 hours 28 minutes 55 seconds ago">2017-04-08 01:40</td>
 | 
				
			||||||
 | 
					        <td class="text-center" style="color: green;">10</td>
 | 
				
			||||||
 | 
					        <td class="text-center" style="color: red;">1</td>
 | 
				
			||||||
 | 
					        <td class="text-center">206</td>
 | 
				
			||||||
 | 
					        </tr>
 | 
				
			||||||
 | 
					        </tbody>
 | 
				
			||||||
        </table>
 | 
					        </table>
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -52,15 +106,19 @@ class TestNyaaEngine(SearxTestCase):
 | 
				
			|||||||
        results = nyaa.response(resp)
 | 
					        results = nyaa.response(resp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.assertEqual(type(results), list)
 | 
					        self.assertEqual(type(results), list)
 | 
				
			||||||
        self.assertEqual(len(results), 1)
 | 
					        self.assertEqual(len(results), 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        r = results[0]
 | 
					        r = results[0]
 | 
				
			||||||
        self.assertTrue(r['url'].find('www.nyaa.se/?page3') >= 0)
 | 
					        self.assertTrue(r['url'].find('1') >= 0)
 | 
				
			||||||
        self.assertTrue(r['torrentfile'].find('www.nyaa.se/?page_dl') >= 0)
 | 
					        self.assertTrue(r['torrentfile'].find('1.torrent') >= 0)
 | 
				
			||||||
        self.assertTrue(r['content'].find('English-translated Anime') >= 0)
 | 
					        self.assertTrue(r['content'].find('Anime - English-translated') >= 0)
 | 
				
			||||||
        self.assertTrue(r['content'].find('Downloaded 666 times.') >= 0)
 | 
					        self.assertTrue(r['content'].find('Downloaded 12 times.') >= 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.assertEqual(r['title'], 'Sample torrent title')
 | 
					        self.assertEqual(r['title'], 'Sample title 1')
 | 
				
			||||||
        self.assertEqual(r['seed'], 1)
 | 
					        self.assertEqual(r['seed'], 1)
 | 
				
			||||||
        self.assertEqual(r['leech'], 3)
 | 
					        self.assertEqual(r['leech'], 3)
 | 
				
			||||||
        self.assertEqual(r['filesize'], 10 * 1024 * 1024)
 | 
					        self.assertEqual(r['filesize'], 723700000)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        r = results[1]
 | 
				
			||||||
 | 
					        self.assertTrue(r['url'].find('2') >= 0)
 | 
				
			||||||
 | 
					        self.assertTrue(r['magnetlink'].find('magnet:') >= 0)
 | 
				
			||||||
 | 
				
			|||||||
@ -139,9 +139,9 @@ class TestSwisscowsEngine(SearxTestCase):
 | 
				
			|||||||
            <div id="regions-popup">
 | 
					            <div id="regions-popup">
 | 
				
			||||||
                <div>
 | 
					                <div>
 | 
				
			||||||
                    <ul>
 | 
					                    <ul>
 | 
				
			||||||
                        <li><a data-val="browser"></a></li>
 | 
					                        <li><a data-search-language="browser"></a></li>
 | 
				
			||||||
                        <li><a data-val="de-CH"></a></li>
 | 
					                        <li><a data-search-language="de-CH"></a></li>
 | 
				
			||||||
                        <li><a data-val="fr-CH"></a></li>
 | 
					                        <li><a data-search-language="fr-CH"></a></li>
 | 
				
			||||||
                    </ul>
 | 
					                    </ul>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,7 @@ class TestTorrentzEngine(SearxTestCase):
 | 
				
			|||||||
        params = torrentz.request(query, dic)
 | 
					        params = torrentz.request(query, dic)
 | 
				
			||||||
        self.assertTrue('url' in params)
 | 
					        self.assertTrue('url' in params)
 | 
				
			||||||
        self.assertTrue(query in params['url'])
 | 
					        self.assertTrue(query in params['url'])
 | 
				
			||||||
        self.assertTrue('torrentz.eu' in params['url'])
 | 
					        self.assertTrue('torrentz2.eu' in params['url'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_response(self):
 | 
					    def test_response(self):
 | 
				
			||||||
        resp = mock.Mock(text='<html></html>')
 | 
					        resp = mock.Mock(text='<html></html>')
 | 
				
			||||||
@ -30,13 +30,11 @@ class TestTorrentzEngine(SearxTestCase):
 | 
				
			|||||||
              books ebooks
 | 
					              books ebooks
 | 
				
			||||||
            </dt>
 | 
					            </dt>
 | 
				
			||||||
            <dd>
 | 
					            <dd>
 | 
				
			||||||
              <span class="v">1</span>
 | 
					              <span>1</span>
 | 
				
			||||||
              <span class="a">
 | 
					              <span title="1503595924">5 hours</span>
 | 
				
			||||||
                <span title="Sun, 22 Nov 2015 03:01:42">4 months</span>
 | 
					              <span>30 MB</span>
 | 
				
			||||||
              </span>
 | 
					              <span>14</span>
 | 
				
			||||||
              <span class="s">30 MB</span>
 | 
					              <span>1</span>
 | 
				
			||||||
              <span class="u">14</span>
 | 
					 | 
				
			||||||
              <span class="d">1</span>
 | 
					 | 
				
			||||||
            </dd>
 | 
					            </dd>
 | 
				
			||||||
          </dl>
 | 
					          </dl>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -48,13 +46,11 @@ class TestTorrentzEngine(SearxTestCase):
 | 
				
			|||||||
              books ebooks
 | 
					              books ebooks
 | 
				
			||||||
            </dt>
 | 
					            </dt>
 | 
				
			||||||
            <dd>
 | 
					            <dd>
 | 
				
			||||||
              <span class="v">1</span>
 | 
					              <span>1</span>
 | 
				
			||||||
              <span class="a">
 | 
					              <span title="1503595924 aaa">5 hours</span>
 | 
				
			||||||
                <span title="Sun, 2124091j0j190gm42">4 months</span>
 | 
					              <span>30MB</span>
 | 
				
			||||||
              </span>
 | 
					              <span>5,555</span>
 | 
				
			||||||
              <span class="s">30MB</span>
 | 
					              <span>1,234,567</span>
 | 
				
			||||||
              <span class="u">5,555</span>
 | 
					 | 
				
			||||||
              <span class="d">1,234,567</span>
 | 
					 | 
				
			||||||
            </dd>
 | 
					            </dd>
 | 
				
			||||||
          </dl>
 | 
					          </dl>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
@ -68,10 +64,10 @@ class TestTorrentzEngine(SearxTestCase):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        # testing against the first result
 | 
					        # testing against the first result
 | 
				
			||||||
        r = results[0]
 | 
					        r = results[0]
 | 
				
			||||||
        self.assertEqual(r['url'], 'https://torrentz.eu/4362e08b1d80e1820fb2550b752f9f3126fe76d6')
 | 
					        self.assertEqual(r['url'], 'https://torrentz2.eu/4362e08b1d80e1820fb2550b752f9f3126fe76d6')
 | 
				
			||||||
        self.assertEqual(r['title'], 'Completely valid info books ebooks')
 | 
					        self.assertEqual(r['title'], 'Completely valid info books ebooks')
 | 
				
			||||||
        # 22 Nov 2015 03:01:42
 | 
					        # 22 Nov 2015 03:01:42
 | 
				
			||||||
        self.assertEqual(r['publishedDate'], datetime(2015, 11, 22, 3, 1, 42))
 | 
					        self.assertEqual(r['publishedDate'], datetime.fromtimestamp(1503595924))
 | 
				
			||||||
        self.assertEqual(r['seed'], 14)
 | 
					        self.assertEqual(r['seed'], 14)
 | 
				
			||||||
        self.assertEqual(r['leech'], 1)
 | 
					        self.assertEqual(r['leech'], 1)
 | 
				
			||||||
        self.assertEqual(r['filesize'], 30 * 1024 * 1024)
 | 
					        self.assertEqual(r['filesize'], 30 * 1024 * 1024)
 | 
				
			||||||
@ -79,7 +75,7 @@ class TestTorrentzEngine(SearxTestCase):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        # testing against the second result
 | 
					        # testing against the second result
 | 
				
			||||||
        r = results[1]
 | 
					        r = results[1]
 | 
				
			||||||
        self.assertEqual(r['url'], 'https://torrentz.eu/poaskdpokaspod')
 | 
					        self.assertEqual(r['url'], 'https://torrentz2.eu/poaskdpokaspod')
 | 
				
			||||||
        self.assertEqual(r['title'], 'Invalid hash and date and filesize books ebooks')
 | 
					        self.assertEqual(r['title'], 'Invalid hash and date and filesize books ebooks')
 | 
				
			||||||
        self.assertEqual(r['seed'], 5555)
 | 
					        self.assertEqual(r['seed'], 5555)
 | 
				
			||||||
        self.assertEqual(r['leech'], 1234567)
 | 
					        self.assertEqual(r['leech'], 1234567)
 | 
				
			||||||
 | 
				
			|||||||
@ -8,13 +8,13 @@
 | 
				
			|||||||
# are written in current directory to avoid overwriting in case something goes wrong.
 | 
					# are written in current directory to avoid overwriting in case something goes wrong.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from requests import get
 | 
					from requests import get
 | 
				
			||||||
from urllib import urlencode
 | 
					 | 
				
			||||||
from lxml.html import fromstring
 | 
					from lxml.html import fromstring
 | 
				
			||||||
from json import loads, dumps
 | 
					from json import loads, dump
 | 
				
			||||||
import io
 | 
					import io
 | 
				
			||||||
from sys import path
 | 
					from sys import path
 | 
				
			||||||
path.append('../searx')  # noqa
 | 
					path.append('../searx')  # noqa
 | 
				
			||||||
from searx import settings
 | 
					from searx import settings
 | 
				
			||||||
 | 
					from searx.url_utils import urlencode
 | 
				
			||||||
from searx.engines import initialize_engines, engines
 | 
					from searx.engines import initialize_engines, engines
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Geonames API for country names.
 | 
					# Geonames API for country names.
 | 
				
			||||||
@ -70,7 +70,7 @@ def get_country_name(locale):
 | 
				
			|||||||
    json = loads(response.text)
 | 
					    json = loads(response.text)
 | 
				
			||||||
    content = json.get('geonames', None)
 | 
					    content = json.get('geonames', None)
 | 
				
			||||||
    if content is None or len(content) != 1:
 | 
					    if content is None or len(content) != 1:
 | 
				
			||||||
        print "No country name found for " + locale[0] + "-" + locale[1]
 | 
					        print("No country name found for " + locale[0] + "-" + locale[1])
 | 
				
			||||||
        return ''
 | 
					        return ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return content[0].get('countryName', '')
 | 
					    return content[0].get('countryName', '')
 | 
				
			||||||
@ -84,11 +84,11 @@ def fetch_supported_languages():
 | 
				
			|||||||
            try:
 | 
					            try:
 | 
				
			||||||
                engines_languages[engine_name] = engines[engine_name].fetch_supported_languages()
 | 
					                engines_languages[engine_name] = engines[engine_name].fetch_supported_languages()
 | 
				
			||||||
            except Exception as e:
 | 
					            except Exception as e:
 | 
				
			||||||
                print e
 | 
					                print(e)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # write json file
 | 
					    # write json file
 | 
				
			||||||
    with io.open(engines_languages_file, "w", encoding="utf-8") as f:
 | 
					    with io.open(engines_languages_file, "w", encoding="utf-8") as f:
 | 
				
			||||||
        f.write(unicode(dumps(engines_languages, ensure_ascii=False, encoding="utf-8")))
 | 
					        dump(engines_languages, f, ensure_ascii=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Join all language lists.
 | 
					# Join all language lists.
 | 
				
			||||||
@ -97,7 +97,7 @@ def join_language_lists():
 | 
				
			|||||||
    global languages
 | 
					    global languages
 | 
				
			||||||
    # include wikipedia first for more accurate language names
 | 
					    # include wikipedia first for more accurate language names
 | 
				
			||||||
    languages = {code: lang for code, lang
 | 
					    languages = {code: lang for code, lang
 | 
				
			||||||
                 in engines_languages['wikipedia'].iteritems()
 | 
					                 in engines_languages['wikipedia'].items()
 | 
				
			||||||
                 if valid_code(code)}
 | 
					                 if valid_code(code)}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for engine_name in engines_languages:
 | 
					    for engine_name in engines_languages:
 | 
				
			||||||
@ -121,7 +121,7 @@ def join_language_lists():
 | 
				
			|||||||
    # filter list to include only languages supported by most engines
 | 
					    # filter list to include only languages supported by most engines
 | 
				
			||||||
    min_supported_engines = int(0.70 * len(engines_languages))
 | 
					    min_supported_engines = int(0.70 * len(engines_languages))
 | 
				
			||||||
    languages = {code: lang for code, lang
 | 
					    languages = {code: lang for code, lang
 | 
				
			||||||
                 in languages.iteritems()
 | 
					                 in languages.items()
 | 
				
			||||||
                 if len(lang.get('counter', [])) >= min_supported_engines or
 | 
					                 if len(lang.get('counter', [])) >= min_supported_engines or
 | 
				
			||||||
                 len(languages.get(code.split('-')[0], {}).get('counter', [])) >= min_supported_engines}
 | 
					                 len(languages.get(code.split('-')[0], {}).get('counter', [])) >= min_supported_engines}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -165,7 +165,7 @@ def filter_single_country_languages():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# Write languages.py.
 | 
					# Write languages.py.
 | 
				
			||||||
def write_languages_file():
 | 
					def write_languages_file():
 | 
				
			||||||
    new_file = open(languages_file, 'w')
 | 
					    new_file = open(languages_file, 'wb')
 | 
				
			||||||
    file_content = '# -*- coding: utf-8 -*-\n'\
 | 
					    file_content = '# -*- coding: utf-8 -*-\n'\
 | 
				
			||||||
                   + '# list of language codes\n'\
 | 
					                   + '# list of language codes\n'\
 | 
				
			||||||
                   + '# this file is generated automatically by utils/update_search_languages.py\n'\
 | 
					                   + '# this file is generated automatically by utils/update_search_languages.py\n'\
 | 
				
			||||||
 | 
				
			|||||||
@ -7,9 +7,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
SEARX_DIR='searx'
 | 
					SEARX_DIR='searx'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pybabel extract -F babel.cfg -o messages.pot $SEARX_DIR
 | 
					pybabel extract -F babel.cfg -o messages.pot "$SEARX_DIR"
 | 
				
			||||||
for f in `ls $SEARX_DIR'/translations/'`; do
 | 
					for f in `ls "$SEARX_DIR"'/translations/'`; do
 | 
				
			||||||
    pybabel update -N -i messages.pot -d $SEARX_DIR'/translations/' -l $f
 | 
					    pybabel update -N -i messages.pot -d "$SEARX_DIR"'/translations/' -l "$f"
 | 
				
			||||||
done
 | 
					done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
echo '[!] update done, edit .po files if required and run pybabel compile -d searx/translations/'
 | 
					echo '[!] update done, edit .po files if required and run pybabel compile -d searx/translations/'
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user