forked from Ponysearch/Ponysearch
Merge branch 'searxng:master' into master
This commit is contained in:
commit
a4788f8d90
41 changed files with 250 additions and 296 deletions
|
@ -1,6 +1,5 @@
|
||||||
searxng is a fork from `searx <https://github.com/searx/searx>`_ and is
|
searxng is a fork from `searx <https://github.com/searx/searx>`_ and is
|
||||||
maintained by Alexandre Flament (`@dalf <https://github.com/dalf>`_) and Markus
|
maintained by Markus Heiser (`@return42 <https://github.com/return42>`_)
|
||||||
Heiser (`@return42 <https://github.com/return42>`_)
|
|
||||||
|
|
||||||
People who have submitted patches/translations, reported bugs, consulted
|
People who have submitted patches/translations, reported bugs, consulted
|
||||||
features or generally made searx better:
|
features or generally made searx better:
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -76,7 +76,7 @@ test.shell:
|
||||||
|
|
||||||
MANAGE += buildenv
|
MANAGE += buildenv
|
||||||
MANAGE += weblate.translations.commit weblate.push.translations
|
MANAGE += weblate.translations.commit weblate.push.translations
|
||||||
MANAGE += data.all data.languages data.useragents data.osm_keys_tags
|
MANAGE += data.all data.traits data.useragents
|
||||||
MANAGE += docs.html docs.live docs.gh-pages docs.prebuild docs.clean
|
MANAGE += docs.html docs.live docs.gh-pages docs.prebuild docs.clean
|
||||||
MANAGE += docker.build docker.push docker.buildx
|
MANAGE += docker.build docker.push docker.buildx
|
||||||
MANAGE += gecko.driver
|
MANAGE += gecko.driver
|
||||||
|
|
|
@ -6,49 +6,66 @@ Configured Engines
|
||||||
|
|
||||||
.. sidebar:: Further reading ..
|
.. sidebar:: Further reading ..
|
||||||
|
|
||||||
|
- :ref:`settings categories_as_tabs`
|
||||||
- :ref:`engines-dev`
|
- :ref:`engines-dev`
|
||||||
- :ref:`settings engine`
|
- :ref:`settings engine`
|
||||||
|
- :ref:`general engine configuration`
|
||||||
Explanation of the :ref:`general engine configuration` shown in the table
|
|
||||||
:ref:`configured engines`.
|
|
||||||
|
|
||||||
.. jinja:: searx
|
.. jinja:: searx
|
||||||
|
|
||||||
SearXNG supports {{engines | length}} search engines (of which {{enabled_engine_count}} are enabled by default).
|
SearXNG supports {{engines | length}} search engines of which
|
||||||
|
{{enabled_engine_count}} are enabled by default.
|
||||||
|
|
||||||
|
Engines can be assigned to multiple :ref:`categories <engine categories>`.
|
||||||
|
The UI displays the tabs that are configured in :ref:`categories_as_tabs
|
||||||
|
<settings categories_as_tabs>`. In addition to these UI categories (also
|
||||||
|
called *tabs*), engines can be queried by their name or the categories they
|
||||||
|
belong to, by using a :ref:`\!bing syntax <search-syntax>`.
|
||||||
|
|
||||||
|
.. contents:: Contents
|
||||||
|
:depth: 2
|
||||||
|
:local:
|
||||||
|
:backlinks: entry
|
||||||
|
|
||||||
|
.. jinja:: searx
|
||||||
|
|
||||||
{% for category, engines in categories_as_tabs.items() %}
|
{% for category, engines in categories_as_tabs.items() %}
|
||||||
|
|
||||||
{{category}} search engines
|
tab ``!{{category.replace(' ', '_')}}``
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
{% for group, engines in engines | group_engines_in_tab %}
|
{% for group, group_bang, engines in engines | group_engines_in_tab %}
|
||||||
|
|
||||||
{% if loop.length > 1 %}
|
{% if loop.length > 1 %}
|
||||||
{{group}}
|
{% if group_bang %}group ``{{group_bang}}``{% else %}{{group}}{% endif %}
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
.. flat-table::
|
.. flat-table::
|
||||||
:header-rows: 2
|
:header-rows: 2
|
||||||
:stub-columns: 1
|
:stub-columns: 1
|
||||||
|
:widths: 10 1 10 1 1 1 1 1 1 1
|
||||||
|
|
||||||
* - :cspan:`5` Engines configured by default (in :ref:`settings.yml <engine settings>`)
|
* - :cspan:`5` Engines configured by default (in :ref:`settings.yml <engine settings>`)
|
||||||
- :cspan:`3` :ref:`Supported features <engine file>`
|
- :cspan:`3` :ref:`Supported features <engine file>`
|
||||||
|
|
||||||
* - Name
|
* - Name
|
||||||
- Shortcut
|
- !bang
|
||||||
- Module
|
- Module
|
||||||
- Disabled
|
- Disabled
|
||||||
- Timeout
|
- Timeout
|
||||||
- Weight
|
- Weight
|
||||||
- Paging
|
- Paging
|
||||||
- Language, Region
|
- Locale
|
||||||
- Safe search
|
- Safe search
|
||||||
- Time range
|
- Time range
|
||||||
|
|
||||||
{% for mod in engines %}
|
{% for mod in engines %}
|
||||||
|
|
||||||
* - `{{mod.name}} <{{mod.about and mod.about.website}}>`_
|
* - `{{mod.name}} <{{mod.about and mod.about.website}}>`_
|
||||||
|
{%- if mod.about and mod.about.language %}
|
||||||
|
({{mod.about.language | upper}})
|
||||||
|
{%- endif %}
|
||||||
- ``!{{mod.shortcut}}``
|
- ``!{{mod.shortcut}}``
|
||||||
- {%- if 'searx.engines.' + mod.__name__ in documented_modules %}
|
- {%- if 'searx.engines.' + mod.__name__ in documented_modules %}
|
||||||
:py:mod:`~searx.engines.{{mod.__name__}}`
|
:py:mod:`~searx.engines.{{mod.__name__}}`
|
||||||
|
@ -56,9 +73,6 @@ Explanation of the :ref:`general engine configuration` shown in the table
|
||||||
:origin:`{{mod.__name__}} <searx/engines/{{mod.__name__}}.py>`
|
:origin:`{{mod.__name__}} <searx/engines/{{mod.__name__}}.py>`
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
- {{(mod.disabled and "y") or ""}}
|
- {{(mod.disabled and "y") or ""}}
|
||||||
{%- if mod.about and mod.about.language %}
|
|
||||||
({{mod.about.language | upper}})
|
|
||||||
{%- endif %}
|
|
||||||
- {{mod.timeout}}
|
- {{mod.timeout}}
|
||||||
- {{mod.weight or 1 }}
|
- {{mod.weight or 1 }}
|
||||||
{% if mod.engine_type == 'online' %}
|
{% if mod.engine_type == 'online' %}
|
||||||
|
|
|
@ -311,7 +311,6 @@ Global Settings
|
||||||
``results_on_new_tab``:
|
``results_on_new_tab``:
|
||||||
Open result links in a new tab by default.
|
Open result links in a new tab by default.
|
||||||
|
|
||||||
|
|
||||||
.. _settings redis:
|
.. _settings redis:
|
||||||
|
|
||||||
``redis:``
|
``redis:``
|
||||||
|
@ -457,6 +456,9 @@ Communication with search engines.
|
||||||
``max_redirects`` :
|
``max_redirects`` :
|
||||||
30 by default. Maximum redirect before it is an error.
|
30 by default. Maximum redirect before it is an error.
|
||||||
|
|
||||||
|
|
||||||
|
.. _settings categories_as_tabs:
|
||||||
|
|
||||||
``categories_as_tabs:``
|
``categories_as_tabs:``
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
@ -477,6 +479,15 @@ Categories not listed here can still be searched with the :ref:`search-syntax`.
|
||||||
files:
|
files:
|
||||||
social media:
|
social media:
|
||||||
|
|
||||||
|
Engines are added to ``categories:`` (compare :ref:`engine categories`), the
|
||||||
|
categories listed in ``categories_as_tabs`` are shown as tabs in the UI. If
|
||||||
|
there are no active engines in a category, the tab is not displayed (e.g. if a
|
||||||
|
user disables all engines in a category).
|
||||||
|
|
||||||
|
On the preferences page (``/preferences``) -- under *engines* -- there is an
|
||||||
|
additional tab, called *other*. In this tab are all engines listed that are not
|
||||||
|
in one of the UI tabs (not included in ``categories_as_tabs``).
|
||||||
|
|
||||||
.. _settings engine:
|
.. _settings engine:
|
||||||
|
|
||||||
Engine settings
|
Engine settings
|
||||||
|
@ -503,7 +514,7 @@ engine is shown. Most of the options have a default value or even are optional.
|
||||||
disabled: false
|
disabled: false
|
||||||
language: en_US
|
language: en_US
|
||||||
tokens: [ 'my-secret-token' ]
|
tokens: [ 'my-secret-token' ]
|
||||||
weigth: 1
|
weight: 1
|
||||||
display_error_messages: true
|
display_error_messages: true
|
||||||
about:
|
about:
|
||||||
website: https://example.com
|
website: https://example.com
|
||||||
|
@ -552,10 +563,21 @@ engine is shown. Most of the options have a default value or even are optional.
|
||||||
to build and send a ``Accept-Language`` header in the request to the origin
|
to build and send a ``Accept-Language`` header in the request to the origin
|
||||||
search engine.
|
search engine.
|
||||||
|
|
||||||
|
.. _engine categories:
|
||||||
|
|
||||||
``categories`` : optional
|
``categories`` : optional
|
||||||
Define in which categories this engine will be active. Most of the time, it is
|
Specifies to which categories the engine should be added. Engines can be
|
||||||
defined in the code of the engine, but in a few cases it is useful, like when
|
assigned to multiple categories.
|
||||||
describing multiple search engine using the same code.
|
|
||||||
|
Categories can be shown as tabs (:ref:`settings categories_as_tabs`) in the
|
||||||
|
UI. A search in a tab (in the UI) will query all engines that are active in
|
||||||
|
this tab. In the preferences page (``/preferences``) -- under *engines* --
|
||||||
|
users can select what engine should be active when querying in this tab.
|
||||||
|
|
||||||
|
Alternatively, :ref:`\!bang <search-syntax>` can be used to search all engines
|
||||||
|
in a category, regardless of whether they are active or not, or whether they
|
||||||
|
are in a tab of the UI or not. For example, ``!dictionaries`` can be used to
|
||||||
|
query all search engines in that category (group).
|
||||||
|
|
||||||
``timeout`` : optional
|
``timeout`` : optional
|
||||||
Timeout of the search with the current search engine. **Be careful, it will
|
Timeout of the search with the current search engine. **Be careful, it will
|
||||||
|
@ -581,7 +603,7 @@ engine is shown. Most of the options have a default value or even are optional.
|
||||||
A list of secret tokens to make this engine *private*, more details see
|
A list of secret tokens to make this engine *private*, more details see
|
||||||
:ref:`private engines`.
|
:ref:`private engines`.
|
||||||
|
|
||||||
``weigth`` : default ``1``
|
``weight`` : default ``1``
|
||||||
Weighting of the results of this engine.
|
Weighting of the results of this engine.
|
||||||
|
|
||||||
``display_error_messages`` : default ``true``
|
``display_error_messages`` : default ``true``
|
||||||
|
|
|
@ -46,7 +46,7 @@ Engine File
|
||||||
======================= =========== ========================================================
|
======================= =========== ========================================================
|
||||||
argument type information
|
argument type information
|
||||||
======================= =========== ========================================================
|
======================= =========== ========================================================
|
||||||
categories list pages, in which the engine is working
|
categories list categories, in which the engine is working
|
||||||
paging boolean support multiple pages
|
paging boolean support multiple pages
|
||||||
time_range_support boolean support search time range
|
time_range_support boolean support search time range
|
||||||
engine_type str - ``online`` :ref:`[ref] <demo online engine>` by
|
engine_type str - ``online`` :ref:`[ref] <demo online engine>` by
|
||||||
|
|
32
manage
32
manage
|
@ -77,9 +77,9 @@ weblate.:
|
||||||
push.translations: push translation changes from SearXNG to Weblate's counterpart
|
push.translations: push translation changes from SearXNG to Weblate's counterpart
|
||||||
to.translations: Update 'translations' branch with last additions from Weblate.
|
to.translations: Update 'translations' branch with last additions from Weblate.
|
||||||
data.:
|
data.:
|
||||||
all : update searx/languages.py and ./data/*
|
all : update searx/sxng_locales.py and searx/data/*
|
||||||
languages : update searx/data/engines_languages.json & searx/languages.py
|
traits : update searx/data/engine_traits.json & searx/sxng_locales.py
|
||||||
useragents: update searx/data/useragents.json with the most recent versions of Firefox.
|
useragents: update searx/data/useragents.json with the most recent versions of Firefox
|
||||||
docs.:
|
docs.:
|
||||||
html : build HTML documentation
|
html : build HTML documentation
|
||||||
live : autobuild HTML documentation while editing
|
live : autobuild HTML documentation while editing
|
||||||
|
@ -386,27 +386,33 @@ weblate.push.translations() {
|
||||||
|
|
||||||
data.all() {
|
data.all() {
|
||||||
( set -e
|
( set -e
|
||||||
|
|
||||||
pyenv.activate
|
pyenv.activate
|
||||||
data.languages
|
data.traits
|
||||||
data.useragents
|
data.useragents
|
||||||
data.osm_keys_tags
|
|
||||||
|
build_msg DATA "update searx/data/osm_keys_tags.json"
|
||||||
|
pyenv.cmd python searxng_extra/update/update_osm_keys_tags.py
|
||||||
build_msg DATA "update searx/data/ahmia_blacklist.txt"
|
build_msg DATA "update searx/data/ahmia_blacklist.txt"
|
||||||
python searxng_extra/update/update_ahmia_blacklist.py
|
python searxng_extra/update/update_ahmia_blacklist.py
|
||||||
build_msg DATA "update searx/data/wikidata_units.json"
|
build_msg DATA "update searx/data/wikidata_units.json"
|
||||||
python searxng_extra/update/update_wikidata_units.py
|
python searxng_extra/update/update_wikidata_units.py
|
||||||
build_msg DATA "update searx/data/currencies.json"
|
build_msg DATA "update searx/data/currencies.json"
|
||||||
python searxng_extra/update/update_currencies.py
|
python searxng_extra/update/update_currencies.py
|
||||||
|
build_msg DATA "update searx/data/external_bangs.json"
|
||||||
|
python searxng_extra/update/update_external_bangs.py
|
||||||
|
build_msg DATA "update searx/data/engine_descriptions.json"
|
||||||
|
python searxng_extra/update/update_engine_descriptions.py
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
data.languages() {
|
data.traits() {
|
||||||
( set -e
|
( set -e
|
||||||
pyenv.activate
|
pyenv.activate
|
||||||
build_msg ENGINES "fetch languages .."
|
build_msg DATA "update searx/data/engine_traits.json"
|
||||||
python searxng_extra/update/update_languages.py
|
python searxng_extra/update/update_engine_traits.py
|
||||||
build_msg ENGINES "update update searx/languages.py"
|
build_msg ENGINES "update searx/sxng_locales.py"
|
||||||
build_msg DATA "update searx/data/engines_languages.json"
|
|
||||||
)
|
)
|
||||||
dump_return $?
|
dump_return $?
|
||||||
}
|
}
|
||||||
|
@ -417,12 +423,6 @@ data.useragents() {
|
||||||
dump_return $?
|
dump_return $?
|
||||||
}
|
}
|
||||||
|
|
||||||
data.osm_keys_tags() {
|
|
||||||
build_msg DATA "update searx/data/osm_keys_tags.json"
|
|
||||||
pyenv.cmd python searxng_extra/update/update_osm_keys_tags.py
|
|
||||||
dump_return $?
|
|
||||||
}
|
|
||||||
|
|
||||||
docs.prebuild() {
|
docs.prebuild() {
|
||||||
build_msg DOCS "build ${DOCS_BUILD}/includes"
|
build_msg DOCS "build ${DOCS_BUILD}/includes"
|
||||||
(
|
(
|
||||||
|
|
|
@ -2,7 +2,7 @@ mock==5.0.1
|
||||||
nose2[coverage_plugin]==0.12.0
|
nose2[coverage_plugin]==0.12.0
|
||||||
cov-core==1.15.0
|
cov-core==1.15.0
|
||||||
black==22.12.0
|
black==22.12.0
|
||||||
pylint==2.17.1
|
pylint==2.17.2
|
||||||
splinter==0.19.0
|
splinter==0.19.0
|
||||||
selenium==4.8.3
|
selenium==4.8.3
|
||||||
twine==4.0.2
|
twine==4.0.2
|
||||||
|
|
|
@ -81,7 +81,7 @@ class Engine: # pylint: disable=too-few-public-methods
|
||||||
# settings.yml
|
# settings.yml
|
||||||
|
|
||||||
categories: List[str]
|
categories: List[str]
|
||||||
"""Tabs, in which the engine is working."""
|
"""Specifies to which :ref:`engine categories` the engine should be added."""
|
||||||
|
|
||||||
name: str
|
name: str
|
||||||
"""Name that will be used across SearXNG to define this engine. In settings, on
|
"""Name that will be used across SearXNG to define this engine. In settings, on
|
||||||
|
|
|
@ -45,7 +45,7 @@ ENGINE_DEFAULT_ARGS = {
|
||||||
"about": {},
|
"about": {},
|
||||||
}
|
}
|
||||||
# set automatically when an engine does not have any tab category
|
# set automatically when an engine does not have any tab category
|
||||||
OTHER_CATEGORY = 'other'
|
DEFAULT_CATEGORY = 'other'
|
||||||
|
|
||||||
|
|
||||||
# Defaults for the namespace of an engine module, see :py:func:`load_engine`
|
# Defaults for the namespace of an engine module, see :py:func:`load_engine`
|
||||||
|
@ -132,7 +132,7 @@ def load_engine(engine_data: dict) -> Optional[Engine]:
|
||||||
set_loggers(engine, engine_name)
|
set_loggers(engine, engine_name)
|
||||||
|
|
||||||
if not any(cat in settings['categories_as_tabs'] for cat in engine.categories):
|
if not any(cat in settings['categories_as_tabs'] for cat in engine.categories):
|
||||||
engine.categories.append(OTHER_CATEGORY)
|
engine.categories.append(DEFAULT_CATEGORY)
|
||||||
|
|
||||||
return engine
|
return engine
|
||||||
|
|
||||||
|
|
|
@ -198,13 +198,11 @@ def response(resp):
|
||||||
url = link.attrib.get('href')
|
url = link.attrib.get('href')
|
||||||
title = extract_text(link)
|
title = extract_text(link)
|
||||||
|
|
||||||
# Make sure that the element is free of <a href> links and <span class='algoSlug_icon'>
|
|
||||||
content = eval_xpath(result, '(.//p)[1]')
|
content = eval_xpath(result, '(.//p)[1]')
|
||||||
for p in content:
|
for p in content:
|
||||||
|
# Make sure that the element is free of <a href> links
|
||||||
for e in p.xpath('.//a'):
|
for e in p.xpath('.//a'):
|
||||||
e.getparent().remove(e)
|
e.getparent().remove(e)
|
||||||
for e in p.xpath('.//span[@class="algoSlug_icon"]'):
|
|
||||||
e.getparent().remove(e)
|
|
||||||
content = extract_text(content)
|
content = extract_text(content)
|
||||||
|
|
||||||
# get the real URL either using the URL shown to user or following the Bing URL
|
# get the real URL either using the URL shown to user or following the Bing URL
|
||||||
|
|
|
@ -36,7 +36,7 @@ about = {
|
||||||
send_accept_language_header = True
|
send_accept_language_header = True
|
||||||
|
|
||||||
# engine dependent config
|
# engine dependent config
|
||||||
categories = ["others"]
|
categories = ["weather"]
|
||||||
URL = "https://duckduckgo.com/js/spice/forecast/{query}/{lang}"
|
URL = "https://duckduckgo.com/js/spice/forecast/{query}/{lang}"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,133 +0,0 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
# lint: pylint
|
|
||||||
"""
|
|
||||||
Gigablast (Web)
|
|
||||||
"""
|
|
||||||
# pylint: disable=invalid-name, use-dict-literal
|
|
||||||
|
|
||||||
import re
|
|
||||||
from time import time
|
|
||||||
from json import loads
|
|
||||||
from urllib.parse import urlencode
|
|
||||||
from searx.network import get
|
|
||||||
|
|
||||||
# about
|
|
||||||
about = {
|
|
||||||
"website": 'https://www.gigablast.com',
|
|
||||||
"wikidata_id": 'Q3105449',
|
|
||||||
"official_api_documentation": 'https://gigablast.com/api.html',
|
|
||||||
"use_official_api": True,
|
|
||||||
"require_api_key": False,
|
|
||||||
"results": 'JSON',
|
|
||||||
}
|
|
||||||
|
|
||||||
# engine dependent config
|
|
||||||
categories = ['general', 'web']
|
|
||||||
# gigablast's pagination is totally damaged, don't use it
|
|
||||||
paging = False
|
|
||||||
safesearch = True
|
|
||||||
|
|
||||||
# search-url
|
|
||||||
base_url = 'https://gigablast.com'
|
|
||||||
search_path = '/search?'
|
|
||||||
|
|
||||||
# ugly hack: gigablast requires a random extra parameter which can be extracted
|
|
||||||
# from the source code of the gigablast HTTP client
|
|
||||||
extra_param = ''
|
|
||||||
# timestamp of the last fetch of extra_param
|
|
||||||
extra_param_ts = 0
|
|
||||||
# after how many seconds extra_param expire
|
|
||||||
extra_param_expiration_delay = 3000
|
|
||||||
|
|
||||||
gb_userid = ''
|
|
||||||
gb_code = ''
|
|
||||||
|
|
||||||
|
|
||||||
def fetch_extra_param(query_args, headers):
|
|
||||||
|
|
||||||
# example:
|
|
||||||
#
|
|
||||||
# var uxrl='/search?c=main&qlangcountry=en-us&q=south&s=10&rand=1590740241635&n';
|
|
||||||
# uxrl=uxrl+'sab=730863287';
|
|
||||||
#
|
|
||||||
# extra_param --> "rand=1590740241635&nsab=730863287"
|
|
||||||
|
|
||||||
global extra_param, extra_param_ts # pylint: disable=global-statement
|
|
||||||
|
|
||||||
extra_param_ts = time()
|
|
||||||
extra_param_path = search_path + urlencode(query_args)
|
|
||||||
text = get(base_url + extra_param_path, headers=headers).text
|
|
||||||
|
|
||||||
re_var = None
|
|
||||||
for line in text.splitlines():
|
|
||||||
if re_var is None and extra_param_path in line:
|
|
||||||
var = line.split("=")[0].split()[1] # e.g. var --> 'uxrl'
|
|
||||||
re_var = re.compile(var + "\\s*=\\s*" + var + "\\s*\\+\\s*'" + "(.*)" + "'(.*)")
|
|
||||||
extra_param = line.split("'")[1][len(extra_param_path) :]
|
|
||||||
continue
|
|
||||||
if re_var is not None and re_var.search(line):
|
|
||||||
extra_param += re_var.search(line).group(1)
|
|
||||||
break
|
|
||||||
|
|
||||||
|
|
||||||
# do search-request
|
|
||||||
def request(query, params): # pylint: disable=unused-argument
|
|
||||||
query_args = dict(c='main', q=query, dr=1, showgoodimages=0)
|
|
||||||
|
|
||||||
if gb_userid and gb_code:
|
|
||||||
query_args['userid'] = gb_userid
|
|
||||||
query_args['code'] = gb_code
|
|
||||||
|
|
||||||
if params['language'] and params['language'] != 'all':
|
|
||||||
query_args['qlangcountry'] = params['language']
|
|
||||||
query_args['qlang'] = params['language'].split('-')[0]
|
|
||||||
|
|
||||||
if params['safesearch'] >= 1:
|
|
||||||
query_args['ff'] = 1
|
|
||||||
|
|
||||||
# see API http://www.gigablast.com/api.html#/search
|
|
||||||
# Take into account, that the API has some quirks ..
|
|
||||||
if time() > (extra_param_ts + extra_param_expiration_delay):
|
|
||||||
fetch_extra_param(query_args, params['headers'])
|
|
||||||
|
|
||||||
query_args['format'] = 'json'
|
|
||||||
params['url'] = base_url + search_path + urlencode(query_args) + extra_param
|
|
||||||
|
|
||||||
return params
|
|
||||||
|
|
||||||
|
|
||||||
# get response from search-request
|
|
||||||
def response(resp):
|
|
||||||
results = []
|
|
||||||
|
|
||||||
response_json = loads(resp.text)
|
|
||||||
|
|
||||||
# logger.debug('gigablast returns %s results', len(response_json['results']))
|
|
||||||
|
|
||||||
for result in response_json['results']:
|
|
||||||
# see "Example JSON Output (&format=json)"
|
|
||||||
# at http://www.gigablast.com/api.html#/search
|
|
||||||
|
|
||||||
# sort out meaningless result
|
|
||||||
|
|
||||||
title = result.get('title')
|
|
||||||
if len(title) < 2:
|
|
||||||
continue
|
|
||||||
|
|
||||||
url = result.get('url')
|
|
||||||
if len(url) < 9:
|
|
||||||
continue
|
|
||||||
|
|
||||||
content = result.get('sum')
|
|
||||||
if len(content) < 5:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# extend fields
|
|
||||||
|
|
||||||
subtitle = result.get('title')
|
|
||||||
if len(subtitle) > 3 and subtitle != title:
|
|
||||||
title += " - " + subtitle
|
|
||||||
|
|
||||||
results.append(dict(url=url, title=title, content=content))
|
|
||||||
|
|
||||||
return results
|
|
|
@ -15,7 +15,7 @@ about = {
|
||||||
"results": "JSON",
|
"results": "JSON",
|
||||||
}
|
}
|
||||||
|
|
||||||
categories = ["others"]
|
categories = ["weather"]
|
||||||
|
|
||||||
url = "https://wttr.in/{query}?format=j1&lang={lang}"
|
url = "https://wttr.in/{query}?format=j1&lang={lang}"
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ nach dem Begriff **paris** gesucht.
|
||||||
|
|
||||||
## `:` Sprache auswählen
|
## `:` Sprache auswählen
|
||||||
|
|
||||||
Um einen Sprachfilter auszuwählen, verwenden Sie das Präfix`:`. Um ein
|
Um einen Sprachfilter auszuwählen, verwenden Sie das Präfix `:`. Um ein
|
||||||
einfaches Beispiel zu geben:
|
einfaches Beispiel zu geben:
|
||||||
|
|
||||||
- Wikipedia mit einer benutzerdefinierten Sprache durchsuchen
|
- Wikipedia mit einer benutzerdefinierten Sprache durchsuchen
|
||||||
|
|
|
@ -17,7 +17,7 @@ from searx.enginelib import Engine
|
||||||
from searx.plugins import Plugin
|
from searx.plugins import Plugin
|
||||||
from searx.locales import LOCALE_NAMES
|
from searx.locales import LOCALE_NAMES
|
||||||
from searx.webutils import VALID_LANGUAGE_CODE
|
from searx.webutils import VALID_LANGUAGE_CODE
|
||||||
from searx.engines import OTHER_CATEGORY
|
from searx.engines import DEFAULT_CATEGORY
|
||||||
|
|
||||||
|
|
||||||
COOKIE_MAX_AGE = 60 * 60 * 24 * 365 * 5 # 5 years
|
COOKIE_MAX_AGE = 60 * 60 * 24 * 365 * 5 # 5 years
|
||||||
|
@ -259,7 +259,7 @@ class EnginesSetting(BooleanChoices):
|
||||||
choices = {}
|
choices = {}
|
||||||
for engine in engines:
|
for engine in engines:
|
||||||
for category in engine.categories:
|
for category in engine.categories:
|
||||||
if not category in list(settings['categories_as_tabs'].keys()) + [OTHER_CATEGORY]:
|
if not category in list(settings['categories_as_tabs'].keys()) + [DEFAULT_CATEGORY]:
|
||||||
continue
|
continue
|
||||||
choices['{}__{}'.format(engine.name, category)] = not engine.disabled
|
choices['{}__{}'.format(engine.name, category)] = not engine.disabled
|
||||||
super().__init__(default_value, choices)
|
super().__init__(default_value, choices)
|
||||||
|
|
|
@ -15,8 +15,8 @@ __all__ = [
|
||||||
|
|
||||||
CONSTANT_NAMES = {
|
CONSTANT_NAMES = {
|
||||||
# Constants defined in other modules
|
# Constants defined in other modules
|
||||||
'DEFAULT_GROUP_NAME': webutils.DEFAULT_GROUP_NAME,
|
'NO_SUBGROUPING': webutils.NO_SUBGROUPING,
|
||||||
'OTHER_CATEGORY': engines.OTHER_CATEGORY,
|
'DEFAULT_CATEGORY': engines.DEFAULT_CATEGORY,
|
||||||
}
|
}
|
||||||
|
|
||||||
CATEGORY_NAMES = {
|
CATEGORY_NAMES = {
|
||||||
|
|
|
@ -670,17 +670,6 @@ engines:
|
||||||
engine: genius
|
engine: genius
|
||||||
shortcut: gen
|
shortcut: gen
|
||||||
|
|
||||||
- name: gigablast
|
|
||||||
engine: gigablast
|
|
||||||
shortcut: gb
|
|
||||||
timeout: 4.0
|
|
||||||
# API key required, see https://gigablast.com/searchfeed.html
|
|
||||||
# gb_userid: unset
|
|
||||||
# gb_code: unknown
|
|
||||||
disabled: true
|
|
||||||
additional_tests:
|
|
||||||
rosebud: *test_rosebud
|
|
||||||
|
|
||||||
- name: gentoo
|
- name: gentoo
|
||||||
engine: gentoo
|
engine: gentoo
|
||||||
shortcut: ge
|
shortcut: ge
|
||||||
|
|
|
@ -74,6 +74,10 @@ def update_settings(default_settings, user_settings):
|
||||||
else:
|
else:
|
||||||
default_settings[k] = v
|
default_settings[k] = v
|
||||||
|
|
||||||
|
categories_as_tabs = user_settings.get('categories_as_tabs')
|
||||||
|
if categories_as_tabs:
|
||||||
|
default_settings['categories_as_tabs'] = categories_as_tabs
|
||||||
|
|
||||||
# parse the engines
|
# parse the engines
|
||||||
remove_engines = None
|
remove_engines = None
|
||||||
keep_only_engines = None
|
keep_only_engines = None
|
||||||
|
|
|
@ -423,8 +423,11 @@ svg.leaflet-image-layer.leaflet-interactive path {
|
||||||
.leaflet-control-attribution a:focus {
|
.leaflet-control-attribution a:focus {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
.leaflet-control-attribution svg {
|
.leaflet-attribution-flag {
|
||||||
display: inline !important;
|
display: inline !important;
|
||||||
|
vertical-align: baseline !important;
|
||||||
|
width: 1em;
|
||||||
|
height: 0.6669em;
|
||||||
}
|
}
|
||||||
.leaflet-left .leaflet-control-scale {
|
.leaflet-left .leaflet-control-scale {
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
|
@ -438,12 +441,10 @@ svg.leaflet-image-layer.leaflet-interactive path {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
padding: 2px 5px 1px;
|
padding: 2px 5px 1px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
|
||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
background: rgba(255, 255, 255, 0.8);
|
||||||
background: #fff;
|
text-shadow: 1px 1px #fff;
|
||||||
background: rgba(255, 255, 255, 0.5);
|
|
||||||
}
|
}
|
||||||
.leaflet-control-scale-line:not(:first-child) {
|
.leaflet-control-scale-line:not(:first-child) {
|
||||||
border-top: 2px solid #777;
|
border-top: 2px solid #777;
|
||||||
|
@ -537,8 +538,6 @@ svg.leaflet-image-layer.leaflet-interactive path {
|
||||||
}
|
}
|
||||||
.leaflet-popup-scrolled {
|
.leaflet-popup-scrolled {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
border-bottom: 1px solid #ddd;
|
|
||||||
border-top: 1px solid #ddd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.leaflet-oldie .leaflet-popup-content-wrapper {
|
.leaflet-oldie .leaflet-popup-content-wrapper {
|
||||||
|
@ -652,6 +651,6 @@ svg.leaflet-image-layer.leaflet-interactive path {
|
||||||
/* Prevent printers from removing background-images of controls. */
|
/* Prevent printers from removing background-images of controls. */
|
||||||
.leaflet-control {
|
.leaflet-control {
|
||||||
-webkit-print-color-adjust: exact;
|
-webkit-print-color-adjust: exact;
|
||||||
color-adjust: exact;
|
print-color-adjust: exact;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
||||||
{"version":3,"file":"searxng.head.min.js","sources":["../src/js/head/00_init.js"],"sourcesContent":["/* SPDX-License-Identifier: AGPL-3.0-or-later */\n(function (w, d) {\n 'use strict';\n\n // add data- properties\n var script = d.currentScript || (function () {\n var scripts = d.getElementsByTagName('script');\n return scripts[scripts.length - 1];\n })();\n\n w.searxng = {\n settings: JSON.parse(atob(script.getAttribute('client_settings')))\n };\n\n // update the css\n var hmtlElement = d.getElementsByTagName(\"html\")[0];\n hmtlElement.classList.remove('no-js');\n hmtlElement.classList.add('js');\n\n})(window, document);\n"],"names":["w","d","script","currentScript","scripts","getElementsByTagName","length","searxng","settings","JSON","parse","atob","getAttribute","hmtlElement","classList","remove","add","window","document"],"mappings":"CACA,SAAWA,EAAGC,gBAIZ,IAAIC,EAASD,EAAEE,eAAkB,WAC/B,IAAIC,EAAUH,EAAEI,qBAAqB,UACrC,OAAOD,EAAQA,EAAQE,OAAS,GAFD,GAKjCN,EAAEO,QAAU,CACVC,SAAUC,KAAKC,MAAMC,KAAKT,EAAOU,aAAa,sBAIhD,IAAIC,EAAcZ,EAAEI,qBAAqB,QAAQ,GACjDQ,EAAYC,UAAUC,OAAO,SAC7BF,EAAYC,UAAUE,IAAI,OAhB5B,CAkBGC,OAAQC"}
|
{"version":3,"file":"searxng.head.min.js","sources":["../src/js/head/00_init.js"],"sourcesContent":["/* SPDX-License-Identifier: AGPL-3.0-or-later */\n(function (w, d) {\n 'use strict';\n\n // add data- properties\n var script = d.currentScript || (function () {\n var scripts = d.getElementsByTagName('script');\n return scripts[scripts.length - 1];\n })();\n\n w.searxng = {\n settings: JSON.parse(atob(script.getAttribute('client_settings')))\n };\n\n // update the css\n var hmtlElement = d.getElementsByTagName(\"html\")[0];\n hmtlElement.classList.remove('no-js');\n hmtlElement.classList.add('js');\n\n})(window, document);\n"],"names":["w","d","script","currentScript","scripts","getElementsByTagName","length","searxng","settings","JSON","parse","atob","getAttribute","hmtlElement","classList","remove","add","window","document"],"mappings":"CACA,SAAWA,EAAGC,GACZ,aAGA,IAAIC,EAASD,EAAEE,eAAkB,WAC/B,IAAIC,EAAUH,EAAEI,qBAAqB,QAAQ,EAC7C,OAAOD,EAAQA,EAAQE,OAAS,EACjC,EAAE,EAEHN,EAAEO,QAAU,CACVC,SAAUC,KAAKC,MAAMC,KAAKT,EAAOU,aAAa,iBAAiB,CAAC,CAAC,CACnE,EAGA,IAAIC,EAAcZ,EAAEI,qBAAqB,MAAM,EAAE,GACjDQ,EAAYC,UAAUC,OAAO,OAAO,EACpCF,EAAYC,UAAUE,IAAI,IAAI,CAE/B,GAAEC,OAAQC,QAAQ"}
|
2
searx/static/themes/simple/js/searxng.min.js
vendored
2
searx/static/themes/simple/js/searxng.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -65,6 +65,39 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
_Select: function (item) {
|
||||||
|
AutoComplete.defaults._Select.call(this, item);
|
||||||
|
var form = item.closest('form');
|
||||||
|
if (form) {
|
||||||
|
form.submit();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
KeyboardMappings: Object.assign({}, AutoComplete.defaults.KeyboardMappings, {
|
||||||
|
"KeyUpAndDown_up": Object.assign({}, AutoComplete.defaults.KeyboardMappings.KeyUpAndDown_up, {
|
||||||
|
Callback: function (event) {
|
||||||
|
AutoComplete.defaults.KeyboardMappings.KeyUpAndDown_up.Callback.call(this, event);
|
||||||
|
var liActive = this.DOMResults.querySelector("li.active");
|
||||||
|
if (liActive) {
|
||||||
|
AutoComplete.defaults._Select.call(this, liActive);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
"Tab": Object.assign({}, AutoComplete.defaults.KeyboardMappings.Enter, {
|
||||||
|
Conditions: [{
|
||||||
|
Is: 9,
|
||||||
|
Not: false
|
||||||
|
}],
|
||||||
|
Callback: function (event) {
|
||||||
|
if (this.DOMResults.getAttribute("class").indexOf("open") != -1) {
|
||||||
|
var liActive = this.DOMResults.querySelector("li.active");
|
||||||
|
if (liActive !== null) {
|
||||||
|
AutoComplete.defaults._Select.call(this, liActive);
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}),
|
||||||
}, "#" + qinput_id);
|
}, "#" + qinput_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,8 +113,8 @@
|
||||||
--color-toolkit-engine-tooltip-background: #fff;
|
--color-toolkit-engine-tooltip-background: #fff;
|
||||||
--color-toolkit-loader-border: rgba(0, 0, 0, 0.2);
|
--color-toolkit-loader-border: rgba(0, 0, 0, 0.2);
|
||||||
--color-toolkit-loader-borderleft: rgba(255, 255, 255, 0);
|
--color-toolkit-loader-borderleft: rgba(255, 255, 255, 0);
|
||||||
--color-doc-code: #300;
|
--color-doc-code: #003;
|
||||||
--color-doc-code-background: #fdd;
|
--color-doc-code-background: #ddeaff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark-themes() {
|
.dark-themes() {
|
||||||
|
@ -225,8 +225,8 @@
|
||||||
--color-toolkit-engine-tooltip-background: #222;
|
--color-toolkit-engine-tooltip-background: #222;
|
||||||
--color-toolkit-loader-border: rgba(255, 255, 255, 0.2);
|
--color-toolkit-loader-border: rgba(255, 255, 255, 0.2);
|
||||||
--color-toolkit-loader-borderleft: rgba(0, 0, 0, 0);
|
--color-toolkit-loader-borderleft: rgba(0, 0, 0, 0);
|
||||||
--color-doc-code: #fdd;
|
--color-doc-code: #ddd;
|
||||||
--color-doc-code-background: #300;
|
--color-doc-code-background: #4d5a6f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dark Theme (autoswitch based on device pref)
|
/// Dark Theme (autoswitch based on device pref)
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
.info-page {
|
.info-page {
|
||||||
code {
|
code {
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
color: var(--color-doc-code);
|
.rounded-corners-tiny;
|
||||||
background-color: var(--color-doc-code-background);
|
background-color: var(--color-doc-code-background);
|
||||||
padding: 2px 5px;
|
color: var(--color-doc-code);
|
||||||
.rounded-corners(5px);
|
padding: 0.2rem;
|
||||||
|
border: 0 none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,15 @@
|
||||||
font-size: 90%;
|
font-size: 90%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bang {
|
||||||
|
.ltr-text-align-left();
|
||||||
|
.rounded-corners-tiny;
|
||||||
|
background-color: var(--color-doc-code-background);
|
||||||
|
color: var(--color-doc-code);
|
||||||
|
padding: 0.2rem;
|
||||||
|
border: 0 none;
|
||||||
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
}
|
}
|
||||||
|
@ -114,6 +123,10 @@
|
||||||
.engine-description {
|
.engine-description {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bang {
|
||||||
|
margin: 0.3rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
} -%}
|
} -%}
|
||||||
<div id="categories" class="search_categories">{{- '' -}}
|
<div id="categories" class="search_categories">{{- '' -}}
|
||||||
<div id="categories_container">
|
<div id="categories_container">
|
||||||
{%- for category in categories_as_tabs -%}
|
{%- for category in categories -%}
|
||||||
<div class="category"><input type="checkbox" id="checkbox_{{ category|replace(' ', '_') }}" name="category_{{ category }}"{% if category in selected_categories %} checked="checked"{% endif %}/>
|
<div class="category"><input type="checkbox" id="checkbox_{{ category|replace(' ', '_') }}" name="category_{{ category }}"{% if category in selected_categories %} checked="checked"{% endif %}/>
|
||||||
<label for="checkbox_{{ category|replace(' ', '_') }}" class="tooltips">
|
<label for="checkbox_{{ category|replace(' ', '_') }}" class="tooltips">
|
||||||
{{- icon_big(category_icons[category]) if category in category_icons else icon_big('globe-outline') -}}
|
{{- icon_big(category_icons[category]) if category in category_icons else icon_big('globe-outline') -}}
|
||||||
|
|
|
@ -32,7 +32,8 @@
|
||||||
{{ _('View error logs and submit a bug report') -}}
|
{{ _('View error logs and submit a bug report') -}}
|
||||||
</a>
|
</a>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
|
<p><span class="right">{{ _("!bang for this engine") }}</span>{% for bang in [search_engine.name] + [search_engine.shortcut] %}<span class="bang"> {{ '!' + bang.replace(' ', '_') }}</span>{% endfor %}</p>
|
||||||
|
<p><span class="right">{{ _("!bang for its categories") }}</span>{% for bang in search_engine.categories %}<span class="bang"> {{ '!' + bang.replace(' ', '_') }}</span>{% endfor %}</p>
|
||||||
</div>
|
</div>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
{%- endmacro %}
|
{%- endmacro %}
|
||||||
|
@ -298,18 +299,18 @@
|
||||||
<p>{{ _('Currently used search engines') }}</p>
|
<p>{{ _('Currently used search engines') }}</p>
|
||||||
{{ tabs_open() }}
|
{{ tabs_open() }}
|
||||||
{% set ns = namespace(checked=true) %}
|
{% set ns = namespace(checked=true) %}
|
||||||
{% for categ in categories_as_tabs + [OTHER_CATEGORY] %}
|
{% for categ in categories_as_tabs + [DEFAULT_CATEGORY] %}
|
||||||
{{ tab_header('enginetab', 'category' + categ, _(categ), ns.checked )}}
|
{{ tab_header('enginetab', 'category' + categ, _(categ), ns.checked )}}
|
||||||
{% set ns.checked = false %}
|
{% set ns.checked = false %}
|
||||||
{% if categ == OTHER_CATEGORY %}
|
{% if categ == DEFAULT_CATEGORY %}
|
||||||
<p>{{_('This tab does not show up for search results, but you can search the engines listed here via bangs.')}}</p>
|
<p>{{_('This tab dues not exists in the user interface, but you can search in these engines by its !bangs.')}} <a href="{{ url_for('info', pagename='search-syntax') }}">ⓘ</a></p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="scrollx">
|
<div class="scrollx">
|
||||||
<table class="striped table_engines">
|
<table class="striped table_engines">
|
||||||
<tr>{{- "" -}}
|
<tr>{{- "" -}}
|
||||||
<th class="engine_checkbox">{{ _("Allow") }}</th>{{- "" -}}
|
<th class="engine_checkbox">{{ _("Allow") }}</th>{{- "" -}}
|
||||||
<th class="name">{{ _("Engine name") }}</th>{{- "" -}}
|
<th class="name">{{ _("Engine name") }}</th>{{- "" -}}
|
||||||
<th class="shortcut">{{ _("Shortcut") }}</th>{{- "" -}}
|
<th class="shortcut">{{ _("Bang") }}</th>{{- "" -}}
|
||||||
<th>{{ _("Supports selected language") }}</th>{{- "" -}}
|
<th>{{ _("Supports selected language") }}</th>{{- "" -}}
|
||||||
<th>{{ _("SafeSearch") }}</th>{{- "" -}}
|
<th>{{ _("SafeSearch") }}</th>{{- "" -}}
|
||||||
<th>{{ _("Time range") }}</th>{{- "" -}}
|
<th>{{ _("Time range") }}</th>{{- "" -}}
|
||||||
|
@ -317,9 +318,12 @@
|
||||||
<th>{{ _("Max time") }}</th>{{- "" -}}
|
<th>{{ _("Max time") }}</th>{{- "" -}}
|
||||||
{%- if enable_metrics %}<th>{{ _("Reliability") }}</th>{% endif -%}
|
{%- if enable_metrics %}<th>{{ _("Reliability") }}</th>{% endif -%}
|
||||||
</tr>
|
</tr>
|
||||||
{% for group, engines in engines_by_category[categ] | group_engines_in_tab %}
|
{% for group, group_bang, engines in engines_by_category[categ] | group_engines_in_tab %}
|
||||||
{% if loop.length > 1 %}
|
{% if loop.length > 1 %}
|
||||||
<tr><th colspan="9" class="engine-group">{{_(group)}}</th></tr>
|
<tr>
|
||||||
|
<th class="engine-group" colspan="2">{{_(group)}}</th>
|
||||||
|
<th class="engine-group" colspan="7">{% if group_bang %}<span class="bang">{{group_bang}}</span>{% endif %}</th>
|
||||||
|
</tr>{{- "" -}}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% for search_engine in engines %}
|
{% for search_engine in engines %}
|
||||||
{% if not search_engine.private %}
|
{% if not search_engine.private %}
|
||||||
|
@ -329,13 +333,13 @@
|
||||||
<th class="name" data-engine-name="{{ search_engine.name }}">{% if search_engine.enable_http %}{{ icon_big('warning', 'No HTTPS') }}{% endif -%}
|
<th class="name" data-engine-name="{{ search_engine.name }}">{% if search_engine.enable_http %}{{ icon_big('warning', 'No HTTPS') }}{% endif -%}
|
||||||
<label for="{{ engine_id }}">
|
<label for="{{ engine_id }}">
|
||||||
{{- search_engine.name -}}
|
{{- search_engine.name -}}
|
||||||
{%- if search_engine.about and search_engine.about.language -%}
|
{%- if search_engine.about and search_engine.about.language %}
|
||||||
({{search_engine.about.language | upper}})
|
({{search_engine.about.language | upper}})
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
</label>
|
</label>
|
||||||
{{- engine_about(search_engine) -}}
|
{{- engine_about(search_engine) -}}
|
||||||
</th>{{- "" -}}
|
</th>{{- "" -}}
|
||||||
<td class="shortcut">{{ shortcuts[search_engine.name] }}</td>{{- "" -}}
|
<td class="shortcut"><span class="bang">{{ '!' + shortcuts[search_engine.name] }}</span></td>{{- "" -}}
|
||||||
<td>{{ checkbox(None, supports[search_engine.name]['supports_selected_language'], true) }}</td>{{- "" -}}
|
<td>{{ checkbox(None, supports[search_engine.name]['supports_selected_language'], true) }}</td>{{- "" -}}
|
||||||
<td>{{ checkbox(None, supports[search_engine.name]['safesearch'], true) }}</td>{{- "" -}}
|
<td>{{ checkbox(None, supports[search_engine.name]['safesearch'], true) }}</td>{{- "" -}}
|
||||||
<td>{{ checkbox(None, supports[search_engine.name]['time_range_support'], true) }}</td>{{- "" -}}
|
<td>{{ checkbox(None, supports[search_engine.name]['time_range_support'], true) }}</td>{{- "" -}}
|
||||||
|
|
Binary file not shown.
|
@ -10,20 +10,22 @@
|
||||||
# Kuka Manó <dumpster@perjel.hu>, 2022.
|
# Kuka Manó <dumpster@perjel.hu>, 2022.
|
||||||
# Markus Heiser <markus.heiser@darmarit.de>, 2022, 2023.
|
# Markus Heiser <markus.heiser@darmarit.de>, 2022, 2023.
|
||||||
# Lakatos Tamás <tomimost@gmail.com>, 2022.
|
# Lakatos Tamás <tomimost@gmail.com>, 2022.
|
||||||
|
# return42 <markus.heiser@darmarit.de>, 2023.
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: searx\n"
|
"Project-Id-Version: searx\n"
|
||||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||||
"POT-Creation-Date: 2023-02-20 11:22+0000\n"
|
"POT-Creation-Date: 2023-02-20 11:22+0000\n"
|
||||||
"PO-Revision-Date: 2023-01-06 07:14+0000\n"
|
"PO-Revision-Date: 2023-04-03 06:37+0000\n"
|
||||||
"Last-Translator: Markus Heiser <markus.heiser@darmarit.de>\n"
|
"Last-Translator: return42 <markus.heiser@darmarit.de>\n"
|
||||||
|
"Language-Team: Hungarian <https://translate.codeberg.org/projects/searxng/"
|
||||||
|
"searxng/hu/>\n"
|
||||||
"Language: hu\n"
|
"Language: hu\n"
|
||||||
"Language-Team: Hungarian "
|
|
||||||
"<https://weblate.bubu1.eu/projects/searxng/searxng/hu/>\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=utf-8\n"
|
"Content-Type: text/plain; charset=utf-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||||
|
"X-Generator: Weblate 4.16.4\n"
|
||||||
"Generated-By: Babel 2.11.0\n"
|
"Generated-By: Babel 2.11.0\n"
|
||||||
|
|
||||||
#. CONSTANT_NAMES['DEFAULT_GROUP_NAME']
|
#. CONSTANT_NAMES['DEFAULT_GROUP_NAME']
|
||||||
|
@ -381,18 +383,23 @@ msgid ""
|
||||||
"This plugin checks if the address of the request is a Tor exit-node, and "
|
"This plugin checks if the address of the request is a Tor exit-node, and "
|
||||||
"informs the user if it is; like check.torproject.org, but from SearXNG."
|
"informs the user if it is; like check.torproject.org, but from SearXNG."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Ez a beépülő modul ellenőrzi, hogy a kérés címe Tor kilépési csomópont-e, és "
|
||||||
|
"értesíti a felhasználót, ha igen; mint a check.torproject.org, de a SearXNG-"
|
||||||
|
"től."
|
||||||
|
|
||||||
#: searx/plugins/tor_check.py:62
|
#: searx/plugins/tor_check.py:62
|
||||||
msgid ""
|
msgid ""
|
||||||
"Could not download the list of Tor exit-nodes from: "
|
"Could not download the list of Tor exit-nodes from: "
|
||||||
"https://check.torproject.org/exit-addresses"
|
"https://check.torproject.org/exit-addresses"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Nem sikerült letölteni a Tor kilépési csomópontok listáját innen: "
|
||||||
|
"https://check.torproject.org/exit-addresses"
|
||||||
|
|
||||||
#: searx/plugins/tor_check.py:78
|
#: searx/plugins/tor_check.py:78
|
||||||
msgid ""
|
msgid ""
|
||||||
"You are using Tor and it looks like you have this external IP address: "
|
"You are using Tor and it looks like you have this external IP address: "
|
||||||
"{ip_address}"
|
"{ip_address}"
|
||||||
msgstr ""
|
msgstr "Ön Tor-t használ, és úgy tűnik, ez a külső IP-címe: {ip_address}"
|
||||||
|
|
||||||
#: searx/plugins/tor_check.py:86
|
#: searx/plugins/tor_check.py:86
|
||||||
msgid "You are not using Tor and you have this external IP address: {ip_address}"
|
msgid "You are not using Tor and you have this external IP address: {ip_address}"
|
||||||
|
@ -1541,4 +1548,3 @@ msgstr "videó elrejtése"
|
||||||
|
|
||||||
#~ msgid "Automatically detect the query search language and switch to it."
|
#~ msgid "Automatically detect the query search language and switch to it."
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -11,7 +11,7 @@ msgstr ""
|
||||||
"Project-Id-Version: PROJECT VERSION\n"
|
"Project-Id-Version: PROJECT VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||||
"POT-Creation-Date: 2023-02-20 11:22+0000\n"
|
"POT-Creation-Date: 2023-02-20 11:22+0000\n"
|
||||||
"PO-Revision-Date: 2023-03-30 12:37+0000\n"
|
"PO-Revision-Date: 2023-04-03 06:37+0000\n"
|
||||||
"Last-Translator: return42 <markus.heiser@darmarit.de>\n"
|
"Last-Translator: return42 <markus.heiser@darmarit.de>\n"
|
||||||
"Language-Team: Norwegian Bokmål <https://translate.codeberg.org/projects/"
|
"Language-Team: Norwegian Bokmål <https://translate.codeberg.org/projects/"
|
||||||
"searxng/searxng/nb_NO/>\n"
|
"searxng/searxng/nb_NO/>\n"
|
||||||
|
@ -575,7 +575,7 @@ msgstr "Forvalgt språk"
|
||||||
#: searx/templates/simple/filters/languages.html:4
|
#: searx/templates/simple/filters/languages.html:4
|
||||||
#: searx/templates/simple/preferences.html:119
|
#: searx/templates/simple/preferences.html:119
|
||||||
msgid "Auto-detect"
|
msgid "Auto-detect"
|
||||||
msgstr ""
|
msgstr "Sug meg"
|
||||||
|
|
||||||
#: searx/templates/simple/preferences.html:126
|
#: searx/templates/simple/preferences.html:126
|
||||||
msgid "What language do you prefer for search?"
|
msgid "What language do you prefer for search?"
|
||||||
|
|
Binary file not shown.
|
@ -14,13 +14,14 @@
|
||||||
# Peter Martin <weblate@pe7er.com>, 2022.
|
# Peter Martin <weblate@pe7er.com>, 2022.
|
||||||
# Max Westen <max@maxwesten.nl>, 2023.
|
# Max Westen <max@maxwesten.nl>, 2023.
|
||||||
# gjveld <gjveld@gmail.com>, 2023.
|
# gjveld <gjveld@gmail.com>, 2023.
|
||||||
|
# Vistaus <vistausss@fastmail.com>, 2023.
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: searx\n"
|
"Project-Id-Version: searx\n"
|
||||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||||
"POT-Creation-Date: 2023-02-20 11:22+0000\n"
|
"POT-Creation-Date: 2023-02-20 11:22+0000\n"
|
||||||
"PO-Revision-Date: 2023-02-28 22:04+0000\n"
|
"PO-Revision-Date: 2023-04-01 14:37+0000\n"
|
||||||
"Last-Translator: gjveld <gjveld@gmail.com>\n"
|
"Last-Translator: Vistaus <vistausss@fastmail.com>\n"
|
||||||
"Language-Team: Dutch <https://translate.codeberg.org/projects/searxng/"
|
"Language-Team: Dutch <https://translate.codeberg.org/projects/searxng/"
|
||||||
"searxng/nl/>\n"
|
"searxng/nl/>\n"
|
||||||
"Language: nl\n"
|
"Language: nl\n"
|
||||||
|
@ -28,7 +29,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=utf-8\n"
|
"Content-Type: text/plain; charset=utf-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||||
"X-Generator: Weblate 4.15.2\n"
|
"X-Generator: Weblate 4.16.4\n"
|
||||||
"Generated-By: Babel 2.11.0\n"
|
"Generated-By: Babel 2.11.0\n"
|
||||||
|
|
||||||
#. CONSTANT_NAMES['DEFAULT_GROUP_NAME']
|
#. CONSTANT_NAMES['DEFAULT_GROUP_NAME']
|
||||||
|
@ -74,7 +75,7 @@ msgstr "video’s"
|
||||||
#. CATEGORY_NAMES['IT']
|
#. CATEGORY_NAMES['IT']
|
||||||
#: searx/searxng.msg
|
#: searx/searxng.msg
|
||||||
msgid "it"
|
msgid "it"
|
||||||
msgstr "IT"
|
msgstr "it"
|
||||||
|
|
||||||
#. CATEGORY_NAMES['NEWS']
|
#. CATEGORY_NAMES['NEWS']
|
||||||
#: searx/searxng.msg
|
#: searx/searxng.msg
|
||||||
|
@ -89,7 +90,7 @@ msgstr "kaart"
|
||||||
#. CATEGORY_NAMES['ONIONS']
|
#. CATEGORY_NAMES['ONIONS']
|
||||||
#: searx/searxng.msg
|
#: searx/searxng.msg
|
||||||
msgid "onions"
|
msgid "onions"
|
||||||
msgstr "uien"
|
msgstr "onions"
|
||||||
|
|
||||||
#. CATEGORY_NAMES['SCIENCE']
|
#. CATEGORY_NAMES['SCIENCE']
|
||||||
#: searx/searxng.msg
|
#: searx/searxng.msg
|
||||||
|
@ -99,7 +100,7 @@ msgstr "wetenschap"
|
||||||
#. CATEGORY_GROUPS['APPS']
|
#. CATEGORY_GROUPS['APPS']
|
||||||
#: searx/searxng.msg
|
#: searx/searxng.msg
|
||||||
msgid "apps"
|
msgid "apps"
|
||||||
msgstr "Apps"
|
msgstr "apps"
|
||||||
|
|
||||||
#. CATEGORY_GROUPS['DICTIONARIES']
|
#. CATEGORY_GROUPS['DICTIONARIES']
|
||||||
#: searx/searxng.msg
|
#: searx/searxng.msg
|
||||||
|
@ -119,17 +120,17 @@ msgstr "paketten"
|
||||||
#. CATEGORY_GROUPS['Q_A']
|
#. CATEGORY_GROUPS['Q_A']
|
||||||
#: searx/searxng.msg
|
#: searx/searxng.msg
|
||||||
msgid "q&a"
|
msgid "q&a"
|
||||||
msgstr "vraag&antwoord"
|
msgstr "vraag en antwoord"
|
||||||
|
|
||||||
#. CATEGORY_GROUPS['REPOS']
|
#. CATEGORY_GROUPS['REPOS']
|
||||||
#: searx/searxng.msg
|
#: searx/searxng.msg
|
||||||
msgid "repos"
|
msgid "repos"
|
||||||
msgstr "repos"
|
msgstr "repo's"
|
||||||
|
|
||||||
#. CATEGORY_GROUPS['SOFTWARE_WIKIS']
|
#. CATEGORY_GROUPS['SOFTWARE_WIKIS']
|
||||||
#: searx/searxng.msg
|
#: searx/searxng.msg
|
||||||
msgid "software wikis"
|
msgid "software wikis"
|
||||||
msgstr "software wikis"
|
msgstr "softwarewikis"
|
||||||
|
|
||||||
#. CATEGORY_GROUPS['WEB']
|
#. CATEGORY_GROUPS['WEB']
|
||||||
#: searx/searxng.msg
|
#: searx/searxng.msg
|
||||||
|
@ -144,7 +145,7 @@ msgstr "wetenschapelijke publicaties"
|
||||||
#. STYLE_NAMES['AUTO']
|
#. STYLE_NAMES['AUTO']
|
||||||
#: searx/searxng.msg
|
#: searx/searxng.msg
|
||||||
msgid "auto"
|
msgid "auto"
|
||||||
msgstr "auto"
|
msgstr "automatisch"
|
||||||
|
|
||||||
#. STYLE_NAMES['LIGHT']
|
#. STYLE_NAMES['LIGHT']
|
||||||
#: searx/searxng.msg
|
#: searx/searxng.msg
|
||||||
|
@ -162,11 +163,11 @@ msgstr "verlopen"
|
||||||
|
|
||||||
#: searx/webapp.py:166
|
#: searx/webapp.py:166
|
||||||
msgid "parsing error"
|
msgid "parsing error"
|
||||||
msgstr "fout bij ontleden"
|
msgstr "verwerkingsfout"
|
||||||
|
|
||||||
#: searx/webapp.py:167
|
#: searx/webapp.py:167
|
||||||
msgid "HTTP protocol error"
|
msgid "HTTP protocol error"
|
||||||
msgstr "HTTP-protocolfout"
|
msgstr "Http-protocolfout"
|
||||||
|
|
||||||
#: searx/webapp.py:168
|
#: searx/webapp.py:168
|
||||||
msgid "network error"
|
msgid "network error"
|
||||||
|
@ -174,31 +175,31 @@ msgstr "netwerkfout"
|
||||||
|
|
||||||
#: searx/webapp.py:169
|
#: searx/webapp.py:169
|
||||||
msgid "SSL error: certificate validation has failed"
|
msgid "SSL error: certificate validation has failed"
|
||||||
msgstr "SSL-fout: certificaatvalidatie is mislukt"
|
msgstr "Ssl-fout: de certificaatvalidatie is mislukt"
|
||||||
|
|
||||||
#: searx/webapp.py:171
|
#: searx/webapp.py:171
|
||||||
msgid "unexpected crash"
|
msgid "unexpected crash"
|
||||||
msgstr "onverwacht falen"
|
msgstr "onverwachte crash"
|
||||||
|
|
||||||
#: searx/webapp.py:178
|
#: searx/webapp.py:178
|
||||||
msgid "HTTP error"
|
msgid "HTTP error"
|
||||||
msgstr "HTTP-fout"
|
msgstr "Http-fout"
|
||||||
|
|
||||||
#: searx/webapp.py:179
|
#: searx/webapp.py:179
|
||||||
msgid "HTTP connection error"
|
msgid "HTTP connection error"
|
||||||
msgstr "HTTP-verbindingsfout"
|
msgstr "Http-verbindingsfout"
|
||||||
|
|
||||||
#: searx/webapp.py:185
|
#: searx/webapp.py:185
|
||||||
msgid "proxy error"
|
msgid "proxy error"
|
||||||
msgstr "proxy-fout"
|
msgstr "proxyfout"
|
||||||
|
|
||||||
#: searx/webapp.py:186
|
#: searx/webapp.py:186
|
||||||
msgid "CAPTCHA"
|
msgid "CAPTCHA"
|
||||||
msgstr "CAPTCHA"
|
msgstr "Captcha"
|
||||||
|
|
||||||
#: searx/webapp.py:187
|
#: searx/webapp.py:187
|
||||||
msgid "too many requests"
|
msgid "too many requests"
|
||||||
msgstr "te veel aanvragen"
|
msgstr "teveel verzoeken"
|
||||||
|
|
||||||
#: searx/webapp.py:188
|
#: searx/webapp.py:188
|
||||||
msgid "access denied"
|
msgid "access denied"
|
||||||
|
@ -206,11 +207,11 @@ msgstr "toegang geweigerd"
|
||||||
|
|
||||||
#: searx/webapp.py:189
|
#: searx/webapp.py:189
|
||||||
msgid "server API error"
|
msgid "server API error"
|
||||||
msgstr "server-API-fout"
|
msgstr "server-api-fout"
|
||||||
|
|
||||||
#: searx/webapp.py:368
|
#: searx/webapp.py:368
|
||||||
msgid "No item found"
|
msgid "No item found"
|
||||||
msgstr "Geen resultaat gevonden"
|
msgstr "Er is geen resultaat gevonden"
|
||||||
|
|
||||||
#: searx/engines/qwant.py:217
|
#: searx/engines/qwant.py:217
|
||||||
#: searx/templates/simple/result_templates/images.html:20 searx/webapp.py:370
|
#: searx/templates/simple/result_templates/images.html:20 searx/webapp.py:370
|
||||||
|
@ -219,11 +220,11 @@ msgstr "Bron"
|
||||||
|
|
||||||
#: searx/webapp.py:372
|
#: searx/webapp.py:372
|
||||||
msgid "Error loading the next page"
|
msgid "Error loading the next page"
|
||||||
msgstr "Fout bij het laden van de volgende pagina"
|
msgstr "De volgende pagina kan niet worden geladen"
|
||||||
|
|
||||||
#: searx/webapp.py:524 searx/webapp.py:964
|
#: searx/webapp.py:524 searx/webapp.py:964
|
||||||
msgid "Invalid settings, please edit your preferences"
|
msgid "Invalid settings, please edit your preferences"
|
||||||
msgstr "Ongeldige instellingen, gelieve je voorkeuren bij te werken"
|
msgstr "De instellingen zijn ongeldig - werk ze bij"
|
||||||
|
|
||||||
#: searx/webapp.py:540
|
#: searx/webapp.py:540
|
||||||
msgid "Invalid settings"
|
msgid "Invalid settings"
|
||||||
|
@ -247,7 +248,7 @@ msgstr "{hours} uur, {minutes} minu(u)t(en) geleden"
|
||||||
|
|
||||||
#: searx/answerers/random/answerer.py:67
|
#: searx/answerers/random/answerer.py:67
|
||||||
msgid "Random value generator"
|
msgid "Random value generator"
|
||||||
msgstr "Generator van willekeurige waarden"
|
msgstr "Willekeurigewaardegenerator"
|
||||||
|
|
||||||
#: searx/answerers/random/answerer.py:68
|
#: searx/answerers/random/answerer.py:68
|
||||||
msgid "Generate different random values"
|
msgid "Generate different random values"
|
||||||
|
@ -259,7 +260,7 @@ msgstr "Statistische functies"
|
||||||
|
|
||||||
#: searx/answerers/statistics/answerer.py:48
|
#: searx/answerers/statistics/answerer.py:48
|
||||||
msgid "Compute {functions} of the arguments"
|
msgid "Compute {functions} of the arguments"
|
||||||
msgstr "Bereken {functions} van de argumenten"
|
msgstr "Bereken {functions} van de opties"
|
||||||
|
|
||||||
#: searx/engines/openstreetmap.py:160
|
#: searx/engines/openstreetmap.py:160
|
||||||
msgid "Get directions"
|
msgid "Get directions"
|
||||||
|
@ -281,7 +282,9 @@ msgstr "Kanaal"
|
||||||
msgid ""
|
msgid ""
|
||||||
"{numCitations} citations from the year {firstCitationVelocityYear} to "
|
"{numCitations} citations from the year {firstCitationVelocityYear} to "
|
||||||
"{lastCitationVelocityYear}"
|
"{lastCitationVelocityYear}"
|
||||||
msgstr "citaties van dit jaar"
|
msgstr ""
|
||||||
|
"{numCitations} citaties van {firstCitationVelocityYear} tot "
|
||||||
|
"{lastCitationVelocityYear}"
|
||||||
|
|
||||||
#: searx/engines/tineye.py:40
|
#: searx/engines/tineye.py:40
|
||||||
msgid ""
|
msgid ""
|
||||||
|
|
|
@ -63,7 +63,7 @@ from searx.settings_defaults import OUTPUT_FORMATS
|
||||||
from searx.settings_loader import get_default_settings_path
|
from searx.settings_loader import get_default_settings_path
|
||||||
from searx.exceptions import SearxParameterException
|
from searx.exceptions import SearxParameterException
|
||||||
from searx.engines import (
|
from searx.engines import (
|
||||||
OTHER_CATEGORY,
|
DEFAULT_CATEGORY,
|
||||||
categories,
|
categories,
|
||||||
engines,
|
engines,
|
||||||
engine_shortcuts,
|
engine_shortcuts,
|
||||||
|
@ -373,16 +373,15 @@ def get_translations():
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def _get_enable_categories(all_categories: Iterable[str]):
|
def get_enabled_categories(category_names: Iterable[str]):
|
||||||
disabled_engines = request.preferences.engines.get_disabled()
|
"""The categories in ``category_names```for which there is no active engine
|
||||||
enabled_categories = set(
|
are filtered out and a reduced list is returned."""
|
||||||
# pylint: disable=consider-using-dict-items
|
|
||||||
category
|
enabled_engines = [item[0] for item in request.preferences.engines.get_enabled()]
|
||||||
for engine_name in engines
|
enabled_categories = set()
|
||||||
for category in engines[engine_name].categories
|
for engine_name in enabled_engines:
|
||||||
if (engine_name, category) not in disabled_engines
|
enabled_categories.update(engines[engine_name].categories)
|
||||||
)
|
return [x for x in category_names if x in enabled_categories]
|
||||||
return [x for x in all_categories if x in enabled_categories]
|
|
||||||
|
|
||||||
|
|
||||||
def get_pretty_url(parsed_url: urllib.parse.ParseResult):
|
def get_pretty_url(parsed_url: urllib.parse.ParseResult):
|
||||||
|
@ -434,8 +433,8 @@ def render(template_name: str, **kwargs):
|
||||||
kwargs['theme'] = request.preferences.get_value('theme')
|
kwargs['theme'] = request.preferences.get_value('theme')
|
||||||
kwargs['method'] = request.preferences.get_value('method')
|
kwargs['method'] = request.preferences.get_value('method')
|
||||||
kwargs['categories_as_tabs'] = list(settings['categories_as_tabs'].keys())
|
kwargs['categories_as_tabs'] = list(settings['categories_as_tabs'].keys())
|
||||||
kwargs['categories'] = _get_enable_categories(categories.keys())
|
kwargs['categories'] = get_enabled_categories(settings['categories_as_tabs'].keys())
|
||||||
kwargs['OTHER_CATEGORY'] = OTHER_CATEGORY
|
kwargs['DEFAULT_CATEGORY'] = DEFAULT_CATEGORY
|
||||||
|
|
||||||
# i18n
|
# i18n
|
||||||
kwargs['sxng_locales'] = [l for l in sxng_locales if l[0] in settings['search']['languages']]
|
kwargs['sxng_locales'] = [l for l in sxng_locales if l[0] in settings['search']['languages']]
|
||||||
|
|
|
@ -18,7 +18,7 @@ from codecs import getincrementalencoder
|
||||||
from flask_babel import gettext, format_date
|
from flask_babel import gettext, format_date
|
||||||
|
|
||||||
from searx import logger, settings
|
from searx import logger, settings
|
||||||
from searx.engines import OTHER_CATEGORY
|
from searx.engines import DEFAULT_CATEGORY
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from searx.enginelib import Engine
|
from searx.enginelib import Engine
|
||||||
|
@ -222,26 +222,29 @@ def is_flask_run_cmdline():
|
||||||
return frames[-2].filename.endswith('flask/cli.py')
|
return frames[-2].filename.endswith('flask/cli.py')
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_GROUP_NAME = 'others'
|
NO_SUBGROUPING = 'without further subgrouping'
|
||||||
|
|
||||||
|
|
||||||
def group_engines_in_tab(engines: Iterable[Engine]) -> List[Tuple[str, Iterable[Engine]]]:
|
def group_engines_in_tab(engines: Iterable[Engine]) -> List[Tuple[str, Iterable[Engine]]]:
|
||||||
"""Groups an Iterable of engines by their first non tab category"""
|
"""Groups an Iterable of engines by their first non tab category (first subgroup)"""
|
||||||
|
|
||||||
def get_group(eng):
|
def get_subgroup(eng):
|
||||||
non_tab_categories = [
|
non_tab_categories = [c for c in eng.categories if c not in tabs + [DEFAULT_CATEGORY]]
|
||||||
c for c in eng.categories if c not in list(settings['categories_as_tabs'].keys()) + [OTHER_CATEGORY]
|
return non_tab_categories[0] if len(non_tab_categories) > 0 else NO_SUBGROUPING
|
||||||
]
|
|
||||||
return non_tab_categories[0] if len(non_tab_categories) > 0 else DEFAULT_GROUP_NAME
|
|
||||||
|
|
||||||
groups = itertools.groupby(sorted(engines, key=get_group), get_group)
|
|
||||||
|
|
||||||
def group_sort_key(group):
|
def group_sort_key(group):
|
||||||
return (group[0] == DEFAULT_GROUP_NAME, group[0].lower())
|
return (group[0] == NO_SUBGROUPING, group[0].lower())
|
||||||
|
|
||||||
sorted_groups = sorted(((name, list(engines)) for name, engines in groups), key=group_sort_key)
|
|
||||||
|
|
||||||
def engine_sort_key(engine):
|
def engine_sort_key(engine):
|
||||||
return (engine.about.get('language', ''), engine.name)
|
return (engine.about.get('language', ''), engine.name)
|
||||||
|
|
||||||
return [(groupname, sorted(engines, key=engine_sort_key)) for groupname, engines in sorted_groups]
|
tabs = list(settings['categories_as_tabs'].keys())
|
||||||
|
subgroups = itertools.groupby(sorted(engines, key=get_subgroup), get_subgroup)
|
||||||
|
sorted_groups = sorted(((name, list(engines)) for name, engines in subgroups), key=group_sort_key)
|
||||||
|
|
||||||
|
ret_val = []
|
||||||
|
for groupname, engines in sorted_groups:
|
||||||
|
group_bang = '!' + groupname.replace(' ', '_') if groupname != NO_SUBGROUPING else ''
|
||||||
|
ret_val.append((groupname, group_bang, sorted(engines, key=engine_sort_key)))
|
||||||
|
|
||||||
|
return ret_val
|
||||||
|
|
Loading…
Reference in a new issue