Cron package that syncs jobs from matrixhost portal API, schedules execution with timezone-aware timing, and posts results to Matrix rooms. Includes Brave Search, reminder, and browser scrape (placeholder) executors with formatter. 31 pytest tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
64 lines
2.0 KiB
Python
64 lines
2.0 KiB
Python
"""Brave Search executor for cron jobs."""
|
|
|
|
import logging
|
|
import os
|
|
|
|
import httpx
|
|
|
|
from .formatter import format_search_results
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
BRAVE_API_KEY = os.environ.get("BRAVE_API_KEY", "")
|
|
|
|
|
|
async def execute_brave_search(job: dict, send_text, **_kwargs) -> dict:
|
|
"""Run a Brave Search query, dedup against known keys, post new results to Matrix."""
|
|
if not BRAVE_API_KEY:
|
|
return {"status": "error", "error": "BRAVE_API_KEY not configured"}
|
|
|
|
config = job.get("config", {})
|
|
query = config.get("query", "")
|
|
max_results = config.get("maxResults", 10)
|
|
target_room = job["targetRoom"]
|
|
dedup_keys = set(job.get("dedupKeys", []))
|
|
|
|
if not query:
|
|
return {"status": "error", "error": "No search query configured"}
|
|
|
|
try:
|
|
async with httpx.AsyncClient(timeout=15.0) as client:
|
|
resp = await client.get(
|
|
"https://api.search.brave.com/res/v1/web/search",
|
|
headers={
|
|
"Accept": "application/json",
|
|
"X-Subscription-Token": BRAVE_API_KEY,
|
|
},
|
|
params={"q": query, "count": max_results, "text_decorations": False},
|
|
)
|
|
resp.raise_for_status()
|
|
data = resp.json()
|
|
|
|
results = data.get("web", {}).get("results", [])
|
|
if not results:
|
|
return {"status": "no_results"}
|
|
|
|
# Dedup by URL
|
|
new_results = [r for r in results if r.get("url") not in dedup_keys]
|
|
|
|
if not new_results:
|
|
return {"status": "no_results"}
|
|
|
|
msg = format_search_results(job["name"], new_results)
|
|
await send_text(target_room, msg)
|
|
|
|
new_keys = [r["url"] for r in new_results if r.get("url")]
|
|
return {
|
|
"status": "success",
|
|
"newDedupKeys": new_keys,
|
|
}
|
|
|
|
except Exception as exc:
|
|
logger.error("Brave search cron failed: %s", exc, exc_info=True)
|
|
return {"status": "error", "error": str(exc)}
|