24 Commits

Author SHA1 Message Date
d0ee97582c changed configuration
Some checks failed
Documentation / Release (push) Has been cancelled
Integration / Python 3.10 (push) Has been cancelled
Integration / Python 3.11 (push) Has been cancelled
Integration / Python 3.12 (push) Has been cancelled
Integration / Python 3.13 (push) Has been cancelled
Integration / Python 3.9 (push) Has been cancelled
Integration / Theme (push) Has been cancelled
Integration / Docker (push) Has been cancelled
Security / Container (push) Has been cancelled
Checker / Search (push) Has been cancelled
Translation / Update (push) Has been cancelled
Translation / Pull Request (push) Has been cancelled
Update searx.data / update_ahmia_blacklist.py (push) Has been cancelled
Update searx.data / update_currencies.py (push) Has been cancelled
Update searx.data / update_engine_descriptions.py (push) Has been cancelled
Update searx.data / update_engine_traits.py (push) Has been cancelled
Update searx.data / update_external_bangs.py (push) Has been cancelled
Update searx.data / update_firefox_version.py (push) Has been cancelled
Update searx.data / update_wikidata_units.py (push) Has been cancelled
2025-07-19 18:11:19 +00:00
ac3dd7b804 replaced favicon
Some checks failed
Security / Container (push) Has been cancelled
Documentation / Release (push) Has been cancelled
Integration / Python 3.10 (push) Has been cancelled
Integration / Python 3.11 (push) Has been cancelled
Integration / Python 3.12 (push) Has been cancelled
Integration / Python 3.13 (push) Has been cancelled
Integration / Python 3.9 (push) Has been cancelled
Integration / Theme (push) Has been cancelled
Integration / Docker (push) Has been cancelled
2025-05-10 23:53:49 -05:00
3075003825 changed branding
Some checks failed
Documentation / Release (push) Has been cancelled
Integration / Python 3.10 (push) Has been cancelled
Integration / Python 3.11 (push) Has been cancelled
Integration / Python 3.12 (push) Has been cancelled
Integration / Python 3.13 (push) Has been cancelled
Integration / Python 3.9 (push) Has been cancelled
Integration / Theme (push) Has been cancelled
Integration / Docker (push) Has been cancelled
2025-05-10 23:38:21 -05:00
c6f1156bc6 changed approach, got rid of settings.yml binding entirely
Some checks failed
Documentation / Release (push) Has been cancelled
Integration / Python 3.10 (push) Has been cancelled
Integration / Python 3.11 (push) Has been cancelled
Integration / Python 3.12 (push) Has been cancelled
Integration / Python 3.13 (push) Has been cancelled
Integration / Python 3.9 (push) Has been cancelled
Integration / Theme (push) Has been cancelled
Integration / Docker (push) Has been cancelled
2025-05-10 22:50:37 -05:00
cf5dbbbc77 fixed...? 2025-05-10 22:45:56 -05:00
8477fb4846 oh, portainer didn't like that one 2025-05-10 22:43:33 -05:00
8204f4ee72 sets the config volume to read-only 2025-05-10 22:37:36 -05:00
9d9a0fe95e reverted 2025-05-10 22:31:02 -05:00
427a84d823 attempt #2 2025-05-10 22:29:01 -05:00
e971a3d7ab experimental mobile touchscreen support for oneko 2025-05-10 22:20:36 -05:00
89cb563793 fixed issue where oneko.gif was not referenced correctly, causing invisible neko 2025-05-10 21:51:46 -05:00
ac5c83b87d fixed typo in docker compose 2025-05-10 21:45:51 -05:00
34437e8491 implemented oneko 2025-05-10 21:41:29 -05:00
3d30ed1caa updated compose file to be able to define the port in an env var
Some checks failed
Documentation / Release (push) Has been cancelled
Integration / Python 3.10 (push) Has been cancelled
Integration / Python 3.11 (push) Has been cancelled
Integration / Python 3.12 (push) Has been cancelled
Integration / Python 3.13 (push) Has been cancelled
Integration / Python 3.9 (push) Has been cancelled
Integration / Theme (push) Has been cancelled
Integration / Docker (push) Has been cancelled
2025-05-10 20:46:57 -05:00
2ee495b383 whoops
Some checks failed
Documentation / Release (push) Has been cancelled
Integration / Python 3.10 (push) Has been cancelled
Integration / Python 3.11 (push) Has been cancelled
Integration / Python 3.12 (push) Has been cancelled
Integration / Python 3.13 (push) Has been cancelled
Integration / Python 3.9 (push) Has been cancelled
Integration / Theme (push) Has been cancelled
Integration / Docker (push) Has been cancelled
2025-05-10 20:31:49 -05:00
c27fd585ce carried over branding from current install
Some checks failed
Documentation / Release (push) Has been cancelled
Integration / Python 3.10 (push) Has been cancelled
Integration / Python 3.11 (push) Has been cancelled
Integration / Python 3.12 (push) Has been cancelled
Integration / Python 3.13 (push) Has been cancelled
Integration / Python 3.9 (push) Has been cancelled
Integration / Theme (push) Has been cancelled
Integration / Docker (push) Has been cancelled
2025-05-10 20:29:32 -05:00
89425caaa6 changed the embed description to nekosearch-branded desc. I think.
Some checks failed
Documentation / Release (push) Has been cancelled
Integration / Python 3.10 (push) Has been cancelled
Integration / Python 3.11 (push) Has been cancelled
Integration / Python 3.12 (push) Has been cancelled
Integration / Python 3.13 (push) Has been cancelled
Integration / Python 3.9 (push) Has been cancelled
Integration / Theme (push) Has been cancelled
Integration / Docker (push) Has been cancelled
2025-05-10 20:03:08 -05:00
52347c1843 added pull_policy to docker-compose
Some checks failed
Documentation / Release (push) Has been cancelled
Integration / Python 3.10 (push) Has been cancelled
Integration / Python 3.11 (push) Has been cancelled
Integration / Python 3.12 (push) Has been cancelled
Integration / Python 3.13 (push) Has been cancelled
Integration / Python 3.9 (push) Has been cancelled
Integration / Theme (push) Has been cancelled
Integration / Docker (push) Has been cancelled
2025-05-10 19:44:39 -05:00
c5b2bff2c5 whoops, teehee, swapped ports on compose
Some checks failed
Documentation / Release (push) Has been cancelled
Integration / Python 3.10 (push) Has been cancelled
Integration / Python 3.11 (push) Has been cancelled
Integration / Python 3.12 (push) Has been cancelled
Integration / Python 3.13 (push) Has been cancelled
Integration / Python 3.9 (push) Has been cancelled
Integration / Theme (push) Has been cancelled
Integration / Docker (push) Has been cancelled
2025-05-10 19:30:43 -05:00
61059eff9c fixed docker-compose (maybe
Some checks failed
Documentation / Release (push) Has been cancelled
Integration / Python 3.10 (push) Has been cancelled
Integration / Python 3.11 (push) Has been cancelled
Integration / Python 3.12 (push) Has been cancelled
Integration / Python 3.13 (push) Has been cancelled
Integration / Python 3.9 (push) Has been cancelled
Integration / Theme (push) Has been cancelled
Integration / Docker (push) Has been cancelled
2025-05-10 19:15:00 -05:00
d159f8384f added docker-compose.yml for continuous integration
Some checks failed
Documentation / Release (push) Has been cancelled
Integration / Python 3.10 (push) Has been cancelled
Integration / Python 3.11 (push) Has been cancelled
Integration / Python 3.12 (push) Has been cancelled
Integration / Python 3.13 (push) Has been cancelled
Integration / Python 3.9 (push) Has been cancelled
Integration / Theme (push) Has been cancelled
Integration / Docker (push) Has been cancelled
2025-05-10 19:08:22 -05:00
Ivan Gabaldon
1b787ed35e [mod] refactor integration.yml (#4763)
Style changes, cleanup and improved integration with CI by leveraging the use of
shared cache between all workflows.
2025-05-10 13:59:31 +02:00
Ivan Gabaldon
8e2e7774d7 [mod] new l10n.yml workflow (#4734)
l10n.yml will run after integration.yml finishes successfully (will defer anything depending on integration.yml until heavy loads like container building are moved to separate workflows) and in master branch.

* After every integration.yml workflow completes successfully, only the `update` job runs.
* Dispatch and Crontab triggers only the `pr` job.

Style changes, cleanup and improved integration with CI by leveraging the use of shared cache between all workflows (not functional until all workflows have been refactored).
2025-05-10 13:08:20 +02:00
Ivan Gabaldon
e982b9f732 [fix] documentation should run on push/pr
Instead of executing the workflow after integration.yml completes correctly, let's run this workflow parallel to integration.yml restoring the original behaviour.
2025-05-10 07:41:42 +02:00
23 changed files with 1182 additions and 503 deletions

1
.env Normal file
View File

@@ -0,0 +1 @@
NEKOSEARCH_PORT="8080"

View File

@@ -4,11 +4,10 @@ name: Documentation
# yamllint disable-line rule:truthy
on:
workflow_dispatch:
workflow_run:
workflows:
- Integration
types:
- completed
push:
branches:
- master
pull_request:
branches:
- master
@@ -24,7 +23,6 @@ env:
jobs:
release:
if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'
name: Release
runs-on: ubuntu-24.04-arm
permissions:
@@ -56,7 +54,8 @@ jobs:
- name: Build documentation
run: make V=1 docs.clean docs.html
- name: Release
- if: github.ref_name == 'master'
name: Release
uses: JamesIves/github-pages-deploy-action@v4
with:
folder: "dist/docs"

View File

@@ -1,100 +1,106 @@
---
name: Integration
on: # yamllint disable-line rule:truthy
# yamllint disable-line rule:truthy
on:
push:
branches: ["master"]
branches:
- master
pull_request:
branches: ["master"]
branches:
- master
concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }}
cancel-in-progress: false
permissions:
contents: read
env:
PYTHON_VERSION: "3.13"
jobs:
python:
test:
name: Python ${{ matrix.python-version }}
runs-on: ubuntu-24.04
strategy:
matrix:
os: [ubuntu-24.04]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
python-version:
- "3.9"
- "3.10"
- "3.11"
- "3.12"
- "3.13"
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Ubuntu packages
run: |
sudo ./utils/searxng.sh install packages
- name: Set up Python
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
architecture: 'x64'
python-version: "${{ matrix.python-version }}"
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: "false"
- name: Setup cache Python
uses: actions/cache@v4
with:
key: "python-${{ matrix.python-version }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
restore-keys: "python-${{ matrix.python-version }}-${{ runner.arch }}-"
path: "./local/"
- name: Setup venv
run: make V=1 install
- name: Run tests
run: make V=1 ci.test
themes:
name: Themes
runs-on: ubuntu-24.04
theme:
name: Theme
runs-on: ubuntu-24.04-arm
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Ubuntu packages
run: sudo ./utils/searxng.sh install buildhost
- name: Set up Python
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
architecture: 'x64'
- name: Build themes
run: make themes.all
python-version: "${{ env.PYTHON_VERSION }}"
babel:
name: Update translations branch
runs-on: ubuntu-24.04
if: ${{ github.repository_owner == 'searxng' && github.ref == 'refs/heads/master' }}
needs:
- python
- themes
permissions:
contents: write # for make V=1 weblate.push.translations
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: '0'
token: ${{ secrets.WEBLATE_GITHUB_TOKEN }}
- name: Set up Python
uses: actions/setup-python@v5
persist-credentials: "false"
- name: Setup Node.js
uses: actions/setup-node@v4
with:
python-version: '3.12'
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
node-version-file: "./.nvmrc"
- name: Setup cache Node.js
uses: actions/cache@v4
with:
path: |
./local
./.nvm
./node_modules
key: python-ubuntu-20.04-3.12-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
- name: weblate & git setup
env:
WEBLATE_CONFIG: ${{ secrets.WEBLATE_CONFIG }}
run: |
mkdir -p ~/.config
echo "${WEBLATE_CONFIG}" > ~/.config/weblate
git config --global user.email "searxng-bot@users.noreply.github.com"
git config --global user.name "searxng-bot"
- name: Update transations
id: update
run: |
make V=1 weblate.push.translations
key: "nodejs-${{ runner.arch }}-${{ hashFiles('./.nvmrc', './package.json') }}"
path: "./client/simple/node_modules/"
- name: Setup cache Python
uses: actions/cache@v4
with:
key: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
restore-keys: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-"
path: "./local/"
- name: Setup venv
run: make V=1 install
- name: Build
run: make themes.all
dockers:
name: Docker
if: github.ref == 'refs/heads/master'
needs:
- python
- themes
- test
- theme
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
runs-on: ubuntu-24.04

136
.github/workflows/l10n.yml vendored Normal file
View File

@@ -0,0 +1,136 @@
---
name: Translation
# yamllint disable-line rule:truthy
on:
workflow_dispatch:
workflow_run:
workflows:
- Integration
types:
- completed
branches:
- master
schedule:
- cron: "05 07 * * 5"
concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }}
cancel-in-progress: false
permissions:
contents: read
env:
PYTHON_VERSION: "3.13"
jobs:
update:
if: github.repository_owner == 'searxng' && github.event.workflow_run.conclusion == 'success'
name: Update
runs-on: ubuntu-24.04-arm
permissions:
# For "make V=1 weblate.push.translations"
contents: write
steps:
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "${{ env.PYTHON_VERSION }}"
- name: Checkout
uses: actions/checkout@v4
with:
token: "${{ secrets.WEBLATE_GITHUB_TOKEN }}"
fetch-depth: "0"
- name: Setup cache Python
uses: actions/cache@v4
with:
key: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
restore-keys: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-"
path: "./local/"
- name: Setup venv
run: make V=1 install
- name: Setup Weblate
run: |
mkdir -p ~/.config
echo "${{ secrets.WEBLATE_CONFIG }}" > ~/.config/weblate
- name: Setup Git
run: |
git config --global user.email "searxng-bot@users.noreply.github.com"
git config --global user.name "searxng-bot"
- name: Update translations
run: make V=1 weblate.push.translations
pr:
if: |
github.repository_owner == 'searxng'
&& (github.event_name == 'workflow_dispatch' || github.event_name == 'schedule')
name: Pull Request
runs-on: ubuntu-24.04-arm
permissions:
# For "make V=1 weblate.translations.commit"
contents: write
# For action "peter-evans/create-pull-request"
pull-requests: write
steps:
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "${{ env.PYTHON_VERSION }}"
- name: Checkout
uses: actions/checkout@v4
with:
token: "${{ secrets.WEBLATE_GITHUB_TOKEN }}"
fetch-depth: "0"
- name: Setup cache Python
uses: actions/cache@v4
with:
key: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
restore-keys: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-"
path: "./local/"
- name: Setup venv
run: make V=1 install
- name: Setup Weblate
run: |
mkdir -p ~/.config
echo "${{ secrets.WEBLATE_CONFIG }}" > ~/.config/weblate
- name: Setup Git
run: |
git config --global user.email "searxng-bot@users.noreply.github.com"
git config --global user.name "searxng-bot"
- name: Merge and push translation updates
run: make V=1 weblate.translations.commit
- name: Create PR
id: cpr
uses: peter-evans/create-pull-request@v7
with:
author: "${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>"
committer: "searxng-bot <searxng-bot@users.noreply.github.com>"
title: "[l10n] update translations from Weblate"
commit-message: "[l10n] update translations from Weblate"
branch: "translations_update"
delete-branch: "true"
draft: "false"
signoff: "false"
labels: |
translation
- name: Display information
run: |
echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}"

