1 Commits

Author SHA1 Message Date
searxng-bot
6cc4350a34 [l10n] update translations from Weblate
f290f4ffe - 2025-04-15 - return42 <return42@noreply.codeberg.org>
4a9134b03 - 2025-04-14 - DZDevelopers <dzdevelopers@noreply.codeberg.org>
a8c86581d - 2025-04-14 - aindriu80 <aindriu80@noreply.codeberg.org>
2b5395719 - 2025-04-11 - ayame30 <ayame30@noreply.codeberg.org>
448a443fa - 2025-04-11 - ayame30 <ayame30@noreply.codeberg.org>
2025-04-18 07:10:33 +00:00
29 changed files with 394 additions and 768 deletions

View File

@@ -31,8 +31,8 @@
"stylelint-prettier": "^5.0.3",
"svgo": "^3.3.2",
"swiped-events": "^1.2.0",
"vite": "^6.3.2",
"vite-plugin-static-copy": "^2.3.1",
"vite": "^6.2.6",
"vite-plugin-static-copy": "^2.3.0",
"vite-plugin-stylelint": "^6.0.0",
"webpack": "^5.99.5",
"webpack-cli": "^6.0.1"
@@ -1486,9 +1486,9 @@
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.0.tgz",
"integrity": "sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg==",
"version": "4.34.7",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.7.tgz",
"integrity": "sha512-l6CtzHYo8D2TQ3J7qJNpp3Q1Iye56ssIAtqbM2H8axxCEEwvN7o8Ze9PuIapbxFL3OHrJU2JBX6FIIVnP/rYyw==",
"cpu": [
"arm"
],
@@ -1500,9 +1500,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.0.tgz",
"integrity": "sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w==",
"version": "4.34.7",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.7.tgz",
"integrity": "sha512-KvyJpFUueUnSp53zhAa293QBYqwm94TgYTIfXyOTtidhm5V0LbLCJQRGkQClYiX3FXDQGSvPxOTD/6rPStMMDg==",
"cpu": [
"arm64"
],
@@ -1514,9 +1514,9 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.0.tgz",
"integrity": "sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ==",
"version": "4.34.7",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.7.tgz",
"integrity": "sha512-jq87CjmgL9YIKvs8ybtIC98s/M3HdbqXhllcy9EdLV0yMg1DpxES2gr65nNy7ObNo/vZ/MrOTxt0bE5LinL6mA==",
"cpu": [
"arm64"
],
@@ -1528,9 +1528,9 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.0.tgz",
"integrity": "sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA==",
"version": "4.34.7",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.7.tgz",
"integrity": "sha512-rSI/m8OxBjsdnMMg0WEetu/w+LhLAcCDEiL66lmMX4R3oaml3eXz3Dxfvrxs1FbzPbJMaItQiksyMfv1hoIxnA==",
"cpu": [
"x64"
],
@@ -1542,9 +1542,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-arm64": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.0.tgz",
"integrity": "sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg==",
"version": "4.34.7",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.7.tgz",
"integrity": "sha512-oIoJRy3ZrdsXpFuWDtzsOOa/E/RbRWXVokpVrNnkS7npz8GEG++E1gYbzhYxhxHbO2om1T26BZjVmdIoyN2WtA==",
"cpu": [
"arm64"
],
@@ -1556,9 +1556,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-x64": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.0.tgz",
"integrity": "sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw==",
"version": "4.34.7",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.7.tgz",
"integrity": "sha512-X++QSLm4NZfZ3VXGVwyHdRf58IBbCu9ammgJxuWZYLX0du6kZvdNqPwrjvDfwmi6wFdvfZ/s6K7ia0E5kI7m8Q==",
"cpu": [
"x64"
],
@@ -1570,9 +1570,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.0.tgz",
"integrity": "sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA==",
"version": "4.34.7",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.7.tgz",
"integrity": "sha512-Z0TzhrsNqukTz3ISzrvyshQpFnFRfLunYiXxlCRvcrb3nvC5rVKI+ZXPFG/Aa4jhQa1gHgH3A0exHaRRN4VmdQ==",
"cpu": [
"arm"
],
@@ -1584,9 +1584,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.0.tgz",
"integrity": "sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg==",
"version": "4.34.7",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.7.tgz",
"integrity": "sha512-nkznpyXekFAbvFBKBy4nNppSgneB1wwG1yx/hujN3wRnhnkrYVugMTCBXED4+Ni6thoWfQuHNYbFjgGH0MBXtw==",
"cpu": [
"arm"
],
@@ -1598,9 +1598,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.0.tgz",
"integrity": "sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg==",
"version": "4.34.7",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.7.tgz",
"integrity": "sha512-KCjlUkcKs6PjOcxolqrXglBDcfCuUCTVlX5BgzgoJHw+1rWH1MCkETLkLe5iLLS9dP5gKC7mp3y6x8c1oGBUtA==",
"cpu": [
"arm64"
],
@@ -1612,9 +1612,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.0.tgz",
"integrity": "sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ==",
"version": "4.34.7",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.7.tgz",
"integrity": "sha512-uFLJFz6+utmpbR313TTx+NpPuAXbPz4BhTQzgaP0tozlLnGnQ6rCo6tLwaSa6b7l6gRErjLicXQ1iPiXzYotjw==",
"cpu": [
"arm64"
],
@@ -1626,9 +1626,9 @@
]
},
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.0.tgz",
"integrity": "sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg==",
"version": "4.34.7",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.7.tgz",
"integrity": "sha512-ws8pc68UcJJqCpneDFepnwlsMUFoWvPbWXT/XUrJ7rWUL9vLoIN3GAasgG+nCvq8xrE3pIrd+qLX/jotcLy0Qw==",
"cpu": [
"loong64"
],
@@ -1640,9 +1640,9 @@
]
},
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.0.tgz",
"integrity": "sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw==",
"version": "4.34.7",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.7.tgz",
"integrity": "sha512-vrDk9JDa/BFkxcS2PbWpr0C/LiiSLxFbNOBgfbW6P8TBe9PPHx9Wqbvx2xgNi1TOAyQHQJ7RZFqBiEohm79r0w==",
"cpu": [
"ppc64"
],
@@ -1654,23 +1654,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.0.tgz",
"integrity": "sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA==",
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-riscv64-musl": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.0.tgz",
"integrity": "sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ==",
"version": "4.34.7",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.7.tgz",
"integrity": "sha512-rB+ejFyjtmSo+g/a4eovDD1lHWHVqizN8P0Hm0RElkINpS0XOdpaXloqM4FBkF9ZWEzg6bezymbpLmeMldfLTw==",
"cpu": [
"riscv64"
],
@@ -1682,9 +1668,9 @@
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.0.tgz",
"integrity": "sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw==",
"version": "4.34.7",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.7.tgz",
"integrity": "sha512-nNXNjo4As6dNqRn7OrsnHzwTgtypfRA3u3AKr0B3sOOo+HkedIbn8ZtFnB+4XyKJojIfqDKmbIzO1QydQ8c+Pw==",
"cpu": [
"s390x"
],
@@ -1696,9 +1682,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.0.tgz",
"integrity": "sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ==",
"version": "4.34.7",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.7.tgz",
"integrity": "sha512-9kPVf9ahnpOMSGlCxXGv980wXD0zRR3wyk8+33/MXQIpQEOpaNe7dEHm5LMfyRZRNt9lMEQuH0jUKj15MkM7QA==",
"cpu": [
"x64"
],
@@ -1710,9 +1696,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.0.tgz",
"integrity": "sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw==",
"version": "4.34.7",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.7.tgz",
"integrity": "sha512-7wJPXRWTTPtTFDFezA8sle/1sdgxDjuMoRXEKtx97ViRxGGkVQYovem+Q8Pr/2HxiHp74SSRG+o6R0Yq0shPwQ==",
"cpu": [
"x64"
],
@@ -1724,9 +1710,9 @@
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.0.tgz",
"integrity": "sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ==",
"version": "4.34.7",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.7.tgz",
"integrity": "sha512-MN7aaBC7mAjsiMEZcsJvwNsQVNZShgES/9SzWp1HC9Yjqb5OpexYnRjF7RmE4itbeesHMYYQiAtUAQaSKs2Rfw==",
"cpu": [
"arm64"
],
@@ -1738,9 +1724,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.0.tgz",
"integrity": "sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA==",
"version": "4.34.7",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.7.tgz",
"integrity": "sha512-aeawEKYswsFu1LhDM9RIgToobquzdtSc4jSVqHV8uApz4FVvhFl/mKh92wc8WpFc6aYCothV/03UjY6y7yLgbg==",
"cpu": [
"ia32"
],
@@ -1752,9 +1738,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.0.tgz",
"integrity": "sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ==",
"version": "4.34.7",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.7.tgz",
"integrity": "sha512-4ZedScpxxIrVO7otcZ8kCX1mZArtH2Wfj3uFCxRJ9NO80gg1XV0U/b2f/MKaGwj2X3QopHfoWiDQ917FRpwY3w==",
"cpu": [
"x64"
],
@@ -1829,9 +1815,9 @@
}
},
"node_modules/@types/estree": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz",
"integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==",
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
"dev": true,
"license": "MIT"
},
@@ -5637,13 +5623,13 @@
}
},
"node_modules/rollup": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.0.tgz",
"integrity": "sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w==",
"version": "4.34.7",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.7.tgz",
"integrity": "sha512-8qhyN0oZ4x0H6wmBgfKxJtxM7qS98YJ0k0kNh5ECVtuchIJ7z9IVVvzpmtQyT10PXKMtBxYr1wQ5Apg8RS8kXQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/estree": "1.0.7"
"@types/estree": "1.0.6"
},
"bin": {
"rollup": "dist/bin/rollup"
@@ -5653,26 +5639,25 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.40.0",
"@rollup/rollup-android-arm64": "4.40.0",
"@rollup/rollup-darwin-arm64": "4.40.0",
"@rollup/rollup-darwin-x64": "4.40.0",
"@rollup/rollup-freebsd-arm64": "4.40.0",
"@rollup/rollup-freebsd-x64": "4.40.0",
"@rollup/rollup-linux-arm-gnueabihf": "4.40.0",
"@rollup/rollup-linux-arm-musleabihf": "4.40.0",
"@rollup/rollup-linux-arm64-gnu": "4.40.0",
"@rollup/rollup-linux-arm64-musl": "4.40.0",
"@rollup/rollup-linux-loongarch64-gnu": "4.40.0",
"@rollup/rollup-linux-powerpc64le-gnu": "4.40.0",
"@rollup/rollup-linux-riscv64-gnu": "4.40.0",
"@rollup/rollup-linux-riscv64-musl": "4.40.0",
"@rollup/rollup-linux-s390x-gnu": "4.40.0",
"@rollup/rollup-linux-x64-gnu": "4.40.0",
"@rollup/rollup-linux-x64-musl": "4.40.0",
"@rollup/rollup-win32-arm64-msvc": "4.40.0",
"@rollup/rollup-win32-ia32-msvc": "4.40.0",
"@rollup/rollup-win32-x64-msvc": "4.40.0",
"@rollup/rollup-android-arm-eabi": "4.34.7",
"@rollup/rollup-android-arm64": "4.34.7",
"@rollup/rollup-darwin-arm64": "4.34.7",
"@rollup/rollup-darwin-x64": "4.34.7",
"@rollup/rollup-freebsd-arm64": "4.34.7",
"@rollup/rollup-freebsd-x64": "4.34.7",
"@rollup/rollup-linux-arm-gnueabihf": "4.34.7",
"@rollup/rollup-linux-arm-musleabihf": "4.34.7",
"@rollup/rollup-linux-arm64-gnu": "4.34.7",
"@rollup/rollup-linux-arm64-musl": "4.34.7",
"@rollup/rollup-linux-loongarch64-gnu": "4.34.7",
"@rollup/rollup-linux-powerpc64le-gnu": "4.34.7",
"@rollup/rollup-linux-riscv64-gnu": "4.34.7",
"@rollup/rollup-linux-s390x-gnu": "4.34.7",
"@rollup/rollup-linux-x64-gnu": "4.34.7",
"@rollup/rollup-linux-x64-musl": "4.34.7",
"@rollup/rollup-win32-arm64-msvc": "4.34.7",
"@rollup/rollup-win32-ia32-msvc": "4.34.7",
"@rollup/rollup-win32-x64-msvc": "4.34.7",
"fsevents": "~2.3.2"
}
},
@@ -6807,18 +6792,15 @@
"license": "MIT"
},
"node_modules/vite": {
"version": "6.3.2",
"resolved": "https://registry.npmjs.org/vite/-/vite-6.3.2.tgz",
"integrity": "sha512-ZSvGOXKGceizRQIZSz7TGJ0pS3QLlVY/9hwxVh17W3re67je1RKYzFHivZ/t0tubU78Vkyb9WnHPENSBCzbckg==",
"version": "6.2.6",
"resolved": "https://registry.npmjs.org/vite/-/vite-6.2.6.tgz",
"integrity": "sha512-9xpjNl3kR4rVDZgPNdTL0/c6ao4km69a/2ihNQbcANz8RuCOK3hQBmLSJf3bRKVQjVMda+YvizNE8AwvogcPbw==",
"dev": true,
"license": "MIT",
"dependencies": {
"esbuild": "^0.25.0",
"fdir": "^6.4.3",
"picomatch": "^4.0.2",
"postcss": "^8.5.3",
"rollup": "^4.34.9",
"tinyglobby": "^0.2.12"
"rollup": "^4.30.1"
},
"bin": {
"vite": "bin/vite.js"
@@ -6882,9 +6864,9 @@
}
},
"node_modules/vite-plugin-static-copy": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-2.3.1.tgz",
"integrity": "sha512-EfsPcBm3ewg3UMG8RJaC0ADq6/qnUZnokXx4By4+2cAcipjT9i0Y0owIJGqmZI7d6nxk4qB1q5aXOwNuSyPdyA==",
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-2.3.0.tgz",
"integrity": "sha512-LLKwhhHetGaCnWz4mas4qqjjguDka6/6b4+SeIohRroj8aCE7QTfiZECfPecslFQkWZ3HdQuq5kOPmWZjNYlKA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -6961,34 +6943,6 @@
}
}
},
"node_modules/vite/node_modules/fdir": {
"version": "6.4.3",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz",
"integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"picomatch": "^3 || ^4"
},
"peerDependenciesMeta": {
"picomatch": {
"optional": true
}
}
},
"node_modules/vite/node_modules/picomatch": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/watchpack": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz",

