aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/search-ddgs.sh
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/search-ddgs.sh')
-rwxr-xr-xscripts/search-ddgs.sh54
1 files changed, 54 insertions, 0 deletions
diff --git a/scripts/search-ddgs.sh b/scripts/search-ddgs.sh
new file mode 100755
index 0000000..2f818b7
--- /dev/null
+++ b/scripts/search-ddgs.sh
@@ -0,0 +1,54 @@
+#!/usr/bin/env bash
+# Searches with ddgs and writes the results as JSON to standard output.
+#
+# scripts/search-ddgs.sh "<query>" [number of results]
+#
+# ddgs queries several engines (DuckDuckGo, Brave, Mojeek, Startpage…) with no
+# key needed. This script exists so the assistant configuration does not have
+# to know anything about uv or Python environments: a usable ddgs is found
+# here and the output is normalized.
+#
+# Beware of two things that look equivalent and are not:
+# · `curl` against html.duckduckgo.com returns HTTP 202 with an anti-bot
+# page and no results. Measured, not assumed.
+# · The keyless api.duckduckgo.com API (Instant Answer) returns nothing for
+# almost anything that is not an encyclopedia entity.
+# The ddgs library does work because it rotates engines and headers.
+set -euo pipefail
+
+QUERY="${1:?usage: search-ddgs.sh \"<query>\" [n]}"
+MAX="${2:-5}"
+
+PROGRAM=$(cat <<'PY'
+import json, sys
+from ddgs import DDGS
+query, max_results = sys.argv[1], int(sys.argv[2])
+try:
+ rows = DDGS().text(query, max_results=max_results)
+except Exception as e: # noqa: BLE001
+ print(json.dumps({"error": f"{type(e).__name__}: {e}"}), file=sys.stderr)
+ raise SystemExit(1)
+print(json.dumps(rows, ensure_ascii=False))
+PY
+)
+
+# 1) The `uv tool install ddgs` environment: the fast path, since the package
+# does not have to be resolved on every search.
+TOOL_PY="$HOME/.local/share/uv/tools/ddgs/bin/python"
+if [ -x "$TOOL_PY" ]; then
+ exec "$TOOL_PY" -c "$PROGRAM" "$QUERY" "$MAX"
+fi
+
+# 2) A system Python that already has ddgs installed.
+if python3 -c "import ddgs" >/dev/null 2>&1; then
+ exec python3 -c "$PROGRAM" "$QUERY" "$MAX"
+fi
+
+# 3) uvx, which downloads it on the fly. Works without installing anything,
+# but adds several seconds to every search: better `uv tool install ddgs`.
+if command -v uvx >/dev/null 2>&1; then
+ exec uvx --quiet --from ddgs python -c "$PROGRAM" "$QUERY" "$MAX"
+fi
+
+echo '{"error":"ddgs is not available. Install it with: uv tool install ddgs"}' >&2
+exit 1