mirror of
https://github.com/searxng/searxng.git
synced 2026-07-31 12:21:24 +00:00
Compare commits
1 Commits
dependabot
...
ci-data-up
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7595a2c32 |
39
.github/scripts/ai_policy.cjs
vendored
39
.github/scripts/ai_policy.cjs
vendored
@@ -1,39 +0,0 @@
|
||||
// Closes issues and prs whose authors/agents don't accept the ai policy
|
||||
// https://github.com/searxng/searxng/blob/master/AI_POLICY.rst
|
||||
|
||||
module.exports = async ({ github, context }) => {
|
||||
const item = context.payload.pull_request || context.payload.issue;
|
||||
const body = item.body || '';
|
||||
const kind = context.payload.pull_request ? 'pull request' : 'issue';
|
||||
|
||||
// https://github.com/searxng/searxng/pull/6476#discussion_r3683782481
|
||||
const hasBox = /\[[Xx]\].*AI Policy/.test(body);
|
||||
const hasRef = /\[AI Policy\]:\s*https:\/\/github\.com\/searxng\/searxng\/.*AI_POLICY/.test(body);
|
||||
if (hasBox && hasRef) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { owner, repo } = context.repo;
|
||||
await github.rest.issues.createComment({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: item.number,
|
||||
body:
|
||||
'Hello! Thank you for your contribution.\n\n' +
|
||||
`Unfortunately your ${kind} was closed as the AI Policy has not been accepted.\n\n` +
|
||||
`Please open a new ${kind} after confirming your contribution aligns with our AI Policy.`,
|
||||
});
|
||||
await github.rest.issues.addLabels({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: item.number,
|
||||
labels: ['invalid:slop'],
|
||||
});
|
||||
await github.rest.issues.update({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: item.number,
|
||||
state: 'closed',
|
||||
state_reason: 'not_planned',
|
||||
});
|
||||
};
|
||||
38
.github/workflows/ai-policy.yml
vendored
38
.github/workflows/ai-policy.yml
vendored
@@ -1,38 +0,0 @@
|
||||
---
|
||||
# yamllint disable rule:line-length
|
||||
name: AI Policy
|
||||
|
||||
# Closes any new issues and PRs from people (or agents) who don't accept the AI Policy
|
||||
|
||||
# yamllint disable-line rule:truthy
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
pull_request_target:
|
||||
types: [opened]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: Check AI Policy
|
||||
# for issues with an author who has not contributed before
|
||||
if: >-
|
||||
github.event.sender.type != 'Bot' &&
|
||||
contains(fromJSON('["NONE","FIRST_TIMER","FIRST_TIME_CONTRIBUTOR"]'),
|
||||
github.event.issue.author_association ||
|
||||
github.event.pull_request.author_association)
|
||||
runs-on: ubuntu-26.04-arm
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: "false"
|
||||
|
||||
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
with:
|
||||
script: |
|
||||
const script = require('./.github/scripts/ai_policy.cjs');
|
||||
await script({ github, context });
|
||||
56
client/simple/package-lock.json
generated
56
client/simple/package-lock.json
generated
@@ -11,16 +11,16 @@
|
||||
"dependencies": {
|
||||
"ionicons": "^8.0.13",
|
||||
"normalize.css": "8.0.1",
|
||||
"ol": "^10.10.0",
|
||||
"ol": "^10.9.0",
|
||||
"swiped-events": "1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.5.5",
|
||||
"@types/node": "^26.1.2",
|
||||
"@types/node": "^26.1.1",
|
||||
"browserslist": "^4.28.7",
|
||||
"browserslist-to-esbuild": "^2.1.1",
|
||||
"edge.js": "^6.5.1",
|
||||
"less": "^4.8.1",
|
||||
"less": "^4.8.0",
|
||||
"mathjs": "^15.2.0",
|
||||
"sharp": "~0.35.3",
|
||||
"sort-package-json": "^4.0.0",
|
||||
@@ -1648,9 +1648,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "26.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.2.tgz",
|
||||
"integrity": "sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg==",
|
||||
"version": "26.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.1.tgz",
|
||||
"integrity": "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -2881,9 +2881,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/geotiff": {
|
||||
"version": "3.1.0-beta.0",
|
||||
"resolved": "https://registry.npmjs.org/geotiff/-/geotiff-3.1.0-beta.0.tgz",
|
||||
"integrity": "sha512-wbVwOaQYuN+ywly5NoMXn37nHslwkQg5EFHqMeUTtjDACrSag0EEVlFsc+2DK3Pzmmp6XzJW2RTZOamPsBM6ng==",
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/geotiff/-/geotiff-3.0.5.tgz",
|
||||
"integrity": "sha512-OWcL9S9+yDZ6iAlXMt32T1iwUApJM8UiD47xbm6ZP1h33d10fqkPs14EG/ttT5EnefpZSx3G15iDFC5FxUNUwA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@petamoriken/float16": "^3.9.3",
|
||||
@@ -3304,9 +3304,9 @@
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/less": {
|
||||
"version": "4.8.1",
|
||||
"resolved": "https://registry.npmjs.org/less/-/less-4.8.1.tgz",
|
||||
"integrity": "sha512-jQ3lRIo1aUtiWVYXZ7mk4+V4BjCGswF3IxTLJ+4RUta8ZiHh8lhkig2G8dya2eCcyR1dYUvzuV46EkJN8PSwww==",
|
||||
"version": "4.8.0",
|
||||
"resolved": "https://registry.npmjs.org/less/-/less-4.8.0.tgz",
|
||||
"integrity": "sha512-7Y7DJBMbsW29UGjOG6NGvxQEx71AaDcrryBwYCMaFwn0kj8FkSueKN9r9WexVOetKEhXh38kL++WJncfkEpS+g==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
@@ -3812,15 +3812,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ol": {
|
||||
"version": "10.10.0",
|
||||
"resolved": "https://registry.npmjs.org/ol/-/ol-10.10.0.tgz",
|
||||
"integrity": "sha512-tLPKn6zl+6uWdPufYlqG/lQzuVUTVmfwahQqVr5+wZNyZecyAtIhMTyOtKpu7ooNDLY2sEjKZNXw9HL+sOjC1A==",
|
||||
"version": "10.9.0",
|
||||
"resolved": "https://registry.npmjs.org/ol/-/ol-10.9.0.tgz",
|
||||
"integrity": "sha512-svbbgVQUmEHaKpLQ8kRySojs59Brvgl2zYIrqG9eQNXGfsbi55rQasZIDpwpQzDL6OlzrUb0H4hQaiX9wDoGmA==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"@types/rbush": "4.0.0",
|
||||
"earcut": "^3.0.0",
|
||||
"geotiff": "^3.1.0-beta.0",
|
||||
"pbf": "5.1.2",
|
||||
"geotiff": "^3.0.5 || ^3.1.0-beta.0",
|
||||
"pbf": "4.0.1",
|
||||
"rbush": "^4.0.0",
|
||||
"zarrita": "^0.7.1"
|
||||
},
|
||||
@@ -3830,19 +3830,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/pako": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-2.2.0.tgz",
|
||||
"integrity": "sha512-zJq6RP/5q+TO2OpFV3FHzlPnFjmkb7Nc99a5SNjJE+uu/PkpChs+NIZSSzbBoD+6kjiISXjfYdwj1ZRQ81dz/w==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/puzrin"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/nodeca"
|
||||
}
|
||||
],
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
|
||||
"integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==",
|
||||
"license": "(MIT AND Zlib)"
|
||||
},
|
||||
"node_modules/parent-module": {
|
||||
@@ -3894,9 +3884,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/pbf": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/pbf/-/pbf-5.1.2.tgz",
|
||||
"integrity": "sha512-mnvGdvOrIvJOBGUEdGkrVXjN8E/VkIJCkf2eS1DH2yv82ORUlLttmDt0rWY38yYZmVwciZwBUvHM20qxBZf40w==",
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pbf/-/pbf-4.0.1.tgz",
|
||||
"integrity": "sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"resolve-protobuf-schema": "^2.1.0"
|
||||
|
||||
@@ -25,16 +25,16 @@
|
||||
"dependencies": {
|
||||
"ionicons": "^8.0.13",
|
||||
"normalize.css": "8.0.1",
|
||||
"ol": "^10.10.0",
|
||||
"ol": "^10.9.0",
|
||||
"swiped-events": "1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.5.5",
|
||||
"@types/node": "^26.1.2",
|
||||
"@types/node": "^26.1.1",
|
||||
"browserslist": "^4.28.7",
|
||||
"browserslist-to-esbuild": "^2.1.1",
|
||||
"edge.js": "^6.5.1",
|
||||
"less": "^4.8.1",
|
||||
"less": "^4.8.0",
|
||||
"mathjs": "^15.2.0",
|
||||
"sharp": "~0.35.3",
|
||||
"sort-package-json": "^4.0.0",
|
||||
|
||||
8
docs/dev/engines/online/presearch.rst
Normal file
8
docs/dev/engines/online/presearch.rst
Normal file
@@ -0,0 +1,8 @@
|
||||
.. _engine presearch:
|
||||
|
||||
================
|
||||
Presearch Engine
|
||||
================
|
||||
|
||||
.. automodule:: searx.engines.presearch
|
||||
:members:
|
||||
@@ -20,11 +20,15 @@ If you don't trust anyone, you can set up your own, see :ref:`installation`.
|
||||
|
||||
- :ref:`self hosted <installation>`
|
||||
- :ref:`no user tracking / no profiling <SearXNG protect privacy>`
|
||||
- javascript & cookies are optional
|
||||
- script & cookies are optional
|
||||
- secure, encrypted connections
|
||||
- :ref:`{{engines | length}} search engines <configured engines>`
|
||||
- `58 translations <https://translate.codeberg.org/projects/searxng/searxng/>`_
|
||||
- about 70 `well maintained <https://uptime.searxng.org/>`__ instances on searx.space_
|
||||
- :ref:`easy integration of search engines <demo online engine>`
|
||||
- professional development: `CI <https://github.com/searxng/searxng/actions>`_,
|
||||
`quality assurance <https://dev.searxng.org/>`_ &
|
||||
`automated tested UI <https://dev.searxng.org/screenshots.html>`_
|
||||
|
||||
.. sidebar:: be a part
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ from . import Answerer, AnswererInfo
|
||||
|
||||
def random_characters():
|
||||
random_string_letters = string.ascii_lowercase + string.digits + string.ascii_uppercase
|
||||
return random.choices(random_string_letters, k=random.randint(8, 32))
|
||||
return [random.choice(random_string_letters) for _ in range(random.randint(8, 32))]
|
||||
|
||||
|
||||
def random_string():
|
||||
|
||||
@@ -62,7 +62,7 @@ def bing(query: str, _sxng_locale: str) -> list[str]:
|
||||
# bing search autocompleter
|
||||
base_url = "https://www.bing.com/AS/Suggestions?"
|
||||
# cvid has to be a 32 character long string consisting of numbers and uppsercase characters
|
||||
cvid = ''.join(random.choices(string.ascii_uppercase + string.digits, k=32))
|
||||
cvid = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(32))
|
||||
response = get(base_url + urlencode({'qry': query, 'csr': 1, 'cvid': cvid}))
|
||||
results: list[str] = []
|
||||
|
||||
|
||||
@@ -151,6 +151,6 @@ def get_token() -> str:
|
||||
if token:
|
||||
token = token.decode('UTF-8') # type: ignore
|
||||
else:
|
||||
token = ''.join(random.choices(string.ascii_lowercase + string.digits, k=16))
|
||||
token = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(16))
|
||||
valkey_client.set(TOKEN_KEY, token, ex=TOKEN_LIVE_TIME)
|
||||
return token
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -288,7 +288,7 @@
|
||||
"oc": "Kwanza",
|
||||
"pa": "ਅੰਗੋਲਨ ਕਵਾਂਜ਼ਾ",
|
||||
"pl": "Kwanza",
|
||||
"pt": "kwanza",
|
||||
"pt": "Kwanza",
|
||||
"ru": "ангольская кванза",
|
||||
"si": "ක්වන්සා",
|
||||
"sr": "анголска кванза",
|
||||
@@ -334,7 +334,6 @@
|
||||
"ro": "Peso argentinian",
|
||||
"ru": "аргентинское песо",
|
||||
"sk": "Argentinské peso",
|
||||
"sl": "argentinski peso",
|
||||
"sr": "аргентински пезос",
|
||||
"sv": "Argentinsk peso",
|
||||
"ta": "ஆர்ஜென்டின பீசோ",
|
||||
@@ -2003,7 +2002,7 @@
|
||||
"eo": "ganaa cedio",
|
||||
"es": "cedi",
|
||||
"fi": "Cedi",
|
||||
"fr": "cedi",
|
||||
"fr": "Cedi",
|
||||
"ga": "cedi",
|
||||
"gl": "Cedi",
|
||||
"he": "סדי גאני",
|
||||
@@ -2953,7 +2952,7 @@
|
||||
"pap": "won nortkoreano",
|
||||
"pl": "won północnokoreański",
|
||||
"pt": "won norte-coreano",
|
||||
"ro": "won nord-coreean",
|
||||
"ro": "Won nord-coreean",
|
||||
"ru": "вона КНДР",
|
||||
"sk": "severokorejsky won",
|
||||
"sl": "severnokorejski von",
|
||||
@@ -3095,7 +3094,6 @@
|
||||
"ca": "tenge",
|
||||
"cs": "Tenge",
|
||||
"cy": "tenge Casachstan",
|
||||
"da": "Tenge",
|
||||
"de": "Tenge",
|
||||
"en": "Kazakhstani tenge",
|
||||
"eo": "kazaĥa tengo",
|
||||
@@ -4836,7 +4834,6 @@
|
||||
"nl": "Seychelse roepie",
|
||||
"pl": "Rupia seszelska",
|
||||
"pt": "rupia das Seicheles",
|
||||
"ro": "rupie seychelloză",
|
||||
"ru": "сейшельская рупия",
|
||||
"sk": "Seychelská rupia",
|
||||
"sl": "sejšelska rupija",
|
||||
@@ -5067,7 +5064,6 @@
|
||||
"nl": "Somalische shilling",
|
||||
"pl": "Szyling somalijski",
|
||||
"pt": "xelim somaliano",
|
||||
"ro": "șiling somalez",
|
||||
"ru": "сомалийский шиллинг",
|
||||
"sk": "Somálsky šiling",
|
||||
"sl": "somalski šiling",
|
||||
@@ -5887,7 +5883,6 @@
|
||||
"ja": "ドン",
|
||||
"ko": "베트남 동",
|
||||
"lt": "Vietnamo dongas",
|
||||
"ms": "Dồng Vietnam",
|
||||
"nl": "Vietnamese dong",
|
||||
"oc": "Dong",
|
||||
"pa": "ਵੀਅਤਨਾਮੀ ਦੋਙ",
|
||||
@@ -6127,8 +6122,7 @@
|
||||
"ro": "Gulden caraibian",
|
||||
"ru": "Карибский гульден",
|
||||
"sk": "Karibský gulden",
|
||||
"sl": "karibski goldinar",
|
||||
"sv": "Karibisk gulden"
|
||||
"sl": "karibski goldinar"
|
||||
},
|
||||
"XDR": {
|
||||
"ar": "حقوق السحب الخاصة",
|
||||
@@ -6730,8 +6724,6 @@
|
||||
"antilliaanse gulden": "ANG",
|
||||
"antilski gulden": "ANG",
|
||||
"aoa": "AOA",
|
||||
"apvienotās karalistes ekonomika": "GBP",
|
||||
"apvienotās karalistes saimniecība": "GBP",
|
||||
"apvienotās karalistes sterliņu mārciņa": "GBP",
|
||||
"ar": "MGA",
|
||||
"arab accounting dinar": "XAD",
|
||||
@@ -6844,7 +6836,6 @@
|
||||
"avustralya doları": "AUD",
|
||||
"awg": "AWG",
|
||||
"az arany mint befektetés": "XAU",
|
||||
"az egyesült királyság gazdasága": "GBP",
|
||||
"azerbaidžanin manat": "AZN",
|
||||
"azerbaidžano manatas": "AZN",
|
||||
"azerbaidžānas manats": "AZN",
|
||||
@@ -7028,7 +7019,6 @@
|
||||
"bir etíope": "ETB",
|
||||
"biras": "ETB",
|
||||
"birleşik arap emirlikleri dirhemi": "AED",
|
||||
"birleşik krallık ekonomisi": "GBP",
|
||||
"birma kjato": "MMK",
|
||||
"birr": "ETB",
|
||||
"birr da etiópia": "ETB",
|
||||
@@ -7116,19 +7106,15 @@
|
||||
"brit font": "GBP",
|
||||
"brita pundo": "GBP",
|
||||
"britaj pundoj": "GBP",
|
||||
"britannian talous": "GBP",
|
||||
"britanska funta": "GBP",
|
||||
"britanski funt": "GBP",
|
||||
"britische wirtschaft": "GBP",
|
||||
"britisches pfund": "GBP",
|
||||
"british economy": "GBP",
|
||||
"british pound": "GBP",
|
||||
"britisk pund": "GBP",
|
||||
"britiske pund": "GBP",
|
||||
"brits pond": "GBP",
|
||||
"britse pond": "GBP",
|
||||
"britská libra": "GBP",
|
||||
"brittisk ekonomi": "GBP",
|
||||
"brittiska pund": "GBP",
|
||||
"brittiskt pund": "GBP",
|
||||
"brunei doları": "BND",
|
||||
@@ -7212,7 +7198,6 @@
|
||||
"cedi du ghana": "GHS",
|
||||
"cedi ghana": "GHS",
|
||||
"cedi ghanese": "GHS",
|
||||
"cedi ghanéen": "GHS",
|
||||
"centr afrika franko": "XAF",
|
||||
"central african cfa franc": "XAF",
|
||||
"centralafrikansk cfa franc": "XAF",
|
||||
@@ -7315,6 +7300,7 @@
|
||||
"colón costa ricense": "CRC",
|
||||
"colón costa riquenho": "CRC",
|
||||
"colón costa riquense": "CRC",
|
||||
"colón costa riqueny": "CRC",
|
||||
"colón costaricain": "CRC",
|
||||
"colón costaricano": "CRC",
|
||||
"colón costaricien": "CRC",
|
||||
@@ -8427,7 +8413,6 @@
|
||||
"dólares canadenses": "CAD",
|
||||
"dólares estadounidenses": "USD",
|
||||
"dólares neozelandeses": "NZD",
|
||||
"dồng vietnam": "VND",
|
||||
"dram": "AMD",
|
||||
"dram armean": "AMD",
|
||||
"dram armenia": "AMD",
|
||||
@@ -8451,7 +8436,6 @@
|
||||
"droits de tirage speciaux": "XDR",
|
||||
"droits de tirage spéciaux": "XDR",
|
||||
"dschibuti franc": "DJF",
|
||||
"dvn": "VND",
|
||||
"dzd": "DZD",
|
||||
"dzsibuti frank": "DJF",
|
||||
"džibučio frankas": "DJF",
|
||||
@@ -8465,21 +8449,6 @@
|
||||
"eastern caribbean currency union": "XCD",
|
||||
"eastern caribbean dollar": "XCD",
|
||||
"ec$": "XCD",
|
||||
"economi'r deyrnas unedig": "GBP",
|
||||
"economia": "GBP",
|
||||
"economia del regne unit": "GBP",
|
||||
"economia del regno unito": "GBP",
|
||||
"economia del reialme unit": "GBP",
|
||||
"economia del reino unido": "GBP",
|
||||
"economia do reino unido": "GBP",
|
||||
"economia regatului unit": "GBP",
|
||||
"economie du royaume uni": "GBP",
|
||||
"economie van het verenigd koninkrijk": "GBP",
|
||||
"economía del reino unido": "GBP",
|
||||
"economía do reino unido": "GBP",
|
||||
"economy": "GBP",
|
||||
"economy of the uk": "GBP",
|
||||
"economy of the united kingdom": "GBP",
|
||||
"egipatska funta": "EGP",
|
||||
"egipta pundo": "EGP",
|
||||
"egipto svaras": "EGP",
|
||||
@@ -8499,12 +8468,6 @@
|
||||
"einr": "INR",
|
||||
"eiro": "EUR",
|
||||
"ekialdeko karibeko dolar": "XCD",
|
||||
"ekonomi britania raya": "GBP",
|
||||
"ekonomi united kingdom": "GBP",
|
||||
"ekonomie van die verenigde koninkryk": "GBP",
|
||||
"ekonomika spojeného království": "GBP",
|
||||
"ekonomika v spojenom kráľovstve": "GBP",
|
||||
"ekonomio de britujo": "GBP",
|
||||
"el peso": "GTQ",
|
||||
"emalangeni": "SZL",
|
||||
"emas sebagai pelaburan": "XAU",
|
||||
@@ -8536,7 +8499,6 @@
|
||||
"ermenistan dramı": "AMD",
|
||||
"ern": "ERN",
|
||||
"erreal brasildar": "BRL",
|
||||
"erresuma batuko ekonomia": "GBP",
|
||||
"errublo": "RUB",
|
||||
"errublo errusiar": "RUB",
|
||||
"errupia indiar": "INR",
|
||||
@@ -8607,8 +8569,6 @@
|
||||
"eyrir": "ISK",
|
||||
"e£": "EGP",
|
||||
"èuro": "EUR",
|
||||
"économie britannique": "GBP",
|
||||
"économie du royaume uni": "GBP",
|
||||
"észak ír font": "GBP",
|
||||
"észak koreai von": "KPW",
|
||||
"e₹": "INR",
|
||||
@@ -8742,9 +8702,6 @@
|
||||
"forintti": "HUF",
|
||||
"forinți": "HUF",
|
||||
"fòrint": "HUF",
|
||||
"förenade konungariket storbritannien och irlands ekonomi": "GBP",
|
||||
"förenade konungariket storbritannien och nordirlands ekonomi": "GBP",
|
||||
"förenade kungarikets ekonomi": "GBP",
|
||||
"franak cfp": "XPF",
|
||||
"franc": [
|
||||
"XPF",
|
||||
@@ -8997,9 +8954,6 @@
|
||||
"gold als kapitalanlage": "XAU",
|
||||
"gold as an investment": "XAU",
|
||||
"gold as currency": "XAU",
|
||||
"gospodarka wielkiej brytanii": "GBP",
|
||||
"gospodarstvo ujedinjenog kraljevstva": "GBP",
|
||||
"gospodarstvo združenega kraljestva": "GBP",
|
||||
"gourde": "HTG",
|
||||
"gourde haiti": "HTG",
|
||||
"gourde haitiano": "HTG",
|
||||
@@ -9419,7 +9373,6 @@
|
||||
"juaņs": "CNY",
|
||||
"juhokoréjsky won": "KRW",
|
||||
"juhosudánska libra": "SSP",
|
||||
"jungtinės karalystės ekonomika": "GBP",
|
||||
"jungtinių arabų emyratų dirhamas": "AED",
|
||||
"jungtinių valstijų doleris": "USD",
|
||||
"južnoafrički rand": "ZAR",
|
||||
@@ -9484,7 +9437,6 @@
|
||||
"karibi forint": "XCG",
|
||||
"karibia guldeno": "XCG",
|
||||
"karibischer gulden": "XCG",
|
||||
"karibisk gulden": "XCG",
|
||||
"karibski goldinar": "XCG",
|
||||
"karibský gulden": "XCG",
|
||||
"karipski gulden": "XCG",
|
||||
@@ -9545,9 +9497,6 @@
|
||||
"kina papua nugini": "PGK",
|
||||
"kina papuana": "PGK",
|
||||
"kina papuásia": "PGK",
|
||||
"kinh tế anh": "GBP",
|
||||
"kinh tế vương quốc anh": "GBP",
|
||||
"kinh tế vương quốc liên hiệp anh và bắc ireland": "GBP",
|
||||
"kip": "LAK",
|
||||
"kip laos": "LAK",
|
||||
"kip laosiano": "LAK",
|
||||
@@ -11192,7 +11141,6 @@
|
||||
"põhja korea won": "KPW",
|
||||
"põhja makedoonia denaar": "MKD",
|
||||
"prata como investimento": "XAG",
|
||||
"produits agricole de l'angleterre": "GBP",
|
||||
"pula": "BWP",
|
||||
"pula botswana": "BWP",
|
||||
"pula botswanais": "BWP",
|
||||
@@ -11243,7 +11191,6 @@
|
||||
"qatarisk rial": "QAR",
|
||||
"qäpik": "AZN",
|
||||
"qindarka": "ALL",
|
||||
"quanza": "AOA",
|
||||
"quetzal": "GTQ",
|
||||
"quetzal guatemala": "GTQ",
|
||||
"quetzal guatemalteco": "GTQ",
|
||||
@@ -11569,7 +11516,6 @@
|
||||
"rupia del pakistan": "PKR",
|
||||
"rupia dell'india": "INR",
|
||||
"rupia delle seychelles": "SCR",
|
||||
"rupia din seychelles": "SCR",
|
||||
"rupia do nepal": "NPR",
|
||||
"rupia do paquistão": "PKR",
|
||||
"rupia do seri lanca": "LKR",
|
||||
@@ -11625,7 +11571,6 @@
|
||||
],
|
||||
"rupie indiană": "INR",
|
||||
"rupie indiane": "INR",
|
||||
"rupie seychelloză": "SCR",
|
||||
"rupies índies": "INR",
|
||||
"rupija": [
|
||||
"NPR",
|
||||
@@ -12055,10 +12000,6 @@
|
||||
"sterliņu mārciņa": "GBP",
|
||||
"stērliņu mārciņa": "GBP",
|
||||
"stn": "STN",
|
||||
"storbritannien och irlands ekonomi": "GBP",
|
||||
"storbritannien och nordirlands ekonomi": "GBP",
|
||||
"storbritanniens ekonomi": "GBP",
|
||||
"storbritanniens økonomi": "GBP",
|
||||
"stredoafrický frank": "XAF",
|
||||
"středoafrický frank": "XAF",
|
||||
"sucre": "XSU",
|
||||
@@ -12108,7 +12049,6 @@
|
||||
"suriye lirası": "SYP",
|
||||
"suudi arabistan riyali": "SAR",
|
||||
"suudi riyali": "SAR",
|
||||
"suurbritannia majandus": "GBP",
|
||||
"suurbritannia nael": "GBP",
|
||||
"suurbritannia naelsterling": "GBP",
|
||||
"suvereni bolivar": "VES",
|
||||
@@ -12215,7 +12155,6 @@
|
||||
"švicarski frank": "CHF",
|
||||
"švýcarský frank": "CHF",
|
||||
"șekel nou": "ILS",
|
||||
"șiling somalez": "SOS",
|
||||
"şekel": "ILS",
|
||||
"şili pesosu": "CLP",
|
||||
"s₣": "CHF",
|
||||
@@ -12558,8 +12497,6 @@
|
||||
"uguiya": "MRU",
|
||||
"ugx": "UGX",
|
||||
"ui": "UYI",
|
||||
"uk economy": "GBP",
|
||||
"uk's economy": "GBP",
|
||||
"ukl": "GBP",
|
||||
"ukraina grivna": "UAH",
|
||||
"ukraina hrivno": "UAH",
|
||||
@@ -12600,8 +12537,6 @@
|
||||
"unidades de inversion": "MXV",
|
||||
"unidades de inversión": "MXV",
|
||||
"united arab emirates dirham": "AED",
|
||||
"united kingdom economy": "GBP",
|
||||
"united kingdom's economy": "GBP",
|
||||
"united states dollar": [
|
||||
"USN",
|
||||
"USD"
|
||||
@@ -12703,7 +12638,6 @@
|
||||
"venemaa rubla": "RUB",
|
||||
"venezuelai bolívar": "VES",
|
||||
"venezuelan digital bolívar": "VED",
|
||||
"verenigd koninkrijk economie": "GBP",
|
||||
"verenigde arabiese emirate dirham": "AED",
|
||||
"verenigde arabische emiraten dirham": "AED",
|
||||
"ves": "VES",
|
||||
@@ -12735,12 +12669,6 @@
|
||||
"wir euro": "CHE",
|
||||
"wir franc": "CHW",
|
||||
"wir franken": "CHW",
|
||||
"wirtschaft": "GBP",
|
||||
"wirtschaft des vereinigten königreichs": "GBP",
|
||||
"wirtschaft im vereinigten königreich": "GBP",
|
||||
"wirtschaft in dem vereinigten königreich": "GBP",
|
||||
"wirtschaft vom vereinigten königreich": "GBP",
|
||||
"wirtschaft von dem vereinigten königreich": "GBP",
|
||||
"wit russische roebel": "BYN",
|
||||
"won": "KRW",
|
||||
"won bắc triều tiên": "KPW",
|
||||
@@ -12834,7 +12762,6 @@
|
||||
"yeşil burun adaları eskudosu": "CVE",
|
||||
"yên nhật": "JPY",
|
||||
"yhdistyneen kuningaskunnan punta": "GBP",
|
||||
"yhdistyneen kuningaskunnan talous": "GBP",
|
||||
"yhdistyneiden arabiemiraattien dirhami": "AED",
|
||||
"yhdysvaltain dollari": "USD",
|
||||
"ytl": "TRY",
|
||||
@@ -13584,8 +13511,6 @@
|
||||
"египетский фунт": "EGP",
|
||||
"единая система региональных взаиморасчётов": "XSU",
|
||||
"единая система региональных взаиморасчетов": "XSU",
|
||||
"економіка великобританії": "GBP",
|
||||
"економіка великої британії": "GBP",
|
||||
"енглеска фунта": "GBP",
|
||||
"еритрейська накфа": "ERN",
|
||||
"еритрејска накфа": "ERN",
|
||||
@@ -13642,8 +13567,6 @@
|
||||
"израелски шекел": "ILS",
|
||||
"израильский новый шекель": "ILS",
|
||||
"източнокарибски долар": "XCD",
|
||||
"икономика на великобритания": "GBP",
|
||||
"икономика на обединеното кралство": "GBP",
|
||||
"индийска рупия": "INR",
|
||||
"индийская рупия": "INR",
|
||||
"индијска рупија": "INR",
|
||||
@@ -14057,7 +13980,6 @@
|
||||
"PLZ",
|
||||
"PLN"
|
||||
],
|
||||
"привреда уједињеног краљевства": "GBP",
|
||||
"пула": "BWP",
|
||||
"південно африканський ранд": "ZAR",
|
||||
"південнокорейська вона": "KRW",
|
||||
@@ -14145,7 +14067,6 @@
|
||||
"севернокорејски вон": "KPW",
|
||||
"северо корейская вона": "KPW",
|
||||
"северокорейская вона": "KPW",
|
||||
"седі": "GHS",
|
||||
"сейшел рупиясе": "SCR",
|
||||
"сейшелска рупия": "SCR",
|
||||
"сейшельская рупия": "SCR",
|
||||
@@ -14198,8 +14119,6 @@
|
||||
"старый румынский лей": "RON",
|
||||
"стерлинг фунты": "GBP",
|
||||
"стерлиң фунты": "GBP",
|
||||
"стопанство на великобритания": "GBP",
|
||||
"стопанство на обединеното кралство": "GBP",
|
||||
"суверен боливар": "VES",
|
||||
"суверенний болівар": "VES",
|
||||
"суверенный боливар": "VES",
|
||||
@@ -14450,7 +14369,6 @@
|
||||
"шриланкийска рупия": "LKR",
|
||||
"шриланчанска рупија": "LKR",
|
||||
"щатски долар": "USD",
|
||||
"экономика великобритании": "GBP",
|
||||
"эритрейская накфа": "ERN",
|
||||
"эритрея накфасы": "ERN",
|
||||
"эсватини лилангение": "SZL",
|
||||
@@ -14600,8 +14518,6 @@
|
||||
"יואן סיני": "CNY",
|
||||
"ין יפני": "JPY",
|
||||
"כארתולי לארי": "GEL",
|
||||
"כלכלת בריטניה": "GBP",
|
||||
"כלכלת הממלכה המאוחדת": "GBP",
|
||||
"כתר דני": "DKK",
|
||||
"כתר נורבגי": "NOK",
|
||||
"כתר נורווגי": "NOK",
|
||||
@@ -14749,7 +14665,6 @@
|
||||
"استثمار البلاتين": "XPT",
|
||||
"استثمار الذهب": "XAU",
|
||||
"استثمار الفضة": "XAG",
|
||||
"اقتصاد المملكة المتحدة": "GBP",
|
||||
"الاستثمار في الذهب": "XAU",
|
||||
"الأوقية الموريتانية": "MRU",
|
||||
"البات": "THB",
|
||||
@@ -14803,7 +14718,6 @@
|
||||
"أوقية": "MRU",
|
||||
"أوقية موريتانية": "MRU",
|
||||
"أوقيه موريتانيه": "MRU",
|
||||
"إقتصاد بريطانى": "GBP",
|
||||
"إيسكودو جزر الرأس الأخضر": "CVE",
|
||||
"بات": "THB",
|
||||
"بات تايلاندي": "THB",
|
||||
@@ -15186,7 +15100,6 @@
|
||||
"মালদ্বীপীয় রুফিয়াহ": "MVR",
|
||||
"মিয়ানমার ক্যত": "MMK",
|
||||
"মিশরীয় পাউন্ড": "EGP",
|
||||
"যুক্তরাজ্যের অর্থনীতি": "GBP",
|
||||
"রুশ রুবল": "RUB",
|
||||
"রেনমিনবি": "CNY",
|
||||
"রেন্মিন্বি": "CNY",
|
||||
@@ -15818,7 +15731,6 @@
|
||||
"엔": "JPY",
|
||||
"엔화": "JPY",
|
||||
"영국 파운드": "GBP",
|
||||
"영국의 경제": "GBP",
|
||||
"예멘 리알": "YER",
|
||||
"예멘 리얄": "YER",
|
||||
"예멘리얄": "YER",
|
||||
@@ -16026,11 +15938,9 @@
|
||||
"イエメン・リアル": "YER",
|
||||
"イエメン・リヤル": "YER",
|
||||
"イエメン・リヤール": "YER",
|
||||
"イギリスの経済": "GBP",
|
||||
"イギリスの通貨": "GBP",
|
||||
"イギリスポンド": "GBP",
|
||||
"イギリス・ポンド": "GBP",
|
||||
"イギリス経済": "GBP",
|
||||
"イラクの通貨": "IQD",
|
||||
"イラク・ディナール": "IQD",
|
||||
"イランの通貨": "IRR",
|
||||
@@ -16332,7 +16242,6 @@
|
||||
"英ポンド": "GBP",
|
||||
"西アフリカcfaフラン": "XOF",
|
||||
"豪ドル": "AUD",
|
||||
"財政・経済政策": "GBP",
|
||||
"越南銅": "VND",
|
||||
"金投資": "XAU",
|
||||
"韓国ウォン": "KRW",
|
||||
|
||||
@@ -81,7 +81,6 @@
|
||||
"ca": "ca",
|
||||
"ckb": "ckb",
|
||||
"cs": "cs",
|
||||
"cv": "cv",
|
||||
"cy": "cy",
|
||||
"da": "da",
|
||||
"de": "de",
|
||||
@@ -131,6 +130,7 @@
|
||||
"ne": "ne",
|
||||
"nl": "nl",
|
||||
"no": "no",
|
||||
"ny": "ny",
|
||||
"om": "om",
|
||||
"pa": "pa",
|
||||
"pl": "pl",
|
||||
@@ -8446,7 +8446,6 @@
|
||||
"IR",
|
||||
"IS",
|
||||
"IT",
|
||||
"JE",
|
||||
"JM",
|
||||
"JO",
|
||||
"JP",
|
||||
@@ -8476,7 +8475,6 @@
|
||||
"MC",
|
||||
"MD",
|
||||
"ME",
|
||||
"MF",
|
||||
"MG",
|
||||
"MH",
|
||||
"MK",
|
||||
@@ -8543,7 +8541,6 @@
|
||||
"SS",
|
||||
"ST",
|
||||
"SV",
|
||||
"SX",
|
||||
"SY",
|
||||
"SZ",
|
||||
"TC",
|
||||
@@ -8691,7 +8688,6 @@
|
||||
"th": "thai",
|
||||
"ti": "tigrinya",
|
||||
"tk": "turkmen",
|
||||
"to": "tonga",
|
||||
"tr": "turkish",
|
||||
"tt": "tatar",
|
||||
"uk": "ukrainian",
|
||||
|
||||
@@ -82,7 +82,7 @@ fragment SXNG_query on Query {
|
||||
|
||||
def setup(_) -> bool:
|
||||
global SXNG_query # pylint: disable=global-statement
|
||||
rand_str: str = "".join(random.choices(string.ascii_letters, k=5))
|
||||
rand_str: str = "".join(random.choice(string.ascii_letters) for _ in range(5))
|
||||
SXNG_query = SXNG_query.replace("SXNG_query", "PhotoSearchPaginationContainer_query_1" + rand_str)
|
||||
return True
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ base_url = "https://api.bilibili.com/x/web-interface/search/type"
|
||||
|
||||
cookie = {
|
||||
"innersign": "0",
|
||||
"buvid3": "".join(random.choices(string.hexdigits, k=16)) + "infoc",
|
||||
"buvid3": "".join(random.choice(string.hexdigits) for _ in range(16)) + "infoc",
|
||||
"i-wanna-go-back": "-1",
|
||||
"b_ut": "7",
|
||||
"FEED_LIVE_VERSION": "V8",
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
"""Keenable is a fast web search with keyless mode support"""
|
||||
|
||||
import typing as t
|
||||
|
||||
from datetime import datetime
|
||||
from searx.extended_types import SXNG_Response
|
||||
from searx.result_types import EngineResults
|
||||
from searx.utils import searxng_useragent
|
||||
|
||||
if t.TYPE_CHECKING:
|
||||
from searx.search.processors import OnlineParams
|
||||
|
||||
about = {
|
||||
"website": "https://keenable.ai",
|
||||
"official_api_documentation": "https://docs.keenable.ai",
|
||||
"use_official_api": True,
|
||||
"require_api_key": False,
|
||||
"results": "JSON",
|
||||
}
|
||||
api_key = ""
|
||||
""" Optional API Key. You can create a key at `the official website
|
||||
<https://keenable.ai/signup>'_ if you need higher rate limits."""
|
||||
|
||||
categories = ["general"]
|
||||
|
||||
base_url = "https://api.keenable.ai"
|
||||
keenable_mode = "pro"
|
||||
|
||||
|
||||
def request(query: str, params: "OnlineParams"):
|
||||
if api_key:
|
||||
params["url"] = f"{base_url}/v1/search"
|
||||
params["headers"]["X-API-KEY"] = api_key
|
||||
else:
|
||||
params["url"] = f"{base_url}/v1/search/public"
|
||||
|
||||
params["method"] = "POST"
|
||||
params["headers"]["X-Keenable-Title"] = searxng_useragent()
|
||||
params["json"] = {"query": query, "mode": keenable_mode}
|
||||
|
||||
|
||||
def response(resp: "SXNG_Response") -> EngineResults:
|
||||
res = EngineResults()
|
||||
|
||||
results: list[dict[str, str]] = resp.json()["results"] # type: ignore[reportAny]
|
||||
|
||||
for result in results:
|
||||
published = None
|
||||
pub = result.get("published_at")
|
||||
if pub:
|
||||
try:
|
||||
published = datetime.fromisoformat(pub.rstrip("Z"))
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
res.add(
|
||||
res.types.MainResult(
|
||||
url=result["url"],
|
||||
title=result["title"],
|
||||
content=result["description"] or result["snippet"],
|
||||
publishedDate=published,
|
||||
)
|
||||
)
|
||||
|
||||
return res
|
||||
305
searx/engines/presearch.py
Normal file
305
searx/engines/presearch.py
Normal file
@@ -0,0 +1,305 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
"""Presearch supports the search types listed in :py:obj:`search_type` (general,
|
||||
images, videos, news).
|
||||
|
||||
Configured ``presarch`` engines:
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
- name: presearch
|
||||
engine: presearch
|
||||
search_type: search
|
||||
categories: [general, web]
|
||||
|
||||
- name: presearch images
|
||||
...
|
||||
search_type: images
|
||||
categories: [images, web]
|
||||
|
||||
- name: presearch videos
|
||||
...
|
||||
search_type: videos
|
||||
categories: [general, web]
|
||||
|
||||
- name: presearch news
|
||||
...
|
||||
search_type: news
|
||||
categories: [news, web]
|
||||
|
||||
.. hint::
|
||||
|
||||
By default Presearch's video category is intentionally placed into::
|
||||
|
||||
categories: [general, web]
|
||||
|
||||
|
||||
Search type ``video``
|
||||
=====================
|
||||
|
||||
The results in the video category are most often links to pages that contain a
|
||||
video, for instance many links from Preasearch's video category link content
|
||||
from facebook (aka Meta) or Twitter (aka X). Since these are not real links to
|
||||
video streams SearXNG can't use the video template for this and if SearXNG can't
|
||||
use this template, then the user doesn't want to see these hits in the videos
|
||||
category.
|
||||
|
||||
|
||||
Languages & Regions
|
||||
===================
|
||||
|
||||
In Presearch there are languages for the UI and regions for narrowing down the
|
||||
search. If we set "auto" for the region in the WEB-UI of Presearch and cookie
|
||||
``use_local_search_results=false``, then the defaults are set for both (the
|
||||
language and the region) from the ``Accept-Language`` header.
|
||||
|
||||
Since the region is already "auto" by default, we only need to set the
|
||||
``use_local_search_results`` cookie and send the ``Accept-Language`` header. We
|
||||
have to set these values in both requests we send to Presearch; in the first
|
||||
request to get the request-ID from Presearch and in the final request to get the
|
||||
result list.
|
||||
|
||||
The time format returned by Presearch varies depending on the language set.
|
||||
Multiple different formats can be supported by using ``dateutil`` parser, but
|
||||
it doesn't support formats such as "N time ago", "vor N time" (German),
|
||||
"Hace N time" (Spanish). Because of this, the dates are simply joined together
|
||||
with the rest of other metadata.
|
||||
|
||||
|
||||
Implementations
|
||||
===============
|
||||
|
||||
"""
|
||||
|
||||
from urllib.parse import urlencode, urlparse
|
||||
from searx import locales
|
||||
from searx.network import get
|
||||
from searx.utils import gen_useragent, html_to_text, parse_duration_string
|
||||
|
||||
about = {
|
||||
"website": "https://presearch.io",
|
||||
"wikidata_id": "Q7240905",
|
||||
"official_api_documentation": "https://docs.presearch.io/nodes/api",
|
||||
"use_official_api": False,
|
||||
"require_api_key": False,
|
||||
"results": "JSON",
|
||||
}
|
||||
paging = True
|
||||
safesearch = True
|
||||
time_range_support = True
|
||||
categories = ["general", "web"] # general, images, videos, news
|
||||
|
||||
# HTTP2 requests immediately get blocked by a CAPTCHA
|
||||
enable_http2 = False
|
||||
|
||||
search_type = "search"
|
||||
"""must be any of ``search``, ``images``, ``videos``, ``news``"""
|
||||
|
||||
base_url = "https://presearch.com"
|
||||
safesearch_map = {0: 'false', 1: 'true', 2: 'true'}
|
||||
|
||||
|
||||
def init(_):
|
||||
if search_type not in ['search', 'images', 'videos', 'news']:
|
||||
raise ValueError(f'presearch search_type: {search_type}')
|
||||
|
||||
|
||||
def _get_request_id(query, params):
|
||||
|
||||
args = {
|
||||
"q": query,
|
||||
"page": params["pageno"],
|
||||
}
|
||||
|
||||
if params["time_range"]:
|
||||
args["time"] = params["time_range"]
|
||||
|
||||
url = f"{base_url}/{search_type}?{urlencode(args)}"
|
||||
|
||||
headers = {
|
||||
'User-Agent': gen_useragent(),
|
||||
'Cookie': (
|
||||
f"b=1;"
|
||||
f" presearch_session=;"
|
||||
f" use_local_search_results=false;"
|
||||
f" use_safe_search={safesearch_map[params['safesearch']]}"
|
||||
),
|
||||
}
|
||||
if params['searxng_locale'] != 'all':
|
||||
l = locales.get_locale(params['searxng_locale'])
|
||||
|
||||
# Presearch narrows down the search by region. In SearXNG when the user
|
||||
# does not set a region (e.g. 'en-CA' / canada) we cannot hand over a region.
|
||||
|
||||
# We could possibly use searx.locales.get_official_locales to determine
|
||||
# in which regions this language is an official one, but then we still
|
||||
# wouldn't know which region should be given more weight / Presearch
|
||||
# performs an IP-based geolocation of the user, we don't want that in
|
||||
# SearXNG ;-)
|
||||
|
||||
if l and l.territory:
|
||||
headers['Accept-Language'] = f"{l.language}-{l.territory},{l.language};" "q=0.9,*;" "q=0.5"
|
||||
|
||||
resp = get(url, headers=headers, timeout=5)
|
||||
|
||||
for line in resp.text.split("\n"):
|
||||
if "window.searchId = " in line:
|
||||
return line.split("= ")[1][:-1].replace('"', ""), resp.cookies
|
||||
|
||||
raise RuntimeError("Couldn't find any request id for presearch")
|
||||
|
||||
|
||||
def request(query, params):
|
||||
request_id, cookies = _get_request_id(query, params)
|
||||
params["headers"]["Accept"] = "application/json"
|
||||
params["url"] = f"{base_url}/results?id={request_id}"
|
||||
params["cookies"] = cookies
|
||||
|
||||
return params
|
||||
|
||||
|
||||
def _strip_leading_strings(text):
|
||||
for x in ['wikipedia', 'google']:
|
||||
if text.lower().endswith(x):
|
||||
text = text[: -len(x)]
|
||||
return text.strip()
|
||||
|
||||
|
||||
def _fix_title(title, url):
|
||||
"""
|
||||
Titles from Presearch shows domain + title without spacing, and HTML
|
||||
This function removes these 2 issues.
|
||||
Transforming "translate.google.co.in<em>Google</em> Translate" into "Google Translate"
|
||||
"""
|
||||
parsed_url = urlparse(url)
|
||||
domain = parsed_url.netloc
|
||||
title = html_to_text(title)
|
||||
# Fixes issue where domain would show up in the title
|
||||
# translate.google.co.inGoogle Translate -> Google Translate
|
||||
if (
|
||||
title.startswith(domain)
|
||||
and len(title) > len(domain)
|
||||
and not title.startswith(domain + "/")
|
||||
and not title.startswith(domain + " ")
|
||||
):
|
||||
title = title.removeprefix(domain)
|
||||
return title
|
||||
|
||||
|
||||
def parse_search_query(json_results):
|
||||
results = []
|
||||
if not json_results:
|
||||
return results
|
||||
|
||||
for item in json_results.get('specialSections', {}).get('topStoriesCompact', {}).get('data', []):
|
||||
result = {
|
||||
'url': item['link'],
|
||||
'title': _fix_title(item['title'], item['link']),
|
||||
'thumbnail': item['image'],
|
||||
'content': '',
|
||||
'metadata': item.get('source'),
|
||||
}
|
||||
results.append(result)
|
||||
|
||||
for item in json_results.get('standardResults', []):
|
||||
result = {
|
||||
'url': item['link'],
|
||||
'title': _fix_title(item['title'], item['link']),
|
||||
'content': html_to_text(item['description']),
|
||||
}
|
||||
results.append(result)
|
||||
|
||||
info = json_results.get('infoSection', {}).get('data')
|
||||
if info:
|
||||
attributes = []
|
||||
for item in info.get('about', []):
|
||||
|
||||
text = html_to_text(item)
|
||||
if ':' in text:
|
||||
# split text into key / value
|
||||
label, value = text.split(':', 1)
|
||||
else:
|
||||
# In other languages (tested with zh-TW) a colon is represented
|
||||
# by a different symbol --> then we split at the first space.
|
||||
label, value = text.split(' ', 1)
|
||||
label = label[:-1]
|
||||
|
||||
value = _strip_leading_strings(value)
|
||||
attributes.append({'label': label, 'value': value})
|
||||
content = []
|
||||
for item in [info.get('subtitle'), info.get('description')]:
|
||||
if not item:
|
||||
continue
|
||||
item = _strip_leading_strings(html_to_text(item))
|
||||
if item:
|
||||
content.append(item)
|
||||
|
||||
results.append(
|
||||
{
|
||||
'infobox': info['title'],
|
||||
'id': info['title'],
|
||||
'img_src': info.get('image'),
|
||||
'content': ' | '.join(content),
|
||||
'attributes': attributes,
|
||||
}
|
||||
)
|
||||
return results
|
||||
|
||||
|
||||
def response(resp):
|
||||
results = []
|
||||
json_resp = resp.json()
|
||||
|
||||
if search_type == 'search':
|
||||
results = parse_search_query(json_resp.get('results', {}))
|
||||
|
||||
elif search_type == 'images':
|
||||
for item in json_resp.get('images', []):
|
||||
results.append(
|
||||
{
|
||||
'template': 'images.html',
|
||||
'title': html_to_text(item['title']),
|
||||
'url': item.get('link'),
|
||||
'img_src': item.get('image'),
|
||||
'thumbnail_src': item.get('thumbnail'),
|
||||
}
|
||||
)
|
||||
|
||||
elif search_type == 'videos':
|
||||
# The results in the video category are most often links to pages that contain
|
||||
# a video and not to a video stream --> SearXNG can't use the video template.
|
||||
|
||||
for item in json_resp.get('videos', []):
|
||||
duration = item.get('duration')
|
||||
if duration:
|
||||
duration = parse_duration_string(duration)
|
||||
|
||||
results.append(
|
||||
{
|
||||
'title': html_to_text(item['title']),
|
||||
'url': item.get('link'),
|
||||
'content': item.get('description', ''),
|
||||
'thumbnail': item.get('image'),
|
||||
'length': duration,
|
||||
}
|
||||
)
|
||||
|
||||
elif search_type == 'news':
|
||||
for item in json_resp.get('news', []):
|
||||
source = item.get('source')
|
||||
# Bug on their end, time sometimes returns "</a>"
|
||||
time = html_to_text(item.get('time')).strip()
|
||||
metadata = [source]
|
||||
if time != "":
|
||||
metadata.append(time)
|
||||
|
||||
results.append(
|
||||
{
|
||||
'title': html_to_text(item['title']),
|
||||
'url': item.get('link'),
|
||||
'content': html_to_text(item.get('description', '')),
|
||||
'metadata': ' / '.join(metadata),
|
||||
'thumbnail': item.get('image'),
|
||||
}
|
||||
)
|
||||
|
||||
return results
|
||||
74
searx/engines/reddit.py
Normal file
74
searx/engines/reddit.py
Normal file
@@ -0,0 +1,74 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
"""Reddit"""
|
||||
|
||||
import json
|
||||
from datetime import datetime
|
||||
from urllib.parse import urlencode, urljoin, urlparse
|
||||
|
||||
# about
|
||||
about = {
|
||||
"website": 'https://www.reddit.com/',
|
||||
"wikidata_id": 'Q1136',
|
||||
"official_api_documentation": 'https://www.reddit.com/dev/api',
|
||||
"use_official_api": True,
|
||||
"require_api_key": False,
|
||||
"results": 'JSON',
|
||||
}
|
||||
|
||||
# engine dependent config
|
||||
categories = ['social media']
|
||||
page_size = 25
|
||||
|
||||
# search-url
|
||||
base_url = 'https://www.reddit.com/'
|
||||
search_url = base_url + 'search.json?{query}'
|
||||
|
||||
|
||||
def request(query, params):
|
||||
|
||||
query = urlencode({'q': query, 'limit': page_size})
|
||||
params['url'] = search_url.format(query=query)
|
||||
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
|
||||
img_results = []
|
||||
text_results = []
|
||||
|
||||
search_results = json.loads(resp.text)
|
||||
|
||||
# return empty array if there are no results
|
||||
if 'data' not in search_results:
|
||||
return []
|
||||
|
||||
posts = search_results.get('data', {}).get('children', [])
|
||||
|
||||
# process results
|
||||
for post in posts:
|
||||
data = post['data']
|
||||
|
||||
# extract post information
|
||||
params = {'url': urljoin(base_url, data['permalink']), 'title': data['title']}
|
||||
|
||||
# if thumbnail field contains a valid URL, we need to change template
|
||||
thumbnail = data['thumbnail']
|
||||
url_info = urlparse(thumbnail)
|
||||
# netloc & path
|
||||
if url_info[1] != '' and url_info[2] != '':
|
||||
params['img_src'] = data['url']
|
||||
params['thumbnail_src'] = thumbnail
|
||||
params['template'] = 'images.html'
|
||||
img_results.append(params)
|
||||
else:
|
||||
created = datetime.fromtimestamp(data['created_utc'])
|
||||
content = data['selftext']
|
||||
if len(content) > 500:
|
||||
content = content[:500] + '...'
|
||||
params['content'] = content
|
||||
params['publishedDate'] = created
|
||||
text_results.append(params)
|
||||
|
||||
# show images first and text results second
|
||||
return img_results + text_results
|
||||
@@ -9,7 +9,6 @@ import codecs
|
||||
import hashlib
|
||||
import json
|
||||
import random
|
||||
import string
|
||||
|
||||
from datetime import datetime
|
||||
from urllib.parse import urlencode
|
||||
@@ -44,8 +43,8 @@ paging = True
|
||||
|
||||
base_url = "https://api.swisscows.com"
|
||||
|
||||
CAESAR_ALPHABET = string.ascii_uppercase
|
||||
NONCE_ALPHABET = string.ascii_letters + string.digits + "-._~"
|
||||
CAESAR_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
NONCE_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"
|
||||
|
||||
time_range_map = {"day": "Day", "week": "Week", "month": "Month", "year": "Year"}
|
||||
|
||||
@@ -93,7 +92,7 @@ def generate_nonce(length: int = 32) -> str:
|
||||
"""
|
||||
Generate a random char sequence with the given length.
|
||||
"""
|
||||
return "".join(random.choices(NONCE_ALPHABET, k=length))
|
||||
return "".join([random.choice(NONCE_ALPHABET) for _ in range(length)])
|
||||
|
||||
|
||||
def caesar_shift_with_switch_case(s: str, offset: int = 13) -> str:
|
||||
|
||||
@@ -1461,12 +1461,6 @@ engines:
|
||||
description: "Demo index of Kavunka, a statistical search engine"
|
||||
results: HTML
|
||||
|
||||
- name: keenable
|
||||
engine: keenable
|
||||
shortcut: keen
|
||||
disabled: true
|
||||
inactive: true
|
||||
|
||||
- name: kozmonavt
|
||||
engine: xpath
|
||||
search_url: https://kozmonavt.su/s?q={query}
|
||||
@@ -2022,6 +2016,41 @@ engines:
|
||||
shortcut: poc
|
||||
disabled: true
|
||||
|
||||
- name: presearch
|
||||
engine: presearch
|
||||
search_type: search
|
||||
categories: [general, web]
|
||||
shortcut: ps
|
||||
timeout: 4.0
|
||||
disabled: true
|
||||
|
||||
- name: presearch images
|
||||
engine: presearch
|
||||
network: presearch
|
||||
search_type: images
|
||||
categories: [images, web]
|
||||
timeout: 4.0
|
||||
shortcut: psimg
|
||||
disabled: true
|
||||
|
||||
- name: presearch videos
|
||||
engine: presearch
|
||||
network: presearch
|
||||
search_type: videos
|
||||
categories: [general, web]
|
||||
timeout: 4.0
|
||||
shortcut: psvid
|
||||
disabled: true
|
||||
|
||||
- name: presearch news
|
||||
engine: presearch
|
||||
network: presearch
|
||||
search_type: news
|
||||
categories: [news, web]
|
||||
timeout: 4.0
|
||||
shortcut: psnews
|
||||
disabled: true
|
||||
|
||||
- name: pub.dev
|
||||
engine: xpath
|
||||
shortcut: pd
|
||||
@@ -2147,6 +2176,12 @@ engines:
|
||||
require_api_key: false
|
||||
results: JSON
|
||||
|
||||
- name: reddit
|
||||
engine: reddit
|
||||
shortcut: re
|
||||
page_size: 25
|
||||
disabled: true
|
||||
|
||||
- name: reuters
|
||||
engine: reuters
|
||||
shortcut: reu
|
||||
|
||||
@@ -15,10 +15,8 @@ sxng_locales = (
|
||||
('bg', 'Български', '', 'Bulgarian', '\U0001f310'),
|
||||
('bg-BG', 'Български', 'България', 'Bulgarian', '\U0001f1e7\U0001f1ec'),
|
||||
('ca', 'Català', '', 'Catalan', '\U0001f310'),
|
||||
('ca-ES', 'Català', 'Espanya', 'Catalan', '\U0001f1ea\U0001f1f8'),
|
||||
('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'),
|
||||
@@ -51,7 +49,6 @@ sxng_locales = (
|
||||
('es-VE', 'Español', 'Venezuela', 'Spanish', '\U0001f1fb\U0001f1ea'),
|
||||
('et', 'Eesti', '', 'Estonian', '\U0001f310'),
|
||||
('et-EE', 'Eesti', 'Eesti', 'Estonian', '\U0001f1ea\U0001f1ea'),
|
||||
('fa', 'فارسی', '', 'Persian', '\U0001f310'),
|
||||
('fi', 'Suomi', '', 'Finnish', '\U0001f310'),
|
||||
('fi-FI', 'Suomi', 'Suomi', 'Finnish', '\U0001f1eb\U0001f1ee'),
|
||||
('fil', 'Filipino', '', 'Filipino', '\U0001f310'),
|
||||
@@ -77,10 +74,6 @@ sxng_locales = (
|
||||
('ja-JP', '日本語', '日本', 'Japanese', '\U0001f1ef\U0001f1f5'),
|
||||
('ko', '한국어', '', 'Korean', '\U0001f310'),
|
||||
('ko-KR', '한국어', '대한민국', 'Korean', '\U0001f1f0\U0001f1f7'),
|
||||
('lt', 'Lietuvių', '', 'Lithuanian', '\U0001f310'),
|
||||
('lt-LT', 'Lietuvių', 'Lietuva', 'Lithuanian', '\U0001f1f1\U0001f1f9'),
|
||||
('lv', 'Latviešu', '', 'Latvian', '\U0001f310'),
|
||||
('lv-LV', 'Latviešu', 'Latvija', 'Latvian', '\U0001f1f1\U0001f1fb'),
|
||||
('mi', 'Māori', '', 'Māori', '\U0001f310'),
|
||||
('mi-NZ', 'Māori', 'Aotearoa', 'Māori', '\U0001f1f3\U0001f1ff'),
|
||||
('nb', 'Norsk Bokmål', '', 'Norwegian Bokmål', '\U0001f310'),
|
||||
@@ -100,9 +93,6 @@ sxng_locales = (
|
||||
('ru', 'Русский', '', 'Russian', '\U0001f310'),
|
||||
('ru-RU', 'Русский', 'Россия', 'Russian', '\U0001f1f7\U0001f1fa'),
|
||||
('sk', 'Slovenčina', '', 'Slovak', '\U0001f310'),
|
||||
('sk-SK', 'Slovenčina', 'Slovensko', 'Slovak', '\U0001f1f8\U0001f1f0'),
|
||||
('sl', 'Slovenščina', '', 'Slovenian', '\U0001f310'),
|
||||
('sl-SI', 'Slovenščina', 'Slovenija', 'Slovenian', '\U0001f1f8\U0001f1ee'),
|
||||
('sq', 'Shqip', '', 'Albanian', '\U0001f310'),
|
||||
('sv', 'Svenska', '', 'Swedish', '\U0001f310'),
|
||||
('sv-FI', 'Svenska', 'Finland', 'Swedish', '\U0001f1eb\U0001f1ee'),
|
||||
@@ -112,7 +102,6 @@ sxng_locales = (
|
||||
('tr', 'Türkçe', '', 'Turkish', '\U0001f310'),
|
||||
('tr-TR', 'Türkçe', 'Türkiye', 'Turkish', '\U0001f1f9\U0001f1f7'),
|
||||
('uk', 'Українська', '', 'Ukrainian', '\U0001f310'),
|
||||
('uk-UA', 'Українська', 'Україна', 'Ukrainian', '\U0001f1fa\U0001f1e6'),
|
||||
('vi', 'Tiếng Việt', '', 'Vietnamese', '\U0001f310'),
|
||||
('vi-VN', 'Tiếng Việt', 'Việt Nam', 'Vietnamese', '\U0001f1fb\U0001f1f3'),
|
||||
('zh', '中文', '', 'Chinese', '\U0001f310'),
|
||||
|
||||
@@ -13,7 +13,7 @@ from tests import SearxTestCase
|
||||
|
||||
|
||||
def random_string(length, choices=string.ascii_letters):
|
||||
return ''.join(random.choices(choices, k=length))
|
||||
return ''.join(random.choice(choices) for _ in range(length))
|
||||
|
||||
|
||||
class TestUtils(SearxTestCase):
|
||||
|
||||
Reference in New Issue
Block a user