View File

@@ -29,8 +29,8 @@
"stylelint-prettier": "^5.0.3",
"svgo": "^3.3.2",
"swiped-events": "^1.2.0",
"vite": "^6.3.2",
"vite-plugin-static-copy": "^2.3.1",
"vite": "^6.2.6",
"vite-plugin-static-copy": "^2.3.0",
"vite-plugin-stylelint": "^6.0.0",
"webpack": "^5.99.5",
"webpack-cli": "^6.0.1"

View File

@@ -16,14 +16,8 @@
open_metrics: ''
``debug`` : ``$SEARXNG_DEBUG``
In debug mode, the server provides an interactive debugger, will reload when
code is changed and activates a verbose logging.
.. attention::
The debug setting is intended for local development server. Don't
activate debug (don't use a development server) when deploying to
production.
Allow a more detailed log if you run SearXNG directly. Display *detailed* error
messages in the browser too, so this must be deactivated in production.
``donation_url`` :
Set value to ``true`` to use your own donation page written in the

View File

@@ -14,7 +14,6 @@
limiter: false
public_instance: false
image_proxy: false
method: "POST"
default_http_headers:
X-Content-Type-Options : nosniff
X-Download-Options : noopen
@@ -51,11 +50,6 @@
``image_proxy`` : ``$SEARXNG_IMAGE_PROXY``
Allow your instance of SearXNG of being able to proxy images. Uses memory space.
.. _method:
``method`` : ``$SEARXNG_METHOD``
Whether to use ``GET`` or ``POST`` HTTP method when searching.
.. _HTTP headers: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers
``default_http_headers`` :

View File

@@ -4,5 +4,10 @@
Mullvad-Leta
============
.. contents:: Contents
:depth: 2
:local:
:backlinks: entry
.. automodule:: searx.engines.mullvad_leta
:members:

View File

@@ -22,18 +22,18 @@ searx_dir = abspath(dirname(__file__))
searx_parent_dir = abspath(dirname(dirname(__file__)))
settings = {}
sxng_debug = False
searx_debug = False
logger = logging.getLogger('searx')
_unset = object()
def init_settings():
"""Initialize global ``settings`` and ``sxng_debug`` variables and
"""Initialize global ``settings`` and ``searx_debug`` variables and
``logger`` from ``SEARXNG_SETTINGS_PATH``.
"""
global settings, sxng_debug # pylint: disable=global-variable-not-assigned
global settings, searx_debug # pylint: disable=global-variable-not-assigned
cfg, msg = searx.settings_loader.load_settings(load_user_settings=True)
cfg = cfg or {}
@@ -42,8 +42,8 @@ def init_settings():
settings.clear()
settings.update(cfg)
sxng_debug = get_setting("general.debug")
if sxng_debug:
searx_debug = settings['general']['debug']
if searx_debug:
_logging_config_debug()
else:
logging.basicConfig(level=LOG_LEVEL_PROD, format=LOG_FORMAT_PROD)

View File

@@ -6628,172 +6628,6 @@
"to-TO": "to"
}
},
"mullvadleta": {
"all_locale": null,
"custom": {},
"data_type": "traits_v1",
"languages": {
"ar": "ar",
"bg": "bg",
"ca": "ca",
"cs": "cs",
"da": "da",
"de": "de",
"en": "en",
"es": "es",
"et": "et",
"fi": "fi",
"fr": "fr",
"he": "he",
"hr": "hr",
"hu": "hu",
"is": "is",
"it": "it",
"ja": "jp",
"ko": "ko",
"lt": "lt",
"lv": "lv",
"nb": "nb",
"nl": "nl",
"pl": "pl",
"pt": "pt",
"ro": "ro",
"ru": "ru",
"sk": "sk",
"sl": "sl",
"sr": "sr",
"sv": "sv",
"tr": "tr",
"zh_Hans": "zh-hant",
"zh_Hant": "zh-hans"
},
"regions": {
"ar-SA": "sa",
"da-DK": "dk",
"de-AT": "at",
"de-BE": "be",
"de-CH": "ch",
"de-DE": "de",
"en-AU": "au",
"en-CA": "ca",
"en-GB": "uk",
"en-IN": "in",
"en-NZ": "nz",
"en-PH": "ph",
"en-US": "us",
"en-ZA": "za",
"es-AR": "ar",
"es-CL": "cl",
"es-ES": "es",
"es-MX": "mx",
"fi-FI": "fi",
"fr-BE": "be",
"fr-CA": "ca",
"fr-CH": "ch",
"fr-FR": "fr",
"id-ID": "id",
"it-CH": "ch",
"it-IT": "it",
"ja-JP": "jp",
"ko-KR": "kr",
"ms-MY": "my",
"nb-NO": "no",
"nl-BE": "be",
"nl-NL": "nl",
"pl-PL": "pl",
"pt-BR": "br",
"pt-PT": "pt",
"ru-RU": "ru",
"se-SE": "se",
"tr-TR": "tr",
"zh-CN": "cn",
"zh-HK": "hk",
"zh-TW": "tw"
}
},
"mullvadleta brave": {
"all_locale": null,
"custom": {},
"data_type": "traits_v1",
"languages": {
"ar": "ar",
"bg": "bg",
"ca": "ca",
"cs": "cs",
"da": "da",
"de": "de",
"en": "en",
"es": "es",
"et": "et",
"fi": "fi",
"fr": "fr",
"he": "he",
"hr": "hr",
"hu": "hu",
"is": "is",
"it": "it",
"ja": "jp",
"ko": "ko",
"lt": "lt",
"lv": "lv",
"nb": "nb",
"nl": "nl",
"pl": "pl",
"pt": "pt",
"ro": "ro",
"ru": "ru",
"sk": "sk",
"sl": "sl",
"sr": "sr",
"sv": "sv",
"tr": "tr",
"zh_Hans": "zh-hant",
"zh_Hant": "zh-hans"
},
"regions": {
"ar-SA": "sa",
"da-DK": "dk",
"de-AT": "at",
"de-BE": "be",
"de-CH": "ch",
"de-DE": "de",
"en-AU": "au",
"en-CA": "ca",
"en-GB": "uk",
"en-IN": "in",
"en-NZ": "nz",
"en-PH": "ph",
"en-US": "us",
"en-ZA": "za",
"es-AR": "ar",
"es-CL": "cl",
"es-ES": "es",
"es-MX": "mx",
"fi-FI": "fi",
"fr-BE": "be",
"fr-CA": "ca",
"fr-CH": "ch",
"fr-FR": "fr",
"id-ID": "id",
"it-CH": "ch",
"it-IT": "it",
"ja-JP": "jp",
"ko-KR": "kr",
"ms-MY": "my",
"nb-NO": "no",
"nl-BE": "be",
"nl-NL": "nl",
"pl-PL": "pl",
"pt-BR": "br",
"pt-PT": "pt",
"ru-RU": "ru",
"se-SE": "se",
"tr-TR": "tr",
"zh-CN": "cn",
"zh-HK": "hk",
"zh-TW": "tw"
}
},
"odysee": {
"all_locale": null,
"custom": {},

View File

@@ -1,61 +1,46 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""Mullvad Leta is a search engine proxy. Currently Leta only offers text
search results not image, news or any other types of search result. Leta acts
as a proxy to Google and Brave search results. You can select which backend
search engine you wish to use, see (:py:obj:`leta_engine`).
"""This is the implementation of the Mullvad-Leta meta-search engine.
This engine **REQUIRES** that searxng operate within a Mullvad VPN
If using docker, consider using gluetun for easily connecting to the Mullvad
- https://github.com/qdm12/gluetun
Otherwise, follow instructions provided by Mullvad for enabling the VPN on Linux
- https://mullvad.net/en/help/install-mullvad-app-linux
.. hint::
Leta caches each search for up to 30 days. For example, if you use search
terms like ``news``, contrary to your intention you'll get very old results!
Configuration
=============
The engine has the following additional settings:
- :py:obj:`leta_engine` (:py:obj:`LetaEnginesType`)
You can configure one Leta engine for Google and one for Brave:
.. code:: yaml
- name: mullvadleta
engine: mullvad_leta
leta_engine: google
shortcut: ml
- name: mullvadleta brave
engine: mullvad_leta
network: mullvadleta # use network from engine "mullvadleta" configured above
leta_engine: brave
shortcut: mlb
Implementations
===============
The :py:obj:`EngineTraits` is empty by default. Maintainers have to run
``make data.traits`` (in the Mullvad VPN / :py:obj:`fetch_traits`) and rebase
the modified JSON file ``searx/data/engine_traits.json`` on every single
update of SearXNG!
"""
from __future__ import annotations
import typing
from urllib.parse import urlencode
import babel
from typing import TYPE_CHECKING
from httpx import Response
from lxml import html
from searx.enginelib.traits import EngineTraits
from searx.locales import get_official_locales, language_tag, region_tag
from searx.utils import eval_xpath_list
from searx.result_types import EngineResults, MainResult
from searx.locales import region_tag, get_official_locales
from searx.utils import eval_xpath, extract_text, eval_xpath_list
from searx.exceptions import SearxEngineResponseException
if typing.TYPE_CHECKING:
if TYPE_CHECKING:
import logging
logger = logging.getLogger()
traits: EngineTraits
use_cache: bool = True # non-cache use only has 100 searches per day!
leta_engine: str = 'google'
search_url = "https://leta.mullvad.net"
# about
@@ -69,205 +54,154 @@ about = {
}
# engine dependent config
categories = ["general", "web"]
categories = ['general', 'web']
paging = True
max_page = 10
max_page = 50
time_range_support = True
time_range_dict = {
"day": "d",
"week": "w",
"month": "m",
"year": "y",
"day": "d1",
"week": "w1",
"month": "m1",
"year": "y1",
}
LetaEnginesType = typing.Literal["google", "brave"]
"""Engine types supported by mullvadleta."""
leta_engine: LetaEnginesType = "google"
"""Select Leta's engine type from :py:obj:`LetaEnginesType`."""
available_leta_engines = [
'google', # first will be default if provided engine is invalid
'brave',
]
def init(_):
l = typing.get_args(LetaEnginesType)
if leta_engine not in l:
raise ValueError(f"leta_engine '{leta_engine}' is invalid, use one of {', '.join(l)}")
def is_vpn_connected(dom: html.HtmlElement) -> bool:
"""Returns true if the VPN is connected, False otherwise"""
connected_text = extract_text(eval_xpath(dom, '//main/div/p[1]'))
return connected_text != 'You are not connected to Mullvad VPN.'
class DataNodeQueryMetaDataIndices(typing.TypedDict):
"""Indices into query metadata."""
success: int
q: int # pylint: disable=invalid-name
country: int
language: int
lastUpdated: int
engine: int
items: int
infobox: int
news: int
timestamp: int
altered: int
page: int
next: int # if -1, there no more results are available
previous: int
class DataNodeResultIndices(typing.TypedDict):
"""Indices into query resultsdata."""
link: int
snippet: int
title: int
favicon: int
def assign_headers(headers: dict) -> dict:
"""Assigns the headers to make a request to Mullvad Leta"""
headers['Accept'] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"
headers['Content-Type'] = "application/x-www-form-urlencoded"
headers['Host'] = "leta.mullvad.net"
headers['Origin'] = "https://leta.mullvad.net"
return headers
def request(query: str, params: dict):
params["method"] = "GET"
args = {
country = traits.get_region(params.get('searxng_locale', 'all'), traits.all_locale) # type: ignore
result_engine = leta_engine
if leta_engine not in available_leta_engines:
result_engine = available_leta_engines[0]
logger.warning(
'Configured engine "%s" not one of the available engines %s, defaulting to "%s"',
leta_engine,
available_leta_engines,
result_engine,
)
params['url'] = search_url
params['method'] = 'POST'
params['data'] = {
"q": query,
"engine": leta_engine,
"x-sveltekit-invalidated": "001", # hardcoded from all requests seen
"gl": country if country is str else '',
'engine': result_engine,
}
# pylint: disable=undefined-variable
if use_cache:
params['data']['oc'] = "on"
# pylint: enable=undefined-variable
country = traits.get_region(params.get("searxng_locale"), traits.all_locale) # type: ignore
if country:
args["country"] = country
if params['time_range'] in time_range_dict:
params['dateRestrict'] = time_range_dict[params['time_range']]
else:
params['dateRestrict'] = ''
language = traits.get_language(params.get("searxng_locale"), traits.all_locale) # type: ignore
if language:
args["language"] = language
if params['pageno'] > 1:
# Page 1 is n/a, Page 2 is 11, page 3 is 21, ...
params['data']['start'] = ''.join([str(params['pageno'] - 1), "1"])
if params["time_range"] in time_range_dict:
args["lastUpdated"] = time_range_dict[params["time_range"]]
if params["pageno"] > 1:
args["page"] = params["pageno"]
params["url"] = f"{search_url}/search/__data.json?{urlencode(args)}"
if params['headers'] is None:
params['headers'] = {}
assign_headers(params['headers'])
return params
def response(resp: Response) -> EngineResults:
json_response = resp.json()
def extract_result(dom_result: list[html.HtmlElement]):
# Infoboxes sometimes appear in the beginning and will have a length of 0
if len(dom_result) == 3:
[a_elem, h3_elem, p_elem] = dom_result
elif len(dom_result) == 4:
[_, a_elem, h3_elem, p_elem] = dom_result
else:
return None
nodes = json_response["nodes"]
# 0: is None
# 1: has "connected=True", not useful
# 2: query results within "data"
data_nodes = nodes[2]["data"]
# Instead of nested object structure, all objects are flattened into a
# list. Rather, the first object in data_node provides indices into the
# "data_nodes" to access each searchresult (which is an object of more
# indices)
#
# Read the relative TypedDict definitions for details
query_meta_data: DataNodeQueryMetaDataIndices = data_nodes[0]
query_items_indices = query_meta_data["items"]
results = EngineResults()
for idx in data_nodes[query_items_indices]:
query_item_indices: DataNodeResultIndices = data_nodes[idx]
results.add(
MainResult(
url=data_nodes[query_item_indices["link"]],
title=data_nodes[query_item_indices["title"]],
content=data_nodes[query_item_indices["snippet"]],
)
)
return results
return {
'url': extract_text(a_elem.text),
'title': extract_text(h3_elem),
'content': extract_text(p_elem),
}
def fetch_traits(engine_traits: EngineTraits) -> None:
"""Fetch languages and regions from Mullvad-Leta"""
def extract_results(search_results: html.HtmlElement):
for search_result in search_results:
dom_result = eval_xpath_list(search_result, 'div/div/*')
result = extract_result(dom_result)
if result is not None:
yield result
def extract_table_data(table):
for row in table.xpath(".//tr")[2:]:
cells = row.xpath(".//td | .//th") # includes headers and data
if len(cells) > 1: # ensure the column exists
cell0 = cells[0].text_content().strip()
cell1 = cells[1].text_content().strip()
yield [cell0, cell1]
def response(resp: Response):
"""Checks if connected to Mullvad VPN, then extracts the search results from
the DOM resp: requests response object"""
dom = html.fromstring(resp.text)
if not is_vpn_connected(dom):
raise SearxEngineResponseException('Not connected to Mullvad VPN')
search_results = eval_xpath(dom.body, '//main/div[2]/div')
return list(extract_results(search_results))
def fetch_traits(engine_traits: EngineTraits):
"""Fetch languages and regions from Mullvad-Leta
.. warning::
Fetching the engine traits also requires a Mullvad VPN connection. If
not connected, then an error message will print and no traits will be
updated.
"""
# pylint: disable=import-outside-toplevel
# see https://github.com/searxng/searxng/issues/762
from searx.network import get as http_get
from searx.network import post as http_post
# pylint: enable=import-outside-toplevel
resp = http_get(f"{search_url}/documentation")
resp = http_post(search_url, headers=assign_headers({}))
if not isinstance(resp, Response):
print("ERROR: failed to get response from mullvad-leta. Are you connected to the VPN?")
return
if not resp.ok:
print("ERROR: response from mullvad-leta is not OK. Are you connected to the VPN?")
return
dom = html.fromstring(resp.text)
if not is_vpn_connected(dom):
print('ERROR: Not connected to Mullvad VPN')
return
# supported region codes
options = eval_xpath_list(dom.body, '//main/div/form/div[2]/div/select[1]/option')
if options is None or len(options) <= 0:
print('ERROR: could not find any results. Are you connected to the VPN?')
for x in options:
eng_country = x.get("value")
# There are 4 HTML tables on the documentation page for extracting information:
# 0. Keyboard Shortcuts
# 1. Query Parameters (shoutout to Mullvad for accessible docs for integration)
# 2. Country Codes [Country, Code]
# 3. Language Codes [Language, Code]
tables = eval_xpath_list(dom.body, "//table")
if tables is None or len(tables) <= 0:
print("ERROR: could not find any tables. Was the page updated?")
sxng_locales = get_official_locales(eng_country, engine_traits.languages.keys(), regional=True)
language_table = tables[3]
lang_map = {
"zh-hant": "zh_Hans",
"zh-hans": "zh_Hant",
"jp": "ja",
}
for language, code in extract_table_data(language_table):
locale_tag = lang_map.get(code, code).replace("-", "_") # type: ignore
try:
locale = babel.Locale.parse(locale_tag)
except babel.UnknownLocaleError:
print(f"ERROR: Mullvad-Leta language {language} ({code}) is unknown by babel")
if not sxng_locales:
print(
"ERROR: can't map from Mullvad-Leta country %s (%s) to a babel region."
% (x.get('data-name'), eng_country)
)
continue
sxng_tag = language_tag(locale)
engine_traits.languages[sxng_tag] = code
country_table = tables[2]
country_map = {
"cn": "zh-CN",
"hk": "zh-HK",
"jp": "ja-JP",
"my": "ms-MY",
"tw": "zh-TW",
"uk": "en-GB",
"us": "en-US",
}
for country, code in extract_table_data(country_table):
sxng_tag = country_map.get(code)
if sxng_tag:
engine_traits.regions[sxng_tag] = code
continue
try:
locale = babel.Locale.parse(f"{code.lower()}_{code.upper()}")
except babel.UnknownLocaleError:
locale = None
if locale:
engine_traits.regions[region_tag(locale)] = code
continue
official_locales = get_official_locales(code, engine_traits.languages.keys(), regional=True)
if not official_locales:
print(f"ERROR: Mullvad-Leta country '{code}' ({country}) could not be mapped as expected.")
continue
for locale in official_locales:
engine_traits.regions[region_tag(locale)] = code
for sxng_locale in sxng_locales:
engine_traits.regions[region_tag(sxng_locale)] = eng_country

View File

@@ -11,7 +11,7 @@ from searx.exceptions import SearxEngineAPIException, SearxEngineCaptchaExceptio
# Metadata
about = {
"website": "https://quark.sm.cn/",
"website": "https://m.quark.cn/",
"wikidata_id": "Q48816502",
"use_official_api": False,
"require_api_key": False,
@@ -53,7 +53,7 @@ def request(query, params):
category_config = {
'general': {
'endpoint': 'https://quark.sm.cn/s',
'endpoint': 'https://m.quark.cn/s',
'params': {
"q": query,
"layout": "html",

View File

@@ -11,7 +11,7 @@ from lxml import html
from searx.network import get as http_get
about = {
"website": "https://soundcloud.com",
"website": "ttps://soundcloud.com",
"wikidata_id": "Q568769",
"official_api_documentation": "https://developers.soundcloud.com/docs/api/guide",
"use_official_api": False,

View File

@@ -1,51 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""Steam (store) for SearXNG."""
from urllib.parse import urlencode
from searx.utils import html_to_text
from searx.result_types import EngineResults, MainResult
about = {
"website": 'https://store.steampowered.com/',
"wikidata_id": 'Q337535',
"use_official_api": False,
"require_api_key": False,
"results": 'JSON',
}
categories = []
base_url = "https://store.steampowered.com"
def request(query, params):
query_params = {"term": query, "cc": "us", "l": "en"}
params['url'] = f'{base_url}/api/storesearch/?{urlencode(query_params)}'
return params
def response(resp) -> EngineResults:
results = EngineResults()
search_results = resp.json()
for item in search_results.get('items', []):
app_id = item.get('id')
currency = item.get('price', {}).get('currency', 'USD')
price = item.get('price', {}).get('final', 0) / 100
platforms = ', '.join([platform for platform, supported in item.get('platforms', {}).items() if supported])
content = [f'Price: {price:.2f} {currency}', f'Platforms: {platforms}']
results.add(
MainResult(
title=item.get('name'),
content=html_to_text(' | '.join(content)),
url=f'{base_url}/app/{app_id}',
thumbnail=item.get('tiny_image', ''),
)
)
return results

View File

@@ -12,7 +12,7 @@ from typing import Dict
import httpx
from searx import logger, sxng_debug
from searx import logger, searx_debug
from searx.extended_types import SXNG_Response
from .client import new_client, get_loop, AsyncHTTPTransportNoHttp
from .raise_for_httperror import raise_for_httperror
@@ -186,7 +186,7 @@ class Network:
local_address = next(self._local_addresses_cycle)
proxies = next(self._proxies_cycle) # is a tuple so it can be part of the key
key = (verify, max_redirects, local_address, proxies)
hook_log_response = self.log_response if sxng_debug else None
hook_log_response = self.log_response if searx_debug else None
if key not in self._clients or self._clients[key].is_closed:
client = new_client(
self.enable_http,

View File

@@ -155,7 +155,7 @@ class ExternalBangParser(QueryPartParser):
return raw_value.startswith('!!') and len(raw_value) > 2
def __call__(self, raw_value):
value = raw_value[2:].lower()
value = raw_value[2:]
found, bang_ac_list = self._parse(value) if len(value) > 0 else (False, [])
if self.enable_autocomplete:
self._autocomplete(bang_ac_list)
@@ -183,7 +183,7 @@ class BangParser(QueryPartParser):
return raw_value[0] == '!' and (len(raw_value) < 2 or raw_value[1] != '!')
def __call__(self, raw_value):
value = raw_value[1:].replace('-', ' ').replace('_', ' ').lower()
value = raw_value[1:].replace('-', ' ').replace('_', ' ')
found = self._parse(value) if len(value) > 0 else False
if found and raw_value[0] == '!':
self.raw_text_query.specific = True

View File

@@ -10,7 +10,7 @@ from typing import Any, Dict, List, Literal, Optional, Tuple, TypedDict, Union
import redis.exceptions
from searx import logger, settings, sxng_debug
from searx import logger, settings, searx_debug
from searx.redisdb import client as get_redis_client
from searx.exceptions import SearxSettingsException
from searx.search.processors import PROCESSORS
@@ -139,7 +139,7 @@ def initialize():
signal.signal(signal.SIGUSR1, _signal_handler)
# special case when debug is activate
if sxng_debug and settings['checker']['off_when_debug']:
if searx_debug and settings['checker']['off_when_debug']:
logger.info('debug mode: checker is disabled')
return

View File

@@ -101,8 +101,7 @@ server:
# 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
@@ -711,6 +710,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
@@ -1400,21 +1419,14 @@ 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
@@ -1959,11 +1971,6 @@ engines:
categories: [images, web]
shortcut: spi
- name: steam
engine: steam
shortcut: stm
disabled: true
- name: tokyotoshokan
engine: tokyotoshokan
shortcut: tt

View File

@@ -182,7 +182,7 @@ SCHEMA = {
'base_url': SettingsValue((False, str), False, 'SEARXNG_BASE_URL'),
'image_proxy': SettingsValue(bool, False, 'SEARXNG_IMAGE_PROXY'),
'http_protocol_version': SettingsValue(('1.0', '1.1'), '1.0'),
'method': SettingsValue(('POST', 'GET'), 'POST', 'SEARXNG_METHOD'),
'method': SettingsValue(('POST', 'GET'), 'POST'),
'default_http_headers': SettingsValue(dict, {}),
},
'redis': {

View File

@@ -23,7 +23,6 @@ sxng_locales = (
('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'),

View File

@@ -43,14 +43,13 @@
# pxrb <pxrb@users.noreply.translate.codeberg.org>, 2025.
# curtwheeler <curtwheeler@users.noreply.translate.codeberg.org>, 2025.
# return42 <return42@noreply.codeberg.org>, 2025.
# Atul_Eterno <atul_eterno@noreply.codeberg.org>, 2025.
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2025-03-29 09:21+0000\n"
"PO-Revision-Date: 2025-04-24 14:06+0000\n"
"Last-Translator: Atul_Eterno <atul_eterno@noreply.codeberg.org>\n"
"PO-Revision-Date: 2025-04-08 11:34+0000\n"
"Last-Translator: return42 <return42@noreply.codeberg.org>\n"
"Language-Team: Spanish <https://translate.codeberg.org/projects/searxng/"
"searxng/es/>\n"
"Language: es\n"
@@ -554,7 +553,7 @@ msgstr "Calidad del archivo"
#: searx/plugins/ahmia_filter.py:32
msgid "Ahmia blacklist"
msgstr "Lista negra de Ahmia"
msgstr ""
#: searx/plugins/ahmia_filter.py:33
msgid "Filter out onion results that appear in Ahmia's blacklist."
@@ -1211,8 +1210,6 @@ msgid ""
"A URL containing your preferences. This URL can be used to restore your "
"settings on a different device."
msgstr ""
"Una URL conteniendo sus preferencias. Esta URL puede ser usada para "
"restaurar sus ajustes en un dispositivo diferente."
#: searx/templates/simple/preferences/cookies.html:46
msgid "Copy preferences hash"

View File

@@ -16,21 +16,20 @@
# return42 <return42@noreply.codeberg.org>, 2025.
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2025-03-29 09:21+0000\n"
"PO-Revision-Date: 2025-04-20 12:41+0000\n"
"PO-Revision-Date: 2025-03-27 13:44+0000\n"
"Last-Translator: return42 <return42@noreply.codeberg.org>\n"
"Language-Team: Lithuanian <https://translate.codeberg.org/projects/searxng/"
"searxng/lt/>\n"
"Language: lt\n"
"Language-Team: Lithuanian "
"<https://translate.codeberg.org/projects/searxng/searxng/lt/>\n"
"Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100"
" < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < "
"11) ? 1 : n % 1 != 0 ? 2: 3);\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < "
"11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 :"
" n % 1 != 0 ? 2: 3);\n"
"X-Generator: Weblate 5.10.2\n"
"Generated-By: Babel 2.17.0\n"
#. CONSTANT_NAMES['NO_SUBGROUPING']
@@ -526,15 +525,15 @@ msgstr "Failo kokybė"
#: searx/plugins/ahmia_filter.py:32
msgid "Ahmia blacklist"
msgstr "Ahmia juodasis sąrašas"
msgstr ""
#: searx/plugins/ahmia_filter.py:33
msgid "Filter out onion results that appear in Ahmia's blacklist."
msgstr "Išfiltruoti onion rezultatus esančius Ahmia juodajame sąraše."
msgstr ""
#: searx/plugins/calculator.py:38
msgid "Basic Calculator"
msgstr "Bazinis skaičiuotuvas"
msgstr ""
#: searx/plugins/calculator.py:39
msgid "Calculate mathematical expressions via the search bar"
@@ -583,8 +582,6 @@ msgid ""
"Displays your IP if the query is \"ip\" and your user agent if the query "
"is \"user-agent\"."
msgstr ""
"Rodo tavo IP jei užklausa yra „ip“ ir tavo naudotojo agentą jei užklausa yra "
"„user-agent“."
#: searx/plugins/self_info.py:52
msgid "Your IP is: "
@@ -592,7 +589,7 @@ msgstr "Jūsų IP adresas: "
#: searx/plugins/self_info.py:55
msgid "Your user-agent is: "
msgstr "Tavo naudotojo agentas (user-agent) yra: "
msgstr ""
#: searx/plugins/tor_check.py:42
msgid "Tor check plugin"
@@ -609,15 +606,15 @@ msgstr ""
#: searx/plugins/tor_check.py:65
msgid "Could not download the list of Tor exit-nodes from"
msgstr "Nepavyko atsisiųsti Tor išėjimo mazgų iš"
msgstr ""
#: searx/plugins/tor_check.py:72
msgid "You are using Tor and it looks like you have the external IP address"
msgstr "Jūs naudojate Tor ir atrodo, kad turite išorinį IP adresą"
msgstr ""
#: searx/plugins/tor_check.py:76
msgid "You are not using Tor and you have the external IP address"
msgstr "Jūs nenaudojate Tor, tačiau atrodo, kad turite išorinį IP adresą"
msgstr ""
#: searx/plugins/tracker_url_remover.py:37
msgid "Tracker URL remover"
@@ -629,11 +626,11 @@ msgstr "Šalinti seklių argumentus iš grąžinamų URL"
#: searx/plugins/unit_converter.py:49
msgid "Unit converter plugin"
msgstr "Matavimo vienetų konvertavimo papildinys"
msgstr ""
#: searx/plugins/unit_converter.py:50
msgid "Convert between units"
msgstr "Konvertuoti tarp matavimo vienetų"
msgstr ""
#: searx/templates/simple/404.html:4
msgid "Page not found"
@@ -945,7 +942,7 @@ msgstr "Pavyzdžiai"
#: searx/templates/simple/answer/translations.html:21
msgid "Definitions"
msgstr "Apibrėžimai"
msgstr ""
#: searx/templates/simple/answer/translations.html:30
msgid "Synonyms"
@@ -969,7 +966,7 @@ msgstr "Pranešimai iš paieškos sistemų"
#: searx/templates/simple/elements/engines_msg.html:7
msgid "seconds"
msgstr "sekundės"
msgstr ""
#: searx/templates/simple/elements/search_url.html:3
msgid "Search URL"
@@ -1087,11 +1084,11 @@ msgstr "Pakeiskite nuostatose naudojamą paieškos variklį:"
#: searx/templates/simple/messages/no_results.html:22
msgid "Switch to another instance:"
msgstr "Pakeisti instanciją:"
msgstr ""
#: searx/templates/simple/messages/no_results.html:24
msgid "Search for another query or select another category."
msgstr "Ieškoti kitos užklausos arba pasirinkti kitą kategoriją."
msgstr ""
#: searx/templates/simple/messages/no_results.html:25
msgid "Go back to the previous page using the previous page button."
@@ -1104,7 +1101,7 @@ msgstr "Leisti"
#: searx/templates/simple/preferences/answerers.html:5
msgid "Keywords (first word in query)"
msgstr "Raktažodžiai (pirmasis užklausos žodis)"
msgstr ""
#: searx/templates/simple/preferences/answerers.html:6
#: searx/templates/simple/result_templates/packages.html:7
@@ -1181,8 +1178,6 @@ msgid ""
"A URL containing your preferences. This URL can be used to restore your "
"settings on a different device."
msgstr ""
"URL adresas su jūsų nustatymais. Šis URL adresas gali būti panaudotas "
"atstatyti jūsų nustatymus kitame įrenginyje."
#: searx/templates/simple/preferences/cookies.html:46
msgid "Copy preferences hash"
@@ -1198,7 +1193,7 @@ msgstr ""
#: searx/templates/simple/preferences/doi_resolver.html:1
msgid "Digital Object Identifier (DOI)"
msgstr "Skaitmeninis objekto identifikatorius (DOI)"
msgstr ""
#: searx/templates/simple/preferences/doi_resolver.html:6
msgid "Open Access DOI resolver"
@@ -2063,3 +2058,4 @@ msgstr "slėpti vaizdo įrašą"
#~ "Nurodant tinkintus nustatymus nuostatų URL,"
#~ " jūs galite susinchronizuoti nuostatas tarp"
#~ " prietaisų."

View File

@@ -14,23 +14,21 @@
# Vision <vision@users.noreply.translate.codeberg.org>, 2025.
# curtwheeler <curtwheeler@users.noreply.translate.codeberg.org>, 2025.
# return42 <return42@noreply.codeberg.org>, 2025.
# whytf <whytf@noreply.codeberg.org>, 2025.
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2025-03-29 09:21+0000\n"
"PO-Revision-Date: 2025-04-23 19:16+0000\n"
"Last-Translator: whytf <whytf@noreply.codeberg.org>\n"
"Language-Team: Slovak <https://translate.codeberg.org/projects/searxng/"
"searxng/sk/>\n"
"PO-Revision-Date: 2025-03-27 13:44+0000\n"
"Last-Translator: return42 <return42@noreply.codeberg.org>\n"
"Language: sk\n"
"Language-Team: Slovak "
"<https://translate.codeberg.org/projects/searxng/searxng/sk/>\n"
"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 "
"&& n >= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n "
">= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);\n"
"X-Generator: Weblate 5.10.2\n"
"Generated-By: Babel 2.17.0\n"
#. CONSTANT_NAMES['NO_SUBGROUPING']
@@ -435,12 +433,12 @@ msgstr "Pozastavené"
#: searx/webutils.py:314
#, python-brace-format
msgid "{minutes} minute(s) ago"
msgstr "pred {minutes} minútami"
msgstr "pred {minutes} min."
#: searx/webutils.py:315
#, python-brace-format
msgid "{hours} hour(s), {minutes} minute(s) ago"
msgstr "pred {hours} hodinami, {minutes} minútami"
msgstr "pred {hours} hod., {minutes} min."
#: searx/answerers/random.py:69
msgid "Generate different random values"
@@ -526,15 +524,15 @@ msgstr "Kvalita súboru"
#: searx/plugins/ahmia_filter.py:32
msgid "Ahmia blacklist"
msgstr "Čierna listina Ahmia"
msgstr ""
#: searx/plugins/ahmia_filter.py:33
msgid "Filter out onion results that appear in Ahmia's blacklist."
msgstr "Odfiltruj výsledky onion, ktoré sa zobrazujú na čiernej listine Ahmia."
msgstr ""
#: searx/plugins/calculator.py:38
msgid "Basic Calculator"
msgstr "Základná Kalkulačka"
msgstr ""
#: searx/plugins/calculator.py:39
msgid "Calculate mathematical expressions via the search bar"
@@ -628,7 +626,7 @@ msgstr "Odstrániť sledovacie argumenty z vrátenej URL"
#: searx/plugins/unit_converter.py:49
msgid "Unit converter plugin"
msgstr "Modul konvertora jednotiek"
msgstr ""
#: searx/plugins/unit_converter.py:50
msgid "Convert between units"
@@ -1184,8 +1182,6 @@ msgid ""
"A URL containing your preferences. This URL can be used to restore your "
"settings on a different device."
msgstr ""
"Adresa URL obsahujúca vaše preferencie. Túto adresu URL môžete použiť na "
"obnovenie nastavení v inom zariadení."
#: searx/templates/simple/preferences/cookies.html:46
msgid "Copy preferences hash"
@@ -2083,3 +2079,4 @@ msgstr "skryť video"
#~ "Zadaním osobitých nastavení v adrese "
#~ "(URL) nastavení je možné synchronizovať "
#~ "nastavenia do iných zariadení."

View File

@@ -24,22 +24,21 @@
# return42 <return42@users.noreply.translate.codeberg.org>, 2025.
# Eshan-K-I <eshan-k-i@users.noreply.translate.codeberg.org>, 2025.
# rajeeban <rajeeban@users.noreply.translate.codeberg.org>, 2025.
# prashere <prashere@noreply.codeberg.org>, 2025.
msgid ""
msgstr ""
"Project-Id-Version: searx\n"
"Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2025-03-29 09:21+0000\n"
"PO-Revision-Date: 2025-04-22 10:45+0000\n"
"Last-Translator: prashere <prashere@noreply.codeberg.org>\n"
"Language-Team: Tamil <https://translate.codeberg.org/projects/searxng/"
"searxng/ta/>\n"
"PO-Revision-Date: 2025-01-20 03:36+0000\n"
"Last-Translator: rajeeban <rajeeban@users.noreply.translate.codeberg.org>"
"\n"
"Language: ta\n"
"Language-Team: Tamil "
"<https://translate.codeberg.org/projects/searxng/searxng/ta/>\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.10.2\n"
"Generated-By: Babel 2.17.0\n"
#. CONSTANT_NAMES['NO_SUBGROUPING']
@@ -150,7 +149,7 @@ msgstr "கிடங்கு"
#. CATEGORY_GROUPS['SOFTWARE_WIKIS']
#: searx/searxng.msg
msgid "software wikis"
msgstr "மென்பொருள் விக்கி"
msgstr "மென்பொருள் விகி"
#. CATEGORY_GROUPS['WEB']
#: searx/searxng.msg
@@ -2065,3 +2064,4 @@ msgstr "காணொளிகளை மறை"
#~ "preferences URL can be used to "
#~ "sync preferences across devices."
#~ msgstr ""

View File

@@ -6,7 +6,6 @@
# pylint: disable=use-dict-literal
from __future__ import annotations
import inspect
import hashlib
import hmac
import json
@@ -30,8 +29,6 @@ from pygments import highlight
from pygments.lexers import get_lexer_by_name
from pygments.formatters import HtmlFormatter # pylint: disable=no-name-in-module
from werkzeug.serving import is_running_from_reloader
import flask
from flask import (
@@ -51,12 +48,12 @@ from flask_babel import (
format_decimal,
)
import searx
from searx.extended_types import sxng_request
from searx import (
logger,
get_setting,
settings,
searx_debug,
)
from searx import infopage
@@ -84,6 +81,7 @@ from searx.webutils import (
exception_classname_to_text,
new_hmac,
is_hmac_of,
is_flask_run_cmdline,
group_engines_in_tab,
)
from searx.webadapter import (
@@ -130,6 +128,11 @@ logger = logger.getChild('webapp')
warnings.simplefilter("always")
# check secret_key
if not searx_debug and settings['server']['secret_key'] == 'ultrasecretkey':
logger.error('server.secret_key is not changed. Please use something else instead of ultrasecretkey.')
sys.exit(1)
# about static
logger.debug('static directory is %s', settings['ui']['static_path'])
static_files = get_static_files(settings['ui']['static_path'])
@@ -1326,112 +1329,45 @@ def page_not_found(_e):
return render('404.html'), 404
def run():
"""Runs the application on a local development server.
# see https://flask.palletsprojects.com/en/1.1.x/cli/
# True if "FLASK_APP=searx/webapp.py FLASK_ENV=development flask run"
flask_run_development = (
os.environ.get("FLASK_APP") is not None and os.environ.get("FLASK_ENV") == 'development' and is_flask_run_cmdline()
)
This run method is only called when SearXNG is started via ``__main__``::
python -m searx.webapp
Do not use :ref:`run() <flask.Flask.run>` in a production setting. It is
not intended to meet security and performance requirements for a production
server.
It is not recommended to use this function for development with automatic
reloading as this is badly supported. Instead you should be using the flask
command line scripts run support::
flask --app searx.webapp run --debug --reload --host 127.0.0.1 --port 8888
.. _Flask.run: https://flask.palletsprojects.com/en/stable/api/#flask.Flask.run
"""
host: str = get_setting("server.bind_address") # type: ignore
port: int = get_setting("server.port") # type: ignore
if searx.sxng_debug:
logger.debug("run local development server (DEBUG) on %s:%s", host, port)
app.run(
debug=True,
port=port,
host=host,
threaded=True,
extra_files=[DEFAULT_SETTINGS_FILE],
)
else:
logger.debug("run local development server on %s:%s", host, port)
app.run(port=port, host=host, threaded=True)
def is_werkzeug_reload_active() -> bool:
"""Returns ``True`` if server is is launched by :ref:`werkzeug.serving` and
the ``use_reload`` argument was set to ``True``. If this is the case, it
should be avoided that the server is initialized twice (:py:obj:`init`,
:py:obj:`run`).
.. _werkzeug.serving:
https://werkzeug.palletsprojects.com/en/stable/serving/#werkzeug.serving.run_simple
"""
if "uwsgi" in sys.argv:
# server was launched by uWSGI
return False
# https://github.com/searxng/searxng/pull/1656#issuecomment-1214198941
# https://github.com/searxng/searxng/pull/1616#issuecomment-1206137468
frames = inspect.stack()
if len(frames) > 1 and frames[-2].filename.endswith('flask/cli.py'):
# server was launched by "flask run", is argument "--reload" set?
if "--reload" in sys.argv or "--debug" in sys.argv:
return True
elif frames[0].filename.endswith('searx/webapp.py'):
# server was launched by "python -m searx.webapp" / see run()
if searx.sxng_debug:
return True
return False
def init():
if searx.sxng_debug or app.debug:
app.debug = True
searx.sxng_debug = True
# check secret_key in production
if not app.debug and get_setting("server.secret_key") == 'ultrasecretkey':
logger.error("server.secret_key is not changed. Please use something else instead of ultrasecretkey.")
sys.exit(1)
# When automatic reloading is activated stop Flask from initialising twice.
# - https://github.com/pallets/flask/issues/5307#issuecomment-1774646119
# - https://stackoverflow.com/a/25504196
reloader_active = is_werkzeug_reload_active()
werkzeug_run_main = is_running_from_reloader()
if reloader_active and not werkzeug_run_main:
logger.info("in reloading mode and not in main loop, cancel the initialization")
return
# True if reload feature is activated of werkzeug, False otherwise (including uwsgi, etc..)
# __name__ != "__main__" if searx.webapp is imported (make test, make docs, uwsgi...)
# see run() at the end of this file : searx_debug activates the reload feature.
werkzeug_reloader = flask_run_development or (searx_debug and __name__ == "__main__")
# initialize the engines except on the first run of the werkzeug server.
if not werkzeug_reloader or (werkzeug_reloader and os.environ.get("WERKZEUG_RUN_MAIN") == "true"):
locales_initialize()
redis_initialize()
searx.plugins.initialize(app)
metrics: bool = get_setting("general.enable_metrics") # type: ignore
searx.search.initialize(enable_checker=True, check_network=True, enable_metrics=metrics)
searx.search.initialize(
enable_checker=True,
check_network=True,
enable_metrics=get_setting("general.enable_metrics"),
)
limiter.initialize(app, settings)
favicons.init()
def run():
logger.debug('starting webserver on %s:%s', settings['server']['bind_address'], settings['server']['port'])
app.run(
debug=searx_debug,
use_debugger=searx_debug,
port=settings['server']['port'],
host=settings['server']['bind_address'],
threaded=True,
extra_files=[DEFAULT_SETTINGS_FILE],
)
application = app
patch_application(app)
init()
if __name__ == "__main__":
run()

View File

@@ -9,6 +9,7 @@ import csv
import hashlib
import hmac
import re
import inspect
import itertools
import json
from datetime import datetime, timedelta
@@ -315,6 +316,21 @@ def searxng_l10n_timespan(dt: datetime) -> str: # pylint: disable=invalid-name
return format_date(dt)
def is_flask_run_cmdline():
"""Check if the application was started using "flask run" command line
Inspect the callstack.
See https://github.com/pallets/flask/blob/master/src/flask/__main__.py
Returns:
bool: True if the application was started using "flask run".
"""
frames = inspect.stack()
if len(frames) < 2:
return False
return frames[-2].filename.endswith('flask/cli.py')
NO_SUBGROUPING = 'without further subgrouping'

View File

@@ -5,8 +5,13 @@ import pathlib
import os
import aiounittest
# Before import from the searx package, we need to set up the (debug)
# environment. The import of the searx package initialize the searx.settings
# and this in turn takes the defaults from the environment!
os.environ.pop('SEARXNG_SETTINGS_PATH', None)
os.environ['SEARXNG_DEBUG'] = '1'
os.environ['SEARXNG_DEBUG_LOG_LEVEL'] = 'WARNING'
os.environ['SEARXNG_DISABLE_ETC_SETTINGS'] = '1'

View File

@@ -27,6 +27,15 @@ class SearxRobotLayer:
webapp = str(tests_path.parent / 'searx' / 'webapp.py')
exe = 'python'
# The Flask app is started by Flask.run(...), don't enable Flask's debug
# mode, the debugger from Flask will cause wired process model, where
# the server never dies. Further read:
#
# - debug mode: https://flask.palletsprojects.com/quickstart/#debug-mode
# - Flask.run(..): https://flask.palletsprojects.com/api/#flask.Flask.run
os.environ['SEARXNG_DEBUG'] = '0'
# set robot settings path
os.environ['SEARXNG_SETTINGS_PATH'] = str(tests_path / 'robot' / 'settings_robot.yml')