summaryrefslogtreecommitdiff
path: root/searx
diff options
context:
space:
mode:
authorIlya Bogin <ilya.bogin@gmail.com>2026-07-15 19:05:41 +0300
committerBnyro <bnyro@tutanota.com>2026-07-30 16:11:42 +0200
commit0be6f87801022f6b0640644b5c60364891145345 (patch)
tree5cdba8e8afbe01d3f75578e2a6757ad4c3b08787 /searx
parentef3a6ea9fd7e4a8cdae705c376bac7b03f31e674 (diff)
[feat] engines: add keenable (general)
Diffstat (limited to 'searx')
-rw-r--r--searx/engines/keenable.py66
-rw-r--r--searx/settings.yml6
2 files changed, 72 insertions, 0 deletions
diff --git a/searx/engines/keenable.py b/searx/engines/keenable.py
new file mode 100644
index 000000000..5c1f11f0e
--- /dev/null
+++ b/searx/engines/keenable.py
@@ -0,0 +1,66 @@
+# 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
diff --git a/searx/settings.yml b/searx/settings.yml
index ab26f1900..8d615cb87 100644
--- a/searx/settings.yml
+++ b/searx/settings.yml
@@ -1461,6 +1461,12 @@ 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}