11 Commits

Author SHA1 Message Date
dependabot[bot]
ae4b73039f [upd] pypi: Bump sphinx-issues from 5.0.1 to 6.0.0 (#5877)
Bumps [sphinx-issues](https://github.com/sloria/sphinx-issues) from 5.0.1 to 6.0.0.
- [Commits](https://github.com/sloria/sphinx-issues/compare/5.0.1...6.0.0)

---
updated-dependencies:
- dependency-name: sphinx-issues
  dependency-version: 6.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...
2026-03-24 20:58:30 +01:00
Bnyro
220c42c8e9 [feat] engines: add support for aol.com (#5882)
Co-authored-by: Markus Heiser <markus.heiser@darmarit.de>
2026-03-24 20:44:15 +01:00
Markus Heiser
99ec6f296e [mod] drop support for Python releases older than 4 years (#5895)
The end-of-life (EOL) of a Python release is reached after 5 years, with the
last three years dedicated to security fixes. [1]

Unfortunately, this doesn't apply to common libraries (dependencies): bug fixes
are often only included in major releases, and minor releases with corresponding
security fixes are rarely offered.

To make matters worse, these dependencies often prematurely discontinue their
support for older Python releases (because, for example, they want/need to use
new Python features).

If we want to offer secure software, we are faced with the dilemma of either
supporting old Python releases and accepting that there are security bugs in the
dependencies, or ending support for older Python versions before the actual EOL
of the Python release.

[1] https://devguide.python.org/versions/

Closes: https://github.com/searxng/searxng/issues/5869

Signed-off-by: Markus Heiser <markus.heiser@darmarit.de>
2026-03-24 20:26:34 +01:00
Markus Heiser
054174a19d [build] /static 2026-03-24 20:21:27 +01:00
Ruben D.
5e8255f28a [MOD] generate manifest PWA icons (#5859) 2026-03-24 20:21:27 +01:00
Ruben D.
3dc4d5daa8 [mod] add manifest.json template and route (#5859)
URLs, name and colors are automatically rendered into manifest.json.
Furthermore user preference of theme (light, dark, black) and theme colors are
respected.  Theme colors can be set in settings.yml
2026-03-24 20:21:27 +01:00
Markus Heiser
924fc52f54 [build] /static 2026-03-24 19:39:11 +01:00
Markus Heiser
8d44ff51e2 [mod] remove the "Submit a new issue on Github" form (#5896)
Submitting an issue on GitHub isn't a end user task .. most issue reports coming
from this form are not filled out, since end users are not familiar with the
needs of a developer community.

Closes: https://github.com/searxng/searxng/issues/5820
Signed-off-by: Markus Heiser <markus.heiser@darmarit.de>
2026-03-24 19:39:11 +01:00
Bnyro
f8056b5e44 [chore] make data.traits 2026-03-24 15:55:54 +01:00
Bnyro
71cea1d87f [feat] engines: add boardreader engine (#5881) 2026-03-24 15:55:54 +01:00
Markus Heiser
c4f51aa4ac [fix] google engine - don't set __Secure-ENID in the HTTP header (#5894)
PR #5892 only deepends on the UA and the __Secure-ENID is not needed [1].

[1] https://github.com/searxng/searxng/pull/5892#issuecomment-4114835195

Suggested-by: @yeyuchen198

Signed-off-by: Markus Heiser <markus.heiser@darmarit.de>
2026-03-24 15:16:47 +01:00
26 changed files with 725 additions and 156 deletions

View File

@@ -27,7 +27,6 @@ jobs:
strategy:
matrix:
python-version:
- "3.10"
- "3.11"
- "3.12"
- "3.13"

View File

@@ -1,38 +0,0 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
.stats_endpoint {
.github-issue-button {
display: block;
font-size: 16px;
}
.issue-hide {
display: none;
}
input[type="checked"] {
position: absolute;
}
label {
margin: 1rem 1rem 1rem 0;
}
.step_content {
margin: 1rem 1rem 1rem 2rem;
}
.step1,
.step2 {
visibility: hidden;
}
.step1_delay {
transition: visibility 0s linear 4s;
}
#step1:checked ~ .step1,
#step2:checked ~ .step2 {
visibility: visible;
}
}

View File

@@ -11,7 +11,6 @@
@import "animations.less";
@import "embedded.less";
@import "info.less";
@import "new_issue.less";
@import "stats.less";
@import "result_templates.less";
@import "weather.less";

View File

@@ -18,8 +18,10 @@ export type Src2Dest = {
* Convert a list of SVG files to PNG.
*
* @param items - Array of SVG files (src: SVG, dest:PNG) to convert.
* @param width - (optional) width of the PNG pictures
* @param height - (optional) height of the PNG pictures.
*/
export const svg2png = (items: Src2Dest[]): void => {
export const svg2png = (items: Src2Dest[], width?: number, height?: number): void => {
for (const item of items) {
fs.mkdirSync(path.dirname(item.dest), { recursive: true });
@@ -29,6 +31,9 @@ export const svg2png = (items: Src2Dest[]): void => {
compressionLevel: 9,
palette: true
})
.resize(width, height, {
fit: "contain"
})
.toFile(item.dest)
.then((info) => {
console.log(`[svg2png] created ${item.dest} -- bytes: ${info.size}, w:${info.width}px, h:${info.height}px`);

View File

@@ -17,13 +17,15 @@ import { type Src2Dest, svg2png, svg2svg } from "./img.ts";
* Vite plugin to convert a list of SVG files to PNG.
*
* @param items - Array of SVG files (src: SVG, dest:PNG) to convert.
* @param width - (optional) width of the PNG picture
* @param height - (optional) height of the PNG picture
*/
export const plg_svg2png = (items: Src2Dest[]): Plugin => {
export const plg_svg2png = (items: Src2Dest[], width?: number, height?: number): Plugin => {
return {
name: "searxng-simple-svg2png",
apply: "build",
writeBundle: () => {
svg2png(items);
svg2png(items, width, height);
}
};
};

View File

@@ -132,6 +132,28 @@ export default {
}
]),
// SearXNG PWA Icons (static)
plg_svg2png(
[
{
src: `${PATH.brand}/searxng-wordmark.svg`,
dest: `${PATH.dist}/img/512.png`
}
],
512,
512
),
plg_svg2png(
[
{
src: `${PATH.brand}/searxng-wordmark.svg`,
dest: `${PATH.dist}/img/192.png`
}
],
192,
192
),
// -- svg
plg_svg2svg(
[

View File

@@ -0,0 +1,8 @@
.. _aol engine:
===
AOL
===
.. automodule:: searx.engines.aol
:members:

View File

@@ -1,6 +1,6 @@
[tools]
# minimal version we support
python = "3.10"
python = "3.11"
node = "25"
go = "1.24.5"
shellcheck = "0.11.0"

View File

@@ -8,7 +8,7 @@ selenium==4.41.0
Pallets-Sphinx-Themes==2.5.0
Sphinx==8.2.3 ; python_version >= '3.11'
Sphinx==8.1.3 ; python_version < '3.11'
sphinx-issues==5.0.1
sphinx-issues==6.0.0
sphinx-jinja==2.0.2
sphinx-tabs==3.5.0
sphinxcontrib-programoutput==0.19

View File

@@ -18,6 +18,17 @@ class BrandCustom(msgspec.Struct, kw_only=True, forbid_unknown_fields=True):
"""Custom entries in the footer of the WEB page: ``[title]: [link]``"""
class ThemeColors(msgspec.Struct, kw_only=True, forbid_unknown_fields=True):
"""Custom settings for theme colors in the brand section."""
theme_color_light: str = "#3050ff"
background_color_light: str = "#fff"
theme_color_dark: str = "#58f"
background_color_dark: str = "#222428"
theme_color_black: str = "#3050ff"
background_color_black: str = "#000"
class SettingsBrand(msgspec.Struct, kw_only=True, forbid_unknown_fields=True):
"""Options for configuring brand properties.
@@ -54,6 +65,9 @@ class SettingsBrand(msgspec.Struct, kw_only=True, forbid_unknown_fields=True):
:members:
"""
pwa_colors: ThemeColors = msgspec.field(default_factory=ThemeColors)
"""Custom settings for PWA colors."""
# new_issue_url is a hackish solution tailored for only one hoster (GH). As
# long as we don't have a more general solution, we should support it in the
# given function, but it should not be expanded further.

View File

@@ -119,7 +119,6 @@
"lo": "lo",
"lt": "lt",
"lv": "lv",
"mfe": "mfe",
"mg": "mg",
"mk": "mk",
"ml": "ml",
@@ -131,6 +130,7 @@
"ne": "ne",
"nl": "nl",
"no": "no",
"ny": "ny",
"om": "om",
"pa": "pa",
"pl": "pl",
@@ -338,9 +338,11 @@
"ar-TD": "ar-td",
"ar-TN": "ar-tn",
"ar-YE": "ar-ye",
"az-AZ": "az-az",
"be-BY": "be-by",
"bg-BG": "bg-bg",
"bn-BD": "bn-bd",
"bs-BA": "bs-ba",
"ca-AD": "ca-ad",
"cs-CZ": "cs-cz",
"da-DK": "da-dk",
@@ -350,6 +352,8 @@
"de-DE": "de-de",
"de-LI": "de-li",
"de-LU": "de-lu",
"dv-MV": "dv-mv",
"dz-BT": "dz-bt",
"el-CY": "el-cy",
"el-GR": "el-gr",
"en-AG": "en-ag",
@@ -462,6 +466,7 @@
"fa-IR": "fa-ir",
"fi-FI": "fi-fi",
"fil-PH": "fil-ph",
"fo-FO": "fo-fo",
"fr-BE": "fr-be",
"fr-BF": "fr-bf",
"fr-BI": "fr-bi",
@@ -507,10 +512,14 @@
"fr-WF": "fr-wf",
"fr-YT": "fr-yt",
"ga-IE": "ga-ie",
"gn-PY": "gn-py",
"gsw-CH": "gsw-ch",
"gsw-LI": "gsw-li",
"he-IL": "he-il",
"hi-IN": "hi-in",
"hr-BA": "hr-ba",
"hr-HR": "hr-hr",
"ht-HT": "ht-ht",
"hu-HU": "hu-hu",
"hy-AM": "hy-am",
"id-ID": "id-id",
@@ -522,19 +531,25 @@
"ja-JP": "ja-jp",
"ka-GE": "ka-ge",
"kk-KZ": "kk-kz",
"kl-GL": "kl-gl",
"km-KH": "km-kh",
"ko-KR": "ko-kr",
"ky-KG": "ky-kg",
"lb-LU": "lb-lu",
"lo-LA": "lo-la",
"lt-LT": "lt-lt",
"lv-LV": "lv-lv",
"mg-MG": "mg-mg",
"mi-NZ": "mi-nz",
"mk-MK": "mk-mk",
"mn-MN": "mn-mn",
"ms-BN": "ms-bn",
"ms-MY": "ms-my",
"ms-SG": "ms-sg",
"mt-MT": "mt-mt",
"my-MM": "my-mm",
"nb-NO": "nb-no",
"nd-ZW": "nd-zw",
"ne-NP": "ne-np",
"nl-AW": "nl-aw",
"nl-BE": "nl-be",
@@ -543,7 +558,11 @@
"nl-SR": "nl-sr",
"nl-SX": "nl-sx",
"nn-NO": "nn-no",
"ny-MW": "ny-mw",
"pap-AW": "pap-aw",
"pap-CW": "pap-cw",
"pl-PL": "pl-pl",
"ps-AF": "ps-af",
"pt-AO": "pt-ao",
"pt-BR": "pt-br",
"pt-CV": "pt-cv",
@@ -556,6 +575,7 @@
"qu-BO": "qu-bo",
"qu-EC": "qu-ec",
"qu-PE": "qu-pe",
"rn-BI": "rn-bi",
"ro-MD": "ro-md",
"ro-RO": "ro-ro",
"ru-BY": "ru-by",
@@ -563,22 +583,43 @@
"ru-KZ": "ru-kz",
"ru-RU": "ru-ru",
"ru-UA": "ru-ua",
"rw-RW": "rw-rw",
"sg-CF": "sg-cf",
"si-LK": "si-lk",
"sk-SK": "sk-sk",
"sl-SI": "sl-si",
"sn-ZW": "sn-zw",
"so-SO": "so-so",
"sq-AL": "sq-al",
"sr-BA": "sr-ba",
"sr-ME": "sr-me",
"sr-RS": "sr-rs",
"ss-SZ": "ss-sz",
"st-LS": "st-ls",
"sv-FI": "sv-fi",
"sv-SE": "sv-se",
"sw-KE": "sw-ke",
"sw-TZ": "sw-tz",
"sw-UG": "sw-ug",
"ta-LK": "ta-lk",
"ta-SG": "ta-sg",
"tg-TJ": "tg-tj",
"th-TH": "th-th",
"ti-ER": "ti-er",
"tk-TM": "tk-tm",
"tn-BW": "tn-bw",
"to-TO": "to-to",
"tpi-PG": "tpi-pg",
"tr-CY": "tr-cy",
"tr-TR": "tr-tr",
"tzm-MA": "tzm-ma",
"uk-UA": "uk-ua",
"ur-PK": "ur-pk",
"uz-UZ": "uz-uz",
"vi-VN": "vi-vn",
"wo-SN": "wo-sn",
"yo-NG": "yo-ng",
"yue-MO": "yue-mo",
"zh-CN": "zh-cn",
"zh-HK": "en-hk",
"zh-MO": "zh-mo",
@@ -702,9 +743,11 @@
"ar-TD": "ar-td",
"ar-TN": "ar-tn",
"ar-YE": "ar-ye",
"az-AZ": "az-az",
"be-BY": "be-by",
"bg-BG": "bg-bg",
"bn-BD": "bn-bd",
"bs-BA": "bs-ba",
"ca-AD": "ca-ad",
"cs-CZ": "cs-cz",
"da-DK": "da-dk",
@@ -714,6 +757,8 @@
"de-DE": "de-de",
"de-LI": "de-li",
"de-LU": "de-lu",
"dv-MV": "dv-mv",
"dz-BT": "dz-bt",
"el-CY": "el-cy",
"el-GR": "el-gr",
"en-AG": "en-ag",
@@ -826,6 +871,7 @@
"fa-IR": "fa-ir",
"fi-FI": "fi-fi",
"fil-PH": "fil-ph",
"fo-FO": "fo-fo",
"fr-BE": "fr-be",
"fr-BF": "fr-bf",
"fr-BI": "fr-bi",
@@ -871,10 +917,14 @@
"fr-WF": "fr-wf",
"fr-YT": "fr-yt",
"ga-IE": "ga-ie",
"gn-PY": "gn-py",
"gsw-CH": "gsw-ch",
"gsw-LI": "gsw-li",
"he-IL": "he-il",
"hi-IN": "hi-in",
"hr-BA": "hr-ba",
"hr-HR": "hr-hr",
"ht-HT": "ht-ht",
"hu-HU": "hu-hu",
"hy-AM": "hy-am",
"id-ID": "id-id",
@@ -886,19 +936,25 @@
"ja-JP": "ja-jp",
"ka-GE": "ka-ge",
"kk-KZ": "kk-kz",
"kl-GL": "kl-gl",
"km-KH": "km-kh",
"ko-KR": "ko-kr",
"ky-KG": "ky-kg",
"lb-LU": "lb-lu",
"lo-LA": "lo-la",
"lt-LT": "lt-lt",
"lv-LV": "lv-lv",
"mg-MG": "mg-mg",
"mi-NZ": "mi-nz",
"mk-MK": "mk-mk",
"mn-MN": "mn-mn",
"ms-BN": "ms-bn",
"ms-MY": "ms-my",
"ms-SG": "ms-sg",
"mt-MT": "mt-mt",
"my-MM": "my-mm",
"nb-NO": "nb-no",
"nd-ZW": "nd-zw",
"ne-NP": "ne-np",
"nl-AW": "nl-aw",
"nl-BE": "nl-be",
@@ -907,7 +963,11 @@
"nl-SR": "nl-sr",
"nl-SX": "nl-sx",
"nn-NO": "nn-no",
"ny-MW": "ny-mw",
"pap-AW": "pap-aw",
"pap-CW": "pap-cw",
"pl-PL": "pl-pl",
"ps-AF": "ps-af",
"pt-AO": "pt-ao",
"pt-BR": "pt-br",
"pt-CV": "pt-cv",
@@ -920,6 +980,7 @@
"qu-BO": "qu-bo",
"qu-EC": "qu-ec",
"qu-PE": "qu-pe",
"rn-BI": "rn-bi",
"ro-MD": "ro-md",
"ro-RO": "ro-ro",
"ru-BY": "ru-by",
@@ -927,22 +988,43 @@
"ru-KZ": "ru-kz",
"ru-RU": "ru-ru",
"ru-UA": "ru-ua",
"rw-RW": "rw-rw",
"sg-CF": "sg-cf",
"si-LK": "si-lk",
"sk-SK": "sk-sk",
"sl-SI": "sl-si",
"sn-ZW": "sn-zw",
"so-SO": "so-so",
"sq-AL": "sq-al",
"sr-BA": "sr-ba",
"sr-ME": "sr-me",
"sr-RS": "sr-rs",
"ss-SZ": "ss-sz",
"st-LS": "st-ls",
"sv-FI": "sv-fi",
"sv-SE": "sv-se",
"sw-KE": "sw-ke",
"sw-TZ": "sw-tz",
"sw-UG": "sw-ug",
"ta-LK": "ta-lk",
"ta-SG": "ta-sg",
"tg-TJ": "tg-tj",
"th-TH": "th-th",
"ti-ER": "ti-er",
"tk-TM": "tk-tm",
"tn-BW": "tn-bw",
"to-TO": "to-to",
"tpi-PG": "tpi-pg",
"tr-CY": "tr-cy",
"tr-TR": "tr-tr",
"tzm-MA": "tzm-ma",
"uk-UA": "uk-ua",
"ur-PK": "ur-pk",
"uz-UZ": "uz-uz",
"vi-VN": "vi-vn",
"wo-SN": "wo-sn",
"yo-NG": "yo-ng",
"yue-MO": "yue-mo",
"zh-CN": "zh-cn",
"zh-HK": "en-hk",
"zh-MO": "zh-mo",
@@ -1066,9 +1148,11 @@
"ar-TD": "ar-td",
"ar-TN": "ar-tn",
"ar-YE": "ar-ye",
"az-AZ": "az-az",
"be-BY": "be-by",
"bg-BG": "bg-bg",
"bn-BD": "bn-bd",
"bs-BA": "bs-ba",
"ca-AD": "ca-ad",
"cs-CZ": "cs-cz",
"da-DK": "da-dk",
@@ -1078,6 +1162,8 @@
"de-DE": "de-de",
"de-LI": "de-li",
"de-LU": "de-lu",
"dv-MV": "dv-mv",
"dz-BT": "dz-bt",
"el-CY": "el-cy",
"el-GR": "el-gr",
"en-AG": "en-ag",
@@ -1190,6 +1276,7 @@
"fa-IR": "fa-ir",
"fi-FI": "fi-fi",
"fil-PH": "fil-ph",
"fo-FO": "fo-fo",
"fr-BE": "fr-be",
"fr-BF": "fr-bf",
"fr-BI": "fr-bi",
@@ -1235,10 +1322,14 @@
"fr-WF": "fr-wf",
"fr-YT": "fr-yt",
"ga-IE": "ga-ie",
"gn-PY": "gn-py",
"gsw-CH": "gsw-ch",
"gsw-LI": "gsw-li",
"he-IL": "he-il",
"hi-IN": "hi-in",
"hr-BA": "hr-ba",
"hr-HR": "hr-hr",
"ht-HT": "ht-ht",
"hu-HU": "hu-hu",
"hy-AM": "hy-am",
"id-ID": "id-id",
@@ -1250,19 +1341,25 @@
"ja-JP": "ja-jp",
"ka-GE": "ka-ge",
"kk-KZ": "kk-kz",
"kl-GL": "kl-gl",
"km-KH": "km-kh",
"ko-KR": "ko-kr",
"ky-KG": "ky-kg",
"lb-LU": "lb-lu",
"lo-LA": "lo-la",
"lt-LT": "lt-lt",
"lv-LV": "lv-lv",
"mg-MG": "mg-mg",
"mi-NZ": "mi-nz",
"mk-MK": "mk-mk",
"mn-MN": "mn-mn",
"ms-BN": "ms-bn",
"ms-MY": "ms-my",
"ms-SG": "ms-sg",
"mt-MT": "mt-mt",
"my-MM": "my-mm",
"nb-NO": "nb-no",
"nd-ZW": "nd-zw",
"ne-NP": "ne-np",
"nl-AW": "nl-aw",
"nl-BE": "nl-be",
@@ -1271,7 +1368,11 @@
"nl-SR": "nl-sr",
"nl-SX": "nl-sx",
"nn-NO": "nn-no",
"ny-MW": "ny-mw",
"pap-AW": "pap-aw",
"pap-CW": "pap-cw",
"pl-PL": "pl-pl",
"ps-AF": "ps-af",
"pt-AO": "pt-ao",
"pt-BR": "pt-br",
"pt-CV": "pt-cv",
@@ -1284,6 +1385,7 @@
"qu-BO": "qu-bo",
"qu-EC": "qu-ec",
"qu-PE": "qu-pe",
"rn-BI": "rn-bi",
"ro-MD": "ro-md",
"ro-RO": "ro-ro",
"ru-BY": "ru-by",
@@ -1291,22 +1393,43 @@
"ru-KZ": "ru-kz",
"ru-RU": "ru-ru",
"ru-UA": "ru-ua",
"rw-RW": "rw-rw",
"sg-CF": "sg-cf",
"si-LK": "si-lk",
"sk-SK": "sk-sk",
"sl-SI": "sl-si",
"sn-ZW": "sn-zw",
"so-SO": "so-so",
"sq-AL": "sq-al",
"sr-BA": "sr-ba",
"sr-ME": "sr-me",
"sr-RS": "sr-rs",
"ss-SZ": "ss-sz",
"st-LS": "st-ls",
"sv-FI": "sv-fi",
"sv-SE": "sv-se",
"sw-KE": "sw-ke",
"sw-TZ": "sw-tz",
"sw-UG": "sw-ug",
"ta-LK": "ta-lk",
"ta-SG": "ta-sg",
"tg-TJ": "tg-tj",
"th-TH": "th-th",
"ti-ER": "ti-er",
"tk-TM": "tk-tm",
"tn-BW": "tn-bw",
"to-TO": "to-to",
"tpi-PG": "tpi-pg",
"tr-CY": "tr-cy",
"tr-TR": "tr-tr",
"tzm-MA": "tzm-ma",
"uk-UA": "uk-ua",
"ur-PK": "ur-pk",
"uz-UZ": "uz-uz",
"vi-VN": "vi-vn",
"wo-SN": "wo-sn",
"yo-NG": "yo-ng",
"yue-MO": "yue-mo",
"zh-CN": "en-hk",
"zh-HK": "en-hk",
"zh-MO": "zh-mo",
@@ -1430,9 +1553,11 @@
"ar-TD": "ar-td",
"ar-TN": "ar-tn",
"ar-YE": "ar-ye",
"az-AZ": "az-az",
"be-BY": "be-by",
"bg-BG": "bg-bg",
"bn-BD": "bn-bd",
"bs-BA": "bs-ba",
"ca-AD": "ca-ad",
"cs-CZ": "cs-cz",
"da-DK": "da-dk",
@@ -1442,6 +1567,8 @@
"de-DE": "de-de",
"de-LI": "de-li",
"de-LU": "de-lu",
"dv-MV": "dv-mv",
"dz-BT": "dz-bt",
"el-CY": "el-cy",
"el-GR": "el-gr",
"en-AG": "en-ag",
@@ -1554,6 +1681,7 @@
"fa-IR": "fa-ir",
"fi-FI": "fi-fi",
"fil-PH": "fil-ph",
"fo-FO": "fo-fo",
"fr-BE": "fr-be",
"fr-BF": "fr-bf",
"fr-BI": "fr-bi",
@@ -1599,10 +1727,14 @@
"fr-WF": "fr-wf",
"fr-YT": "fr-yt",
"ga-IE": "ga-ie",
"gn-PY": "gn-py",
"gsw-CH": "gsw-ch",
"gsw-LI": "gsw-li",
"he-IL": "he-il",
"hi-IN": "hi-in",
"hr-BA": "hr-ba",
"hr-HR": "hr-hr",
"ht-HT": "ht-ht",
"hu-HU": "hu-hu",
"hy-AM": "hy-am",
"id-ID": "id-id",
@@ -1614,19 +1746,25 @@
"ja-JP": "ja-jp",
"ka-GE": "ka-ge",
"kk-KZ": "kk-kz",
"kl-GL": "kl-gl",
"km-KH": "km-kh",
"ko-KR": "ko-kr",
"ky-KG": "ky-kg",
"lb-LU": "lb-lu",
"lo-LA": "lo-la",
"lt-LT": "lt-lt",
"lv-LV": "lv-lv",
"mg-MG": "mg-mg",
"mi-NZ": "mi-nz",
"mk-MK": "mk-mk",
"mn-MN": "mn-mn",
"ms-BN": "ms-bn",
"ms-MY": "ms-my",
"ms-SG": "ms-sg",
"mt-MT": "mt-mt",
"my-MM": "my-mm",
"nb-NO": "nb-no",
"nd-ZW": "nd-zw",
"ne-NP": "ne-np",
"nl-AW": "nl-aw",
"nl-BE": "nl-be",
@@ -1635,7 +1773,11 @@
"nl-SR": "nl-sr",
"nl-SX": "nl-sx",
"nn-NO": "nn-no",
"ny-MW": "ny-mw",
"pap-AW": "pap-aw",
"pap-CW": "pap-cw",
"pl-PL": "pl-pl",
"ps-AF": "ps-af",
"pt-AO": "pt-ao",
"pt-BR": "pt-br",
"pt-CV": "pt-cv",
@@ -1648,6 +1790,7 @@
"qu-BO": "qu-bo",
"qu-EC": "qu-ec",
"qu-PE": "qu-pe",
"rn-BI": "rn-bi",
"ro-MD": "ro-md",
"ro-RO": "ro-ro",
"ru-BY": "ru-by",
@@ -1655,22 +1798,43 @@
"ru-KZ": "ru-kz",
"ru-RU": "ru-ru",
"ru-UA": "ru-ua",
"rw-RW": "rw-rw",
"sg-CF": "sg-cf",
"si-LK": "si-lk",
"sk-SK": "sk-sk",
"sl-SI": "sl-si",
"sn-ZW": "sn-zw",
"so-SO": "so-so",
"sq-AL": "sq-al",
"sr-BA": "sr-ba",
"sr-ME": "sr-me",
"sr-RS": "sr-rs",
"ss-SZ": "ss-sz",
"st-LS": "st-ls",
"sv-FI": "sv-fi",
"sv-SE": "sv-se",
"sw-KE": "sw-ke",
"sw-TZ": "sw-tz",
"sw-UG": "sw-ug",
"ta-LK": "ta-lk",
"ta-SG": "ta-sg",
"tg-TJ": "tg-tj",
"th-TH": "th-th",
"ti-ER": "ti-er",
"tk-TM": "tk-tm",
"tn-BW": "tn-bw",
"to-TO": "to-to",
"tpi-PG": "tpi-pg",
"tr-CY": "tr-cy",
"tr-TR": "tr-tr",
"tzm-MA": "tzm-ma",
"uk-UA": "uk-ua",
"ur-PK": "ur-pk",
"uz-UZ": "uz-uz",
"vi-VN": "vi-vn",
"wo-SN": "wo-sn",
"yo-NG": "yo-ng",
"yue-MO": "yue-mo",
"zh-CN": "zh-cn",
"zh-HK": "en-hk",
"zh-MO": "zh-mo",
@@ -1678,6 +1842,55 @@
"zh-TW": "zh-tw"
}
},
"boardreader": {
"all_locale": "All",
"custom": {},
"data_type": "traits_v1",
"languages": {
"ar": "Arabic",
"bg": "Bulgarian",
"ca": "Catalan",
"cs": "Czech",
"da": "Danish",
"de": "German",
"el": "Greek",
"en": "English",
"es": "Spanish",
"et": "Estonian",
"fa": "Persian",
"fi": "Finnish",
"fil": "Filipino",
"fr": "French",
"he": "Hebrew",
"hr": "Croatian",
"hu": "Hungarian",
"id": "Indonesian",
"is": "Icelandic",
"it": "Italian",
"ja": "Japanese",
"kk": "Kazakh",
"ko": "Korean",
"lt": "Lithuanian",
"ms": "Malay",
"nl": "Dutch",
"no": "Norwegian",
"pl": "Polish",
"pt": "Portuguese",
"ro": "Romanian",
"ru": "Russian",
"sk": "Slovak",
"sl": "Slovenian",
"sq": "Albanian",
"sr": "Serbian",
"sv": "Swedish",
"th": "Thai",
"tr": "Turkish",
"uk": "Ukrainian",
"vi": "Vietnamese",
"zh": "Chinese"
},
"regions": {}
},
"brave": {
"all_locale": "all",
"custom": {
@@ -7847,6 +8060,7 @@
"ja": "ja",
"jv": "jv",
"ka": "ka",
"kaa": "kaa",
"km": "km",
"kn": "kn",
"ko": "ko",
@@ -7911,6 +8125,7 @@
"custom": {
"WIKIPEDIA_LANGUAGES": [
"ab",
"abstract",
"ace",
"ady",
"af",
@@ -8057,6 +8272,7 @@
"ka",
"kaa",
"kab",
"kai",
"kaj",
"kbd",
"kbp",
@@ -8297,6 +8513,7 @@
"ja": "ja.wikipedia.org",
"jv": "jv.wikipedia.org",
"ka": "ka.wikipedia.org",
"kaa": "kaa.wikipedia.org",
"km": "km.wikipedia.org",
"kn": "kn.wikipedia.org",
"ko": "ko.wikipedia.org",
@@ -8390,6 +8607,7 @@
"ja": "ja",
"jv": "jv",
"ka": "ka",
"kaa": "kaa",
"km": "km",
"kn": "kn",
"ko": "ko",
@@ -9065,4 +9283,4 @@
},
"regions": {}
}
}
}

208
searx/engines/aol.py Normal file
View File

@@ -0,0 +1,208 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""AOL supports WEB, image, and video search. Internally, it uses the Bing
index.
AOL doesn't seem to support setting the language via request parameters, instead
the results are based on the URL. For example, there is
- `search.aol.com <https://search.aol.com>`_ for English results
- `suche.aol.de <https://suche.aol.de>`_ for German results
However, AOL offers its services only in a few regions:
- en-US: search.aol.com
- de-DE: suche.aol.de
- fr-FR: recherche.aol.fr
- en-GB: search.aol.co.uk
- en-CA: search.aol.ca
In order to still offer sufficient support for language and region, the `search
keywords`_ known from Bing, ``language`` and ``loc`` (region), are added to the
search term (AOL is basically just a proxy for Bing).
.. _search keywords:
https://support.microsoft.com/en-us/topic/advanced-search-keywords-ea595928-5d63-4a0b-9c6b-0b769865e78a
"""
from urllib.parse import urlencode, unquote_plus
import typing as t
from lxml import html
from dateutil import parser
from searx.result_types import EngineResults
from searx.utils import eval_xpath_list, eval_xpath, extract_text
if t.TYPE_CHECKING:
from searx.extended_types import SXNG_Response
from searx.search.processors import OnlineParams
about = {
"website": "https://www.aol.com",
"wikidata_id": "Q2407",
"official_api_documentation": None,
"use_official_api": False,
"require_api_key": False,
"results": "HTML",
}
categories = ["general"]
search_type = "search" # supported: search, image, video
paging = True
safesearch = True
time_range_support = True
results_per_page = 10
base_url = "https://search.aol.com"
time_range_map = {"day": "1d", "week": "1w", "month": "1m", "year": "1y"}
safesearch_map = {0: "p", 1: "r", 2: "i"}
def init(_):
if search_type not in ("search", "image", "video"):
raise ValueError(f"unsupported search type {search_type}")
def request(query: str, params: "OnlineParams") -> None:
language, region = (params["searxng_locale"].split("-") + [None])[:2]
if language and language != "all":
query = f"{query} language:{language}"
if region:
query = f"{query} loc:{region}"
args: dict[str, str | int | None] = {
"q": query,
"b": params["pageno"] * results_per_page + 1, # page is 1-indexed
"pz": results_per_page,
}
if params["time_range"]:
args["fr2"] = "time"
args["age"] = params["time_range"]
else:
args["fr2"] = "sb-top-search"
params["cookies"]["sB"] = f"vm={safesearch_map[params['safesearch']]}"
params["url"] = f"{base_url}/aol/{search_type}?{urlencode(args)}"
logger.debug(params)
def _deobfuscate_url(obfuscated_url: str) -> str | None:
# URL looks like "https://search.aol.com/click/_ylt=AwjFSDjd;_ylu=JfsdjDFd/RV=2/RE=1774058166/RO=10/RU=https%3a%2f%2fen.wikipedia.org%2fwiki%2fTree/RK=0/RS=BP2CqeMLjscg4n8cTmuddlEQA2I-" # pylint: disable=line-too-long
if not obfuscated_url:
return None
for part in obfuscated_url.split("/"):
if part.startswith("RU="):
return unquote_plus(part[3:])
# pattern for de-obfuscating URL not found, fall back to Yahoo's tracking link
return obfuscated_url
def _general_results(doc: html.HtmlElement) -> EngineResults:
res = EngineResults()
for result in eval_xpath_list(doc, "//div[@id='web']//ol/li[not(contains(@class, 'first'))]"):
obfuscated_url = extract_text(eval_xpath(result, ".//h3/a/@href"))
if not obfuscated_url:
continue
url = _deobfuscate_url(obfuscated_url)
if not url:
continue
res.add(
res.types.MainResult(
url=url,
title=extract_text(eval_xpath(result, ".//h3/a")) or "",
content=extract_text(eval_xpath(result, ".//div[contains(@class, 'compText')]")) or "",
thumbnail=extract_text(eval_xpath(result, ".//a[contains(@class, 'thm')]/img/@data-src")) or "",
)
)
return res
def _video_results(doc: html.HtmlElement) -> EngineResults:
res = EngineResults()
for result in eval_xpath_list(doc, "//div[contains(@class, 'results')]//ol/li"):
obfuscated_url = extract_text(eval_xpath(result, ".//a/@href"))
if not obfuscated_url:
continue
url = _deobfuscate_url(obfuscated_url)
if not url:
continue
published_date_raw = extract_text(eval_xpath(result, ".//div[contains(@class, 'v-age')]"))
try:
published_date = parser.parse(published_date_raw or "")
except parser.ParserError:
published_date = None
res.add(
res.types.LegacyResult(
{
"template": "videos.html",
"url": url,
"title": extract_text(eval_xpath(result, ".//h3")),
"content": extract_text(eval_xpath(result, ".//div[contains(@class, 'compText')]")),
"thumbnail": extract_text(eval_xpath(result, ".//img[contains(@class, 'thm')]/@src")),
"length": extract_text(eval_xpath(result, ".//span[contains(@class, 'v-time')]")),
"publishedDate": published_date,
}
)
)
return res
def _image_results(doc: html.HtmlElement) -> EngineResults:
res = EngineResults()
for result in eval_xpath_list(doc, "//section[@id='results']//ul/li"):
obfuscated_url = extract_text(eval_xpath(result, "./a/@href"))
if not obfuscated_url:
continue
url = _deobfuscate_url(obfuscated_url)
if not url:
continue
res.add(
res.types.LegacyResult(
{
"template": "images.html",
# results don't have an extra URL, only the image source
"url": url,
"title": extract_text(eval_xpath(result, ".//a/@aria-label")),
"thumbnail_src": extract_text(eval_xpath(result, ".//img/@src")),
"img_src": url,
}
)
)
return res
def response(resp: "SXNG_Response") -> EngineResults:
doc = html.fromstring(resp.text)
match search_type:
case "search":
results = _general_results(doc)
case "image":
results = _image_results(doc)
case "video":
results = _video_results(doc)
case _:
raise ValueError("unsupported search type")
for suggestion in eval_xpath_list(doc, ".//ol[contains(@class, 'searchRightBottom')]//table//a"):
results.add(results.types.LegacyResult({"suggestion": extract_text(suggestion)}))
return results

View File

@@ -0,0 +1,145 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""Boardreader (forum search)"""
import re
from datetime import datetime
from urllib.parse import urlencode
import typing as t
import gettext
import babel
from searx.locales import language_tag
from searx.enginelib import EngineCache
from searx.enginelib.traits import EngineTraits
from searx.engines.json_engine import safe_search_map
from searx.exceptions import SearxEngineAPIException
from searx.network import get, raise_for_httperror
from searx.result_types import EngineResults
from searx.utils import extr, js_obj_str_to_python, html_to_text
if t.TYPE_CHECKING:
from searx.extended_types import SXNG_Response
from searx.search.processors import OnlineParams
about = {
"website": "https://boardreader.com",
"official_api_documentation": None,
"use_official_api": False,
"require_api_key": False,
"results": "JSON",
}
categories = ["general", "social media"]
paging = True
time_range_support = True
base_url = "https://boardreader.com"
time_range_map = {"day": "1", "week": "7", "month": "30", "year": "365"}
CACHE: EngineCache
CACHE_SESSION_ID_KEY = "session_id_key"
KEYWORD_RE = re.compile(r"\[\/?Keyword\]")
def init(engine_settings: dict[str, t.Any]) -> bool:
global CACHE # pylint: disable=global-statement
CACHE = EngineCache(engine_name=engine_settings["name"])
return True
def _get_session_id() -> str:
cached: str | None = CACHE.get(CACHE_SESSION_ID_KEY)
if cached:
return cached
resp = get(base_url)
if resp.status_code != 200:
raise_for_httperror(resp)
session_id = extr(resp.text, "'currentSessionId', '", "'")
if not session_id:
raise SearxEngineAPIException("failed to obtain session id")
CACHE.set(CACHE_SESSION_ID_KEY, session_id)
return session_id
def request(query: str, params: "OnlineParams"):
session_id = _get_session_id()
language: str = traits.get_language(
params["searxng_locale"], default="All"
) # pyright: ignore[reportAssignmentType]
args = {
"query": query,
"page": params["pageno"],
"language": language,
"session_id": session_id,
}
if params["time_range"]:
args["period"] = safe_search_map[params["time_range"]] # pyright: ignore[reportArgumentType]
params["url"] = f"{base_url}/return.php?{urlencode(args)}"
return params
def _remove_keyword_marker(text: str) -> str:
"""
Convert text like "[Keyword]ABCDE[/Keyword]" to "ABCDE".
"""
return html_to_text(KEYWORD_RE.sub("", text))
def response(resp: "SXNG_Response") -> EngineResults:
res = EngineResults()
result: dict[str, str]
for result in resp.json()["SearchResults"]:
res.add(
res.types.MainResult(
title=_remove_keyword_marker(result["Subject"]),
content=_remove_keyword_marker(result["Text"]),
url=result["Url"],
publishedDate=datetime.strptime(result["Published"], "%Y-%m-%d %H:%M:%S"),
metadata=gettext.gettext("Posted by {author}").format(author=result["Author"]),
)
)
return res
def fetch_traits(engine_traits: EngineTraits):
# load main page to be able to find location of JavaScript source code
resp = get(base_url)
if resp.status_code != 200:
raise_for_httperror(resp)
# load actual JavaScript code
script_name = "main." + extr(resp.text, "main.", ".js") + ".js"
script_resp = get(f"{base_url}/{script_name}")
if script_resp.status_code != 200:
raise_for_httperror(resp)
# find list of languages (JavaScript object)
js_object_string = extr(script_resp.text, "languageValues=", "}],") + "}]"
languages: list[dict[str, str]] = js_obj_str_to_python(js_object_string)
# finally, add all parsed languages to the engine traits
language: dict[str, str]
for language in languages:
search_value = language["value"]
for code in language["codes"]:
try:
locale = babel.Locale.parse(code)
except babel.UnknownLocaleError:
continue
sxng_lang = language_tag(locale)
if sxng_lang not in engine_traits.languages:
engine_traits.languages[sxng_lang] = search_value
# "All" is the search value to unset the search language
engine_traits.all_locale = "All"

View File

@@ -269,15 +269,6 @@ def get_google_info(params: "OnlineParams", eng_traits: EngineTraits) -> dict[st
ret_val["headers"]["Accept"] = "*/*"
ret_val["headers"]["User-Agent"] = gen_gsa_useragent()
# Hardcoded default ENID Header required alongside the Android Google App
# User Agent
ret_val["headers"]["__Secure-ENID"] = (
"28.SE=II9FMkz92GewodDwKRBFsMISph7GsQs8JYLdXmAlprl6UcC02O2p7kfQlAWuwT"
"oygcrqHpmwQSH57b0c2kXfRfo35J8aV5FYSeUzYB67hqZQ2tZB7-o0hlTKwb5qMjn8Cf"
"w_AZ2s_6KIFMAl2goXGcXHSfgu4jwZOqShlHCcag0ppy_NnxJYWxpLkaeuGCICwWoIFJ"
"HP6Gy4BOkIEsl1N_k6F6jMF_OklE9qIubiyKkNaA"
)
# Cookies
# - https://github.com/searxng/searxng/pull/1679#issuecomment-1235432746

View File

@@ -18,7 +18,6 @@ general:
open_metrics: ''
brand:
new_issue_url: https://github.com/searxng/searxng/issues/new
docs_url: https://docs.searxng.org/
public_instances: https://searx.space
wiki_url: https://github.com/searxng/searxng/wiki
@@ -28,6 +27,15 @@ brand:
# links:
# Uptime: https://uptime.searxng.org/history/darmarit-org
# About: "https://searxng.org"
# pwa_colors:
# # Custom settings for PWA icon an colors used in manifest.json
# # Default colors are:
# theme_color_light: "#3050ff"
# background_color_light: "fff"
# theme_color_dark: "#58f"
# background_color_dark: "#222428"
# theme_color_black: "#3050ff"
# background_color_black: "#000"
search:
# Filter results. 0: None, 1: Moderate, 2: Strict
@@ -413,6 +421,24 @@ engines:
shortcut: conda
disabled: true
- name: aol
engine: aol
search_type: search
categories: [general]
shortcut: aol
- name: aol images
engine: aol
search_type: image
categories: [images]
shortcut: aoli
- name: aol videos
engine: aol
search_type: video
categories: [videos]
shortcut: aolv
- name: arch linux wiki
engine: archlinux
shortcut: al
@@ -538,6 +564,11 @@ engines:
require_api_key: false
results: HTML
- name: boardreader
engine: boardreader
shortcut: boa
disabled: true
- name: bpb
engine: bpb
shortcut: bpb

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -12,17 +12,16 @@ sxng_locales = (
('af', 'Afrikaans', '', 'Afrikaans', '\U0001f310'),
('ar', 'العربية', '', 'Arabic', '\U0001f310'),
('ar-SA', 'العربية', 'المملكة العربية السعودية', 'Arabic', '\U0001f1f8\U0001f1e6'),
('be', 'Беларуская', '', 'Belarusian', '\U0001f310'),
('bg', 'Български', '', 'Bulgarian', '\U0001f310'),
('bg-BG', 'Български', 'България', 'Bulgarian', '\U0001f1e7\U0001f1ec'),
('ca', 'Català', '', 'Catalan', '\U0001f310'),
('cs', 'Čeština', '', 'Czech', '\U0001f310'),
('cs-CZ', 'Čeština', 'Česko', 'Czech', '\U0001f1e8\U0001f1ff'),
('cy', 'Cymraeg', '', 'Welsh', '\U0001f310'),
('da', 'Dansk', '', 'Danish', '\U0001f310'),
('da-DK', 'Dansk', 'Danmark', 'Danish', '\U0001f1e9\U0001f1f0'),
('de', 'Deutsch', '', 'German', '\U0001f310'),
('de-AT', 'Deutsch', 'Österreich', 'German', '\U0001f1e6\U0001f1f9'),
('de-BE', 'Deutsch', 'Belgien', 'German', '\U0001f1e7\U0001f1ea'),
('de-CH', 'Deutsch', 'Schweiz', 'German', '\U0001f1e8\U0001f1ed'),
('de-DE', 'Deutsch', 'Deutschland', 'German', '\U0001f1e9\U0001f1ea'),
('el', 'Ελληνικά', '', 'Greek', '\U0001f310'),
@@ -31,6 +30,7 @@ sxng_locales = (
('en-AU', 'English', 'Australia', 'English', '\U0001f1e6\U0001f1fa'),
('en-CA', 'English', 'Canada', 'English', '\U0001f1e8\U0001f1e6'),
('en-GB', 'English', 'United Kingdom', 'English', '\U0001f1ec\U0001f1e7'),
('en-HK', 'English', 'Hong Kong SAR China', 'English', '\U0001f1ed\U0001f1f0'),
('en-IE', 'English', 'Ireland', 'English', '\U0001f1ee\U0001f1ea'),
('en-IN', 'English', 'India', 'English', '\U0001f1ee\U0001f1f3'),
('en-NZ', 'English', 'New Zealand', 'English', '\U0001f1f3\U0001f1ff'),
@@ -48,43 +48,37 @@ sxng_locales = (
('es-PE', 'Español', 'Perú', 'Spanish', '\U0001f1f5\U0001f1ea'),
('et', 'Eesti', '', 'Estonian', '\U0001f310'),
('et-EE', 'Eesti', 'Eesti', 'Estonian', '\U0001f1ea\U0001f1ea'),
('eu', 'Euskara', '', 'Basque', '\U0001f310'),
('fa', 'فارسی', '', 'Persian', '\U0001f310'),
('fi', 'Suomi', '', 'Finnish', '\U0001f310'),
('fi-FI', 'Suomi', 'Suomi', 'Finnish', '\U0001f1eb\U0001f1ee'),
('fil', 'Filipino', '', 'Filipino', '\U0001f310'),
('fil-PH', 'Filipino', 'Pilipinas', 'Filipino', '\U0001f1f5\U0001f1ed'),
('fr', 'Français', '', 'French', '\U0001f310'),
('fr-BE', 'Français', 'Belgique', 'French', '\U0001f1e7\U0001f1ea'),
('fr-CA', 'Français', 'Canada', 'French', '\U0001f1e8\U0001f1e6'),
('fr-CH', 'Français', 'Suisse', 'French', '\U0001f1e8\U0001f1ed'),
('fr-FR', 'Français', 'France', 'French', '\U0001f1eb\U0001f1f7'),
('ga', 'Gaeilge', '', 'Irish', '\U0001f310'),
('gd', 'Gàidhlig', '', 'Scottish Gaelic', '\U0001f310'),
('gl', 'Galego', '', 'Galician', '\U0001f310'),
('he', 'עברית', '', 'Hebrew', '\U0001f1ee\U0001f1f1'),
('hi', 'हिन्दी', '', 'Hindi', '\U0001f310'),
('hi-IN', 'हिन्दी', 'भारत', 'Hindi', '\U0001f1ee\U0001f1f3'),
('hr', 'Hrvatski', '', 'Croatian', '\U0001f310'),
('hu', 'Magyar', '', 'Hungarian', '\U0001f310'),
('hu-HU', 'Magyar', 'Magyarország', 'Hungarian', '\U0001f1ed\U0001f1fa'),
('id', 'Indonesia', '', 'Indonesian', '\U0001f310'),
('id-ID', 'Indonesia', 'Indonesia', 'Indonesian', '\U0001f1ee\U0001f1e9'),
('is', 'Íslenska', '', 'Icelandic', '\U0001f310'),
('it', 'Italiano', '', 'Italian', '\U0001f310'),
('it-CH', 'Italiano', 'Svizzera', 'Italian', '\U0001f1e8\U0001f1ed'),
('it-IT', 'Italiano', 'Italia', 'Italian', '\U0001f1ee\U0001f1f9'),
('ja', '日本語', '', 'Japanese', '\U0001f310'),
('ja-JP', '日本語', '日本', 'Japanese', '\U0001f1ef\U0001f1f5'),
('kn', 'ಕನ್ನಡ', '', 'Kannada', '\U0001f310'),
('ko', '한국어', '', 'Korean', '\U0001f310'),
('ko-KR', '한국어', '대한민국', 'Korean', '\U0001f1f0\U0001f1f7'),
('lt', 'Lietuvių', '', 'Lithuanian', '\U0001f310'),
('lv', 'Latviešu', '', 'Latvian', '\U0001f310'),
('ml', 'മലയാളം', '', 'Malayalam', '\U0001f310'),
('mr', 'मराठी', '', 'Marathi', '\U0001f310'),
('nb', 'Norsk Bokmål', '', 'Norwegian Bokmål', '\U0001f310'),
('nb-NO', 'Norsk Bokmål', 'Norge', 'Norwegian Bokmål', '\U0001f1f3\U0001f1f4'),
('nl', 'Nederlands', '', 'Dutch', '\U0001f310'),
('nl-BE', 'Nederlands', 'België', 'Dutch', '\U0001f1e7\U0001f1ea'),
('nl-NL', 'Nederlands', 'Nederland', 'Dutch', '\U0001f1f3\U0001f1f1'),
('nn', 'Norsk Nynorsk', '', 'Norwegian Nynorsk', '\U0001f310'),
('nn-NO', 'Norsk Nynorsk', 'Noreg', 'Norwegian Nynorsk', '\U0001f1f3\U0001f1f4'),
('pl', 'Polski', '', 'Polish', '\U0001f310'),
('pl-PL', 'Polski', 'Polska', 'Polish', '\U0001f1f5\U0001f1f1'),
('pt', 'Português', '', 'Portuguese', '\U0001f310'),
@@ -95,18 +89,15 @@ sxng_locales = (
('ru', 'Русский', '', 'Russian', '\U0001f310'),
('ru-RU', 'Русский', 'Россия', 'Russian', '\U0001f1f7\U0001f1fa'),
('sk', 'Slovenčina', '', 'Slovak', '\U0001f310'),
('sl', 'Slovenščina', '', 'Slovenian', '\U0001f310'),
('sq', 'Shqip', '', 'Albanian', '\U0001f310'),
('sv', 'Svenska', '', 'Swedish', '\U0001f310'),
('sv-FI', 'Svenska', 'Finland', 'Swedish', '\U0001f1eb\U0001f1ee'),
('sv-SE', 'Svenska', 'Sverige', 'Swedish', '\U0001f1f8\U0001f1ea'),
('ta', 'தமிழ்', '', 'Tamil', '\U0001f310'),
('te', 'తెలుగు', '', 'Telugu', '\U0001f310'),
('th', 'ไทย', '', 'Thai', '\U0001f310'),
('th-TH', 'ไทย', 'ไทย', 'Thai', '\U0001f1f9\U0001f1ed'),
('tr', 'Türkçe', '', 'Turkish', '\U0001f310'),
('tr-TR', 'Türkçe', 'Türkiye', 'Turkish', '\U0001f1f9\U0001f1f7'),
('uk', 'Українська', '', 'Ukrainian', '\U0001f310'),
('ur', 'اردو', '', 'Urdu', '\U0001f310'),
('vi', 'Tiếng Việt', '', 'Vietnamese', '\U0001f310'),
('vi-VN', 'Tiếng Việt', 'Việt Nam', 'Vietnamese', '\U0001f1fb\U0001f1f3'),
('zh', '中文', '', 'Chinese', '\U0001f310'),

View File

@@ -5,7 +5,7 @@
<meta name="endpoint" content="{{ endpoint }}">
<meta name="description" content="SearXNG — a privacy-respecting, open metasearch engine">
<meta name="keywords" content="SearXNG, search, search engine, metasearch, meta search">
<meta name="generator" content="searxng/{{ searx_version }}">
<meta name="generator" content="searxng/{{ searxng_version }}">
<meta name="referrer" content="no-referrer">
<meta name="robots" content="noarchive">
<meta name="viewport" content="width=device-width, initial-scale=1">
@@ -26,6 +26,7 @@
<link rel="icon" href="{{ url_for('static', filename='img/favicon.png') }}" sizes="any">
<link rel="icon" href="{{ url_for('static', filename='img/favicon.svg') }}" type="image/svg+xml">
<link rel="apple-touch-icon" href="{{ url_for('static', filename='img/favicon.png') }}">
<link rel="manifest" href="{{ url_for('manifest') }}" />
</head>
<body class="{{ endpoint }}_endpoint" >
<main id="main_{{ self._TemplateReference__context.name|replace("simple/", "")|replace(".html", "") }}" class="{{body_class}}">
@@ -65,8 +66,8 @@
</main>
<footer>
<p>
{{ _('Powered by') }} <a href="{{ url_for('info', pagename='about') }}">SearXNG</a> - {{ searx_version }} — {{ _('a privacy-respecting, open metasearch engine') }}<br>
<a href="{{ searx_git_url }}">{{ _('Source code') }}</a>
{{ _('Powered by') }} <a href="{{ url_for('info', pagename='about') }}">SearXNG</a> - {{ searxng_version }} — {{ _('a privacy-respecting, open metasearch engine') }}<br>
<a href="{{ searxng_git_url }}">{{ _('Source code') }}</a>
| <a href="{{ get_setting('brand.issue_url') }}">{{ _('Issue tracker') }}</a>
{% if enable_metrics %}| <a href="{{ url_for('stats') }}">{{ _('Engine stats') }}</a>{% endif %}
{% if get_setting('brand.public_instances') %}

View File

@@ -0,0 +1,25 @@
{
"name": "{{ instance_name }}",
"short_name": "{{ instance_name }}",
"icons": [
{
"src": "{{ url_for('static', filename='img/favicon.svg', _external=True) }}",
"sizes": "any",
"type": "image/svg+xml"
},
{
"src": "{{ url_for('static', filename='img/192.png', _external=True) }}",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "{{ url_for('static', filename='img/512.png', _external=True) }}",
"sizes": "512x512",
"type": "image/png"
}
],
"start_url": "{{ url_for('index') }}",
"theme_color": "{{ theme_color }}" ,
"background_color": "{{ background_color }}",
"display": "standalone"
}

View File

@@ -1,71 +0,0 @@
{% macro new_issue(engine_name, engine_reliability) %}
<form action="{{ get_setting('brand.new_issue_url') }}" method="GET">
<input name="title" type="hidden" value="Bug: {{ engine_name }} engine">
<input name="labels" type="hidden" value="bug">
<input name="template" type="hidden" value="bug-report.md">
<textarea name="body" class="issue-hide">{{- '' -}}
**Version of SearXNG, commit number if you are using on master branch and stipulate if you forked SearXNG**
{% if searx_git_url and searx_git_url != 'unknow' %}
Repository: {{ searx_git_url }}
Branch: {{ searx_git_branch }}
Version: {{ searx_version }}
<!-- Check if these values are correct -->
{% else %}
<!-- If you are running on master branch using git execute this command
in order to fetch the latest commit ID:
```
git log -1
```
If you are using searxng-docker then look at the bottom of the SearXNG page
and check for the version after "Powered by SearXNG"
Please also stipulate if you are using a forked version of SearxNG and
include a link to the fork source code.
-->
{% endif %}
**How did you install SearXNG?**
<!-- Did you install SearXNG using the official wiki or using searxng-docker
or manually by executing the searx/webapp.py file? -->
**What happened?**
<!-- A clear and concise description of what the bug is. -->
**How To Reproduce**
<!-- How can we reproduce this issue? (as minimally and as precisely as possible) -->
**Expected behavior**
<!-- A clear and concise description of what you expected to happen. -->
**Screenshots & Logs**
<!-- If applicable, add screenshots, logs to help explain your problem. -->
**Additional context**
<!-- Add any other context about the problem here. -->
**Technical report**
{% for error in engine_reliability.errors %}
{% if secondary %}Warning{% else %}Error{% endif %}
{{'\n '}}* Error: {{ error.exception_classname or error.log_message }}
{{' '}}* Percentage: {{ error.percentage }}
{{' '}}* Parameters: `{{ error.log_parameters }}`
{{' '}}* File name: `{{ error.filename }}:{{ error.line_no }}`
{{' '}}* Function: `{{ error.function }}`
{{' '}}* Code: `{{ error.code }}`
{{'\n'-}}
{%- endfor -%}
</textarea>
<input type="checkbox" id="step1">
<label for="step1">{{ _('Start submitting a new issue on GitHub') }}</label>
<div class="step1 step_content">
<p><a href="{{ get_setting('brand.issue_url') }}?q=is%3Aissue+Bug:%20{{ engine_name }} {{ technical_report }}" target="_blank" rel="noreferrer noreferrer">{{ _('Please check for existing bugs about this engine on GitHub') }}</a></p>
</div>
<input class="step1 step1_delay" type="checkbox" id="step2">
<label class="step1 step1_delay" for="step2" >{{ _('I confirm there is no existing bug about the issue I encounter') }}</label>
<div class="step2 step_content">
<p>{{ _('If this is a public instance, please specify the URL in the bug report') }}</p>
<button type="submit" class="github-issue-button button" title="{{ get_setting('brand.new_issue_url') }}">{{ _('Submit a new issue on Github including the above information') }}</button>
</div>
</form>
{% endmacro %}

View File

@@ -1,5 +1,4 @@
{% from 'simple/icons.html' import icon_big %}
{% from 'simple/new_issue.html' import new_issue with context %}
{% extends "simple/page_with_header.html" %}
@@ -124,7 +123,6 @@
{% endif %}
{% endfor %}
{% endfor %}
{{ new_issue(selected_engine_name, engine_reliabilities[selected_engine_name]) }}
</div>
{% endif %}

View File

@@ -419,8 +419,8 @@ def render(template_name: str, **kwargs):
# values from settings
kwargs['search_formats'] = [x for x in settings['search']['formats'] if x != 'html']
kwargs['instance_name'] = get_setting('general.instance_name')
kwargs['searx_version'] = VERSION_STRING
kwargs['searx_git_url'] = GIT_URL
kwargs['searxng_version'] = VERSION_STRING
kwargs['searxng_git_url'] = GIT_URL
kwargs['enable_metrics'] = get_setting('general.enable_metrics')
kwargs['get_setting'] = get_setting
kwargs['get_pretty_url'] = get_pretty_url
@@ -1153,7 +1153,6 @@ def stats():
engine_stats = engine_stats,
engine_reliabilities = engine_reliabilities,
selected_engine_name = selected_engine_name,
searx_git_branch = GIT_BRANCH,
technical_report = technical_report,
# fmt: on
)
@@ -1216,6 +1215,29 @@ def opensearch():
return resp
@app.route('/manifest.json', methods=['GET'])
def manifest():
theme = sxng_request.preferences.get_value('simple_style')
if theme not in ("light", "dark", "black"):
theme = "light"
theme_color = get_setting(f'brand.pwa_colors.theme_color_{theme}')
background_color = get_setting(f'brand.pwa_colors.background_color_{theme}')
ret = render('manifest.json', theme_color=theme_color, background_color=background_color)
resp = Response(response=ret, status=200, mimetype="application/json")
return resp
@app.route('/logo/<resolution>')
def manifest_logo(resolution=0):
theme = sxng_request.preferences.get_value("theme")
return send_from_directory(
os.path.join(app.root_path, settings['ui']['static_path'], 'themes', theme, 'img', 'logos'), # type: ignore
resolution,
mimetype='image/vnd.microsoft.icon',
)
@app.route('/favicon.ico')
def favicon():
theme = sxng_request.preferences.get_value("theme")

View File

@@ -4,7 +4,6 @@ general:
brand:
issue_url: https://github.com/searxng/searxng/issues
new_issue_url: https://github.com/searxng/searxng/issues/new
docs_url: https://docs.searxng.org
public_instances: https://searx.space
wiki_url: https://github.com/searxng/searxng/wiki