View File

@@ -1,59 +0,0 @@
name: "Update translations"
on: # yamllint disable-line rule:truthy
schedule:
- cron: "05 07 * * 5"
workflow_dispatch:
jobs:
babel:
name: "create PR for additions from weblate"
runs-on: ubuntu-24.04
if: ${{ github.repository_owner == 'searxng' && github.ref == 'refs/heads/master' }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: '0'
token: ${{ secrets.WEBLATE_GITHUB_TOKEN }}
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
uses: actions/cache@v4
with:
path: |
./local
./.nvm
./node_modules
key: python-ubuntu-24.04-3.12-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
- name: weblate & git setup
env:
WEBLATE_CONFIG: ${{ secrets.WEBLATE_CONFIG }}
run: |
mkdir -p ~/.config
echo "${WEBLATE_CONFIG}" > ~/.config/weblate
git config --global user.email "searxng-bot@users.noreply.github.com"
git config --global user.name "searxng-bot"
- name: Merge and push transation updates
run: |
make V=1 weblate.translations.commit
- name: Create Pull Request
id: cpr
uses: peter-evans/create-pull-request@v3
with:
token: ${{ secrets.WEBLATE_GITHUB_TOKEN }}
commit-message: '[l10n] update translations from Weblate'
committer: searxng-bot <searxng-bot@users.noreply.github.com>
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
signoff: false
branch: translations_update
delete-branch: true
draft: false
title: '[l10n] update translations from Weblate'
body: |
update translations from Weblate
labels: |
translation

View File

@@ -1,56 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg8"
width="21.508125mm"
height="21.508017mm"
viewBox="0 0 21.508125 21.508015"
version="1.1"
viewBox="0 0 92 92"
height="92mm"
width="92mm">
id="svg1"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs2" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
id="defs1" />
<g
transform="translate(-40.921303,-17.416526)"
id="layer1">
<circle
r="0"
style="fill:none;stroke:#000000;stroke-width:12;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
cy="92"
cx="75"
id="path3713" />
<circle
r="30"
cy="53.902557"
cx="75.921303"
id="path834"
style="fill:none;fill-opacity:1;stroke:#3050ff;stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
id="layer1"
transform="translate(-54.245938,-114.24604)">
<path
d="m 67.514849,37.91524 a 18,18 0 0 1 21.051475,3.312407 18,18 0 0 1 3.137312,21.078282"
id="path852"
style="fill:none;fill-opacity:1;stroke:#3050ff;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
transform="rotate(-46.234709)"
ry="1.8669105e-13"
y="122.08995"
x="3.7063529"
height="39.963303"
width="18.846331"
id="rect912"
style="opacity:1;fill:#3050ff;fill-opacity:1;stroke:none;stroke-width:8;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
style="fill:#222222;fill-opacity:1;stroke:#ffffff;stroke-width:1.50812;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
d="m 55,115 5.000001,4.99999 h 5 L 75,130 70.000002,135 H 60.000001 L 55,130 Z"
id="path2" />
<path
style="fill:#222222;fill-opacity:1;stroke:#ffffff;stroke-width:1.50812;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
d="m 67,119.99999 h 3.000002 L 75,115 v 12.99999 z"
id="path3" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 980 B

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 310 KiB

7
docker-compose.yml Normal file
View File

@@ -0,0 +1,7 @@
services:
nekosearch:
build: .
pull_policy: build
restart: unless-stopped
ports:
- "${NEKOSEARCH_PORT}:8080"

View File

@@ -2,7 +2,7 @@ general:
# Debug mode, only for development. Is overwritten by ${SEARXNG_DEBUG}
debug: false
# displayed name
instance_name: "SearXNG"
instance_name: "nekosearch"
# For example: https://example.com/privacy
privacypolicy_url: false
# use true to use your own donation page written in searx/info/en/donate.md
@@ -32,16 +32,16 @@ brand:
search:
# Filter results. 0: None, 1: Moderate, 2: Strict
safe_search: 0
safe_search: 2
# Existing autocomplete backends: "360search", "baidu", "brave", "dbpedia", "duckduckgo", "google", "yandex",
# "mwmbl", "seznam", "sogou", "stract", "swisscows", "quark", "qwant", "wikipedia" -
# "mwmbl", "seznam", "sogou", "stract", "swisscows", "qwant", "wikipedia" -
# leave blank to turn it off by default.
autocomplete: ""
autocomplete: "duckduckgo"
# minimun characters to type before autocompleter starts
autocomplete_min: 4
# backend for the favicon near URL in search results.
# Available resolvers: "allesedv", "duckduckgo", "google", "yandex" - leave blank to turn it off by default.
favicon_resolver: ""
favicon_resolver: "duckduckgo"
# Default search language - leave blank to detect from browser information or
# use codes from 'languages.py'
default_lang: "auto"
@@ -83,8 +83,8 @@ server:
port: 8888
bind_address: "127.0.0.1"
# public URL of the instance, to ensure correct inbound links. Is overwritten
# by ${SEARXNG_BASE_URL}.
base_url: false # "http://example.com/location"
# by ${SEARXNG_URL}.
base_url: https://nekosear.ch # "http://example.com/location"
# rate limit the number of request on the instance, block some bots.
# Is overwritten by ${SEARXNG_LIMITER}
limiter: false
@@ -95,14 +95,13 @@ server:
# If your instance owns a /etc/searxng/settings.yml file, then set the following
# values there.
secret_key: "ultrasecretkey" # Is overwritten by ${SEARXNG_SECRET}
secret_key: "a9b0aafe71f3dbe131d66762f03e27ab02dfa409541184f3d34036926d7dd79e" # Is overwritten by ${SEARXNG_SECRET}
# Proxy image results through SearXNG. Is overwritten by ${SEARXNG_IMAGE_PROXY}
image_proxy: false
# 1.0 and 1.1 are supported
http_protocol_version: "1.0"
# POST queries are more secure as they don't show up in history but may cause
# problems when using Firefox containers.
# Is overwritten by ${SEARXNG_METHOD}
# problems when using Firefox containers
method: "POST"
default_http_headers:
X-Content-Type-Options: nosniff
@@ -124,13 +123,13 @@ ui:
templates_path: ""
# query_in_title: When true, the result page's titles contains the query
# it decreases the privacy, since the browser can records the page titles.
query_in_title: false
query_in_title: true
# infinite_scroll: When true, automatically loads the next page when scrolling to bottom of the current page.
infinite_scroll: false
infinite_scroll: true
# ui theme
default_theme: simple
# center the results ?
center_alignment: false
center_alignment: true
# URL prefix of the internet archive, don't forget trailing slash (if needed).
# cache_url: "https://webcache.googleusercontent.com/search?q=cache:"
# Default interface locale - leave blank to detect from browser information or
@@ -140,7 +139,7 @@ ui:
# results_on_new_tab: false
theme_args:
# style of simple theme: auto, light, dark
simple_style: auto
simple_style: dark
# Perform search immediately if a category selected.
# Disable to select multiple categories at once and start the search manually.
search_on_category_select: true
@@ -185,7 +184,7 @@ ui:
#
outgoing:
# default timeout in seconds, can be override by engine
request_timeout: 3.0
request_timeout: 6.0
# the maximum timeout in seconds
# max_request_timeout: 10.0
# suffix of searx_useragent, could contain information like an email address
@@ -210,6 +209,14 @@ outgoing:
#
# proxies:
# all://:
# - http://38.33.146.13:2000
# - http://38.33.148.3:2000
# - http://38.38.254.150:2000
# - http://38.33.146.96:2000
#https: http://192.168.1.78:8888
#proxies:
#all://:
#- http://192.168.1.78:8888
# - http://proxy1:8080
# - http://proxy2:8080
#
@@ -217,7 +224,7 @@ outgoing:
#
# Extra seconds to add in order to account for the time taken by the proxy
#
# extra_proxy_timeout: 10
# extra_proxy_timeout: 20
#
# uncomment below section only if you have more than one network interface
# which can be the source of outgoing search requests
@@ -227,38 +234,29 @@ outgoing:
# - 1.1.1.2
# - fe80::/126
# Plugin configuration, for more details see
# External plugin configuration, for more details see
# https://docs.searxng.org/admin/settings/settings_plugins.html
#
plugins:
searx.plugins.calculator.SXNGPlugin:
active: true
searx.plugins.hash_plugin.SXNGPlugin:
active: true
searx.plugins.self_info.SXNGPlugin:
active: true
searx.plugins.unit_converter.SXNGPlugin:
active: true
searx.plugins.ahmia_filter.SXNGPlugin:
active: true
searx.plugins.hostnames.SXNGPlugin:
active: true
searx.plugins.oa_doi_rewrite.SXNGPlugin:
active: false
searx.plugins.tor_check.SXNGPlugin:
active: false
searx.plugins.tracker_url_remover.SXNGPlugin:
active: false
# plugins:
# - mypackage.mymodule.MyPlugin
# - mypackage.mymodule.MyOtherPlugin
# - ...
# Comment or un-comment plugin to activate / deactivate by default.
# https://docs.searxng.org/admin/settings/settings_plugins.html
#
# enabled_plugins:
# # these plugins are enabled if nothing is configured ..
# - 'Basic Calculator'
# - 'Hash plugin'
# - 'Self Information'
# - 'Tracker URL remover'
# - 'Unit converter plugin'
# - 'Ahmia blacklist' # activation depends on outgoing.using_tor_proxy
# # these plugins are disabled if nothing is configured ..
# - 'Hostnames plugin' # see 'hostnames' configuration below
# - 'Open Access DOI rewrite'
# - 'Tor check plugin'
# Configuration of the "Hostnames plugin":
#
@@ -362,11 +360,6 @@ engines:
shortcut: 9g
disabled: true
- name: acfun
engine: acfun
shortcut: acf
disabled: true
- name: adobe stock
engine: adobe_stock
shortcut: asi
@@ -434,11 +427,6 @@ engines:
disabled: true
shortcut: aa
- name: ansa
engine: ansa
shortcut: ans
disabled: true
# - name: annas articles
# engine: annas_archive
# shortcut: aaa
@@ -495,6 +483,7 @@ engines:
engine: artic
shortcut: arc
timeout: 4.0
disabled: true
- name: arxiv
engine: arxiv
@@ -516,27 +505,6 @@ engines:
shortcut: bc
categories: music
- name: baidu
baidu_category: general
categories: [general]
engine: baidu
shortcut: bd
disabled: true
- name: baidu images
baidu_category: images
categories: [images]
engine: baidu
shortcut: bdi
disabled: true
- name: baidu kaifa
baidu_category: it
categories: [it]
engine: baidu
shortcut: bdk
disabled: true
- name: wikipedia
engine: wikipedia
shortcut: wp
@@ -552,7 +520,6 @@ engines:
- name: bing
engine: bing
shortcut: bi
disabled: true
- name: bing images
engine: bing_images
@@ -566,11 +533,6 @@ engines:
engine: bing_videos
shortcut: biv
- name: bitchute
engine: bitchute
shortcut: bit
disabled: true
- name: bitbucket
engine: xpath
paging: true
@@ -619,38 +581,6 @@ engines:
# to show premium or plus results too:
# skip_premium: false
# WARNING: links from chinaso.com voilate users privacy
# Before activate these engines its mandatory to read
# - https://github.com/searxng/searxng/issues/4694
# - https://docs.searxng.org/dev/engines/online/chinaso.html
- name: chinaso news
engine: chinaso
shortcut: chinaso
categories: [news]
chinaso_category: news
chinaso_news_source: all
disabled: true
inactive: true
- name: chinaso images
engine: chinaso
network: chinaso news
shortcut: chinasoi
categories: [images]
chinaso_category: images
disabled: true
inactive: true
- name: chinaso videos
engine: chinaso
network: chinaso news
shortcut: chinasov
categories: [videos]
chinaso_category: videos
disabled: true
inactive: true
- name: cloudflareai
engine: cloudflareai
shortcut: cfai
@@ -725,6 +655,26 @@ engines:
search_type: news
disabled: true
- name: curlie
engine: xpath
shortcut: cl
categories: general
disabled: true
paging: true
lang_all: ''
search_url: https://curlie.org/search?q={query}&lang={lang}&start={pageno}&stime=92452189
page_size: 20
results_xpath: //div[@id="site-list-content"]/div[@class="site-item"]
url_xpath: ./div[@class="title-and-desc"]/a/@href
title_xpath: ./div[@class="title-and-desc"]/a/div
content_xpath: ./div[@class="title-and-desc"]/div[@class="site-descr"]
about:
website: https://curlie.org/
wikidata_id: Q60715723
use_official_api: false
require_api_key: false
results: HTML
- name: currency
engine: currency_convert
categories: general
@@ -744,6 +694,7 @@ engines:
engine: deviantart
shortcut: da
timeout: 3.0
disabled: true
- name: ddg definitions
engine: duckduckgo_definitions
@@ -803,24 +754,24 @@ engines:
results: HTML
# - name: elasticsearch
# shortcut: els
# shortcut: es
# engine: elasticsearch
# base_url: http://localhost:9200
# username: elastic
# password: changeme
# index: my-index
# enable_http: true
# # available options: match, simple_query_string, term, terms, custom
# query_type: match
# # if query_type is set to custom, provide your query here
# # custom_query_json: {"query":{"match_all": {}}}
# # show_metadata: false
# #custom_query_json: {"query":{"match_all": {}}}
# #show_metadata: false
# disabled: true
- name: wikidata
engine: wikidata
shortcut: wd
timeout: 3.0
disabled: true
weight: 2
# add "list" to the array to get results in the results list
display_type: ["infobox"]
@@ -925,6 +876,7 @@ engines:
# api_key: 'apikey' # required!
# Or you can use the html non-stable engine, activated by default
engine: flickr_noapi
disabled: true
- name: free software directory
engine: mediawiki
@@ -1013,11 +965,11 @@ engines:
engine: goodreads
shortcut: good
timeout: 4.0
disabled: true
- name: google
engine: google
shortcut: go
disabled: false
# additional_tests:
# android: *test_android
@@ -1126,27 +1078,6 @@ engines:
require_api_key: false
results: JSON
- name: il post
engine: il_post
shortcut: pst
- name: huggingface
engine: huggingface
shortcut: hf
disabled: true
- name: huggingface datasets
huggingface_endpoint: datasets
engine: huggingface
shortcut: hfd
disabled: true
- name: huggingface spaces
huggingface_endpoint: spaces
engine: huggingface
shortcut: hfs
disabled: true
- name: imdb
engine: imdb
shortcut: imdb
@@ -1180,11 +1111,6 @@ engines:
shortcut: ip
disabled: true
- name: iqiyi
engine: iqiyi
shortcut: iq
disabled: true
- name: jisho
engine: jisho
shortcut: js
@@ -1333,19 +1259,12 @@ engines:
disabled: true
number_of_results: 20
# https://docs.searxng.org/dev/engines/offline/search-indexer-engines.html#module-searx.engines.meilisearch
# - name: meilisearch
# engine: meilisearch
# shortcut: mes
# enable_http: true
# base_url: http://localhost:7700
# index: my-index
# auth_key: Bearer XXXX
- name: microsoft learn
engine: microsoft_learn
shortcut: msl
disabled: true
- name: mixcloud
engine: mixcloud
@@ -1382,11 +1301,6 @@ engines:
shortcut: mwm
disabled: true
- name: niconico
engine: niconico
shortcut: nico
disabled: true
- name: npm
engine: npm
shortcut: npm
@@ -1414,32 +1328,20 @@ engines:
require_api_key: false
results: JSON
# https://docs.searxng.org/dev/engines/online/mullvad_leta.html
- name: mullvadleta
engine: mullvad_leta
disabled: true
leta_engine: google
categories: [general, web]
shortcut: ml
- name: mullvadleta brave
engine: mullvad_leta
network: mullvadleta
disabled: true
leta_engine: brave
categories: [general, web]
shortcut: mlb
# read https://docs.searxng.org/dev/engines/online/mullvad_leta.html
# - name: mullvadleta
# engine: mullvad_leta
# leta_engine: google # choose one of the following: google, brave
# use_cache: true # Only 100 non-cache searches per day, suggested only for private instances
# search_url: https://leta.mullvad.net
# categories: [general, web]
# shortcut: ml
- name: odysee
engine: odysee
shortcut: od
disabled: true
- name: ollama
engine: ollama
shortcut: ollama
disabled: true
- name: openairedatasets
engine: json_engine
paging: true
@@ -1701,24 +1603,11 @@ engines:
shortcut: pypi
engine: pypi
- name: quark
quark_category: general
categories: [general]
engine: quark
shortcut: qk
disabled: true
- name: quark images
quark_category: images
categories: [images]
engine: quark
shortcut: qki
disabled: true
- name: qwant
qwant_categ: web
engine: qwant
shortcut: qw
disabled: true
categories: [general, web]
additional_tests:
rosebud: *test_rosebud
@@ -1776,12 +1665,6 @@ engines:
page_size: 25
disabled: true
- name: reuters
engine: reuters
shortcut: reu
# https://docs.searxng.org/dev/engines/online/reuters.html
# sort_order = "relevance"
- name: right dao
engine: xpath
paging: true
@@ -1836,12 +1719,6 @@ engines:
about:
website: https://searchmysite.net
- name: selfhst icons
engine: selfhst
shortcut: si
inactive: true
disabled: true
- name: sepiasearch
engine: sepiasearch
shortcut: sep
@@ -1972,10 +1849,6 @@ engines:
startpage_categ: images
categories: [images, web]
shortcut: spi
- name: steam
engine: steam
shortcut: stm
disabled: true
- name: tokyotoshokan
@@ -1995,13 +1868,13 @@ engines:
# For this demo of the sqlite engine download:
# https://liste.mediathekview.de/filmliste-v2.db.bz2
# and unpack into searx/data/filmliste-v2.db
# Query to test: "!mediathekview concert"
# Query to test: "!demo concert"
#
# - name: mediathekview
# - name: demo
# engine: sqlite
# shortcut: mediathekview
# categories: [general, videos]
# result_type: MainResult
# shortcut: demo
# categories: general
# result_template: default.html
# database: searx/data/filmliste-v2.db
# query_str: >-
# SELECT title || ' (' || time(duration, 'unixepoch') || ')' AS title,
@@ -2131,13 +2004,13 @@ engines:
- name: wiby
engine: json_engine
paging: true
disabled: true
search_url: https://wiby.me/json/?q={query}&p={pageno}
url_query: URL
title_query: Title
content_query: Snippet
categories: [general, web]
shortcut: wib
disabled: true
about:
website: https://wiby.me/
@@ -2346,8 +2219,8 @@ engines:
- name: mojeek
shortcut: mjk
engine: mojeek
categories: [general, web]
disabled: true
categories: [general, web]
- name: mojeek images
shortcut: mjkimg
@@ -2381,7 +2254,6 @@ engines:
content_xpath: //div[@class="total_dsc_wrap"]/a
first_page_num: 1
page_size: 10
disabled: true
about:
website: https://www.naver.com/
wikidata_id: Q485639
@@ -2670,12 +2542,6 @@ engines:
shortcut: pgo
disabled: true
- name: senscritique
engine: senscritique
shortcut: scr
timeout: 4.0
disabled: true
# Doku engine lets you access to any Doku wiki instance:
# A public one or a privete/corporate one.
# - name: ubuntuwiki

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -1 +1,26 @@
<svg xmlns="http://www.w3.org/2000/svg" width="92mm" height="92mm" viewBox="0 0 92 92"><g transform="translate(-40.921 -17.417)"><circle cx="75.921" cy="53.903" r="30" style="fill:none;fill-opacity:1;stroke:#3050ff;stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path d="M67.515 37.915a18 18 0 0 1 21.051 3.313 18 18 0 0 1 3.138 21.078" style="fill:none;fill-opacity:1;stroke:#3050ff;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><rect width="18.846" height="39.963" x="3.706" y="122.09" ry="0" style="opacity:1;fill:#3050ff;fill-opacity:1;stroke:none;stroke-width:8;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" transform="rotate(-46.235)"/></g></svg>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="21.508125mm"
height="21.508017mm"
viewBox="0 0 21.508125 21.508015"
version="1.1"
id="svg1"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<g
id="layer1"
transform="translate(-54.245938,-114.24604)">
<path
style="fill:#222222;fill-opacity:1;stroke:#ffffff;stroke-width:1.50812;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
d="m 55,115 5.000001,4.99999 h 5 L 75,130 70.000002,135 H 60.000001 L 55,130 Z"
id="path2" />
<path
style="fill:#222222;fill-opacity:1;stroke:#ffffff;stroke-width:1.50812;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
d="m 67,119.99999 h 3.000002 L 75,115 v 12.99999 z"
id="path3" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 726 B

After

Width:  |  Height:  |  Size: 980 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 13 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 310 KiB

View File

@@ -0,0 +1,242 @@
function neko() {
var nekoEl = document.createElement("div");
var nekoPosX = 32;
var nekoPosY = 32;
var mousePosX = 0;
var mousePosY = 0;
var frameCount = 0;
var idleTime = 0;
var idleAnimation = null;
var idleAnimationFrame = 0;
var direction;
var IE = document.all ? true : false;
var nekoSpeed = 10;
var spriteSets = {
idle: [[-3, -3]],
alert: [[-7, -3]],
scratchSelf: [
[-5, 0],
[-6, 0],
[-7, 0],
],
scratchWallN: [
[0, 0],
[0, -1],
],
scratchWallS: [
[-7, -1],
[-6, -2],
],
scratchWallE: [
[-2, -2],
[-2, -3],
],
scratchWallW: [
[-4, 0],
[-4, -1],
],
tired: [[-3, -2]],
sleeping: [
[-2, 0],
[-2, -1],
],
N: [
[-1, -2],
[-1, -3],
],
NE: [
[0, -2],
[0, -3],
],
E: [
[-3, 0],
[-3, -1],
],
SE: [
[-5, -1],
[-5, -2],
],
S: [
[-6, -3],
[-7, -2],
],
SW: [
[-5, -3],
[-6, -1],
],
W: [
[-4, -2],
[-4, -3],
],
NW: [
[-1, 0],
[-1, -1],
],
};
function init() {
nekoEl.id = "oneko";
nekoEl.ariaHidden = true;
nekoEl.style.width = "32px";
nekoEl.style.height = "32px";
nekoEl.style.position = "absolute";
nekoEl.style.pointerEvents = "none";
nekoEl.style.backgroundImage = "url('oneko.gif')";
nekoEl.style.imageRendering = "pixelated";
nekoEl.style.left = nekoPosX - 16 + "px";
nekoEl.style.top = nekoPosY - 16 + "px";
nekoEl.style.zIndex = Number.MAX_VALUE;
document.body.appendChild(nekoEl);
function mousePos(event) {
if (IE) {
event = window.event;
}
mousePosX = event.clientX;
mousePosY = event.clientY - 16;
}
document.onmousemove = mousePos;
window.onekoInterval = setInterval(frame, 100);
}
function setSprite(name, frame) {
var length = spriteSets[name].length;
if (IE) {
length = 0;
// Internet explorer is really fucking dumb
while (length < spriteSets[name].length) {
if (spriteSets[name][length] != null) {
length = length + 1;
continue;
}
break;
}
}
var sprite = spriteSets[name][frame % length];
nekoEl.style.backgroundPosition =
sprite["0"] * 32 + "px " + sprite["1"] * 32 + "px";
}
function resetIdleAnimation() {
idleAnimation = null;
idleAnimationFrame = 0;
}
function idle() {
idleTime = idleTime + 1;
// every ~ 20 seconds
if (
idleTime > 10 &&
Math.floor(Math.random() * 200) == 0 &&
idleAnimation == null
) {
var avalibleIdleAnimations = ["sleeping", "scratchSelf"];
if (nekoPosX < 32) {
avalibleIdleAnimations.push("scratchWallW");
}
if (nekoPosY < 32) {
avalibleIdleAnimations.push("scratchWallN");
}
if (nekoPosX > window.innerWidth - 32) {
avalibleIdleAnimations.push("scratchWallE");
}
if (nekoPosY > window.innerHeight - 32) {
avalibleIdleAnimations.push("scratchWallS");
}
idleAnimation =
avalibleIdleAnimations[
Math.floor(Math.random() * avalibleIdleAnimations.length)
];
}
switch (idleAnimation) {
case "sleeping":
if (idleAnimationFrame < 8) {
setSprite("tired", 0);
break;
}
setSprite("sleeping", Math.floor(idleAnimationFrame / 4));
if (idleAnimationFrame > 192) {
resetIdleAnimation();
}
break;
case "scratchWallN":
case "scratchWallS":
case "scratchWallE":
case "scratchWallW":
case "scratchSelf":
setSprite(idleAnimation, idleAnimationFrame);
if (idleAnimationFrame > 9) {
resetIdleAnimation();
}
break;
default:
setSprite("idle", 0);
return;
}
idleAnimationFrame = idleAnimationFrame + 1;
}
function frame() {
frameCount = frameCount + 1;
var diffX = nekoPosX - mousePosX;
var diffY = nekoPosY - mousePosY;
var distance = Math.sqrt(Math.pow(diffX, 2) + Math.pow(diffY, 2));
if (distance < nekoSpeed || distance < 48) {
idle();
return;
}
idleAnimation = null;
idleAnimationFrame = 0;
if (idleTime > 1) {
setSprite("alert", 0);
// count down after being alerted before moving
idleTime = Math.min(idleTime, 7);
idleTime = idleTime - 1;
return;
}
direction = "";
if (diffY / distance > 0.5) {
direction = "N";
} else if (diffY / distance < -0.5) {
direction = "S";
}
if (diffX / distance > 0.5) {
direction = direction + "W";
} else if (diffX / distance < -0.5) {
direction = direction + "E";
}
setSprite(direction, frameCount);
if (distance > nekoSpeed) {
nekoPosX = nekoPosX - (diffX / distance) * nekoSpeed;
nekoPosY = nekoPosY - (diffY / distance) * nekoSpeed;
} else {
nekoPosX = mousePosX;
nekoPosY = mousePosY;
}
nekoPosX = Math.min(
Math.max(16, nekoPosX),
document.getElementsByTagName("body")[0].clientWidth - 16
);
nekoPosY = Math.min(
Math.max(16, nekoPosY),
document.getElementsByTagName("body")[0].clientHeight - 16
);
nekoEl.style.left = nekoPosX - 16 + "px";
nekoEl.style.top = nekoPosY - 16 + "px";
}
init();
}
neko();

View File

@@ -0,0 +1,291 @@
// oneko.js: https://github.com/adryd325/oneko.js (webring variant)
(function oneko() {
const isReducedMotion =
window.matchMedia(`(prefers-reduced-motion: reduce)`) === true ||
window.matchMedia(`(prefers-reduced-motion: reduce)`).matches === true;
if (isReducedMotion) return;
const nekoEl = document.createElement("div");
let nekoPosX = 32;
let nekoPosY = 32;
let mousePosX = 0;
let mousePosY = 0;
// please use data-neko="true" on your A elements that link to another site with oneko-webring.js instead of this
// this is deprecated and will eventually be removed
const nekoSites = [
"localhost",
];
try {
const searchParams = location.search
.replace("?", "")
.split("&")
.map((keyvaluepair) => keyvaluepair.split("="));
// This is so much repeated code, I don't like it
tmp = searchParams.find((a) => a[0] == "catx");
if (tmp && tmp[1]) nekoPosX = parseInt(tmp[1]);
tmp = searchParams.find((a) => a[0] == "caty");
if (tmp && tmp[1]) nekoPosY = parseInt(tmp[1]);
tmp = searchParams.find((a) => a[0] == "catdx");
if (tmp && tmp[1]) mousePosX = parseInt(tmp[1]);
tmp = searchParams.find((a) => a[0] == "catdy");
if (tmp && tmp[1]) mousePosY = parseInt(tmp[1]);
} catch (e) {
console.error("oneko.js: failed to parse query params.");
console.error(e);
}
function onClick(event) {
const target = event.target.closest("A");
if (target === null || !target.getAttribute("href")) {
return;
}
let newLocation;
try {
newLocation = new URL(target.href);
} catch (e) {
return;
}
if (
(nekoSites.includes(newLocation.host) && newLocation.pathname == "/") ||
target.dataset.neko
) {
newLocation.searchParams.append("catx", Math.floor(nekoPosX));
newLocation.searchParams.append("caty", Math.floor(nekoPosY));
newLocation.searchParams.append("catdx", Math.floor(mousePosX));
newLocation.searchParams.append("catdy", Math.floor(mousePosY));
event.preventDefault();
window.location.href = newLocation.toString();
}
}
document.addEventListener("click", onClick);
let frameCount = 0;
let idleTime = 0;
let idleAnimation = null;
let idleAnimationFrame = 0;
const nekoSpeed = 10;
const spriteSets = {
idle: [[-3, -3]],
alert: [[-7, -3]],
scratchSelf: [
[-5, 0],
[-6, 0],
[-7, 0],
],
scratchWallN: [
[0, 0],
[0, -1],
],
scratchWallS: [
[-7, -1],
[-6, -2],
],
scratchWallE: [
[-2, -2],
[-2, -3],
],
scratchWallW: [
[-4, 0],
[-4, -1],
],
tired: [[-3, -2]],
sleeping: [
[-2, 0],
[-2, -1],
],
N: [
[-1, -2],
[-1, -3],
],
NE: [
[0, -2],
[0, -3],
],
E: [
[-3, 0],
[-3, -1],
],
SE: [
[-5, -1],
[-5, -2],
],
S: [
[-6, -3],
[-7, -2],
],
SW: [
[-5, -3],
[-6, -1],
],
W: [
[-4, -2],
[-4, -3],
],
NW: [
[-1, 0],
[-1, -1],
],
};
function init() {
nekoEl.id = "oneko";
nekoEl.ariaHidden = true;
nekoEl.style.width = "32px";
nekoEl.style.height = "32px";
nekoEl.style.position = "fixed";
nekoEl.style.pointerEvents = "none";
nekoEl.style.imageRendering = "pixelated";
nekoEl.style.left = `${nekoPosX - 16}px`;
nekoEl.style.top = `${nekoPosY - 16}px`;
nekoEl.style.zIndex = Number.MAX_VALUE;
let nekoFile = "./oneko.gif"
const curScript = document.currentScript
if (curScript && curScript.dataset.cat) {
nekoFile = curScript.dataset.cat
}
nekoEl.style.backgroundImage = `url(${nekoFile})`;
document.body.appendChild(nekoEl);
document.addEventListener("mousemove", function (event) {
mousePosX = event.clientX;
mousePosY = event.clientY;
});
window.requestAnimationFrame(onAnimationFrame);
}
let lastFrameTimestamp;
function onAnimationFrame(timestamp) {
// Stops execution if the neko element is removed from DOM
if (!nekoEl.isConnected) {
return;
}
if (!lastFrameTimestamp) {
lastFrameTimestamp = timestamp;
}
if (timestamp - lastFrameTimestamp > 100) {
lastFrameTimestamp = timestamp
frame()
}
window.requestAnimationFrame(onAnimationFrame);
}
function setSprite(name, frame) {
const sprite = spriteSets[name][frame % spriteSets[name].length];
nekoEl.style.backgroundPosition = `${sprite[0] * 32}px ${sprite[1] * 32}px`;
}
function resetIdleAnimation() {
idleAnimation = null;
idleAnimationFrame = 0;
}
function idle() {
idleTime += 1;
// every ~ 20 seconds
if (
idleTime > 10 &&
Math.floor(Math.random() * 200) == 0 &&
idleAnimation == null
) {
let avalibleIdleAnimations = ["sleeping", "scratchSelf"];
if (nekoPosX < 32) {
avalibleIdleAnimations.push("scratchWallW");
}
if (nekoPosY < 32) {
avalibleIdleAnimations.push("scratchWallN");
}
if (nekoPosX > window.innerWidth - 32) {
avalibleIdleAnimations.push("scratchWallE");
}
if (nekoPosY > window.innerHeight - 32) {
avalibleIdleAnimations.push("scratchWallS");
}
idleAnimation =
avalibleIdleAnimations[
Math.floor(Math.random() * avalibleIdleAnimations.length)
];
}
switch (idleAnimation) {
case "sleeping":
if (idleAnimationFrame < 8) {
setSprite("tired", 0);
break;
}
setSprite("sleeping", Math.floor(idleAnimationFrame / 4));
if (idleAnimationFrame > 192) {
resetIdleAnimation();
}
break;
case "scratchWallN":
case "scratchWallS":
case "scratchWallE":
case "scratchWallW":
case "scratchSelf":
setSprite(idleAnimation, idleAnimationFrame);
if (idleAnimationFrame > 9) {
resetIdleAnimation();
}
break;
default:
setSprite("idle", 0);
return;
}
idleAnimationFrame += 1;
}
function frame() {
frameCount += 1;
const diffX = nekoPosX - mousePosX;
const diffY = nekoPosY - mousePosY;
const distance = Math.sqrt(diffX ** 2 + diffY ** 2);
if (distance < nekoSpeed || distance < 48) {
idle();
return;
}
idleAnimation = null;
idleAnimationFrame = 0;
if (idleTime > 1) {
setSprite("alert", 0);
// count down after being alerted before moving
idleTime = Math.min(idleTime, 7);
idleTime -= 1;
return;
}
let direction;
direction = diffY / distance > 0.5 ? "N" : "";
direction += diffY / distance < -0.5 ? "S" : "";
direction += diffX / distance > 0.5 ? "W" : "";
direction += diffX / distance < -0.5 ? "E" : "";
setSprite(direction, frameCount);
nekoPosX -= (diffX / distance) * nekoSpeed;
nekoPosY -= (diffY / distance) * nekoSpeed;
nekoPosX = Math.min(Math.max(16, nekoPosX), window.innerWidth - 16);
nekoPosY = Math.min(Math.max(16, nekoPosY), window.innerHeight - 16);
nekoEl.style.left = `${nekoPosX - 16}px`;
nekoEl.style.top = `${nekoPosY - 16}px`;
}
init();
})();

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -0,0 +1,240 @@
// oneko.js: https://github.com/adryd325/oneko.js
(function oneko() {
const isReducedMotion =
window.matchMedia(`(prefers-reduced-motion: reduce)`) === true ||
window.matchMedia(`(prefers-reduced-motion: reduce)`).matches === true;
if (isReducedMotion) return;
const nekoEl = document.createElement("div");
let nekoPosX = 32;
let nekoPosY = 32;
let mousePosX = 0;
let mousePosY = 0;
let frameCount = 0;
let idleTime = 0;
let idleAnimation = null;
let idleAnimationFrame = 0;
const nekoSpeed = 10;
const spriteSets = {
idle: [[-3, -3]],
alert: [[-7, -3]],
scratchSelf: [
[-5, 0],
[-6, 0],
[-7, 0],
],
scratchWallN: [
[0, 0],
[0, -1],
],
scratchWallS: [
[-7, -1],
[-6, -2],
],
scratchWallE: [
[-2, -2],
[-2, -3],
],
scratchWallW: [
[-4, 0],
[-4, -1],
],
tired: [[-3, -2]],
sleeping: [
[-2, 0],
[-2, -1],
],
N: [
[-1, -2],
[-1, -3],
],
NE: [
[0, -2],
[0, -3],
],
E: [
[-3, 0],
[-3, -1],
],
SE: [
[-5, -1],
[-5, -2],
],
S: [
[-6, -3],
[-7, -2],
],
SW: [
[-5, -3],
[-6, -1],
],
W: [
[-4, -2],
[-4, -3],
],
NW: [
[-1, 0],
[-1, -1],
],
};
function init() {
nekoEl.id = "oneko";
nekoEl.ariaHidden = true;
nekoEl.style.width = "32px";
nekoEl.style.height = "32px";
nekoEl.style.position = "fixed";
nekoEl.style.pointerEvents = "none";
nekoEl.style.imageRendering = "pixelated";
nekoEl.style.left = `${nekoPosX - 16}px`;
nekoEl.style.top = `${nekoPosY - 16}px`;
nekoEl.style.zIndex = 2147483647;
let nekoFile = "/static/themes/simple/js/oneko.gif"
const curScript = document.currentScript
if (curScript && curScript.dataset.cat) {
nekoFile = curScript.dataset.cat
}
nekoEl.style.backgroundImage = `url(${nekoFile})`;
document.body.appendChild(nekoEl);
document.addEventListener("mousemove", function (event) {
mousePosX = event.clientX;
mousePosY = event.clientY;
});
window.requestAnimationFrame(onAnimationFrame);
}
let lastFrameTimestamp;
function onAnimationFrame(timestamp) {
// Stops execution if the neko element is removed from DOM
if (!nekoEl.isConnected) {
return;
}
if (!lastFrameTimestamp) {
lastFrameTimestamp = timestamp;
}
if (timestamp - lastFrameTimestamp > 100) {
lastFrameTimestamp = timestamp
frame()
}
window.requestAnimationFrame(onAnimationFrame);
}
function setSprite(name, frame) {
const sprite = spriteSets[name][frame % spriteSets[name].length];
nekoEl.style.backgroundPosition = `${sprite[0] * 32}px ${sprite[1] * 32}px`;
}
function resetIdleAnimation() {
idleAnimation = null;
idleAnimationFrame = 0;
}
function idle() {
idleTime += 1;
// every ~ 20 seconds
if (
idleTime > 10 &&
Math.floor(Math.random() * 200) == 0 &&
idleAnimation == null
) {
let avalibleIdleAnimations = ["sleeping", "scratchSelf"];
if (nekoPosX < 32) {
avalibleIdleAnimations.push("scratchWallW");
}
if (nekoPosY < 32) {
avalibleIdleAnimations.push("scratchWallN");
}
if (nekoPosX > window.innerWidth - 32) {
avalibleIdleAnimations.push("scratchWallE");
}
if (nekoPosY > window.innerHeight - 32) {
avalibleIdleAnimations.push("scratchWallS");
}
idleAnimation =
avalibleIdleAnimations[
Math.floor(Math.random() * avalibleIdleAnimations.length)
];
}
switch (idleAnimation) {
case "sleeping":
if (idleAnimationFrame < 8) {
setSprite("tired", 0);
break;
}
setSprite("sleeping", Math.floor(idleAnimationFrame / 4));
if (idleAnimationFrame > 192) {
resetIdleAnimation();
}
break;
case "scratchWallN":
case "scratchWallS":
case "scratchWallE":
case "scratchWallW":
case "scratchSelf":
setSprite(idleAnimation, idleAnimationFrame);
if (idleAnimationFrame > 9) {
resetIdleAnimation();
}
break;
default:
setSprite("idle", 0);
return;
}
idleAnimationFrame += 1;
}
function frame() {
frameCount += 1;
const diffX = nekoPosX - mousePosX;
const diffY = nekoPosY - mousePosY;
const distance = Math.sqrt(diffX ** 2 + diffY ** 2);
if (distance < nekoSpeed || distance < 48) {
idle();
return;
}
idleAnimation = null;
idleAnimationFrame = 0;
if (idleTime > 1) {
setSprite("alert", 0);
// count down after being alerted before moving
idleTime = Math.min(idleTime, 7);
idleTime -= 1;
return;
}
let direction;
direction = diffY / distance > 0.5 ? "N" : "";
direction += diffY / distance < -0.5 ? "S" : "";
direction += diffX / distance > 0.5 ? "W" : "";
direction += diffX / distance < -0.5 ? "E" : "";
setSprite(direction, frameCount);
nekoPosX -= (diffX / distance) * nekoSpeed;
nekoPosY -= (diffY / distance) * nekoSpeed;
nekoPosX = Math.min(Math.max(16, nekoPosX), window.innerWidth - 16);
nekoPosY = Math.min(Math.max(16, nekoPosY), window.innerHeight - 16);
nekoEl.style.left = `${nekoPosX - 16}px`;
nekoEl.style.top = `${nekoPosY - 16}px`;
}
init();
})();

View File

@@ -0,0 +1,7 @@
Copyright © 2022 adryd
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,19 @@
# oneko.js
A hacky script I wrote to put a cat on my site.
The default image is `oneko.gif` in the same directory as the script. This can be changed by adding `data-cat="yourimage.png"` to your `<script>` tag.
demo: https://adryd.com
This script is meant to be simple so that it can easily be extended upon. Pull requests adding features not seen in the [original neko program
](https://en.wikipedia.org/wiki/Neko_(software)) will probably not be merged.
implemented in a few different places
- Userscript: https://openuserjs.org/scripts/sjehuda/Oneko_WebMate
- Vencord: https://vencord.dev/plugins/oneko
- Spicetify: https://github.com/kyrie25/spicetify-oneko
feature forks
- Pet the cat: https://github.com/tylxr59/oneko.js/tree/main
- Move the cat using scroll wheel: https://github.com/rozbrajaczpoziomow/fork-oneko.js/tree/main

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>oneko.js</title>
</head>
<body>
<!--[if IE]>
<script src="./oneko-ie6.js"></script>
<![endif]-->
<!--[if !IE]><!-->
<script src="./oneko.js"></script>
<!--<![endif]-->
</body>
</html>

View File

@@ -5,6 +5,12 @@
"src": "js/searxng.head.js",
"isEntry": true
},
"js/oneko.js": {
"file": "js/oneko.js",
"name": "js/oneko.js",
"src": "js/oneko.js",
"isEntry": true
},
"js/searxng.js": {
"file": "js/searxng.min.js",
"name": "js/searxng.min",

Binary file not shown.

View File

@@ -2,8 +2,8 @@
<html class="no-js theme-{{ preferences.get_value('simple_style') or 'auto' }} center-alignment-{{ preferences.get_value('center_alignment') and 'yes' or 'no' }}" lang="{{ locale_rfc5646 }}" {% if rtl %} dir="rtl"{% endif %}>
<head>
<meta charset="UTF-8">
<meta name="description" content="SearXNG — a privacy-respecting, open metasearch engine">
<meta name="keywords" content="SearXNG, search, search engine, metasearch, meta search">
<meta name="description" content="nekosearch — a privacy-respecting, open metasearch engine for nekos">
<meta name="keywords" content="nekosearch, SearXNG, search, search engine, metasearch, meta search">
<meta name="generator" content="searxng/{{ searx_version }}">
<meta name="referrer" content="no-referrer">
<meta name="robots" content="noarchive">
@@ -84,6 +84,7 @@
</footer>
<!--[if gte IE 9]>-->
<script src="{{ url_for('static', filename='js/searxng.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/oneko.js') }}"></script>
<!--<![endif]-->
</body>
</html>