mirror of https://github.com/searxng/searxng.git
Compare commits
2 Commits
07fff4e195
...
ac631cc1a9
Author | SHA1 | Date |
---|---|---|
Markus Heiser | ac631cc1a9 | |
Markus Heiser | e0a3dee3bf |
|
@ -16,9 +16,6 @@ max_line_length = 119
|
||||||
[*.html]
|
[*.html]
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
|
|
||||||
[*.js]
|
|
||||||
indent_size = 2
|
|
||||||
|
|
||||||
[*.json]
|
[*.json]
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
insert_final_newline = ignore
|
insert_final_newline = ignore
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||||
version: 2
|
version: 2
|
||||||
updates:
|
updates:
|
||||||
- package-ecosystem: "pip"
|
- package-ecosystem: "pip"
|
||||||
|
@ -8,9 +8,6 @@ updates:
|
||||||
day: "friday"
|
day: "friday"
|
||||||
open-pull-requests-limit: 5
|
open-pull-requests-limit: 5
|
||||||
target-branch: "master"
|
target-branch: "master"
|
||||||
commit-message:
|
|
||||||
prefix: "[upd] pypi:"
|
|
||||||
|
|
||||||
- package-ecosystem: "npm"
|
- package-ecosystem: "npm"
|
||||||
directory: "/searx/static/themes/simple"
|
directory: "/searx/static/themes/simple"
|
||||||
schedule:
|
schedule:
|
||||||
|
@ -18,5 +15,3 @@ updates:
|
||||||
day: "friday"
|
day: "friday"
|
||||||
open-pull-requests-limit: 5
|
open-pull-requests-limit: 5
|
||||||
target-branch: "master"
|
target-branch: "master"
|
||||||
commit-message:
|
|
||||||
prefix: "[upd] npm:"
|
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
name: "Checker"
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "0 4 * * 5"
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
checker:
|
|
||||||
name: Checker
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install Ubuntu packages
|
|
||||||
run: |
|
|
||||||
sudo ./utils/searxng.sh install packages
|
|
||||||
|
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: '3.11'
|
|
||||||
architecture: 'x64'
|
|
||||||
|
|
||||||
- name: Install Python dependencies
|
|
||||||
run: |
|
|
||||||
make V=1 install
|
|
||||||
|
|
||||||
- name: Checker
|
|
||||||
run: |
|
|
||||||
make search.checker
|
|
|
@ -7,7 +7,7 @@ on:
|
||||||
jobs:
|
jobs:
|
||||||
updateData:
|
updateData:
|
||||||
name: Update data - ${{ matrix.fetch }}
|
name: Update data - ${{ matrix.fetch }}
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-20.04
|
||||||
if: ${{ github.repository_owner == 'searxng'}}
|
if: ${{ github.repository_owner == 'searxng'}}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
@ -29,9 +29,9 @@ jobs:
|
||||||
sudo ./utils/searxng.sh install packages
|
sudo ./utils/searxng.sh install packages
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v2
|
||||||
with:
|
with:
|
||||||
python-version: '3.12'
|
python-version: '3.9'
|
||||||
architecture: 'x64'
|
architecture: 'x64'
|
||||||
|
|
||||||
- name: Install Python dependencies
|
- name: Install Python dependencies
|
||||||
|
@ -46,18 +46,18 @@ jobs:
|
||||||
|
|
||||||
- name: Create Pull Request
|
- name: Create Pull Request
|
||||||
id: cpr
|
id: cpr
|
||||||
uses: peter-evans/create-pull-request@v6
|
uses: peter-evans/create-pull-request@v3
|
||||||
with:
|
with:
|
||||||
commit-message: '[data] update searx.data - ${{ matrix.fetch }}'
|
commit-message: Update searx.data - ${{ matrix.fetch }}
|
||||||
committer: searxng-bot <noreply@github.com>
|
committer: searxng-bot <noreply@github.com>
|
||||||
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
|
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
|
||||||
signoff: false
|
signoff: false
|
||||||
branch: update_data_${{ matrix.fetch }}
|
branch: update_data_${{ matrix.fetch }}
|
||||||
delete-branch: true
|
delete-branch: true
|
||||||
draft: false
|
draft: false
|
||||||
title: '[data] update searx.data - ${{ matrix.fetch }}'
|
title: 'Update searx.data - ${{ matrix.fetch }}'
|
||||||
body: |
|
body: |
|
||||||
update searx.data - ${{ matrix.fetch }}
|
Update searx.data - ${{ matrix.fetch }}
|
||||||
labels: |
|
labels: |
|
||||||
data
|
data
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-20.04]
|
os: [ubuntu-20.04]
|
||||||
python-version: ["3.9", "3.10", "3.11", "3.12",]
|
python-version: ["3.8", "3.9", "3.10", "3.11"]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
@ -25,7 +25,7 @@ jobs:
|
||||||
sudo ./utils/searxng.sh install packages
|
sudo ./utils/searxng.sh install packages
|
||||||
sudo apt install firefox
|
sudo apt install firefox
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
architecture: 'x64'
|
architecture: 'x64'
|
||||||
|
@ -45,6 +45,14 @@ jobs:
|
||||||
make V=1 gecko.driver
|
make V=1 gecko.driver
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: make V=1 ci.test
|
run: make V=1 ci.test
|
||||||
|
- name: Test coverage
|
||||||
|
run: make V=1 test.coverage
|
||||||
|
- name: Store coverage result
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: coverage-${{ matrix.python-version }}
|
||||||
|
path: coverage/
|
||||||
|
retention-days: 60
|
||||||
|
|
||||||
themes:
|
themes:
|
||||||
name: Themes
|
name: Themes
|
||||||
|
@ -55,9 +63,9 @@ jobs:
|
||||||
- name: Install Ubuntu packages
|
- name: Install Ubuntu packages
|
||||||
run: sudo ./utils/searxng.sh install buildhost
|
run: sudo ./utils/searxng.sh install buildhost
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: '3.12'
|
python-version: '3.9'
|
||||||
architecture: 'x64'
|
architecture: 'x64'
|
||||||
- name: Cache Python dependencies
|
- name: Cache Python dependencies
|
||||||
id: cache-python
|
id: cache-python
|
||||||
|
@ -67,7 +75,7 @@ jobs:
|
||||||
./local
|
./local
|
||||||
./.nvm
|
./.nvm
|
||||||
./node_modules
|
./node_modules
|
||||||
key: python-ubuntu-20.04-3.12-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
|
key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
|
||||||
- name: Install node dependencies
|
- name: Install node dependencies
|
||||||
run: make V=1 node.env
|
run: make V=1 node.env
|
||||||
- name: Build themes
|
- name: Build themes
|
||||||
|
@ -87,9 +95,9 @@ jobs:
|
||||||
- name: Install Ubuntu packages
|
- name: Install Ubuntu packages
|
||||||
run: sudo ./utils/searxng.sh install buildhost
|
run: sudo ./utils/searxng.sh install buildhost
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: '3.12'
|
python-version: '3.9'
|
||||||
architecture: 'x64'
|
architecture: 'x64'
|
||||||
- name: Cache Python dependencies
|
- name: Cache Python dependencies
|
||||||
id: cache-python
|
id: cache-python
|
||||||
|
@ -99,7 +107,7 @@ jobs:
|
||||||
./local
|
./local
|
||||||
./.nvm
|
./.nvm
|
||||||
./node_modules
|
./node_modules
|
||||||
key: python-ubuntu-20.04-3.12-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
|
key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
|
||||||
- name: Build documentation
|
- name: Build documentation
|
||||||
run: |
|
run: |
|
||||||
make V=1 docs.clean docs.html
|
make V=1 docs.clean docs.html
|
||||||
|
@ -112,7 +120,7 @@ jobs:
|
||||||
FOLDER: dist/docs
|
FOLDER: dist/docs
|
||||||
CLEAN: true # Automatically remove deleted files from the deploy branch
|
CLEAN: true # Automatically remove deleted files from the deploy branch
|
||||||
SINGLE_COMMIT: True
|
SINGLE_COMMIT: True
|
||||||
COMMIT_MESSAGE: '[doc] build from commit ${{ github.sha }}'
|
COMMIT_MESSAGE: build from commit ${{ github.sha }}
|
||||||
|
|
||||||
babel:
|
babel:
|
||||||
name: Update translations branch
|
name: Update translations branch
|
||||||
|
@ -131,9 +139,9 @@ jobs:
|
||||||
fetch-depth: '0'
|
fetch-depth: '0'
|
||||||
token: ${{ secrets.WEBLATE_GITHUB_TOKEN }}
|
token: ${{ secrets.WEBLATE_GITHUB_TOKEN }}
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: '3.12'
|
python-version: '3.9'
|
||||||
architecture: 'x64'
|
architecture: 'x64'
|
||||||
- name: Cache Python dependencies
|
- name: Cache Python dependencies
|
||||||
id: cache-python
|
id: cache-python
|
||||||
|
@ -143,7 +151,7 @@ jobs:
|
||||||
./local
|
./local
|
||||||
./.nvm
|
./.nvm
|
||||||
./node_modules
|
./node_modules
|
||||||
key: python-ubuntu-20.04-3.12-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
|
key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
|
||||||
- name: weblate & git setup
|
- name: weblate & git setup
|
||||||
env:
|
env:
|
||||||
WEBLATE_CONFIG: ${{ secrets.WEBLATE_CONFIG }}
|
WEBLATE_CONFIG: ${{ secrets.WEBLATE_CONFIG }}
|
||||||
|
@ -155,6 +163,7 @@ jobs:
|
||||||
- name: Update transations
|
- name: Update transations
|
||||||
id: update
|
id: update
|
||||||
run: |
|
run: |
|
||||||
|
git restore utils/brand.env
|
||||||
make V=1 weblate.push.translations
|
make V=1 weblate.push.translations
|
||||||
|
|
||||||
dockers:
|
dockers:
|
||||||
|
@ -175,9 +184,9 @@ jobs:
|
||||||
# make sure "make docker.push" can get the git history
|
# make sure "make docker.push" can get the git history
|
||||||
fetch-depth: '0'
|
fetch-depth: '0'
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: '3.12'
|
python-version: '3.9'
|
||||||
architecture: 'x64'
|
architecture: 'x64'
|
||||||
- name: Cache Python dependencies
|
- name: Cache Python dependencies
|
||||||
id: cache-python
|
id: cache-python
|
||||||
|
@ -187,7 +196,7 @@ jobs:
|
||||||
./local
|
./local
|
||||||
./.nvm
|
./.nvm
|
||||||
./node_modules
|
./node_modules
|
||||||
key: python-ubuntu-20.04-3.12-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
|
key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
if: env.DOCKERHUB_USERNAME != null
|
if: env.DOCKERHUB_USERNAME != null
|
||||||
uses: docker/setup-qemu-action@v1
|
uses: docker/setup-qemu-action@v1
|
||||||
|
|
|
@ -16,9 +16,9 @@ jobs:
|
||||||
fetch-depth: '0'
|
fetch-depth: '0'
|
||||||
token: ${{ secrets.WEBLATE_GITHUB_TOKEN }}
|
token: ${{ secrets.WEBLATE_GITHUB_TOKEN }}
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: '3.12'
|
python-version: '3.9'
|
||||||
architecture: 'x64'
|
architecture: 'x64'
|
||||||
- name: Cache Python dependencies
|
- name: Cache Python dependencies
|
||||||
id: cache-python
|
id: cache-python
|
||||||
|
@ -28,7 +28,7 @@ jobs:
|
||||||
./local
|
./local
|
||||||
./.nvm
|
./.nvm
|
||||||
./node_modules
|
./node_modules
|
||||||
key: python-ubuntu-20.04-3.12-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
|
key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
|
||||||
- name: weblate & git setup
|
- name: weblate & git setup
|
||||||
env:
|
env:
|
||||||
WEBLATE_CONFIG: ${{ secrets.WEBLATE_CONFIG }}
|
WEBLATE_CONFIG: ${{ secrets.WEBLATE_CONFIG }}
|
||||||
|
@ -45,15 +45,15 @@ jobs:
|
||||||
uses: peter-evans/create-pull-request@v3
|
uses: peter-evans/create-pull-request@v3
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.WEBLATE_GITHUB_TOKEN }}
|
token: ${{ secrets.WEBLATE_GITHUB_TOKEN }}
|
||||||
commit-message: '[l10n] update translations from Weblate'
|
commit-message: Update translations
|
||||||
committer: searxng-bot <searxng-bot@users.noreply.github.com>
|
committer: searxng-bot <searxng-bot@users.noreply.github.com>
|
||||||
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
|
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
|
||||||
signoff: false
|
signoff: false
|
||||||
branch: translations_update
|
branch: translations_update
|
||||||
delete-branch: true
|
delete-branch: true
|
||||||
draft: false
|
draft: false
|
||||||
title: '[l10n] update translations from Weblate'
|
title: 'Update translations'
|
||||||
body: |
|
body: |
|
||||||
update translations from Weblate
|
Update translations
|
||||||
labels: |
|
labels: |
|
||||||
translation
|
translation
|
||||||
|
|
|
@ -23,6 +23,3 @@ gh-pages/
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
searx/version_frozen.py
|
searx/version_frozen.py
|
||||||
.dir-locals.el
|
|
||||||
|
|
||||||
.python-version
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# -*- coding: utf-8; mode: conf-unix -*-
|
# -*- coding: utf-8; mode: conf -*-
|
||||||
# lint Python modules using external checkers.
|
# lint Python modules using external checkers.
|
||||||
#
|
#
|
||||||
# This is the main checker controlling the other ones and the reports
|
# This is the main checker controlling the other ones and the reports
|
||||||
|
@ -27,7 +27,7 @@ ignore-patterns=
|
||||||
#init-hook=
|
#init-hook=
|
||||||
|
|
||||||
# Use multiple processes to speed up Pylint.
|
# Use multiple processes to speed up Pylint.
|
||||||
jobs=0
|
jobs=1
|
||||||
|
|
||||||
# List of plugins (as comma separated values of python modules names) to load,
|
# List of plugins (as comma separated values of python modules names) to load,
|
||||||
# usually to register additional checkers.
|
# usually to register additional checkers.
|
||||||
|
@ -338,7 +338,6 @@ valid-metaclass-classmethod-first-arg=mcs
|
||||||
|
|
||||||
# Maximum number of arguments for function / method
|
# Maximum number of arguments for function / method
|
||||||
max-args=8
|
max-args=8
|
||||||
max-positional-arguments=14
|
|
||||||
|
|
||||||
# Maximum number of attributes for a class (see R0902).
|
# Maximum number of attributes for a class (see R0902).
|
||||||
max-attributes=20
|
max-attributes=20
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
python 3.12.0
|
|
||||||
shellcheck 0.9.0
|
|
|
@ -169,8 +169,4 @@ features or generally made searx better:
|
||||||
- @llmII
|
- @llmII
|
||||||
- @blob42 `<https://blob42.xyz>`_
|
- @blob42 `<https://blob42.xyz>`_
|
||||||
- Paolo Basso `<https://github.com/paolobasso99>`
|
- Paolo Basso `<https://github.com/paolobasso99>`
|
||||||
- Bernie Huang `<https://github.com/BernieHuang2008>`
|
- Bernie Huang `<https://github.com/BernieHuang2008>`
|
||||||
- Austin Olacsi `<https://github.com/Austin-Olacsi>`
|
|
||||||
- @micsthepick
|
|
||||||
- Daniel Kukula `<https://github.com/dkuku>`
|
|
||||||
- Patrick Evans `https://github.com/holysoles`
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
## Resources in the documentation
|
## Resources in the documentation
|
||||||
|
|
||||||
* [Development quickstart](https://docs.searxng.org/dev/quickstart.html)
|
* [Development quickstart](https://docs.searxng.org/dev/contribution_guide.html)
|
||||||
* [Contribution guide](https://docs.searxng.org/dev/contribution_guide.html)
|
* [Contribution guide](https://docs.searxng.org/dev/contribution_guide.html)
|
||||||
|
|
||||||
## Submitting PRs
|
## Submitting PRs
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM alpine:3.20
|
FROM alpine:3.18
|
||||||
ENTRYPOINT ["/sbin/tini","--","/usr/local/searxng/dockerfiles/docker-entrypoint.sh"]
|
ENTRYPOINT ["/sbin/tini","--","/usr/local/searxng/dockerfiles/docker-entrypoint.sh"]
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
VOLUME /etc/searxng
|
VOLUME /etc/searxng
|
||||||
|
@ -15,9 +15,7 @@ ENV INSTANCE_NAME=searxng \
|
||||||
MORTY_KEY= \
|
MORTY_KEY= \
|
||||||
MORTY_URL= \
|
MORTY_URL= \
|
||||||
SEARXNG_SETTINGS_PATH=/etc/searxng/settings.yml \
|
SEARXNG_SETTINGS_PATH=/etc/searxng/settings.yml \
|
||||||
UWSGI_SETTINGS_PATH=/etc/searxng/uwsgi.ini \
|
UWSGI_SETTINGS_PATH=/etc/searxng/uwsgi.ini
|
||||||
UWSGI_WORKERS=%k \
|
|
||||||
UWSGI_THREADS=4
|
|
||||||
|
|
||||||
WORKDIR /usr/local/searxng
|
WORKDIR /usr/local/searxng
|
||||||
|
|
||||||
|
@ -35,6 +33,7 @@ RUN apk add --no-cache -t build-dependencies \
|
||||||
git \
|
git \
|
||||||
&& apk add --no-cache \
|
&& apk add --no-cache \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
|
su-exec \
|
||||||
python3 \
|
python3 \
|
||||||
py3-pip \
|
py3-pip \
|
||||||
libxml2 \
|
libxml2 \
|
||||||
|
@ -44,7 +43,7 @@ RUN apk add --no-cache -t build-dependencies \
|
||||||
uwsgi \
|
uwsgi \
|
||||||
uwsgi-python3 \
|
uwsgi-python3 \
|
||||||
brotli \
|
brotli \
|
||||||
&& pip3 install --break-system-packages --no-cache -r requirements.txt \
|
&& pip3 install --no-cache -r requirements.txt \
|
||||||
&& apk del build-dependencies \
|
&& apk del build-dependencies \
|
||||||
&& rm -rf /root/.cache
|
&& rm -rf /root/.cache
|
||||||
|
|
||||||
|
|
10
Makefile
10
Makefile
|
@ -44,10 +44,10 @@ lxc.clean:
|
||||||
|
|
||||||
PHONY += search.checker search.checker.%
|
PHONY += search.checker search.checker.%
|
||||||
search.checker: install
|
search.checker: install
|
||||||
$(Q)./manage pyenv.cmd searxng-checker -v
|
$(Q)./manage pyenv.cmd searx-checker -v
|
||||||
|
|
||||||
search.checker.%: install
|
search.checker.%: install
|
||||||
$(Q)./manage pyenv.cmd searxng-checker -v "$(subst _, ,$(patsubst search.checker.%,%,$@))"
|
$(Q)./manage pyenv.cmd searx-checker -v "$(subst _, ,$(patsubst search.checker.%,%,$@))"
|
||||||
|
|
||||||
PHONY += test ci.test test.shell
|
PHONY += test ci.test test.shell
|
||||||
ci.test: test.yamllint test.black test.pyright test.pylint test.unit test.robot test.rst test.pybabel
|
ci.test: test.yamllint test.black test.pyright test.pylint test.unit test.robot test.rst test.pybabel
|
||||||
|
@ -56,7 +56,7 @@ test.shell:
|
||||||
$(Q)shellcheck -x -s dash \
|
$(Q)shellcheck -x -s dash \
|
||||||
dockerfiles/docker-entrypoint.sh
|
dockerfiles/docker-entrypoint.sh
|
||||||
$(Q)shellcheck -x -s bash \
|
$(Q)shellcheck -x -s bash \
|
||||||
utils/brand.sh \
|
utils/brand.env \
|
||||||
$(MTOOLS) \
|
$(MTOOLS) \
|
||||||
utils/lib.sh \
|
utils/lib.sh \
|
||||||
utils/lib_sxng*.sh \
|
utils/lib_sxng*.sh \
|
||||||
|
@ -74,14 +74,16 @@ test.shell:
|
||||||
|
|
||||||
# wrap ./manage script
|
# wrap ./manage script
|
||||||
|
|
||||||
|
MANAGE += buildenv
|
||||||
MANAGE += weblate.translations.commit weblate.push.translations
|
MANAGE += weblate.translations.commit weblate.push.translations
|
||||||
MANAGE += data.all data.traits data.useragents data.locales
|
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
|
||||||
MANAGE += node.env node.env.dev node.clean
|
MANAGE += node.env node.env.dev node.clean
|
||||||
MANAGE += py.build py.clean
|
MANAGE += py.build py.clean
|
||||||
MANAGE += pyenv pyenv.install pyenv.uninstall
|
MANAGE += pyenv pyenv.install pyenv.uninstall
|
||||||
|
MANAGE += pypi.upload pypi.upload.test
|
||||||
MANAGE += format.python
|
MANAGE += format.python
|
||||||
MANAGE += test.yamllint test.pylint test.pyright test.black test.pybabel test.unit test.coverage test.robot test.rst test.clean
|
MANAGE += test.yamllint test.pylint test.pyright test.black test.pybabel test.unit test.coverage test.robot test.rst test.clean
|
||||||
MANAGE += themes.all themes.simple themes.simple.test pygments.less
|
MANAGE += themes.all themes.simple themes.simple.test pygments.less
|
||||||
|
|
|
@ -66,7 +66,7 @@ A user_, admin_ and developer_ handbook is available on the homepage_.
|
||||||
Contact
|
Contact
|
||||||
=======
|
=======
|
||||||
|
|
||||||
Ask questions or chat with the SearXNG community (this not a chatbot) on
|
Ask questions or just chat about SearXNG on
|
||||||
|
|
||||||
IRC
|
IRC
|
||||||
`#searxng on libera.chat <https://web.libera.chat/?channel=#searxng>`_
|
`#searxng on libera.chat <https://web.libera.chat/?channel=#searxng>`_
|
||||||
|
@ -121,9 +121,9 @@ You can contribute from your browser using `GitHub Codespaces`_:
|
||||||
- Click on the ``Codespaces`` tab instead of ``Local``
|
- Click on the ``Codespaces`` tab instead of ``Local``
|
||||||
- Click on ``Create codespace on master``
|
- Click on ``Create codespace on master``
|
||||||
- VSCode is going to start in the browser
|
- VSCode is going to start in the browser
|
||||||
- Wait for ``git pull && make install`` to appear and then disappear
|
- Wait for ``git pull && make install`` to appears and then to disapear
|
||||||
- You have `120 hours per month`_ (see also your `list of existing Codespaces`_)
|
- You have `120 hours per month`_ (see also your `list of existing Codespaces`_)
|
||||||
- You can start SearXNG using ``make run`` in the terminal or by pressing ``Ctrl+Shift+B``
|
- You can start SearXNG using ``make run`` in the terminal or by pressing ``Ctrl+Shift+B``.
|
||||||
|
|
||||||
.. _GitHub Codespaces: https://docs.github.com/en/codespaces/overview
|
.. _GitHub Codespaces: https://docs.github.com/en/codespaces/overview
|
||||||
.. _120 hours per month: https://github.com/settings/billing
|
.. _120 hours per month: https://github.com/settings/billing
|
||||||
|
|
|
@ -175,4 +175,4 @@ unset MORTY_KEY
|
||||||
|
|
||||||
# Start uwsgi
|
# Start uwsgi
|
||||||
printf 'Listen on %s\n' "${BIND_ADDRESS}"
|
printf 'Listen on %s\n' "${BIND_ADDRESS}"
|
||||||
exec uwsgi --master --uid searxng --gid searxng --http-socket "${BIND_ADDRESS}" "${UWSGI_SETTINGS_PATH}"
|
exec su-exec searxng:searxng uwsgi --master --http-socket "${BIND_ADDRESS}" "${UWSGI_SETTINGS_PATH}"
|
||||||
|
|
|
@ -4,12 +4,8 @@ uid = searxng
|
||||||
gid = searxng
|
gid = searxng
|
||||||
|
|
||||||
# Number of workers (usually CPU count)
|
# Number of workers (usually CPU count)
|
||||||
# default value: %k (= number of CPU core, see Dockerfile)
|
workers = %k
|
||||||
workers = $(UWSGI_WORKERS)
|
threads = 4
|
||||||
|
|
||||||
# Number of threads per worker
|
|
||||||
# default value: 4 (see Dockerfile)
|
|
||||||
threads = $(UWSGI_THREADS)
|
|
||||||
|
|
||||||
# The right granted on the created socket
|
# The right granted on the created socket
|
||||||
chmod-socket = 666
|
chmod-socket = 666
|
||||||
|
@ -42,13 +38,9 @@ buffer-size = 8192
|
||||||
# See https://github.com/searx/searx-docker/issues/24
|
# See https://github.com/searx/searx-docker/issues/24
|
||||||
add-header = Connection: close
|
add-header = Connection: close
|
||||||
|
|
||||||
# Follow SIGTERM convention
|
|
||||||
# See https://github.com/searxng/searxng/issues/3427
|
|
||||||
die-on-term
|
|
||||||
|
|
||||||
# uwsgi serves the static files
|
# uwsgi serves the static files
|
||||||
|
# expires set to one year since there are hashes
|
||||||
static-map = /static=/usr/local/searxng/searx/static
|
static-map = /static=/usr/local/searxng/searx/static
|
||||||
# expires set to one day
|
static-expires = /* 31557600
|
||||||
static-expires = /* 86400
|
|
||||||
static-gzip-all = True
|
static-gzip-all = True
|
||||||
offload-threads = %k
|
offload-threads = %k
|
||||||
|
|
|
@ -69,6 +69,10 @@ Sample response
|
||||||
{
|
{
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"name": "HTTPS rewrite"
|
"name": "HTTPS rewrite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enabled": false,
|
||||||
|
"name": "Vim-like hotkeys"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"safe_search": 0
|
"safe_search": 0
|
||||||
|
@ -84,9 +88,9 @@ HTML of the site. URL of the SearXNG instance and values are customizable.
|
||||||
.. code:: html
|
.. code:: html
|
||||||
|
|
||||||
<form method="post" action="https://example.org/">
|
<form method="post" action="https://example.org/">
|
||||||
<!-- search --> <input type="text" name="q">
|
<!-- search --> <input type="text" name="q" />
|
||||||
<!-- categories --> <input type="hidden" name="categories" value="general,social media">
|
<!-- categories --> <input type="hidden" name="categories" value="general,social media" />
|
||||||
<!-- language --> <input type="hidden" name="lang" value="all">
|
<!-- language --> <input type="hidden" name="lang" value="all" />
|
||||||
<!-- locale --> <input type="hidden" name="locale" value="en">
|
<!-- locale --> <input type="hidden" name="locale" value="en" />
|
||||||
<!-- date filter --> <input type="hidden" name="time_range" value="month">
|
<!-- date filter --> <input type="hidden" name="time_range" value="month" />
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -15,8 +15,6 @@ Administrator documentation
|
||||||
installation-apache
|
installation-apache
|
||||||
update-searxng
|
update-searxng
|
||||||
answer-captcha
|
answer-captcha
|
||||||
searx.favicons
|
|
||||||
searx.limiter
|
|
||||||
api
|
api
|
||||||
architecture
|
architecture
|
||||||
plugins
|
plugins
|
||||||
|
|
|
@ -92,9 +92,6 @@ instance using `docker run <https://docs.docker.com/engine/reference/run/>`_:
|
||||||
searxng/searxng
|
searxng/searxng
|
||||||
2f998.... # container's ID
|
2f998.... # container's ID
|
||||||
|
|
||||||
The environment variables UWSGI_WORKERS and UWSGI_THREADS overwrite the default
|
|
||||||
number of UWSGI processes and UWSGI threads specified in `/etc/searxng/uwsgi.ini`.
|
|
||||||
|
|
||||||
Open your WEB browser and visit the URL:
|
Open your WEB browser and visit the URL:
|
||||||
|
|
||||||
.. code:: sh
|
.. code:: sh
|
||||||
|
|
|
@ -96,7 +96,7 @@ Modify the ``/etc/searxng/settings.yml`` to your needs:
|
||||||
|
|
||||||
.. literalinclude:: ../../utils/templates/etc/searxng/settings.yml
|
.. literalinclude:: ../../utils/templates/etc/searxng/settings.yml
|
||||||
:language: yaml
|
:language: yaml
|
||||||
:end-before: # hostnames:
|
:end-before: # hostname_replace:
|
||||||
|
|
||||||
To see the entire file jump to :origin:`utils/templates/etc/searxng/settings.yml`
|
To see the entire file jump to :origin:`utils/templates/etc/searxng/settings.yml`
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ Modify the ``/etc/searxng/settings.yml`` to your needs:
|
||||||
|
|
||||||
.. literalinclude:: ../../searx/settings.yml
|
.. literalinclude:: ../../searx/settings.yml
|
||||||
:language: yaml
|
:language: yaml
|
||||||
:end-before: # hostnames:
|
:end-before: # hostname_replace:
|
||||||
|
|
||||||
To see the entire file jump to :origin:`searx/settings.yml`
|
To see the entire file jump to :origin:`searx/settings.yml`
|
||||||
|
|
||||||
|
|
|
@ -1,251 +0,0 @@
|
||||||
.. _favicons:
|
|
||||||
|
|
||||||
========
|
|
||||||
Favicons
|
|
||||||
========
|
|
||||||
|
|
||||||
.. sidebar:: warning
|
|
||||||
|
|
||||||
Don't activate the favicons before reading the documentation.
|
|
||||||
|
|
||||||
.. contents::
|
|
||||||
:depth: 2
|
|
||||||
:local:
|
|
||||||
:backlinks: entry
|
|
||||||
|
|
||||||
Activating the favicons in SearXNG is very easy, but this **generates a
|
|
||||||
significantly higher load** in the client/server communication and increases
|
|
||||||
resources needed on the server.
|
|
||||||
|
|
||||||
To mitigate these disadvantages, various methods have been implemented,
|
|
||||||
including a *cache*. The cache must be parameterized according to your own
|
|
||||||
requirements and maintained regularly.
|
|
||||||
|
|
||||||
To activate favicons in SearXNG's result list, set a default
|
|
||||||
``favicon_resolver`` in the :ref:`search <settings search>` settings:
|
|
||||||
|
|
||||||
.. code:: yaml
|
|
||||||
|
|
||||||
search:
|
|
||||||
favicon_resolver: "duckduckgo"
|
|
||||||
|
|
||||||
By default and without any extensions, SearXNG serves these resolvers:
|
|
||||||
|
|
||||||
- ``duckduckgo``
|
|
||||||
- ``allesedv``
|
|
||||||
- ``google``
|
|
||||||
- ``yandex``
|
|
||||||
|
|
||||||
With the above setting favicons are displayed, the user has the option to
|
|
||||||
deactivate this feature in his settings. If the user is to have the option of
|
|
||||||
selecting from several *resolvers*, a further setting is required / but this
|
|
||||||
setting will be discussed :ref:`later <register resolvers>` in this article,
|
|
||||||
first we have to setup the favicons cache.
|
|
||||||
|
|
||||||
Infrastructure
|
|
||||||
==============
|
|
||||||
|
|
||||||
The infrastructure for providing the favicons essentially consists of three
|
|
||||||
parts:
|
|
||||||
|
|
||||||
- :py:obj:`Favicons-Proxy <.favicons.proxy>` (aka *proxy*)
|
|
||||||
- :py:obj:`Favicons-Resolvers <.favicons.resolvers>` (aka *resolver*)
|
|
||||||
- :py:obj:`Favicons-Cache <.favicons.cache>` (aka *cache*)
|
|
||||||
|
|
||||||
To protect the privacy of users, the favicons are provided via a *proxy*. This
|
|
||||||
*proxy* is automatically activated with the above activation of a *resolver*.
|
|
||||||
Additional requests are required to provide the favicons: firstly, the *proxy*
|
|
||||||
must process the incoming requests and secondly, the *resolver* must make
|
|
||||||
outgoing requests to obtain the favicons from external sources.
|
|
||||||
|
|
||||||
A *cache* has been developed to massively reduce both, incoming and outgoing
|
|
||||||
requests. This *cache* is also activated automatically with the above
|
|
||||||
activation of a *resolver*. In its defaults, however, the *cache* is minimal
|
|
||||||
and not well suitable for a production environment!
|
|
||||||
|
|
||||||
.. _favicon cache setup:
|
|
||||||
|
|
||||||
Setting up the cache
|
|
||||||
====================
|
|
||||||
|
|
||||||
To parameterize the *cache* and more settings of the favicons infrastructure, a
|
|
||||||
TOML_ configuration is created in the file ``/etc/searxng/favicons.toml``.
|
|
||||||
|
|
||||||
.. code:: toml
|
|
||||||
|
|
||||||
[favicons]
|
|
||||||
|
|
||||||
cfg_schema = 1 # config's schema version no.
|
|
||||||
|
|
||||||
[favicons.cache]
|
|
||||||
|
|
||||||
db_url = "/var/cache/searxng/faviconcache.db" # default: "/tmp/faviconcache.db"
|
|
||||||
LIMIT_TOTAL_BYTES = 2147483648 # 2 GB / default: 50 MB
|
|
||||||
# HOLD_TIME = 5184000 # 60 days / default: 30 days
|
|
||||||
# BLOB_MAX_BYTES = 40960 # 40 KB / default 20 KB
|
|
||||||
# MAINTENANCE_MODE = "off" # default: "auto"
|
|
||||||
# MAINTENANCE_PERIOD = 600 # 10min / default: 1h
|
|
||||||
|
|
||||||
:py:obj:`cfg_schema <.FaviconConfig.cfg_schema>`:
|
|
||||||
Is required to trigger any processes required for future upgrades / don't
|
|
||||||
change it.
|
|
||||||
|
|
||||||
:py:obj:`cache.db_url <.FaviconCacheConfig.db_url>`:
|
|
||||||
The path to the (SQLite_) database file. The default path is in the `/tmp`_
|
|
||||||
folder, which is deleted on every reboot and is therefore unsuitable for a
|
|
||||||
production environment. The FHS_ provides the folder for the
|
|
||||||
application cache
|
|
||||||
|
|
||||||
The FHS_ provides the folder `/var/cache`_ for the cache of applications, so a
|
|
||||||
suitable storage location of SearXNG's caches is folder ``/var/cache/searxng``.
|
|
||||||
In container systems, a volume should be mounted for this folder and in a
|
|
||||||
standard installation (compare :ref:`create searxng user`), the folder must be
|
|
||||||
created and the user under which the SearXNG process is running must be given
|
|
||||||
write permission to this folder.
|
|
||||||
|
|
||||||
.. code:: bash
|
|
||||||
|
|
||||||
$ sudo mkdir /var/cache/searxng
|
|
||||||
$ sudo chown root:searxng /var/cache/searxng/
|
|
||||||
$ sudo chmod g+w /var/cache/searxng/
|
|
||||||
|
|
||||||
:py:obj:`cache.LIMIT_TOTAL_BYTES <.FaviconCacheConfig.LIMIT_TOTAL_BYTES>`:
|
|
||||||
Maximum of bytes stored in the cache of all blobs. The limit is only reached
|
|
||||||
at each maintenance interval after which the oldest BLOBs are deleted; the
|
|
||||||
limit is exceeded during the maintenance period.
|
|
||||||
|
|
||||||
.. attention::
|
|
||||||
|
|
||||||
If the maintenance period is too long or maintenance is switched
|
|
||||||
off completely, the cache grows uncontrollably.
|
|
||||||
|
|
||||||
SearXNG hosters can change other parameters of the cache as required:
|
|
||||||
|
|
||||||
- :py:obj:`cache.HOLD_TIME <.FaviconCacheConfig.HOLD_TIME>`
|
|
||||||
- :py:obj:`cache.BLOB_MAX_BYTES <.FaviconCacheConfig.BLOB_MAX_BYTES>`
|
|
||||||
|
|
||||||
|
|
||||||
Maintenance of the cache
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
Regular maintenance of the cache is required! By default, regular maintenance
|
|
||||||
is triggered automatically as part of the client requests:
|
|
||||||
|
|
||||||
- :py:obj:`cache.MAINTENANCE_MODE <.FaviconCacheConfig.MAINTENANCE_MODE>` (default ``auto``)
|
|
||||||
- :py:obj:`cache.MAINTENANCE_PERIOD <.FaviconCacheConfig.MAINTENANCE_PERIOD>` (default ``6000`` / 1h)
|
|
||||||
|
|
||||||
As an alternative to maintenance as part of the client request process, it is
|
|
||||||
also possible to carry out maintenance using an external process. For example,
|
|
||||||
by creating a :man:`crontab` entry for maintenance:
|
|
||||||
|
|
||||||
.. code:: bash
|
|
||||||
|
|
||||||
$ python -m searx.favicons cache maintenance
|
|
||||||
|
|
||||||
The following command can be used to display the state of the cache:
|
|
||||||
|
|
||||||
.. code:: bash
|
|
||||||
|
|
||||||
$ python -m searx.favicons cache state
|
|
||||||
|
|
||||||
|
|
||||||
.. _favicon proxy setup:
|
|
||||||
|
|
||||||
Proxy configuration
|
|
||||||
===================
|
|
||||||
|
|
||||||
Most of the options of the :py:obj:`Favicons-Proxy <.favicons.proxy>` are
|
|
||||||
already set sensibly with settings from the :ref:`settings.yml <searxng
|
|
||||||
settings.yml>` and should not normally be adjusted.
|
|
||||||
|
|
||||||
.. code:: toml
|
|
||||||
|
|
||||||
[favicons.proxy]
|
|
||||||
|
|
||||||
max_age = 5184000 # 60 days / default: 7 days (604800 sec)
|
|
||||||
|
|
||||||
|
|
||||||
:py:obj:`max_age <.FaviconProxyConfig.max_age>`:
|
|
||||||
The `HTTP Cache-Control max-age`_ response directive indicates that the
|
|
||||||
response remains fresh until N seconds after the response is generated. This
|
|
||||||
setting therefore determines how long a favicon remains in the client's cache.
|
|
||||||
As a rule, in the favicons infrastructure of SearXNG's this setting only
|
|
||||||
affects favicons whose byte size exceeds :ref:`BLOB_MAX_BYTES <favicon cache
|
|
||||||
setup>` (the other favicons that are already in the cache are embedded as
|
|
||||||
`data URL`_ in the :py:obj:`generated HTML <.favicons.proxy.favicon_url>`,
|
|
||||||
which can greatly reduce the number of additional requests).
|
|
||||||
|
|
||||||
.. _register resolvers:
|
|
||||||
|
|
||||||
Register resolvers
|
|
||||||
------------------
|
|
||||||
|
|
||||||
A :py:obj:`resolver <.favicon.resolvers>` is a function that obtains the favicon
|
|
||||||
from an external source. The resolver functions available to the user are
|
|
||||||
registered with their fully qualified name (FQN_) in a ``resolver_map``.
|
|
||||||
|
|
||||||
If no ``resolver_map`` is defined in the ``favicon.toml``, the favicon
|
|
||||||
infrastructure of SearXNG generates this ``resolver_map`` automatically
|
|
||||||
depending on the ``settings.yml``. SearXNG would automatically generate the
|
|
||||||
following TOML configuration from the following YAML configuration:
|
|
||||||
|
|
||||||
.. code:: yaml
|
|
||||||
|
|
||||||
search:
|
|
||||||
favicon_resolver: "duckduckgo"
|
|
||||||
|
|
||||||
.. code:: toml
|
|
||||||
|
|
||||||
[favicons.proxy.resolver_map]
|
|
||||||
|
|
||||||
"duckduckgo" = "searx.favicons.resolvers.duckduckgo"
|
|
||||||
|
|
||||||
If this automatism is not desired, then (and only then) a separate
|
|
||||||
``resolver_map`` must be created. For example, to give the user two resolvers to
|
|
||||||
choose from, the following configuration could be used:
|
|
||||||
|
|
||||||
.. code:: toml
|
|
||||||
|
|
||||||
[favicons.proxy.resolver_map]
|
|
||||||
|
|
||||||
"duckduckgo" = "searx.favicons.resolvers.duckduckgo"
|
|
||||||
"allesedv" = "searx.favicons.resolvers.allesedv"
|
|
||||||
# "google" = "searx.favicons.resolvers.google"
|
|
||||||
# "yandex" = "searx.favicons.resolvers.yandex"
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
With each resolver, the resource requirement increases significantly.
|
|
||||||
|
|
||||||
The number of resolvers increases:
|
|
||||||
|
|
||||||
- the number of incoming/outgoing requests and
|
|
||||||
- the number of favicons to be stored in the cache.
|
|
||||||
|
|
||||||
In the following we list the resolvers available in the core of SearXNG, but via
|
|
||||||
the FQN_ it is also possible to implement your own resolvers and integrate them
|
|
||||||
into the *proxy*:
|
|
||||||
|
|
||||||
- :py:obj:`searx.favicons.resolvers.duckduckgo`
|
|
||||||
- :py:obj:`searx.favicons.resolvers.allesedv`
|
|
||||||
- :py:obj:`searx.favicons.resolvers.google`
|
|
||||||
- :py:obj:`searx.favicons.resolvers.yandex`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. _SQLite:
|
|
||||||
https://www.sqlite.org/
|
|
||||||
.. _FHS:
|
|
||||||
https://refspecs.linuxfoundation.org/FHS_3.0/fhs/index.html
|
|
||||||
.. _`/var/cache`:
|
|
||||||
https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch05s05.html
|
|
||||||
.. _`/tmp`:
|
|
||||||
https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch03s18.html
|
|
||||||
.. _TOML:
|
|
||||||
https://toml.io/en/
|
|
||||||
.. _HTTP Cache-Control max-age:
|
|
||||||
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#response_directives
|
|
||||||
.. _data URL:
|
|
||||||
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs
|
|
||||||
.. _FQN: https://en.wikipedia.org/wiki/Fully_qualified_name
|
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
.. _limiter:
|
|
||||||
|
|
||||||
=======
|
|
||||||
Limiter
|
|
||||||
=======
|
|
||||||
|
|
||||||
.. sidebar:: info
|
|
||||||
|
|
||||||
The limiter requires a :ref:`Redis <settings redis>` database.
|
|
||||||
|
|
||||||
.. contents::
|
|
||||||
:depth: 2
|
|
||||||
:local:
|
|
||||||
:backlinks: entry
|
|
||||||
|
|
||||||
.. automodule:: searx.limiter
|
|
||||||
:members:
|
|
|
@ -1,5 +1,3 @@
|
||||||
.. _searxng settings.yml:
|
|
||||||
|
|
||||||
========
|
========
|
||||||
Settings
|
Settings
|
||||||
========
|
========
|
||||||
|
|
|
@ -204,7 +204,7 @@ Example configuration to restrict access to the Arch Linux Wiki engine:
|
||||||
tokens: [ 'my-secret-token' ]
|
tokens: [ 'my-secret-token' ]
|
||||||
|
|
||||||
Unless a user has configured the right token, the engine is going to be hidden
|
Unless a user has configured the right token, the engine is going to be hidden
|
||||||
from them. It is not going to be included in the list of engines on the
|
from him/her. It is not going to be included in the list of engines on the
|
||||||
Preferences page and in the output of `/config` REST API call.
|
Preferences page and in the output of `/config` REST API call.
|
||||||
|
|
||||||
Tokens can be added to one's configuration on the Preferences page under "Engine
|
Tokens can be added to one's configuration on the Preferences page under "Engine
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
search:
|
search:
|
||||||
safe_search: 0
|
safe_search: 0
|
||||||
autocomplete: ""
|
autocomplete: ""
|
||||||
favicon_resolver: ""
|
|
||||||
default_lang: ""
|
default_lang: ""
|
||||||
ban_time_on_fail: 5
|
ban_time_on_fail: 5
|
||||||
max_ban_time_on_fail: 120
|
max_ban_time_on_fail: 120
|
||||||
|
@ -42,11 +41,6 @@
|
||||||
- ``qwant``
|
- ``qwant``
|
||||||
- ``wikipedia``
|
- ``wikipedia``
|
||||||
|
|
||||||
``favicon_resolver``:
|
|
||||||
To activate favicons in SearXNG's result list select a default
|
|
||||||
favicon-resolver, leave blank to turn off the feature. Don't activate the
|
|
||||||
favicons before reading the :ref:`Favicons documentation <favicons>`.
|
|
||||||
|
|
||||||
``default_lang``:
|
``default_lang``:
|
||||||
Default search language - leave blank to detect from browser information or
|
Default search language - leave blank to detect from browser information or
|
||||||
use codes from :origin:`searx/languages.py`.
|
use codes from :origin:`searx/languages.py`.
|
||||||
|
|
|
@ -12,42 +12,39 @@
|
||||||
bind_address: "127.0.0.1"
|
bind_address: "127.0.0.1"
|
||||||
secret_key: "ultrasecretkey" # change this!
|
secret_key: "ultrasecretkey" # change this!
|
||||||
limiter: false
|
limiter: false
|
||||||
public_instance: false
|
|
||||||
image_proxy: false
|
image_proxy: false
|
||||||
default_http_headers:
|
default_http_headers:
|
||||||
X-Content-Type-Options : nosniff
|
X-Content-Type-Options : nosniff
|
||||||
|
X-XSS-Protection : 1; mode=block
|
||||||
X-Download-Options : noopen
|
X-Download-Options : noopen
|
||||||
X-Robots-Tag : noindex, nofollow
|
X-Robots-Tag : noindex, nofollow
|
||||||
Referrer-Policy : no-referrer
|
Referrer-Policy : no-referrer
|
||||||
|
|
||||||
``base_url`` : ``$SEARXNG_URL``
|
|
||||||
The base URL where SearXNG is deployed. Used to create correct inbound links.
|
|
||||||
|
|
||||||
``port`` & ``bind_address``: ``$SEARXNG_PORT`` & ``$SEARXNG_BIND_ADDRESS``
|
``base_url`` : ``$SEARXNG_URL`` :ref:`buildenv <make buildenv>`
|
||||||
|
The base URL where SearXNG is deployed. Used to create correct inbound links.
|
||||||
|
If you change the value, don't forget to rebuild instance's environment
|
||||||
|
(:ref:`utils/brand.env <make buildenv>`)
|
||||||
|
|
||||||
|
``port`` & ``bind_address``: ``$SEARXNG_PORT`` & ``$SEARXNG_BIND_ADDRESS`` :ref:`buildenv <make buildenv>`
|
||||||
Port number and *bind address* of the SearXNG web application if you run it
|
Port number and *bind address* of the SearXNG web application if you run it
|
||||||
directly using ``python searx/webapp.py``. Doesn't apply to a SearXNG
|
directly using ``python searx/webapp.py``. Doesn't apply to a SearXNG
|
||||||
services running behind a proxy and using socket communications.
|
services running behind a proxy and using socket communications. If you
|
||||||
|
change the value, don't forget to rebuild instance's environment
|
||||||
|
(:ref:`utils/brand.env <make buildenv>`)
|
||||||
|
|
||||||
``secret_key`` : ``$SEARXNG_SECRET``
|
``secret_key`` : ``$SEARXNG_SECRET``
|
||||||
Used for cryptography purpose.
|
Used for cryptography purpose.
|
||||||
|
|
||||||
``limiter`` : ``$SEARXNG_LIMITER``
|
.. _limiter:
|
||||||
|
|
||||||
|
``limiter`` :
|
||||||
Rate limit the number of request on the instance, block some bots. The
|
Rate limit the number of request on the instance, block some bots. The
|
||||||
:ref:`limiter` requires a :ref:`settings redis` database.
|
:ref:`limiter src` requires a :ref:`settings redis` database.
|
||||||
|
|
||||||
.. _public_instance:
|
|
||||||
|
|
||||||
``public_instance`` : ``$SEARXNG_PUBLIC_INSTANCE``
|
|
||||||
|
|
||||||
Setting that allows to enable features specifically for public instances (not
|
|
||||||
needed for local usage). By set to ``true`` the following features are
|
|
||||||
activated:
|
|
||||||
|
|
||||||
- :py:obj:`searx.botdetection.link_token` in the :ref:`limiter`
|
|
||||||
|
|
||||||
.. _image_proxy:
|
.. _image_proxy:
|
||||||
|
|
||||||
``image_proxy`` : ``$SEARXNG_IMAGE_PROXY``
|
``image_proxy`` :
|
||||||
Allow your instance of SearXNG of being able to proxy images. Uses memory space.
|
Allow your instance of SearXNG of being able to proxy images. Uses memory space.
|
||||||
|
|
||||||
.. _HTTP headers: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers
|
.. _HTTP headers: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers
|
||||||
|
|
|
@ -20,11 +20,10 @@
|
||||||
theme_args:
|
theme_args:
|
||||||
simple_style: auto
|
simple_style: auto
|
||||||
search_on_category_select: true
|
search_on_category_select: true
|
||||||
hotkeys: default
|
|
||||||
|
|
||||||
.. _static_use_hash:
|
.. _static_use_hash:
|
||||||
|
|
||||||
``static_use_hash`` : ``$SEARXNG_STATIC_USE_HASH``
|
``static_use_hash`` :
|
||||||
Enables `cache busting`_ of static files.
|
Enables `cache busting`_ of static files.
|
||||||
|
|
||||||
``default_locale`` :
|
``default_locale`` :
|
||||||
|
@ -58,13 +57,10 @@
|
||||||
Name of the theme you want to use by default on your SearXNG instance.
|
Name of the theme you want to use by default on your SearXNG instance.
|
||||||
|
|
||||||
``theme_args.simple_style``:
|
``theme_args.simple_style``:
|
||||||
Style of simple theme: ``auto``, ``light``, ``dark``, ``black``
|
Style of simple theme: ``auto``, ``light``, ``dark``
|
||||||
|
|
||||||
``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.
|
||||||
|
|
||||||
``search_on_category_select``:
|
``search_on_category_select``:
|
||||||
Perform search immediately if a category selected. Disable to select multiple categories.
|
Perform search immediately if a category selected. Disable to select multiple categories.
|
||||||
|
|
||||||
``hotkeys``:
|
|
||||||
Hotkeys to use in the search interface: ``default``, ``vim`` (Vim-like).
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ ${fedora_build}
|
||||||
|
|
||||||
(${SERVICE_USER})$ command -v python && python --version
|
(${SERVICE_USER})$ command -v python && python --version
|
||||||
$SEARXNG_PYENV/bin/python
|
$SEARXNG_PYENV/bin/python
|
||||||
Python 3.11.10
|
Python 3.8.1
|
||||||
|
|
||||||
# update pip's boilerplate ..
|
# update pip's boilerplate ..
|
||||||
pip install -U pip
|
pip install -U pip
|
||||||
|
@ -123,7 +123,7 @@ ${fedora_build}
|
||||||
|
|
||||||
# jump to SearXNG's working tree and install SearXNG into virtualenv
|
# jump to SearXNG's working tree and install SearXNG into virtualenv
|
||||||
(${SERVICE_USER})$ cd \"$SEARXNG_SRC\"
|
(${SERVICE_USER})$ cd \"$SEARXNG_SRC\"
|
||||||
(${SERVICE_USER})$ pip install --use-pep517 --no-build-isolation -e .
|
(${SERVICE_USER})$ pip install -e .
|
||||||
|
|
||||||
|
|
||||||
.. END manage.sh update_packages
|
.. END manage.sh update_packages
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
import sys, os
|
import sys, os
|
||||||
from pathlib import Path
|
|
||||||
from pallets_sphinx_themes import ProjectLink
|
from pallets_sphinx_themes import ProjectLink
|
||||||
|
|
||||||
from searx import get_setting
|
from searx import get_setting
|
||||||
|
@ -13,6 +13,7 @@ project = 'SearXNG'
|
||||||
copyright = 'SearXNG team'
|
copyright = 'SearXNG team'
|
||||||
author = 'SearXNG team'
|
author = 'SearXNG team'
|
||||||
release, version = VERSION_STRING, VERSION_STRING
|
release, version = VERSION_STRING, VERSION_STRING
|
||||||
|
|
||||||
SEARXNG_URL = get_setting('server.base_url') or 'https://example.org/searxng'
|
SEARXNG_URL = get_setting('server.base_url') or 'https://example.org/searxng'
|
||||||
ISSUE_URL = get_setting('brand.issue_url')
|
ISSUE_URL = get_setting('brand.issue_url')
|
||||||
DOCS_URL = get_setting('brand.docs_url')
|
DOCS_URL = get_setting('brand.docs_url')
|
||||||
|
@ -21,9 +22,6 @@ PRIVACYPOLICY_URL = get_setting('general.privacypolicy_url')
|
||||||
CONTACT_URL = get_setting('general.contact_url')
|
CONTACT_URL = get_setting('general.contact_url')
|
||||||
WIKI_URL = get_setting('brand.wiki_url')
|
WIKI_URL = get_setting('brand.wiki_url')
|
||||||
|
|
||||||
SOURCEDIR = Path(__file__).parent.parent / "searx"
|
|
||||||
os.environ['SOURCEDIR'] = str(SOURCEDIR)
|
|
||||||
|
|
||||||
# hint: sphinx.ext.viewcode won't highlight when 'highlight_language' [1] is set
|
# hint: sphinx.ext.viewcode won't highlight when 'highlight_language' [1] is set
|
||||||
# to string 'none' [2]
|
# to string 'none' [2]
|
||||||
#
|
#
|
||||||
|
@ -127,7 +125,6 @@ extensions = [
|
||||||
"sphinx_tabs.tabs", # https://github.com/djungelorm/sphinx-tabs
|
"sphinx_tabs.tabs", # https://github.com/djungelorm/sphinx-tabs
|
||||||
'myst_parser', # https://www.sphinx-doc.org/en/master/usage/markdown.html
|
'myst_parser', # https://www.sphinx-doc.org/en/master/usage/markdown.html
|
||||||
'notfound.extension', # https://github.com/readthedocs/sphinx-notfound-page
|
'notfound.extension', # https://github.com/readthedocs/sphinx-notfound-page
|
||||||
'sphinxcontrib.autodoc_pydantic', # https://github.com/mansenfranzen/autodoc_pydantic
|
|
||||||
]
|
]
|
||||||
|
|
||||||
autodoc_default_options = {
|
autodoc_default_options = {
|
||||||
|
|
|
@ -271,54 +271,22 @@ type.
|
||||||
``images``
|
``images``
|
||||||
----------
|
----------
|
||||||
|
|
||||||
.. list-table:: Parameter of the **images** media type
|
.. table:: Parameter of the **images** media type:
|
||||||
:header-rows: 2
|
|
||||||
:width: 100%
|
:width: 100%
|
||||||
|
|
||||||
* - result-parameter
|
========================= =====================================================
|
||||||
- Python type
|
result-parameter information
|
||||||
- information
|
------------------------- -----------------------------------------------------
|
||||||
|
template is set to ``images.html``
|
||||||
* - template
|
========================= =====================================================
|
||||||
- :py:class:`str`
|
url string, url to the result site
|
||||||
- is set to ``images.html``
|
title string, title of the result *(partly implemented)*
|
||||||
|
content *(partly implemented)*
|
||||||
* - url
|
publishedDate :py:class:`datetime.datetime`,
|
||||||
- :py:class:`str`
|
time of publish *(partly implemented)*
|
||||||
- url to the result site
|
img\_src string, url to the result image
|
||||||
|
thumbnail\_src string, url to a small-preview image
|
||||||
* - title
|
========================= =====================================================
|
||||||
- :py:class:`str`
|
|
||||||
- title of the result
|
|
||||||
|
|
||||||
* - content
|
|
||||||
- :py:class:`str`
|
|
||||||
- description of the image
|
|
||||||
|
|
||||||
* - publishedDate
|
|
||||||
- :py:class:`datetime <datetime.datetime>`
|
|
||||||
- time of publish
|
|
||||||
|
|
||||||
* - img_src
|
|
||||||
- :py:class:`str`
|
|
||||||
- url to the result image
|
|
||||||
|
|
||||||
* - thumbnail_src
|
|
||||||
- :py:class:`str`
|
|
||||||
- url to a small-preview image
|
|
||||||
|
|
||||||
* - resolution
|
|
||||||
- :py:class:`str`
|
|
||||||
- the resolution of the image (e.g. ``1920 x 1080`` pixel)
|
|
||||||
|
|
||||||
* - img_format
|
|
||||||
- :py:class:`str`
|
|
||||||
- the format of the image (e.g. ``png``)
|
|
||||||
|
|
||||||
* - filesize
|
|
||||||
- :py:class:`str`
|
|
||||||
- size of bytes in :py:obj:`human readable <searx.humanize_bytes>` notation
|
|
||||||
(e.g. ``MB`` for 1024 \* 1024 Bytes filesize).
|
|
||||||
|
|
||||||
|
|
||||||
.. _template videos:
|
.. _template videos:
|
||||||
|
@ -339,8 +307,6 @@ type.
|
||||||
content *(not implemented yet)*
|
content *(not implemented yet)*
|
||||||
publishedDate :py:class:`datetime.datetime`, time of publish
|
publishedDate :py:class:`datetime.datetime`, time of publish
|
||||||
thumbnail string, url to a small-preview image
|
thumbnail string, url to a small-preview image
|
||||||
length :py:class:`datetime.timedelta`, duration of result
|
|
||||||
views string, view count in humanized number format
|
|
||||||
========================= =====================================================
|
========================= =====================================================
|
||||||
|
|
||||||
|
|
||||||
|
@ -500,72 +466,3 @@ type.
|
||||||
- :py:class:`str`
|
- :py:class:`str`
|
||||||
- URL to full article, HTML version
|
- URL to full article, HTML version
|
||||||
|
|
||||||
|
|
||||||
.. _template packages:
|
|
||||||
|
|
||||||
``packages``
|
|
||||||
------------
|
|
||||||
|
|
||||||
.. list-table:: Parameter of the **packages** media type
|
|
||||||
:header-rows: 2
|
|
||||||
:width: 100%
|
|
||||||
|
|
||||||
* - result-parameter
|
|
||||||
- Python type
|
|
||||||
- information
|
|
||||||
|
|
||||||
* - template
|
|
||||||
- :py:class:`str`
|
|
||||||
- is set to ``packages.html``
|
|
||||||
|
|
||||||
* - title
|
|
||||||
- :py:class:`str`
|
|
||||||
- title of the result
|
|
||||||
|
|
||||||
* - content
|
|
||||||
- :py:class:`str`
|
|
||||||
- abstract
|
|
||||||
|
|
||||||
* - package_name
|
|
||||||
- :py:class:`str`
|
|
||||||
- the name of the package
|
|
||||||
|
|
||||||
* - version
|
|
||||||
- :py:class:`str`
|
|
||||||
- the current version of the package
|
|
||||||
|
|
||||||
* - maintainer
|
|
||||||
- :py:class:`str`
|
|
||||||
- the maintainer or author of the project
|
|
||||||
|
|
||||||
* - publishedDate
|
|
||||||
- :py:class:`datetime <datetime.datetime>`
|
|
||||||
- date of latest update or release
|
|
||||||
|
|
||||||
* - tags
|
|
||||||
- :py:class:`List <list>`\ [\ :py:class:`str`\ ]
|
|
||||||
- free tag list
|
|
||||||
|
|
||||||
* - popularity
|
|
||||||
- :py:class:`str`
|
|
||||||
- the popularity of the package, e.g. rating or download count
|
|
||||||
|
|
||||||
* - license_name
|
|
||||||
- :py:class:`str`
|
|
||||||
- the name of the license
|
|
||||||
|
|
||||||
* - license_url
|
|
||||||
- :py:class:`str`
|
|
||||||
- the web location of a license copy
|
|
||||||
|
|
||||||
* - homepage
|
|
||||||
- :py:class:`str`
|
|
||||||
- the url of the project's homepage
|
|
||||||
|
|
||||||
* - source_code_url
|
|
||||||
- :py:class:`str`
|
|
||||||
- the location of the project's source code
|
|
||||||
|
|
||||||
* - links
|
|
||||||
- :py:class:`dict`
|
|
||||||
- additional links in the form of ``{'link_name': 'http://example.com'}``
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ Relational Database Management System (RDBMS) are supported:
|
||||||
|
|
||||||
- :ref:`engine sqlite`
|
- :ref:`engine sqlite`
|
||||||
- :ref:`engine postgresql`
|
- :ref:`engine postgresql`
|
||||||
- :ref:`engine mysql_server` & :ref:`engine mariadb_server`
|
- :ref:`engine mysql_server`
|
||||||
|
|
||||||
All of the engines above are just commented out in the :origin:`settings.yml
|
All of the engines above are just commented out in the :origin:`settings.yml
|
||||||
<searx/settings.yml>`, as you have to set the required attributes for the
|
<searx/settings.yml>`, as you have to set the required attributes for the
|
||||||
|
@ -119,16 +119,3 @@ MySQL
|
||||||
.. automodule:: searx.engines.mysql_server
|
.. automodule:: searx.engines.mysql_server
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
.. _engine mariadb_server:
|
|
||||||
|
|
||||||
MariaDB
|
|
||||||
--------
|
|
||||||
|
|
||||||
.. sidebar:: info
|
|
||||||
|
|
||||||
- :origin:`mariadb_server.py <searx/engines/mariadb_server.py>`
|
|
||||||
- ``pip install`` :pypi:`mariadb <mariadb>`
|
|
||||||
|
|
||||||
|
|
||||||
.. automodule:: searx.engines.mariadb_server
|
|
||||||
:members:
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
.. _alpinelinux engine:
|
|
||||||
|
|
||||||
=====================
|
|
||||||
Alpine Linux Packages
|
|
||||||
=====================
|
|
||||||
|
|
||||||
.. contents::
|
|
||||||
:depth: 2
|
|
||||||
:local:
|
|
||||||
:backlinks: entry
|
|
||||||
|
|
||||||
.. automodule:: searx.engines.alpinelinux
|
|
||||||
:members:
|
|
|
@ -1,13 +0,0 @@
|
||||||
.. _bpb engine:
|
|
||||||
|
|
||||||
===
|
|
||||||
Bpb
|
|
||||||
===
|
|
||||||
|
|
||||||
.. contents:: Contents
|
|
||||||
:depth: 2
|
|
||||||
:local:
|
|
||||||
:backlinks: entry
|
|
||||||
|
|
||||||
.. automodule:: searx.engines.bpb
|
|
||||||
:members:
|
|
|
@ -1,8 +0,0 @@
|
||||||
.. _discourse engine:
|
|
||||||
|
|
||||||
================
|
|
||||||
Discourse Forums
|
|
||||||
================
|
|
||||||
|
|
||||||
.. automodule:: searx.engines.discourse
|
|
||||||
:members:
|
|
|
@ -12,7 +12,7 @@ DuckDuckGo Engines
|
||||||
.. automodule:: searx.engines.duckduckgo
|
.. automodule:: searx.engines.duckduckgo
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
.. automodule:: searx.engines.duckduckgo_extra
|
.. automodule:: searx.engines.duckduckgo_images
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
.. automodule:: searx.engines.duckduckgo_definitions
|
.. automodule:: searx.engines.duckduckgo_definitions
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
.. _gitea geizhals:
|
|
||||||
|
|
||||||
========
|
|
||||||
Geizhals
|
|
||||||
========
|
|
||||||
|
|
||||||
.. automodule:: searx.engines.geizhals
|
|
||||||
:members:
|
|
|
@ -1,8 +0,0 @@
|
||||||
.. _gitea engine:
|
|
||||||
|
|
||||||
=====
|
|
||||||
Gitea
|
|
||||||
=====
|
|
||||||
|
|
||||||
.. automodule:: searx.engines.gitea
|
|
||||||
:members:
|
|
|
@ -1,8 +0,0 @@
|
||||||
.. _gitlab engine:
|
|
||||||
|
|
||||||
======
|
|
||||||
GitLab
|
|
||||||
======
|
|
||||||
|
|
||||||
.. automodule:: searx.engines.gitlab
|
|
||||||
:members:
|
|
|
@ -1,13 +0,0 @@
|
||||||
.. _mastodon engine:
|
|
||||||
|
|
||||||
========
|
|
||||||
Mastodon
|
|
||||||
========
|
|
||||||
|
|
||||||
.. contents:: Contents
|
|
||||||
:depth: 2
|
|
||||||
:local:
|
|
||||||
:backlinks: entry
|
|
||||||
|
|
||||||
.. automodule:: searx.engines.mastodon
|
|
||||||
:members:
|
|
|
@ -1,13 +0,0 @@
|
||||||
.. _mrs engine:
|
|
||||||
|
|
||||||
=========================
|
|
||||||
Matrix Rooms Search (MRS)
|
|
||||||
=========================
|
|
||||||
|
|
||||||
.. contents:: Contents
|
|
||||||
:depth: 2
|
|
||||||
:local:
|
|
||||||
:backlinks: entry
|
|
||||||
|
|
||||||
.. automodule:: searx.engines.mrs
|
|
||||||
:members:
|
|
|
@ -1,13 +0,0 @@
|
||||||
.. _voidlinux mullvad_leta:
|
|
||||||
|
|
||||||
============
|
|
||||||
Mullvad-Leta
|
|
||||||
============
|
|
||||||
|
|
||||||
.. contents:: Contents
|
|
||||||
:depth: 2
|
|
||||||
:local:
|
|
||||||
:backlinks: entry
|
|
||||||
|
|
||||||
.. automodule:: searx.engines.mullvad_leta
|
|
||||||
:members:
|
|
|
@ -1,13 +0,0 @@
|
||||||
.. _engine presearch:
|
|
||||||
|
|
||||||
================
|
|
||||||
Presearch Engine
|
|
||||||
================
|
|
||||||
|
|
||||||
.. contents::
|
|
||||||
:depth: 2
|
|
||||||
:local:
|
|
||||||
:backlinks: entry
|
|
||||||
|
|
||||||
.. automodule:: searx.engines.presearch
|
|
||||||
:members:
|
|
|
@ -1,13 +0,0 @@
|
||||||
.. _RadioBrowser engine:
|
|
||||||
|
|
||||||
============
|
|
||||||
RadioBrowser
|
|
||||||
============
|
|
||||||
|
|
||||||
.. contents::
|
|
||||||
:depth: 2
|
|
||||||
:local:
|
|
||||||
:backlinks: entry
|
|
||||||
|
|
||||||
.. automodule:: searx.engines.radio_browser
|
|
||||||
:members:
|
|
|
@ -1,13 +0,0 @@
|
||||||
.. _voidlinux engine:
|
|
||||||
|
|
||||||
==========================
|
|
||||||
Void Linux binary packages
|
|
||||||
==========================
|
|
||||||
|
|
||||||
.. contents:: Contents
|
|
||||||
:depth: 2
|
|
||||||
:local:
|
|
||||||
:backlinks: entry
|
|
||||||
|
|
||||||
.. automodule:: searx.engines.voidlinux
|
|
||||||
:members:
|
|
|
@ -6,7 +6,6 @@ Developer documentation
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
quickstart
|
quickstart
|
||||||
rtm_asdf
|
|
||||||
contribution_guide
|
contribution_guide
|
||||||
engines/index
|
engines/index
|
||||||
search_api
|
search_api
|
||||||
|
|
|
@ -61,9 +61,13 @@ working tree and release a ``make install`` to get a virtualenv with a
|
||||||
$ make install
|
$ make install
|
||||||
PYENV [virtualenv] installing ./requirements*.txt into local/py3
|
PYENV [virtualenv] installing ./requirements*.txt into local/py3
|
||||||
...
|
...
|
||||||
PYENV [install] pip install --use-pep517 --no-build-isolation -e 'searx[test]'
|
PYENV OK
|
||||||
|
PYENV [install] pip install -e 'searx[test]'
|
||||||
...
|
...
|
||||||
Successfully installed searxng-2023.7.19+a446dea1b
|
Successfully installed argparse-1.4.0 searx
|
||||||
|
BUILDENV INFO:searx:load the default settings from ./searx/settings.yml
|
||||||
|
BUILDENV INFO:searx:Initialisation done
|
||||||
|
BUILDENV build utils/brand.env
|
||||||
|
|
||||||
If you release ``make install`` multiple times the installation will only
|
If you release ``make install`` multiple times the installation will only
|
||||||
rebuild if the sha256 sum of the *requirement files* fails. With other words:
|
rebuild if the sha256 sum of the *requirement files* fails. With other words:
|
||||||
|
@ -78,9 +82,13 @@ the check fails if you edit the requirements listed in
|
||||||
...
|
...
|
||||||
PYENV [virtualenv] installing ./requirements*.txt into local/py3
|
PYENV [virtualenv] installing ./requirements*.txt into local/py3
|
||||||
...
|
...
|
||||||
PYENV [install] pip install --use-pep517 --no-build-isolation -e 'searx[test]'
|
PYENV OK
|
||||||
|
PYENV [install] pip install -e 'searx[test]'
|
||||||
...
|
...
|
||||||
Successfully installed searxng-2023.7.19+a446dea1b
|
Successfully installed argparse-1.4.0 searx
|
||||||
|
BUILDENV INFO:searx:load the default settings from ./searx/settings.yml
|
||||||
|
BUILDENV INFO:searx:Initialisation done
|
||||||
|
BUILDENV build utils/brand.env
|
||||||
|
|
||||||
.. sidebar:: drop environment
|
.. sidebar:: drop environment
|
||||||
|
|
||||||
|
@ -90,6 +98,67 @@ the check fails if you edit the requirements listed in
|
||||||
If you think, something goes wrong with your ./local environment or you change
|
If you think, something goes wrong with your ./local environment or you change
|
||||||
the :origin:`setup.py` file, you have to call :ref:`make clean`.
|
the :origin:`setup.py` file, you have to call :ref:`make clean`.
|
||||||
|
|
||||||
|
.. _make buildenv:
|
||||||
|
|
||||||
|
``make buildenv``
|
||||||
|
=================
|
||||||
|
|
||||||
|
Rebuild instance's environment with the modified settings from the
|
||||||
|
:ref:`settings brand` and :ref:`settings server` section of your
|
||||||
|
:ref:`settings.yml <settings location>`.
|
||||||
|
|
||||||
|
What is the :origin:`utils/brand.env` needed for and why do you need to rebuild
|
||||||
|
it if necessary?
|
||||||
|
|
||||||
|
Short answer: :ref:`installation and maintenance <searxng maintenance>`
|
||||||
|
scripts are running outside of instance's runtime environment and need some
|
||||||
|
values defined in the runtime environment.
|
||||||
|
|
||||||
|
All the SearXNG setups are centralized in the :ref:`settings.yml` file. This
|
||||||
|
setup is available as long we are in a *installed instance*. E.g. the
|
||||||
|
*installed instance* on the server or the *installed developer instance* at
|
||||||
|
``./local`` (the later one is created by a :ref:`make install <make install>` or
|
||||||
|
:ref:`make run <make run>`).
|
||||||
|
|
||||||
|
Tasks running outside of an *installed instance*, especially :ref:`installation
|
||||||
|
and maintenance <searxng maintenance>` tasks running at (pre-) installation time
|
||||||
|
do not have access to the SearXNG setup (from a *installed instance*). Those
|
||||||
|
tasks need a *build environment*.
|
||||||
|
|
||||||
|
The ``make buildenv`` target will update the *build environment* in:
|
||||||
|
|
||||||
|
- :origin:`utils/brand.env`
|
||||||
|
|
||||||
|
Tasks running outside of an *installed instance*, need the following settings
|
||||||
|
from the YAML configuration:
|
||||||
|
|
||||||
|
- ``SEARXNG_URL`` from :ref:`server.base_url <settings server>` (aka
|
||||||
|
``PUBLIC_URL``)
|
||||||
|
- ``SEARXNG_BIND_ADDRESS`` from :ref:`server.bind_address <settings server>`
|
||||||
|
- ``SEARXNG_PORT`` from :ref:`server.port <settings server>`
|
||||||
|
|
||||||
|
The ``GIT_URL`` and ``GIT_BRANCH`` in the origin:`utils/brand.env` file, are
|
||||||
|
read from the git VCS and the branch that is checked out when ``make
|
||||||
|
buildenv`` command runs.
|
||||||
|
|
||||||
|
.. _brand:
|
||||||
|
|
||||||
|
**I would like to create my own brand, how should I proceed?**
|
||||||
|
|
||||||
|
Create a remote branch (``example.org``), checkout the remote branch (on your
|
||||||
|
local developer desktop) and in the :origin:`searx/settings.yml` file in the
|
||||||
|
:ref:`settings server` section set ``base_url``. Run ``make buildenv`` and
|
||||||
|
create a commit for your brand.
|
||||||
|
|
||||||
|
On your server you clone the branch (``example.org``) into your HOME folder
|
||||||
|
``~`` from where you run the :ref:`installation <installation>` and
|
||||||
|
:ref:`maintenance <searxng maintenance>` task.
|
||||||
|
|
||||||
|
To upgrade you brand, rebase on SearXNG's master branch (on your local
|
||||||
|
developer desktop), force push it to your remote branch. Go to your server, do
|
||||||
|
a force pull and run :ref:`sudo -H ./utils/searxng.sh instance update <update
|
||||||
|
searxng>`.
|
||||||
|
|
||||||
.. _make node.env:
|
.. _make node.env:
|
||||||
|
|
||||||
Node.js environment (``make node.env``)
|
Node.js environment (``make node.env``)
|
||||||
|
|
|
@ -292,7 +292,7 @@ content becomes smart.
|
||||||
files & folders origin :origin:`docs/dev/reST.rst` ``:origin:`docs/dev/reST.rst```
|
files & folders origin :origin:`docs/dev/reST.rst` ``:origin:`docs/dev/reST.rst```
|
||||||
pull request :pull:`4` ``:pull:`4```
|
pull request :pull:`4` ``:pull:`4```
|
||||||
patch :patch:`af2cae6` ``:patch:`af2cae6```
|
patch :patch:`af2cae6` ``:patch:`af2cae6```
|
||||||
PyPi package :pypi:`httpx` ``:pypi:`httpx```
|
PyPi package :pypi:`searx` ``:pypi:`searx```
|
||||||
manual page man :man:`bash` ``:man:`bash```
|
manual page man :man:`bash` ``:man:`bash```
|
||||||
intersphinx_
|
intersphinx_
|
||||||
--------------------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -1,121 +0,0 @@
|
||||||
==================
|
|
||||||
Runtime Management
|
|
||||||
==================
|
|
||||||
|
|
||||||
The runtimes are managed with asdf and are activated in this project via the
|
|
||||||
`.tool-versions <.tool-versions>`_. If you have not yet installed asdf_, then
|
|
||||||
chapter :ref:`introduce asdf` may be of help to you.
|
|
||||||
|
|
||||||
.. contents::
|
|
||||||
:depth: 2
|
|
||||||
:local:
|
|
||||||
:backlinks: entry
|
|
||||||
|
|
||||||
|
|
||||||
Get started
|
|
||||||
===========
|
|
||||||
|
|
||||||
If you have asdf installed you can install the runtimes of this project by:
|
|
||||||
|
|
||||||
.. code:: bash
|
|
||||||
|
|
||||||
$ cd /path/to/searxng
|
|
||||||
$ asdf install # will install runtimes listed in .tool-versions
|
|
||||||
...
|
|
||||||
|
|
||||||
Manage Versions
|
|
||||||
===============
|
|
||||||
|
|
||||||
If you want to perform a ``test`` with special runtime versions of nodejs,
|
|
||||||
python or shellcheck, you can patch the ``.tool-versions``:
|
|
||||||
|
|
||||||
.. code:: diff
|
|
||||||
|
|
||||||
--- a/.tool-versions
|
|
||||||
+++ b/.tool-versions
|
|
||||||
@@ -1,2 +1,2 @@
|
|
||||||
-python 3.12.0
|
|
||||||
-shellcheck 0.9.0
|
|
||||||
+python 3.11.6
|
|
||||||
+shellcheck 0.8.0
|
|
||||||
|
|
||||||
To install use ``asdf install`` again. If the runtime tools have changed, any
|
|
||||||
existing (nodejs and python) environments should be cleaned up with a ``make
|
|
||||||
clean``.
|
|
||||||
|
|
||||||
.. code:: bash
|
|
||||||
|
|
||||||
$ asdf install
|
|
||||||
...
|
|
||||||
$ make clean test
|
|
||||||
|
|
||||||
|
|
||||||
.. _introduce asdf:
|
|
||||||
|
|
||||||
Introduce asdf
|
|
||||||
==============
|
|
||||||
|
|
||||||
To `download asdf`_ and `install asdf`_:
|
|
||||||
|
|
||||||
.. code:: bash
|
|
||||||
|
|
||||||
$ git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch <version>
|
|
||||||
$ echo '. "$HOME/.asdf/asdf.sh"' >> ~/.bashrc
|
|
||||||
$ echo '. "$HOME/.asdf/completions/asdf.bash"' >> ~/.bashrc
|
|
||||||
|
|
||||||
Start a new shell and try to `install plugins`_:
|
|
||||||
|
|
||||||
.. code:: bash
|
|
||||||
|
|
||||||
$ asdf plugin-list-all | grep -E '(golang|python|nodejs|shellcheck).git'
|
|
||||||
golang https://github.com/asdf-community/asdf-golang.git
|
|
||||||
nodejs https://github.com/asdf-vm/asdf-nodejs.git
|
|
||||||
python https://github.com/danhper/asdf-python.git
|
|
||||||
shellcheck https://github.com/luizm/asdf-shellcheck.git
|
|
||||||
|
|
||||||
$ asdf plugin add golang https://github.com/asdf-community/asdf-golang.git
|
|
||||||
$ asdf plugin add nodejs https://github.com/asdf-vm/asdf-nodejs.git
|
|
||||||
$ asdf plugin add python https://github.com/danhper/asdf-python.git
|
|
||||||
$ asdf plugin add shellcheck https://github.com/luizm/asdf-shellcheck.git
|
|
||||||
|
|
||||||
Each plugin has dependencies, to compile runtimes visit the URLs from above and
|
|
||||||
look out for the dependencies you need to install on your OS, on Debian for the
|
|
||||||
runtimes listed above you will need:
|
|
||||||
|
|
||||||
.. code:: bash
|
|
||||||
|
|
||||||
$ sudo apt update
|
|
||||||
$ sudo apt install \
|
|
||||||
dirmngr gpg curl gawk coreutils build-essential libssl-dev zlib1g-dev \
|
|
||||||
libbz2-dev libreadline-dev libsqlite3-dev \
|
|
||||||
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
|
|
||||||
|
|
||||||
With dependencies installed you can install/compile runtimes:
|
|
||||||
|
|
||||||
.. code:: bash
|
|
||||||
|
|
||||||
$ asdf install golang latest
|
|
||||||
$ asdf install nodejs latest
|
|
||||||
$ asdf install python latest
|
|
||||||
$ asdf install shellcheck latest
|
|
||||||
|
|
||||||
Python will be compiled and will take a while.
|
|
||||||
|
|
||||||
In the repository the version is defined in `.tool-versions`_. Outside the
|
|
||||||
repository, its recommended that the runtime should use the versions of the OS
|
|
||||||
(`Fallback to System Version`_) / if not already done register the system
|
|
||||||
versions global:
|
|
||||||
|
|
||||||
.. code:: bash
|
|
||||||
|
|
||||||
$ cd /
|
|
||||||
$ asdf global golang system
|
|
||||||
$ asdf global nodejs system
|
|
||||||
$ asdf global python system
|
|
||||||
$ asdf global shellcheck system
|
|
||||||
|
|
||||||
.. _asdf: https://asdf-vm.com/
|
|
||||||
.. _download asdf: https://asdf-vm.com/guide/getting-started.html#_2-download-asdf
|
|
||||||
.. _install asdf: https://asdf-vm.com/guide/getting-started.html#_3-install-asdf
|
|
||||||
.. _install plugins: https://asdf-vm.com/guide/getting-started.html#install-the-plugin
|
|
||||||
.. _Fallback to System Version: https://asdf-vm.com/manage/versions.html#fallback-to-system-version
|
|
|
@ -69,7 +69,7 @@ Parameters
|
||||||
|
|
||||||
``autocomplete`` : default from :ref:`settings search`
|
``autocomplete`` : default from :ref:`settings search`
|
||||||
[ ``google``, ``dbpedia``, ``duckduckgo``, ``mwmbl``, ``startpage``,
|
[ ``google``, ``dbpedia``, ``duckduckgo``, ``mwmbl``, ``startpage``,
|
||||||
``wikipedia``, ``stract``, ``swisscows``, ``qwant`` ]
|
``wikipedia``, ``swisscows``, ``qwant`` ]
|
||||||
|
|
||||||
Service which completes words as you type.
|
Service which completes words as you type.
|
||||||
|
|
||||||
|
@ -103,14 +103,14 @@ Parameters
|
||||||
|
|
||||||
.. disabled by default
|
.. disabled by default
|
||||||
|
|
||||||
``Hostnames_plugin``, ``Open_Access_DOI_rewrite``,
|
``Hostname_replace``, ``Open_Access_DOI_rewrite``,
|
||||||
``Vim-like_hotkeys``, ``Tor_check_plugin``
|
``Vim-like_hotkeys``, ``Tor_check_plugin``
|
||||||
|
|
||||||
``disabled_plugins``: optional
|
``disabled_plugins``: optional
|
||||||
List of disabled plugins.
|
List of disabled plugins.
|
||||||
|
|
||||||
:default:
|
:default:
|
||||||
``Hostnames_plugin``, ``Open_Access_DOI_rewrite``,
|
``Hostname_replace``, ``Open_Access_DOI_rewrite``,
|
||||||
``Vim-like_hotkeys``, ``Tor_check_plugin``
|
``Vim-like_hotkeys``, ``Tor_check_plugin``
|
||||||
|
|
||||||
:values:
|
:values:
|
||||||
|
|
|
@ -78,16 +78,6 @@ Scripts to update static data in :origin:`searx/data/`
|
||||||
.. automodule:: searxng_extra.update.update_pygments
|
.. automodule:: searxng_extra.update.update_pygments
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
.. _update_locales.py:
|
|
||||||
|
|
||||||
``update_locales.py``
|
|
||||||
=====================
|
|
||||||
|
|
||||||
:origin:`[source] <searxng_extra/update/update_locales.py>`
|
|
||||||
|
|
||||||
.. automodule:: searxng_extra.update.update_locales
|
|
||||||
:members:
|
|
||||||
|
|
||||||
|
|
||||||
``update_wikidata_units.py``
|
``update_wikidata_units.py``
|
||||||
============================
|
============================
|
||||||
|
|
|
@ -17,7 +17,7 @@ If you don't trust anyone, you can set up your own, see :ref:`installation`.
|
||||||
- :ref:`no user tracking / no profiling <SearXNG protect privacy>`
|
- :ref:`no user tracking / no profiling <SearXNG protect privacy>`
|
||||||
- script & cookies are optional
|
- script & cookies are optional
|
||||||
- secure, encrypted connections
|
- secure, encrypted connections
|
||||||
- :ref:`about 200 search engines <configured engines>`
|
- :ref:`about 130 search engines <configured engines>`
|
||||||
- `about 60 translations <https://translate.codeberg.org/projects/searxng/searxng/>`_
|
- `about 60 translations <https://translate.codeberg.org/projects/searxng/searxng/>`_
|
||||||
- about 100 `well maintained <https://uptime.searxng.org/>`__ instances on searx.space_
|
- about 100 `well maintained <https://uptime.searxng.org/>`__ instances on searx.space_
|
||||||
- :ref:`easy integration of search engines <demo online engine>`
|
- :ref:`easy integration of search engines <demo online engine>`
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
Why use a private instance?
|
Why use a private instance?
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
.. sidebar:: Is running my own instance worth it?
|
.. sidebar:: Is it worth to run my own instance?
|
||||||
|
|
||||||
\.\.\.is a common question among SearXNG users. Before answering this
|
\.\. is a common question among SearXNG users. Before answering this
|
||||||
question, see what options a SearXNG user has.
|
question, see what options a SearXNG user has.
|
||||||
|
|
||||||
.. contents::
|
.. contents::
|
||||||
|
@ -12,13 +12,13 @@ Why use a private instance?
|
||||||
:local:
|
:local:
|
||||||
:backlinks: entry
|
:backlinks: entry
|
||||||
|
|
||||||
Public instances are open to everyone who has access to their URL. Usually, they
|
Public instances are open to everyone who has access to its URL. Usually, these
|
||||||
are operated by unknown parties (from the users' point of view). Private
|
are operated by unknown parties (from the users' point of view). Private
|
||||||
instances can be used by a select group of people, such as a SearXNG instance for a
|
instances can be used by a select group of people. It is for example a SearXNG of
|
||||||
group of friends, or a company which can be accessed through a VPN. Instances can also be
|
group of friends or a company which can be accessed through VPN. Also it can be
|
||||||
single-user instances, which run locally on the user's machine.
|
single user one which runs on the user's laptop.
|
||||||
|
|
||||||
To gain more insight on how these instances work, let's dive into how SearXNG
|
To gain more insight on how these instances work let's dive into how SearXNG
|
||||||
protects its users.
|
protects its users.
|
||||||
|
|
||||||
.. _SearXNG protect privacy:
|
.. _SearXNG protect privacy:
|
||||||
|
@ -26,26 +26,26 @@ protects its users.
|
||||||
How does SearXNG protect privacy?
|
How does SearXNG protect privacy?
|
||||||
=================================
|
=================================
|
||||||
|
|
||||||
SearXNG protects the privacy of its users in multiple ways, regardless of the type
|
SearXNG protects the privacy of its users in multiple ways regardless of the type
|
||||||
of the instance (private or public). Removal of private data from search requests
|
of the instance (private, public). Removal of private data from search requests
|
||||||
comes in three forms:
|
comes in three forms:
|
||||||
|
|
||||||
1. Removing private data from requests going to search services
|
1. removal of private data from requests going to search services
|
||||||
2. Not forwarding anything from third party services through search services
|
2. not forwarding anything from a third party services through search services
|
||||||
(e.g. advertisement)
|
(e.g. advertisement)
|
||||||
3. Removing private data from requests going to the results pages
|
3. removal of private data from requests going to the result pages
|
||||||
|
|
||||||
Removing private data means not sending cookies to external search engines and
|
Removing private data means not sending cookies to external search engines and
|
||||||
generating a random browser profile for every request. Thus, it does not matter
|
generating a random browser profile for every request. Thus, it does not matter
|
||||||
if a public or private instance handles the request, because it is anonymized in
|
if a public or private instance handles the request, because it is anonymized in
|
||||||
both cases. The IP address used will be the IP of the instance, but SearXNG can also be
|
both cases. IP addresses will be the IP of the instance. But SearXNG can be
|
||||||
configured to use proxy or Tor. `Result proxy
|
configured to use proxy or Tor. `Result proxy
|
||||||
<https://github.com/asciimoo/morty>`__ is supported, too.
|
<https://github.com/asciimoo/morty>`__ is supported, too.
|
||||||
|
|
||||||
SearXNG does not serve ads or tracking content, unlike most search services. Therefore,
|
SearXNG does not serve ads or tracking content unlike most search services. So
|
||||||
private data is not forwarded to third parties who might monetize it. Besides
|
private data is not forwarded to third parties who might monetize it. Besides
|
||||||
protecting users from search services, both the referring page and search query are
|
protecting users from search services, both referring page and search query are
|
||||||
hidden from the results pages being visited.
|
hidden from visited result pages.
|
||||||
|
|
||||||
|
|
||||||
What are the consequences of using public instances?
|
What are the consequences of using public instances?
|
||||||
|
@ -53,11 +53,11 @@ What are the consequences of using public instances?
|
||||||
|
|
||||||
If someone uses a public instance, they have to trust the administrator of that
|
If someone uses a public instance, they have to trust the administrator of that
|
||||||
instance. This means that the user of the public instance does not know whether
|
instance. This means that the user of the public instance does not know whether
|
||||||
their requests are logged, aggregated, and sent or sold to a third party.
|
their requests are logged, aggregated and sent or sold to a third party.
|
||||||
|
|
||||||
Also, public instances without proper protection are more vulnerable to abuse of
|
Also, public instances without proper protection are more vulnerable to abusing
|
||||||
the search service, which may cause the external service to enforce
|
the search service, In this case the external service in exchange returns
|
||||||
CAPTCHAs or to ban the IP address of the instance. Thus, search requests would return less
|
CAPTCHAs or bans the IP of the instance. Thus, search requests return less
|
||||||
results.
|
results.
|
||||||
|
|
||||||
I see. What about private instances?
|
I see. What about private instances?
|
||||||
|
@ -67,10 +67,10 @@ If users run their :ref:`own instances <installation>`, everything is in their
|
||||||
control: the source code, logging settings and private data. Unknown instance
|
control: the source code, logging settings and private data. Unknown instance
|
||||||
administrators do not have to be trusted.
|
administrators do not have to be trusted.
|
||||||
|
|
||||||
Furthermore, as the default settings of their instance are editable, there is no
|
Furthermore, as the default settings of their instance is editable, there is no
|
||||||
need to use cookies to tailor SearXNG to their needs and preferences will not
|
need to use cookies to tailor SearXNG to their needs. So preferences will not be
|
||||||
reset to defaults when clearing browser cookies. As settings are stored on
|
reset to defaults when clearing browser cookies. As settings are stored on
|
||||||
the user's computer, they will not be accessible to others as long as their computer is
|
their computer, it will not be accessible to others as long as their computer is
|
||||||
not compromised.
|
not compromised.
|
||||||
|
|
||||||
Conclusion
|
Conclusion
|
||||||
|
@ -80,7 +80,7 @@ Always use an instance which is operated by people you trust. The privacy
|
||||||
features of SearXNG are available to users no matter what kind of instance they
|
features of SearXNG are available to users no matter what kind of instance they
|
||||||
use.
|
use.
|
||||||
|
|
||||||
For those on the go, or just wanting to try SearXNG for the first time, public
|
If someone is on the go or just wants to try SearXNG for the first time public
|
||||||
instances are the best choice. Public instances are also making the
|
instances are the best choices. Additionally, public instance are making a
|
||||||
world a better place by giving those who cannot, or do not want to, run an
|
world a better place, because those who cannot or do not want to run an
|
||||||
instance access to a privacy-respecting search service.
|
instance, have access to a privacy respecting search service.
|
||||||
|
|
|
@ -12,17 +12,13 @@ Bot Detection
|
||||||
.. automodule:: searx.botdetection
|
.. automodule:: searx.botdetection
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
.. _botdetection ip_lists:
|
.. automodule:: searx.botdetection.limiter
|
||||||
|
:members:
|
||||||
IP lists
|
|
||||||
========
|
|
||||||
|
|
||||||
.. automodule:: searx.botdetection.ip_lists
|
.. automodule:: searx.botdetection.ip_lists
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
|
||||||
.. _botdetection rate limit:
|
|
||||||
|
|
||||||
Rate limit
|
Rate limit
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|
@ -33,8 +29,6 @@ Rate limit
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
|
||||||
.. _botdetection probe headers:
|
|
||||||
|
|
||||||
Probe HTTP headers
|
Probe HTTP headers
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
@ -52,11 +46,3 @@ Probe HTTP headers
|
||||||
|
|
||||||
.. automodule:: searx.botdetection.http_user_agent
|
.. automodule:: searx.botdetection.http_user_agent
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
.. _botdetection config:
|
|
||||||
|
|
||||||
Config
|
|
||||||
======
|
|
||||||
|
|
||||||
.. automodule:: searx.botdetection.config
|
|
||||||
:members:
|
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
.. _favicons source:
|
|
||||||
|
|
||||||
=================
|
|
||||||
Favicons (source)
|
|
||||||
=================
|
|
||||||
|
|
||||||
.. contents::
|
|
||||||
:depth: 2
|
|
||||||
:local:
|
|
||||||
:backlinks: entry
|
|
||||||
|
|
||||||
.. automodule:: searx.favicons
|
|
||||||
:members:
|
|
||||||
|
|
||||||
.. _favicons.config:
|
|
||||||
|
|
||||||
Favicons Config
|
|
||||||
===============
|
|
||||||
|
|
||||||
.. automodule:: searx.favicons.config
|
|
||||||
:members:
|
|
||||||
|
|
||||||
.. _favicons.proxy:
|
|
||||||
|
|
||||||
Favicons Proxy
|
|
||||||
==============
|
|
||||||
|
|
||||||
.. automodule:: searx.favicons.proxy
|
|
||||||
:members:
|
|
||||||
|
|
||||||
.. _favicons.resolver:
|
|
||||||
|
|
||||||
Favicons Resolver
|
|
||||||
=================
|
|
||||||
|
|
||||||
.. automodule:: searx.favicons.resolvers
|
|
||||||
:members:
|
|
||||||
|
|
||||||
.. _favicons.cache:
|
|
||||||
|
|
||||||
Favicons Cache
|
|
||||||
==============
|
|
||||||
|
|
||||||
.. automodule:: searx.favicons.cache
|
|
||||||
:members:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,11 @@ Locales
|
||||||
:backlinks: entry
|
:backlinks: entry
|
||||||
|
|
||||||
.. automodule:: searx.locales
|
.. automodule:: searx.locales
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
|
||||||
|
SearXNG's locale codes
|
||||||
|
======================
|
||||||
|
|
||||||
|
.. automodule:: searx.sxng_locales
|
||||||
|
:members:
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
.. _hostnames plugin:
|
|
||||||
|
|
||||||
================
|
|
||||||
Hostnames plugin
|
|
||||||
================
|
|
||||||
|
|
||||||
.. automodule:: searx.plugins.hostnames
|
|
||||||
:members:
|
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
.. _unit converter plugin:
|
|
||||||
|
|
||||||
=====================
|
|
||||||
Unit converter plugin
|
|
||||||
=====================
|
|
||||||
|
|
||||||
.. automodule:: searx.plugins.unit_converter
|
|
||||||
:members:
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
.. _searx.settings_loader:
|
|
||||||
|
|
||||||
===============
|
|
||||||
Settings Loader
|
|
||||||
===============
|
|
||||||
|
|
||||||
.. automodule:: searx.settings_loader
|
|
||||||
:members:
|
|
|
@ -1,8 +0,0 @@
|
||||||
.. _sqlite db:
|
|
||||||
|
|
||||||
=========
|
|
||||||
SQLite DB
|
|
||||||
=========
|
|
||||||
|
|
||||||
.. automodule:: searx.sqlitedb
|
|
||||||
:members:
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
|
||||||
|
categories = ['general'] # optional
|
||||||
|
|
||||||
|
|
||||||
|
def request(query, params):
|
||||||
|
'''pre-request callback
|
||||||
|
params<dict>:
|
||||||
|
method : POST/GET
|
||||||
|
headers : {}
|
||||||
|
data : {} # if method == POST
|
||||||
|
url : ''
|
||||||
|
category: 'search category'
|
||||||
|
pageno : 1 # number of the requested page
|
||||||
|
'''
|
||||||
|
|
||||||
|
params['url'] = 'https://host/%s' % query
|
||||||
|
|
||||||
|
return params
|
||||||
|
|
||||||
|
|
||||||
|
def response(resp):
|
||||||
|
'''post-response callback
|
||||||
|
resp: requests response object
|
||||||
|
'''
|
||||||
|
return [{'url': '', 'title': '', 'content': ''}]
|
80
manage
80
manage
|
@ -41,10 +41,10 @@ PATH="${REPO_ROOT}/node_modules/.bin:${PATH}"
|
||||||
|
|
||||||
PYOBJECTS="searx"
|
PYOBJECTS="searx"
|
||||||
PY_SETUP_EXTRAS='[test]'
|
PY_SETUP_EXTRAS='[test]'
|
||||||
GECKODRIVER_VERSION="v0.35.0"
|
GECKODRIVER_VERSION="v0.30.0"
|
||||||
# SPHINXOPTS=
|
# SPHINXOPTS=
|
||||||
BLACK_OPTIONS=("--target-version" "py311" "--line-length" "120" "--skip-string-normalization")
|
BLACK_OPTIONS=("--target-version" "py311" "--line-length" "120" "--skip-string-normalization")
|
||||||
BLACK_TARGETS=("--exclude" "(searx/static|searx/languages.py)" "--include" 'searxng.msg|\.pyi?$' "searx" "searxng_extra" "tests")
|
BLACK_TARGETS=("--exclude" "searx/static,searx/languages.py" "--include" 'searxng.msg|\.pyi?$' "searx" "searxng_extra" "tests")
|
||||||
|
|
||||||
_dev_redis_sock="/usr/local/searxng-redis/run/redis.sock"
|
_dev_redis_sock="/usr/local/searxng-redis/run/redis.sock"
|
||||||
# set SEARXNG_REDIS_URL if it is not defined and "{_dev_redis_sock}" exists.
|
# set SEARXNG_REDIS_URL if it is not defined and "{_dev_redis_sock}" exists.
|
||||||
|
@ -52,20 +52,39 @@ if [ -S "${_dev_redis_sock}" ] && [ -z "${SEARXNG_REDIS_URL}" ]; then
|
||||||
export SEARXNG_REDIS_URL="unix://${_dev_redis_sock}?db=0"
|
export SEARXNG_REDIS_URL="unix://${_dev_redis_sock}?db=0"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
pylint.FILES() {
|
||||||
|
|
||||||
|
# List files tagged by comment:
|
||||||
|
#
|
||||||
|
# # lint: pylint
|
||||||
|
#
|
||||||
|
# These py files are linted by test.pylint()
|
||||||
|
|
||||||
|
grep -l -r --include \*.py '^#[[:blank:]]*lint:[[:blank:]]*pylint' searx searxng_extra tests
|
||||||
|
find . -name searxng.msg
|
||||||
|
}
|
||||||
|
|
||||||
YAMLLINT_FILES=()
|
YAMLLINT_FILES=()
|
||||||
while IFS= read -r line; do
|
while IFS= read -r line; do
|
||||||
if [ "$line" != "tests/unit/settings/syntaxerror_settings.yml" ]; then
|
YAMLLINT_FILES+=("$line")
|
||||||
YAMLLINT_FILES+=("$line")
|
|
||||||
fi
|
|
||||||
done <<< "$(git ls-files './tests/*.yml' './searx/*.yml' './utils/templates/etc/searxng/*.yml')"
|
done <<< "$(git ls-files './tests/*.yml' './searx/*.yml' './utils/templates/etc/searxng/*.yml')"
|
||||||
|
|
||||||
RST_FILES=(
|
RST_FILES=(
|
||||||
'README.rst'
|
'README.rst'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
PYLINT_SEARXNG_DISABLE_OPTION="\
|
||||||
|
I,C,R,\
|
||||||
|
W0105,W0212,W0511,W0603,W0613,W0621,W0702,W0703,W1401,\
|
||||||
|
E1136"
|
||||||
|
PYLINT_ADDITIONAL_BUILTINS_FOR_ENGINES="traits,supported_languages,language_aliases,logger,categories"
|
||||||
|
PYLINT_OPTIONS="-m pylint -j 0 --rcfile .pylintrc"
|
||||||
|
|
||||||
help() {
|
help() {
|
||||||
nvm.help
|
nvm.help
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
|
buildenv:
|
||||||
|
rebuild ./utils/brand.env
|
||||||
webapp.:
|
webapp.:
|
||||||
run : run developer instance
|
run : run developer instance
|
||||||
docs.:
|
docs.:
|
||||||
|
@ -92,6 +111,8 @@ pyenv.:
|
||||||
uninstall : uninstall developer installation
|
uninstall : uninstall developer installation
|
||||||
cmd ... : run command ... in virtualenv
|
cmd ... : run command ... in virtualenv
|
||||||
OK : test if virtualenv is OK
|
OK : test if virtualenv is OK
|
||||||
|
pypi.upload:
|
||||||
|
Upload python packages to PyPi (to test use pypi.upload.test)
|
||||||
format.:
|
format.:
|
||||||
python : format Python code source using black
|
python : format Python code source using black
|
||||||
pygments.:
|
pygments.:
|
||||||
|
@ -134,6 +155,29 @@ webapp.run() {
|
||||||
SEARXNG_DEBUG=1 pyenv.cmd python -m searx.webapp
|
SEARXNG_DEBUG=1 pyenv.cmd python -m searx.webapp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildenv() {
|
||||||
|
|
||||||
|
# settings file from repository's working tree are used by default
|
||||||
|
SEARXNG_SETTINGS_PATH="${REPO_ROOT}/searx/settings.yml"
|
||||||
|
|
||||||
|
if [ -f /etc/searx/settings.yml ]; then
|
||||||
|
err_msg "settings.yml in /etc/searx/ is deprecated, move file to folder /etc/searxng/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -r '/etc/searxng/settings.yml' ]; then
|
||||||
|
if ask_yn "should settings read from: /etc/searxng/settings.yml"; then
|
||||||
|
SEARXNG_SETTINGS_PATH='/etc/searxng/settings.yml'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
export SEARXNG_SETTINGS_PATH
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
SEARXNG_DEBUG=1 pyenv.cmd python utils/build_env.py 2>&1 \
|
||||||
|
| prefix_stdout "${_Blue}BUILDENV${_creset} "
|
||||||
|
)
|
||||||
|
return "${PIPESTATUS[0]}"
|
||||||
|
}
|
||||||
|
|
||||||
docker.push() {
|
docker.push() {
|
||||||
docker.build push
|
docker.build push
|
||||||
}
|
}
|
||||||
|
@ -233,7 +277,7 @@ gecko.driver() {
|
||||||
build_msg INSTALL "geckodriver already installed"
|
build_msg INSTALL "geckodriver already installed"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
PLATFORM="$(python -c 'import platform; print(platform.system().lower(), platform.architecture()[0])')"
|
PLATFORM="$(python3 -c 'import platform; 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";;
|
||||||
|
@ -299,8 +343,9 @@ pyenv.install() {
|
||||||
|
|
||||||
( set -e
|
( set -e
|
||||||
pyenv
|
pyenv
|
||||||
build_msg PYENV "[install] pip install --use-pep517 --no-build-isolation -e 'searx${PY_SETUP_EXTRAS}'"
|
build_msg PYENV "[install] pip install -e 'searx${PY_SETUP_EXTRAS}'"
|
||||||
"${PY_ENV_BIN}/python" -m pip install --use-pep517 --no-build-isolation -e ".${PY_SETUP_EXTRAS}"
|
"${PY_ENV_BIN}/python" -m pip install -e ".${PY_SETUP_EXTRAS}"
|
||||||
|
buildenv
|
||||||
)
|
)
|
||||||
local exit_val=$?
|
local exit_val=$?
|
||||||
if [ ! $exit_val -eq 0 ]; then
|
if [ ! $exit_val -eq 0 ]; then
|
||||||
|
@ -315,12 +360,31 @@ pyenv.uninstall() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pypi.upload() {
|
||||||
|
py.clean
|
||||||
|
py.build
|
||||||
|
# https://github.com/pypa/twine
|
||||||
|
pyenv.cmd twine upload "${PYDIST}"/*
|
||||||
|
}
|
||||||
|
|
||||||
|
pypi.upload.test() {
|
||||||
|
py.clean
|
||||||
|
py.build
|
||||||
|
pyenv.cmd twine upload -r testpypi "${PYDIST}"/*
|
||||||
|
}
|
||||||
|
|
||||||
format.python() {
|
format.python() {
|
||||||
build_msg TEST "[format.python] black \$BLACK_TARGETS"
|
build_msg TEST "[format.python] black \$BLACK_TARGETS"
|
||||||
pyenv.cmd black "${BLACK_OPTIONS[@]}" "${BLACK_TARGETS[@]}"
|
pyenv.cmd black "${BLACK_OPTIONS[@]}" "${BLACK_TARGETS[@]}"
|
||||||
dump_return $?
|
dump_return $?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PYLINT_FILES=()
|
||||||
|
while IFS= read -r line; do
|
||||||
|
PYLINT_FILES+=("$line")
|
||||||
|
done <<< "$(pylint.FILES)"
|
||||||
|
|
||||||
# shellcheck disable=SC2119
|
# shellcheck disable=SC2119
|
||||||
main() {
|
main() {
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"eslint": "^9.0.0",
|
"eslint": "^8.18.0",
|
||||||
"pyright": "^1.1.329"
|
"pyright": "^1.1.255"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rm -Rf node_modules package-lock.json"
|
"clean": "rm -Rf node_modules package-lock.json"
|
||||||
|
|
|
@ -1,24 +1,23 @@
|
||||||
mock==5.1.0
|
mock==5.1.0
|
||||||
nose2[coverage_plugin]==0.15.1
|
nose2[coverage_plugin]==0.13.0
|
||||||
cov-core==1.15.0
|
cov-core==1.15.0
|
||||||
black==24.3.0
|
black==22.12.0
|
||||||
pylint==3.3.1
|
pylint==2.17.5
|
||||||
splinter==0.21.0
|
splinter==0.19.0
|
||||||
selenium==4.25.0
|
selenium==4.12.0
|
||||||
Pallets-Sphinx-Themes==2.3.0
|
twine==4.0.2
|
||||||
Sphinx==7.4.7
|
Pallets-Sphinx-Themes==2.1.1
|
||||||
sphinx-issues==5.0.0
|
Sphinx<=7.1.2; python_version == '3.8'
|
||||||
|
Sphinx==7.2.6; python_version > '3.8'
|
||||||
|
sphinx-issues==3.0.1
|
||||||
sphinx-jinja==2.0.2
|
sphinx-jinja==2.0.2
|
||||||
sphinx-tabs==3.4.7
|
sphinx-tabs==3.4.1
|
||||||
sphinxcontrib-programoutput==0.17
|
sphinxcontrib-programoutput==0.17
|
||||||
sphinx-autobuild==2024.10.3
|
sphinx-autobuild==2021.3.14
|
||||||
sphinx-notfound-page==1.0.4
|
sphinx-notfound-page==1.0.0
|
||||||
myst-parser==3.0.1
|
myst-parser==2.0.0
|
||||||
linuxdoc==20240924
|
linuxdoc==20230827
|
||||||
aiounittest==1.4.2
|
aiounittest==1.4.2
|
||||||
yamllint==1.35.1
|
yamllint==1.32.0
|
||||||
wlc==1.15
|
wlc==1.13
|
||||||
coloredlogs==15.0.1
|
coloredlogs==15.0.1
|
||||||
docutils>=0.21.2
|
|
||||||
parameterized==0.9.0
|
|
||||||
autodoc_pydantic==2.2.0
|
|
||||||
|
|
|
@ -1,21 +1,19 @@
|
||||||
certifi==2024.8.30
|
certifi==2023.7.22
|
||||||
babel==2.16.0
|
babel==2.12.1
|
||||||
flask-babel==4.0.0
|
flask-babel==3.1.0
|
||||||
flask==3.0.3
|
flask==2.3.3
|
||||||
jinja2==3.1.4
|
jinja2==3.1.2
|
||||||
lxml==5.3.0
|
lxml==4.9.3
|
||||||
pygments==2.18.0
|
pygments==2.16.1
|
||||||
python-dateutil==2.9.0.post0
|
python-dateutil==2.8.2
|
||||||
pyyaml==6.0.2
|
pyyaml==6.0.1
|
||||||
httpx[http2]==0.24.1
|
httpx[http2]==0.24.1
|
||||||
Brotli==1.1.0
|
Brotli==1.1.0
|
||||||
uvloop==0.21.0
|
uvloop==0.17.0
|
||||||
httpx-socks[asyncio]==0.7.7
|
httpx-socks[asyncio]==0.7.7
|
||||||
setproctitle==1.3.3
|
setproctitle==1.3.2
|
||||||
redis==5.0.8
|
redis==4.6.0
|
||||||
markdown-it-py==3.0.0
|
markdown-it-py==3.0.0
|
||||||
fasttext-predict==0.9.2.2
|
typing_extensions==4.8.0
|
||||||
tomli==2.0.2; python_version < '3.11'
|
fasttext-predict==0.9.2.1
|
||||||
msgspec==0.18.6
|
pytomlpp==1.0.13
|
||||||
eval_type_backport; python_version < '3.9'
|
|
||||||
typer-slim==0.12.5
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
# pylint: disable=missing-module-docstring, cyclic-import
|
# lint: pylint
|
||||||
|
# pylint: disable=missing-module-docstring
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
@ -103,10 +104,3 @@ if max_request_timeout is None:
|
||||||
logger.info('max_request_timeout=%s', repr(max_request_timeout))
|
logger.info('max_request_timeout=%s', repr(max_request_timeout))
|
||||||
else:
|
else:
|
||||||
logger.info('max_request_timeout=%i second(s)', max_request_timeout)
|
logger.info('max_request_timeout=%i second(s)', max_request_timeout)
|
||||||
|
|
||||||
if settings['server']['public_instance']:
|
|
||||||
logger.warning(
|
|
||||||
"Be aware you have activated features intended only for public instances. "
|
|
||||||
"This force the usage of the limiter and link_token / "
|
|
||||||
"see https://docs.searxng.org/admin/searx.limiter.html"
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,30 +1,25 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
# pylint: disable=missing-module-docstring
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from os import listdir
|
from os import listdir
|
||||||
from os.path import realpath, dirname, join, isdir
|
from os.path import realpath, dirname, join, isdir
|
||||||
|
from searx.utils import load_module
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
from searx.utils import load_module
|
|
||||||
|
|
||||||
answerers_dir = dirname(realpath(__file__))
|
answerers_dir = dirname(realpath(__file__))
|
||||||
|
|
||||||
|
|
||||||
def load_answerers():
|
def load_answerers():
|
||||||
answerers = [] # pylint: disable=redefined-outer-name
|
answerers = []
|
||||||
|
|
||||||
for filename in listdir(answerers_dir):
|
for filename in listdir(answerers_dir):
|
||||||
if not isdir(join(answerers_dir, filename)) or filename.startswith('_'):
|
if not isdir(join(answerers_dir, filename)) or filename.startswith('_'):
|
||||||
continue
|
continue
|
||||||
module = load_module('answerer.py', join(answerers_dir, filename))
|
module = load_module('answerer.py', join(answerers_dir, filename))
|
||||||
if not hasattr(module, 'keywords') or not isinstance(module.keywords, tuple) or not module.keywords:
|
if not hasattr(module, 'keywords') or not isinstance(module.keywords, tuple) or not len(module.keywords):
|
||||||
sys.exit(2)
|
exit(2)
|
||||||
answerers.append(module)
|
answerers.append(module)
|
||||||
return answerers
|
return answerers
|
||||||
|
|
||||||
|
|
||||||
def get_answerers_by_keywords(answerers): # pylint:disable=redefined-outer-name
|
def get_answerers_by_keywords(answerers):
|
||||||
by_keyword = defaultdict(list)
|
by_keyword = defaultdict(list)
|
||||||
for answerer in answerers:
|
for answerer in answerers:
|
||||||
for keyword in answerer.keywords:
|
for keyword in answerer.keywords:
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
# pylint: disable=missing-module-docstring
|
|
|
@ -1,6 +1,3 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
# pylint: disable=missing-module-docstring
|
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
# pylint: disable=missing-module-docstring
|
|
|
@ -1,6 +1,3 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
# pylint: disable=missing-module-docstring
|
|
||||||
|
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
from operator import mul
|
from operator import mul
|
||||||
|
|
||||||
|
@ -20,27 +17,27 @@ def answer(query):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
args = list(map(float, parts[1:]))
|
args = list(map(float, parts[1:]))
|
||||||
except: # pylint: disable=bare-except
|
except:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
func = parts[0]
|
func = parts[0]
|
||||||
_answer = None
|
answer = None
|
||||||
|
|
||||||
if func == 'min':
|
if func == 'min':
|
||||||
_answer = min(args)
|
answer = min(args)
|
||||||
elif func == 'max':
|
elif func == 'max':
|
||||||
_answer = max(args)
|
answer = max(args)
|
||||||
elif func == 'avg':
|
elif func == 'avg':
|
||||||
_answer = sum(args) / len(args)
|
answer = sum(args) / len(args)
|
||||||
elif func == 'sum':
|
elif func == 'sum':
|
||||||
_answer = sum(args)
|
answer = sum(args)
|
||||||
elif func == 'prod':
|
elif func == 'prod':
|
||||||
_answer = reduce(mul, args, 1)
|
answer = reduce(mul, args, 1)
|
||||||
|
|
||||||
if _answer is None:
|
if answer is None:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
return [{'answer': str(_answer)}]
|
return [{'answer': str(answer)}]
|
||||||
|
|
||||||
|
|
||||||
# required answerer function
|
# required answerer function
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
# lint: pylint
|
||||||
"""This module implements functions needed for the autocompleter.
|
"""This module implements functions needed for the autocompleter.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# pylint: disable=use-dict-literal
|
# pylint: disable=use-dict-literal
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import html
|
from urllib.parse import urlencode
|
||||||
from urllib.parse import urlencode, quote_plus
|
|
||||||
|
|
||||||
import lxml
|
import lxml
|
||||||
from httpx import HTTPError
|
from httpx import HTTPError
|
||||||
|
@ -16,26 +16,17 @@ from searx.engines import (
|
||||||
engines,
|
engines,
|
||||||
google,
|
google,
|
||||||
)
|
)
|
||||||
from searx.network import get as http_get, post as http_post
|
from searx.network import get as http_get
|
||||||
from searx.exceptions import SearxEngineResponseException
|
from searx.exceptions import SearxEngineResponseException
|
||||||
|
|
||||||
|
|
||||||
def update_kwargs(**kwargs):
|
def get(*args, **kwargs):
|
||||||
if 'timeout' not in kwargs:
|
if 'timeout' not in kwargs:
|
||||||
kwargs['timeout'] = settings['outgoing']['request_timeout']
|
kwargs['timeout'] = settings['outgoing']['request_timeout']
|
||||||
kwargs['raise_for_httperror'] = True
|
kwargs['raise_for_httperror'] = True
|
||||||
|
|
||||||
|
|
||||||
def get(*args, **kwargs):
|
|
||||||
update_kwargs(**kwargs)
|
|
||||||
return http_get(*args, **kwargs)
|
return http_get(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def post(*args, **kwargs):
|
|
||||||
update_kwargs(**kwargs)
|
|
||||||
return http_post(*args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def brave(query, _lang):
|
def brave(query, _lang):
|
||||||
# brave search autocompleter
|
# brave search autocompleter
|
||||||
url = 'https://search.brave.com/api/suggest?'
|
url = 'https://search.brave.com/api/suggest?'
|
||||||
|
@ -154,18 +145,6 @@ def seznam(query, _lang):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def stract(query, _lang):
|
|
||||||
# stract autocompleter (beta)
|
|
||||||
url = f"https://stract.com/beta/api/autosuggest?q={quote_plus(query)}"
|
|
||||||
|
|
||||||
resp = post(url)
|
|
||||||
|
|
||||||
if not resp.ok:
|
|
||||||
return []
|
|
||||||
|
|
||||||
return [html.unescape(suggestion['raw']) for suggestion in resp.json()]
|
|
||||||
|
|
||||||
|
|
||||||
def startpage(query, sxng_locale):
|
def startpage(query, sxng_locale):
|
||||||
"""Autocomplete from Startpage. Supports Startpage's languages"""
|
"""Autocomplete from Startpage. Supports Startpage's languages"""
|
||||||
lui = engines['startpage'].traits.get_language(sxng_locale, 'english')
|
lui = engines['startpage'].traits.get_language(sxng_locale, 'english')
|
||||||
|
@ -244,7 +223,6 @@ backends = {
|
||||||
'mwmbl': mwmbl,
|
'mwmbl': mwmbl,
|
||||||
'seznam': seznam,
|
'seznam': seznam,
|
||||||
'startpage': startpage,
|
'startpage': startpage,
|
||||||
'stract': stract,
|
|
||||||
'swisscows': swisscows,
|
'swisscows': swisscows,
|
||||||
'qwant': qwant,
|
'qwant': qwant,
|
||||||
'wikipedia': wikipedia,
|
'wikipedia': wikipedia,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
# lint: pylint
|
||||||
"""This module implements the :origin:`searxng_msg <babel.cfg>` extractor to
|
"""This module implements the :origin:`searxng_msg <babel.cfg>` extractor to
|
||||||
extract messages from:
|
extract messages from:
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,27 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
# lint: pylint
|
||||||
""".. _botdetection src:
|
""".. _botdetection src:
|
||||||
|
|
||||||
Implementations used for bot detection.
|
X-Forwarded-For
|
||||||
|
===============
|
||||||
|
|
||||||
|
.. attention::
|
||||||
|
|
||||||
|
A correct setup of the HTTP request headers ``X-Forwarded-For`` and
|
||||||
|
``X-Real-IP`` is essential to be able to assign a request to an IP correctly:
|
||||||
|
|
||||||
|
- `NGINX RequestHeader`_
|
||||||
|
- `Apache RequestHeader`_
|
||||||
|
|
||||||
|
.. _NGINX RequestHeader:
|
||||||
|
https://docs.searxng.org/admin/installation-nginx.html#nginx-s-searxng-site
|
||||||
|
.. _Apache RequestHeader:
|
||||||
|
https://docs.searxng.org/admin/installation-apache.html#apache-s-searxng-site
|
||||||
|
|
||||||
|
.. autofunction:: searx.botdetection.get_real_ip
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from ._helpers import dump_request
|
from ._helpers import dump_request
|
||||||
from ._helpers import get_real_ip
|
from ._helpers import get_real_ip
|
||||||
from ._helpers import get_network
|
|
||||||
from ._helpers import too_many_requests
|
from ._helpers import too_many_requests
|
||||||
|
|
||||||
__all__ = ['dump_request', 'get_network', 'get_real_ip', 'too_many_requests']
|
|
||||||
|
|
||||||
redis_client = None
|
|
||||||
cfg = None
|
|
||||||
|
|
||||||
|
|
||||||
def init(_cfg, _redis_client):
|
|
||||||
global redis_client, cfg # pylint: disable=global-statement
|
|
||||||
redis_client = _redis_client
|
|
||||||
cfg = _cfg
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
# lint: pylint
|
||||||
# pylint: disable=missing-module-docstring, invalid-name
|
# pylint: disable=missing-module-docstring, invalid-name
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
@ -12,8 +13,8 @@ from ipaddress import (
|
||||||
import flask
|
import flask
|
||||||
import werkzeug
|
import werkzeug
|
||||||
|
|
||||||
|
from searx.tools import config
|
||||||
from searx import logger
|
from searx import logger
|
||||||
from . import config
|
|
||||||
|
|
||||||
logger = logger.getChild('botdetection')
|
logger = logger.getChild('botdetection')
|
||||||
|
|
||||||
|
@ -103,10 +104,10 @@ def get_real_ip(request: flask.Request) -> str:
|
||||||
if not forwarded_for:
|
if not forwarded_for:
|
||||||
_log_error_only_once("X-Forwarded-For header is not set!")
|
_log_error_only_once("X-Forwarded-For header is not set!")
|
||||||
else:
|
else:
|
||||||
from . import cfg # pylint: disable=import-outside-toplevel, cyclic-import
|
from .limiter import get_cfg # pylint: disable=import-outside-toplevel, cyclic-import
|
||||||
|
|
||||||
forwarded_for = [x.strip() for x in forwarded_for.split(',')]
|
forwarded_for = [x.strip() for x in forwarded_for.split(',')]
|
||||||
x_for: int = cfg['real_ip.x_for'] # type: ignore
|
x_for: int = get_cfg()['real_ip.x_for'] # type: ignore
|
||||||
forwarded_for = forwarded_for[-min(len(forwarded_for), x_for)]
|
forwarded_for = forwarded_for[-min(len(forwarded_for), x_for)]
|
||||||
|
|
||||||
if not real_ip:
|
if not real_ip:
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
# lint: pylint
|
||||||
"""
|
"""
|
||||||
Method ``http_accept``
|
Method ``http_accept``
|
||||||
----------------------
|
----------------------
|
||||||
|
@ -23,7 +24,7 @@ from ipaddress import (
|
||||||
import flask
|
import flask
|
||||||
import werkzeug
|
import werkzeug
|
||||||
|
|
||||||
from . import config
|
from searx.tools import config
|
||||||
from ._helpers import too_many_requests
|
from ._helpers import too_many_requests
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
# lint: pylint
|
||||||
"""
|
"""
|
||||||
Method ``http_accept_encoding``
|
Method ``http_accept_encoding``
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
@ -24,7 +25,7 @@ from ipaddress import (
|
||||||
import flask
|
import flask
|
||||||
import werkzeug
|
import werkzeug
|
||||||
|
|
||||||
from . import config
|
from searx.tools import config
|
||||||
from ._helpers import too_many_requests
|
from ._helpers import too_many_requests
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
# lint: pylint
|
||||||
"""
|
"""
|
||||||
Method ``http_accept_language``
|
Method ``http_accept_language``
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
@ -20,7 +21,7 @@ from ipaddress import (
|
||||||
import flask
|
import flask
|
||||||
import werkzeug
|
import werkzeug
|
||||||
|
|
||||||
from . import config
|
from searx.tools import config
|
||||||
from ._helpers import too_many_requests
|
from ._helpers import too_many_requests
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
# lint: pylint
|
||||||
"""
|
"""
|
||||||
Method ``http_connection``
|
Method ``http_connection``
|
||||||
--------------------------
|
--------------------------
|
||||||
|
@ -21,7 +22,7 @@ from ipaddress import (
|
||||||
import flask
|
import flask
|
||||||
import werkzeug
|
import werkzeug
|
||||||
|
|
||||||
from . import config
|
from searx.tools import config
|
||||||
from ._helpers import too_many_requests
|
from ._helpers import too_many_requests
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
# lint: pylint
|
||||||
"""
|
"""
|
||||||
Method ``http_user_agent``
|
Method ``http_user_agent``
|
||||||
--------------------------
|
--------------------------
|
||||||
|
@ -23,7 +24,7 @@ from ipaddress import (
|
||||||
import flask
|
import flask
|
||||||
import werkzeug
|
import werkzeug
|
||||||
|
|
||||||
from . import config
|
from searx.tools import config
|
||||||
from ._helpers import too_many_requests
|
from ._helpers import too_many_requests
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,7 +35,7 @@ USER_AGENT = (
|
||||||
+ r'|HttpClient|Jersey|Python|libwww-perl|Ruby|SynHttpClient|UniversalFeedParser|Googlebot|GoogleImageProxy'
|
+ r'|HttpClient|Jersey|Python|libwww-perl|Ruby|SynHttpClient|UniversalFeedParser|Googlebot|GoogleImageProxy'
|
||||||
+ r'|bingbot|Baiduspider|yacybot|YandexMobileBot|YandexBot|Yahoo! Slurp|MJ12bot|AhrefsBot|archive.org_bot|msnbot'
|
+ r'|bingbot|Baiduspider|yacybot|YandexMobileBot|YandexBot|Yahoo! Slurp|MJ12bot|AhrefsBot|archive.org_bot|msnbot'
|
||||||
+ r'|MJ12bot|SeznamBot|linkdexbot|Netvibes|SMTBot|zgrab|James BOT|Sogou|Abonti|Pixray|Spinn3r|SemrushBot|Exabot'
|
+ r'|MJ12bot|SeznamBot|linkdexbot|Netvibes|SMTBot|zgrab|James BOT|Sogou|Abonti|Pixray|Spinn3r|SemrushBot|Exabot'
|
||||||
+ r'|ZmEu|BLEXBot|bitlybot|HeadlessChrome'
|
+ r'|ZmEu|BLEXBot|bitlybot'
|
||||||
# unmaintained Farside instances
|
# unmaintained Farside instances
|
||||||
+ r'|'
|
+ r'|'
|
||||||
+ re.escape(r'Mozilla/5.0 (compatible; Farside/0.1.0; +https://farside.link)')
|
+ re.escape(r'Mozilla/5.0 (compatible; Farside/0.1.0; +https://farside.link)')
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
# lint: pylint
|
||||||
""".. _botdetection.ip_limit:
|
""".. _botdetection.ip_limit:
|
||||||
|
|
||||||
Method ``ip_limit``
|
Method ``ip_limit``
|
||||||
|
@ -12,7 +13,8 @@ and at least for a maximum of 10 minutes.
|
||||||
|
|
||||||
The :py:obj:`.link_token` method can be used to investigate whether a request is
|
The :py:obj:`.link_token` method can be used to investigate whether a request is
|
||||||
*suspicious*. To activate the :py:obj:`.link_token` method in the
|
*suspicious*. To activate the :py:obj:`.link_token` method in the
|
||||||
:py:obj:`.ip_limit` method add the following configuration:
|
:py:obj:`.ip_limit` method add the following to your
|
||||||
|
``/etc/searxng/limiter.toml``:
|
||||||
|
|
||||||
.. code:: toml
|
.. code:: toml
|
||||||
|
|
||||||
|
@ -44,12 +46,12 @@ from ipaddress import (
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
import werkzeug
|
import werkzeug
|
||||||
|
from searx.tools import config
|
||||||
|
|
||||||
from searx import redisdb
|
from searx import redisdb
|
||||||
from searx.redislib import incr_sliding_window, drop_counter
|
from searx.redislib import incr_sliding_window, drop_counter
|
||||||
|
|
||||||
from . import link_token
|
from . import link_token
|
||||||
from . import config
|
|
||||||
from ._helpers import (
|
from ._helpers import (
|
||||||
too_many_requests,
|
too_many_requests,
|
||||||
logger,
|
logger,
|
||||||
|
@ -76,11 +78,11 @@ LONG_MAX = 150
|
||||||
LONG_MAX_SUSPICIOUS = 10
|
LONG_MAX_SUSPICIOUS = 10
|
||||||
"""Maximum suspicious requests from one IP in the :py:obj:`LONG_WINDOW`"""
|
"""Maximum suspicious requests from one IP in the :py:obj:`LONG_WINDOW`"""
|
||||||
|
|
||||||
API_WINDOW = 3600
|
API_WONDOW = 3600
|
||||||
"""Time (sec) before sliding window for API requests (format != html) expires."""
|
"""Time (sec) before sliding window for API requests (format != html) expires."""
|
||||||
|
|
||||||
API_MAX = 4
|
API_MAX = 4
|
||||||
"""Maximum requests from one IP in the :py:obj:`API_WINDOW`"""
|
"""Maximum requests from one IP in the :py:obj:`API_WONDOW`"""
|
||||||
|
|
||||||
SUSPICIOUS_IP_WINDOW = 3600 * 24 * 30
|
SUSPICIOUS_IP_WINDOW = 3600 * 24 * 30
|
||||||
"""Time (sec) before sliding window for one suspicious IP expires."""
|
"""Time (sec) before sliding window for one suspicious IP expires."""
|
||||||
|
@ -103,7 +105,7 @@ def filter_request(
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if request.args.get('format', 'html') != 'html':
|
if request.args.get('format', 'html') != 'html':
|
||||||
c = incr_sliding_window(redis_client, 'ip_limit.API_WINDOW:' + network.compressed, API_WINDOW)
|
c = incr_sliding_window(redis_client, 'ip_limit.API_WONDOW:' + network.compressed, API_WONDOW)
|
||||||
if c > API_MAX:
|
if c > API_MAX:
|
||||||
return too_many_requests(network, "too many request in API_WINDOW")
|
return too_many_requests(network, "too many request in API_WINDOW")
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
# lint: pylint
|
||||||
""".. _botdetection.ip_lists:
|
""".. _botdetection.ip_lists:
|
||||||
|
|
||||||
Method ``ip_lists``
|
Method ``ip_lists``
|
||||||
|
@ -12,7 +13,7 @@ The ``ip_lists`` method implements IP :py:obj:`block- <block_ip>` and
|
||||||
[botdetection.ip_lists]
|
[botdetection.ip_lists]
|
||||||
|
|
||||||
pass_ip = [
|
pass_ip = [
|
||||||
'167.235.158.251', # IPv4 of check.searx.space
|
'140.238.172.132', # IPv4 of check.searx.space
|
||||||
'192.168.0.0/16', # IPv4 private network
|
'192.168.0.0/16', # IPv4 private network
|
||||||
'fe80::/10' # IPv6 linklocal
|
'fe80::/10' # IPv6 linklocal
|
||||||
]
|
]
|
||||||
|
@ -32,15 +33,15 @@ from ipaddress import (
|
||||||
IPv6Address,
|
IPv6Address,
|
||||||
)
|
)
|
||||||
|
|
||||||
from . import config
|
from searx.tools import config
|
||||||
from ._helpers import logger
|
from ._helpers import logger
|
||||||
|
|
||||||
logger = logger.getChild('ip_limit')
|
logger = logger.getChild('ip_limit')
|
||||||
|
|
||||||
SEARXNG_ORG = [
|
SEARXNG_ORG = [
|
||||||
# https://github.com/searxng/searxng/pull/2484#issuecomment-1576639195
|
# https://github.com/searxng/searxng/pull/2484#issuecomment-1576639195
|
||||||
'167.235.158.251', # IPv4 check.searx.space
|
'140.238.172.132', # IPv4 check.searx.space
|
||||||
'2a01:04f8:1c1c:8fc2::/64', # IPv6 check.searx.space
|
'2603:c022:0:4900::/56', # IPv6 check.searx.space
|
||||||
]
|
]
|
||||||
"""Passlist of IPs from the SearXNG organization, e.g. `check.searx.space`."""
|
"""Passlist of IPs from the SearXNG organization, e.g. `check.searx.space`."""
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,147 @@
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
# lint: pylint
|
||||||
|
""".. _limiter src:
|
||||||
|
|
||||||
|
Limiter
|
||||||
|
=======
|
||||||
|
|
||||||
|
.. sidebar:: info
|
||||||
|
|
||||||
|
The limiter requires a :ref:`Redis <settings redis>` database.
|
||||||
|
|
||||||
|
Bot protection / IP rate limitation. The intention of rate limitation is to
|
||||||
|
limit suspicious requests from an IP. The motivation behind this is the fact
|
||||||
|
that SearXNG passes through requests from bots and is thus classified as a bot
|
||||||
|
itself. As a result, the SearXNG engine then receives a CAPTCHA or is blocked
|
||||||
|
by the search engine (the origin) in some other way.
|
||||||
|
|
||||||
|
To avoid blocking, the requests from bots to SearXNG must also be blocked, this
|
||||||
|
is the task of the limiter. To perform this task, the limiter uses the methods
|
||||||
|
from the :py:obj:`searx.botdetection`.
|
||||||
|
|
||||||
|
To enable the limiter activate:
|
||||||
|
|
||||||
|
.. code:: yaml
|
||||||
|
|
||||||
|
server:
|
||||||
|
...
|
||||||
|
limiter: true # rate limit the number of request on the instance, block some bots
|
||||||
|
|
||||||
|
and set the redis-url connection. Check the value, it depends on your redis DB
|
||||||
|
(see :ref:`settings redis`), by example:
|
||||||
|
|
||||||
|
.. code:: yaml
|
||||||
|
|
||||||
|
redis:
|
||||||
|
url: unix:///usr/local/searxng-redis/run/redis.sock?db=0
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from ipaddress import ip_address
|
||||||
|
import flask
|
||||||
|
import werkzeug
|
||||||
|
|
||||||
|
from searx.tools import config
|
||||||
|
from searx import logger
|
||||||
|
|
||||||
|
from . import (
|
||||||
|
http_accept,
|
||||||
|
http_accept_encoding,
|
||||||
|
http_accept_language,
|
||||||
|
http_connection,
|
||||||
|
http_user_agent,
|
||||||
|
ip_limit,
|
||||||
|
ip_lists,
|
||||||
|
)
|
||||||
|
|
||||||
|
from ._helpers import (
|
||||||
|
get_network,
|
||||||
|
get_real_ip,
|
||||||
|
dump_request,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger = logger.getChild('botdetection.limiter')
|
||||||
|
|
||||||
|
CFG: config.Config = None # type: ignore
|
||||||
|
|
||||||
|
LIMITER_CFG_SCHEMA = Path(__file__).parent / "limiter.toml"
|
||||||
|
"""Base configuration (schema) of the botdetection."""
|
||||||
|
|
||||||
|
LIMITER_CFG = Path('/etc/searxng/limiter.toml')
|
||||||
|
"""Local Limiter configuration."""
|
||||||
|
|
||||||
|
CFG_DEPRECATED = {
|
||||||
|
# "dummy.old.foo": "config 'dummy.old.foo' exists only for tests. Don't use it in your real project config."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_cfg() -> config.Config:
|
||||||
|
global CFG # pylint: disable=global-statement
|
||||||
|
if CFG is None:
|
||||||
|
CFG = config.Config.from_toml(LIMITER_CFG_SCHEMA, LIMITER_CFG, CFG_DEPRECATED)
|
||||||
|
return CFG
|
||||||
|
|
||||||
|
|
||||||
|
def filter_request(request: flask.Request) -> werkzeug.Response | None:
|
||||||
|
# pylint: disable=too-many-return-statements
|
||||||
|
|
||||||
|
cfg = get_cfg()
|
||||||
|
real_ip = ip_address(get_real_ip(request))
|
||||||
|
network = get_network(real_ip, cfg)
|
||||||
|
|
||||||
|
if request.path == '/healthz':
|
||||||
|
return None
|
||||||
|
|
||||||
|
# link-local
|
||||||
|
|
||||||
|
if network.is_link_local:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# block- & pass- lists
|
||||||
|
#
|
||||||
|
# 1. The IP of the request is first checked against the pass-list; if the IP
|
||||||
|
# matches an entry in the list, the request is not blocked.
|
||||||
|
# 2. If no matching entry is found in the pass-list, then a check is made against
|
||||||
|
# the block list; if the IP matches an entry in the list, the request is
|
||||||
|
# blocked.
|
||||||
|
# 3. If the IP is not in either list, the request is not blocked.
|
||||||
|
|
||||||
|
match, msg = ip_lists.pass_ip(real_ip, cfg)
|
||||||
|
if match:
|
||||||
|
logger.warning("PASS %s: matched PASSLIST - %s", network.compressed, msg)
|
||||||
|
return None
|
||||||
|
|
||||||
|
match, msg = ip_lists.block_ip(real_ip, cfg)
|
||||||
|
if match:
|
||||||
|
logger.error("BLOCK %s: matched BLOCKLIST - %s", network.compressed, msg)
|
||||||
|
return flask.make_response(('IP is on BLOCKLIST - %s' % msg, 429))
|
||||||
|
|
||||||
|
# methods applied on /
|
||||||
|
|
||||||
|
for func in [
|
||||||
|
http_user_agent,
|
||||||
|
]:
|
||||||
|
val = func.filter_request(network, request, cfg)
|
||||||
|
if val is not None:
|
||||||
|
return val
|
||||||
|
|
||||||
|
# methods applied on /search
|
||||||
|
|
||||||
|
if request.path == '/search':
|
||||||
|
|
||||||
|
for func in [
|
||||||
|
http_accept,
|
||||||
|
http_accept_encoding,
|
||||||
|
http_accept_language,
|
||||||
|
http_connection,
|
||||||
|
http_user_agent,
|
||||||
|
ip_limit,
|
||||||
|
]:
|
||||||
|
val = func.filter_request(network, request, cfg)
|
||||||
|
if val is not None:
|
||||||
|
return val
|
||||||
|
logger.debug(f"OK {network}: %s", dump_request(flask.request))
|
||||||
|
return None
|
|
@ -1,4 +1,5 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
# lint: pylint
|
||||||
"""
|
"""
|
||||||
Method ``link_token``
|
Method ``link_token``
|
||||||
---------------------
|
---------------------
|
||||||
|
@ -28,7 +29,7 @@ And in the HTML template from flask a stylesheet link is needed (the value of
|
||||||
|
|
||||||
<link rel="stylesheet"
|
<link rel="stylesheet"
|
||||||
href="{{ url_for('client_token', token=link_token) }}"
|
href="{{ url_for('client_token', token=link_token) }}"
|
||||||
type="text/css" >
|
type="text/css" />
|
||||||
|
|
||||||
.. _X-Forwarded-For:
|
.. _X-Forwarded-For:
|
||||||
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For
|
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For
|
||||||
|
@ -82,7 +83,7 @@ def is_suspicious(network: IPv4Network | IPv6Network, request: flask.Request, re
|
||||||
|
|
||||||
ping_key = get_ping_key(network, request)
|
ping_key = get_ping_key(network, request)
|
||||||
if not redis_client.get(ping_key):
|
if not redis_client.get(ping_key):
|
||||||
logger.info("missing ping (IP: %s) / request: %s", network.compressed, ping_key)
|
logger.warning("missing ping (IP: %s) / request: %s", network.compressed, ping_key)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if renew:
|
if renew:
|
||||||
|
@ -98,13 +99,15 @@ def ping(request: flask.Request, token: str):
|
||||||
The expire time of this ping-key is :py:obj:`PING_LIVE_TIME`.
|
The expire time of this ping-key is :py:obj:`PING_LIVE_TIME`.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from . import redis_client, cfg # pylint: disable=import-outside-toplevel, cyclic-import
|
from . import limiter # pylint: disable=import-outside-toplevel, cyclic-import
|
||||||
|
|
||||||
|
redis_client = redisdb.client()
|
||||||
if not redis_client:
|
if not redis_client:
|
||||||
return
|
return
|
||||||
if not token_is_valid(token):
|
if not token_is_valid(token):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
cfg = limiter.get_cfg()
|
||||||
real_ip = ip_address(get_real_ip(request))
|
real_ip = ip_address(get_real_ip(request))
|
||||||
network = get_network(real_ip, cfg)
|
network = get_network(real_ip, cfg)
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,73 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
"""Compatibility with older versions"""
|
# lint: pylint
|
||||||
|
# pyright: basic
|
||||||
|
"""Module for backward compatibility.
|
||||||
|
|
||||||
# pylint: disable=unused-import
|
"""
|
||||||
|
# pylint: disable=C,R
|
||||||
|
|
||||||
__all__ = [
|
|
||||||
"tomllib",
|
|
||||||
]
|
|
||||||
|
|
||||||
import sys
|
__all__ = ('cached_property',)
|
||||||
|
|
||||||
# TOML (lib) compatibility
|
|
||||||
# ------------------------
|
|
||||||
|
|
||||||
if sys.version_info >= (3, 11):
|
try:
|
||||||
import tomllib
|
from functools import cached_property # type: ignore
|
||||||
else:
|
|
||||||
import tomli as tomllib
|
except ImportError:
|
||||||
|
|
||||||
|
# cache_property has been added in py3.8 [1]
|
||||||
|
#
|
||||||
|
# To support cache_property in py3.7 the implementation from 3.8 has been
|
||||||
|
# copied here. This code can be cleanup with EOL of py3.7.
|
||||||
|
#
|
||||||
|
# [1] https://docs.python.org/3/library/functools.html#functools.cached_property
|
||||||
|
|
||||||
|
from threading import RLock
|
||||||
|
|
||||||
|
_NOT_FOUND = object()
|
||||||
|
|
||||||
|
class cached_property:
|
||||||
|
def __init__(self, func):
|
||||||
|
self.func = func
|
||||||
|
self.attrname = None
|
||||||
|
self.__doc__ = func.__doc__
|
||||||
|
self.lock = RLock()
|
||||||
|
|
||||||
|
def __set_name__(self, owner, name):
|
||||||
|
if self.attrname is None:
|
||||||
|
self.attrname = name
|
||||||
|
elif name != self.attrname:
|
||||||
|
raise TypeError(
|
||||||
|
"Cannot assign the same cached_property to two different names "
|
||||||
|
f"({self.attrname!r} and {name!r})."
|
||||||
|
)
|
||||||
|
|
||||||
|
def __get__(self, instance, owner=None):
|
||||||
|
if instance is None:
|
||||||
|
return self
|
||||||
|
if self.attrname is None:
|
||||||
|
raise TypeError("Cannot use cached_property instance without calling __set_name__ on it.")
|
||||||
|
try:
|
||||||
|
cache = instance.__dict__
|
||||||
|
except AttributeError: # not all objects have __dict__ (e.g. class defines slots)
|
||||||
|
msg = (
|
||||||
|
f"No '__dict__' attribute on {type(instance).__name__!r} "
|
||||||
|
f"instance to cache {self.attrname!r} property."
|
||||||
|
)
|
||||||
|
raise TypeError(msg) from None
|
||||||
|
val = cache.get(self.attrname, _NOT_FOUND)
|
||||||
|
if val is _NOT_FOUND:
|
||||||
|
with self.lock:
|
||||||
|
# check if another thread filled cache while we awaited lock
|
||||||
|
val = cache.get(self.attrname, _NOT_FOUND)
|
||||||
|
if val is _NOT_FOUND:
|
||||||
|
val = self.func(instance)
|
||||||
|
try:
|
||||||
|
cache[self.attrname] = val
|
||||||
|
except TypeError:
|
||||||
|
msg = (
|
||||||
|
f"The '__dict__' attribute on {type(instance).__name__!r} instance "
|
||||||
|
f"does not support item assignment for caching {self.attrname!r} property."
|
||||||
|
)
|
||||||
|
raise TypeError(msg) from None
|
||||||
|
return val
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
# lint: pylint
|
||||||
"""This module holds the *data* created by::
|
"""This module holds the *data* created by::
|
||||||
|
|
||||||
make data.all
|
make data.all
|
||||||
|
@ -14,7 +15,6 @@ __all__ = [
|
||||||
'EXTERNAL_BANGS',
|
'EXTERNAL_BANGS',
|
||||||
'OSM_KEYS_TAGS',
|
'OSM_KEYS_TAGS',
|
||||||
'ENGINE_DESCRIPTIONS',
|
'ENGINE_DESCRIPTIONS',
|
||||||
'LOCALES',
|
|
||||||
'ahmia_blacklist_loader',
|
'ahmia_blacklist_loader',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -50,4 +50,3 @@ EXTERNAL_BANGS = _load('external_bangs.json')
|
||||||
OSM_KEYS_TAGS = _load('osm_keys_tags.json')
|
OSM_KEYS_TAGS = _load('osm_keys_tags.json')
|
||||||
ENGINE_DESCRIPTIONS = _load('engine_descriptions.json')
|
ENGINE_DESCRIPTIONS = _load('engine_descriptions.json')
|
||||||
ENGINE_TRAITS = _load('engine_traits.json')
|
ENGINE_TRAITS = _load('engine_traits.json')
|
||||||
LOCALES = _load('locales.json')
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,69 +0,0 @@
|
||||||
{
|
|
||||||
"LOCALE_NAMES": {
|
|
||||||
"af": "Afrikaans",
|
|
||||||
"ar": "العربية (Arabic)",
|
|
||||||
"bg": "Български (Bulgarian)",
|
|
||||||
"bn": "বাংলা (Bangla)",
|
|
||||||
"bo": "བོད་སྐད་ (Tibetan)",
|
|
||||||
"ca": "Català (Catalan)",
|
|
||||||
"cs": "Čeština (Czech)",
|
|
||||||
"cy": "Cymraeg (Welsh)",
|
|
||||||
"da": "Dansk (Danish)",
|
|
||||||
"de": "Deutsch (German)",
|
|
||||||
"dv": "ދިވެހި (Dhivehi)",
|
|
||||||
"el-GR": "Ελληνικά, Ελλάδα (Greek, Greece)",
|
|
||||||
"en": "English",
|
|
||||||
"eo": "Esperanto",
|
|
||||||
"es": "Español (Spanish)",
|
|
||||||
"et": "Eesti (Estonian)",
|
|
||||||
"eu": "Euskara (Basque)",
|
|
||||||
"fa-IR": "فارسی, ایران (Persian, Iran)",
|
|
||||||
"fi": "Suomi (Finnish)",
|
|
||||||
"fil": "Filipino",
|
|
||||||
"fr": "Français (French)",
|
|
||||||
"gl": "Galego (Galician)",
|
|
||||||
"he": "עברית (Hebrew)",
|
|
||||||
"hr": "Hrvatski (Croatian)",
|
|
||||||
"hu": "Magyar (Hungarian)",
|
|
||||||
"ia": "Interlingua",
|
|
||||||
"id": "Indonesia (Indonesian)",
|
|
||||||
"it": "Italiano (Italian)",
|
|
||||||
"ja": "日本語 (Japanese)",
|
|
||||||
"ko": "한국어 (Korean)",
|
|
||||||
"lt": "Lietuvių (Lithuanian)",
|
|
||||||
"lv": "Latviešu (Latvian)",
|
|
||||||
"ml": "മലയാളം (Malayalam)",
|
|
||||||
"ms": "Melayu (Malay)",
|
|
||||||
"nb-NO": "Norsk bokmål, Norge (Norwegian bokmål, Norway)",
|
|
||||||
"nl": "Nederlands (Dutch)",
|
|
||||||
"nl-BE": "Nederlands, België (Dutch, Belgium)",
|
|
||||||
"oc": "Occitan",
|
|
||||||
"pa": "ਪੰਜਾਬੀ (Punjabi)",
|
|
||||||
"pap": "Papiamento",
|
|
||||||
"pl": "Polski (Polish)",
|
|
||||||
"pt": "Português (Portuguese)",
|
|
||||||
"pt-BR": "Português, Brasil (Portuguese, Brazil)",
|
|
||||||
"ro": "Română (Romanian)",
|
|
||||||
"ru": "Русский (Russian)",
|
|
||||||
"si": "සිංහල (Sinhala)",
|
|
||||||
"sk": "Slovenčina (Slovak)",
|
|
||||||
"sl": "Slovenščina (Slovenian)",
|
|
||||||
"sr": "Српски (Serbian)",
|
|
||||||
"sv": "Svenska (Swedish)",
|
|
||||||
"szl": "Ślōnski (Silesian)",
|
|
||||||
"ta": "தமிழ் (Tamil)",
|
|
||||||
"te": "తెలుగు (Telugu)",
|
|
||||||
"th": "ไทย (Thai)",
|
|
||||||
"tr": "Türkçe (Turkish)",
|
|
||||||
"uk": "Українська (Ukrainian)",
|
|
||||||
"vi": "Tiếng việt (Vietnamese)",
|
|
||||||
"zh-HK": "中文, 中國香港特別行政區 (Chinese, Hong Kong SAR China)",
|
|
||||||
"zh-Hans-CN": "中文, 中国 (Chinese, China)",
|
|
||||||
"zh-Hant-TW": "中文, 台灣 (Chinese, Taiwan)"
|
|
||||||
},
|
|
||||||
"RTL_LOCALES": [
|
|
||||||
"ar",
|
|
||||||
"fa-IR",
|
|
||||||
"he"
|
|
||||||
]
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
|
"versions": [
|
||||||
|
"117.0",
|
||||||
|
"116.0"
|
||||||
|
],
|
||||||
"os": [
|
"os": [
|
||||||
"Windows NT 10.0; Win64; x64",
|
"Windows NT 10.0; Win64; x64",
|
||||||
"X11; Linux x86_64"
|
"X11; Linux x86_64"
|
||||||
],
|
],
|
||||||
"ua": "Mozilla/5.0 ({os}; rv:{version}) Gecko/20100101 Firefox/{version}",
|
"ua": "Mozilla/5.0 ({os}; rv:{version}) Gecko/20100101 Firefox/{version}"
|
||||||
"versions": [
|
|
||||||
"132.0",
|
|
||||||
"131.0"
|
|
||||||
]
|
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,5 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
# lint: pylint
|
||||||
"""Implementations of the framework for the SearXNG engines.
|
"""Implementations of the framework for the SearXNG engines.
|
||||||
|
|
||||||
.. hint::
|
.. hint::
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
# lint: pylint
|
||||||
"""Engine's traits are fetched from the origin engines and stored in a JSON file
|
"""Engine's traits are fetched from the origin engines and stored in a JSON file
|
||||||
in the *data folder*. Most often traits are languages and region codes and
|
in the *data folder*. Most often traits are languages and region codes and
|
||||||
their mapping from SearXNG's representation to the representation in the origin
|
their mapping from SearXNG's representation to the representation in the origin
|
||||||
|
@ -13,7 +14,8 @@ from __future__ import annotations
|
||||||
import json
|
import json
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import types
|
import types
|
||||||
from typing import Dict, Literal, Iterable, Union, Callable, Optional, TYPE_CHECKING
|
from typing import Dict, Iterable, Union, Callable, Optional, TYPE_CHECKING
|
||||||
|
from typing_extensions import Literal, Self
|
||||||
|
|
||||||
from searx import locales
|
from searx import locales
|
||||||
from searx.data import data_dir, ENGINE_TRAITS
|
from searx.data import data_dir, ENGINE_TRAITS
|
||||||
|
@ -134,7 +136,7 @@ class EngineTraits:
|
||||||
return EngineTraits(**dataclasses.asdict(self))
|
return EngineTraits(**dataclasses.asdict(self))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def fetch_traits(cls, engine: Engine) -> Union['EngineTraits', None]:
|
def fetch_traits(cls, engine: Engine) -> Union[Self, None]:
|
||||||
"""Call a function ``fetch_traits(engine_traits)`` from engines namespace to fetch
|
"""Call a function ``fetch_traits(engine_traits)`` from engines namespace to fetch
|
||||||
and set properties from the origin engine in the object ``engine_traits``. If
|
and set properties from the origin engine in the object ``engine_traits``. If
|
||||||
function does not exists, ``None`` is returned.
|
function does not exists, ``None`` is returned.
|
||||||
|
@ -166,7 +168,7 @@ class EngineTraits:
|
||||||
# - name: google italian
|
# - name: google italian
|
||||||
# engine: google
|
# engine: google
|
||||||
# language: it
|
# language: it
|
||||||
# region: it-IT # type: ignore
|
# region: it-IT
|
||||||
|
|
||||||
traits = self.copy()
|
traits = self.copy()
|
||||||
|
|
||||||
|
@ -202,7 +204,7 @@ class EngineTraitsMap(Dict[str, EngineTraits]):
|
||||||
json.dump(self, f, indent=2, sort_keys=True, cls=EngineTraitsEncoder)
|
json.dump(self, f, indent=2, sort_keys=True, cls=EngineTraitsEncoder)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_data(cls) -> 'EngineTraitsMap':
|
def from_data(cls) -> Self:
|
||||||
"""Instantiate :class:`EngineTraitsMap` object from :py:obj:`ENGINE_TRAITS`"""
|
"""Instantiate :class:`EngineTraitsMap` object from :py:obj:`ENGINE_TRAITS`"""
|
||||||
obj = cls()
|
obj = cls()
|
||||||
for k, v in ENGINE_TRAITS.items():
|
for k, v in ENGINE_TRAITS.items():
|
||||||
|
@ -210,7 +212,7 @@ class EngineTraitsMap(Dict[str, EngineTraits]):
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def fetch_traits(cls, log: Callable) -> 'EngineTraitsMap':
|
def fetch_traits(cls, log: Callable) -> Self:
|
||||||
from searx import engines # pylint: disable=cyclic-import, import-outside-toplevel
|
from searx import engines # pylint: disable=cyclic-import, import-outside-toplevel
|
||||||
|
|
||||||
names = list(engines.engines)
|
names = list(engines.engines)
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
# pylint: disable=invalid-name
|
"""
|
||||||
"""1337x
|
1337x
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from urllib.parse import quote, urljoin
|
from urllib.parse import quote, urljoin
|
||||||
from lxml import html
|
from lxml import html
|
||||||
from searx.utils import extract_text, eval_xpath, eval_xpath_list, eval_xpath_getindex
|
from searx.utils import extract_text, get_torrent_size, eval_xpath, eval_xpath_list, eval_xpath_getindex
|
||||||
|
|
||||||
# about
|
# about
|
||||||
about = {
|
about = {
|
||||||
|
@ -40,7 +39,9 @@ def response(resp):
|
||||||
title = extract_text(eval_xpath(result, './td[contains(@class, "name")]/a[2]'))
|
title = extract_text(eval_xpath(result, './td[contains(@class, "name")]/a[2]'))
|
||||||
seed = extract_text(eval_xpath(result, './/td[contains(@class, "seeds")]'))
|
seed = extract_text(eval_xpath(result, './/td[contains(@class, "seeds")]'))
|
||||||
leech = extract_text(eval_xpath(result, './/td[contains(@class, "leeches")]'))
|
leech = extract_text(eval_xpath(result, './/td[contains(@class, "leeches")]'))
|
||||||
filesize = extract_text(eval_xpath(result, './/td[contains(@class, "size")]/text()'))
|
filesize_info = extract_text(eval_xpath(result, './/td[contains(@class, "size")]/text()'))
|
||||||
|
filesize, filesize_multiplier = filesize_info.split()
|
||||||
|
filesize = get_torrent_size(filesize, filesize_multiplier)
|
||||||
|
|
||||||
results.append(
|
results.append(
|
||||||
{
|
{
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue