Some checks failed
CI / Frontend Lint & Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Backend Lint (push) Has been cancelled
CI / Backend Tests (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
Deploy / Build & Push Images (push) Has been cancelled
Deploy / Deploy to Server (push) Has been cancelled
Deploy / Notify (push) Has been cancelled
Adds HUNT (Sniper/Trend/Forge), CFO dashboard (burn rate + kill list), and a plugin-based Analyze side panel with caching and SSRF hardening.
54 lines
1.7 KiB
Python
54 lines
1.7 KiB
Python
"""
|
|
Trend Surfer: fetch trending search queries via public RSS (no API key).
|
|
|
|
Note: This still performs an external HTTP request to Google Trends RSS.
|
|
It's not a paid API and uses public endpoints.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime, timezone
|
|
from typing import Optional
|
|
from xml.etree import ElementTree as ET
|
|
|
|
import httpx
|
|
|
|
|
|
async def fetch_google_trends_daily_rss(geo: str = "US", *, timeout_seconds: float = 10.0) -> list[dict]:
|
|
geo = (geo or "US").upper().strip()
|
|
url = f"https://trends.google.com/trends/trendingsearches/daily/rss?geo={geo}"
|
|
async with httpx.AsyncClient(timeout=timeout_seconds, follow_redirects=True) as client:
|
|
res = await client.get(url)
|
|
res.raise_for_status()
|
|
xml = res.text
|
|
|
|
root = ET.fromstring(xml)
|
|
|
|
items: list[dict] = []
|
|
for item in root.findall(".//item"):
|
|
title = item.findtext("title") or ""
|
|
link = item.findtext("link")
|
|
pub = item.findtext("pubDate")
|
|
approx = item.findtext("{*}approx_traffic") # namespaced
|
|
|
|
published_at: Optional[datetime] = None
|
|
if pub:
|
|
try:
|
|
# Example: "Sat, 14 Dec 2025 00:00:00 +0000"
|
|
published_at = datetime.strptime(pub, "%a, %d %b %Y %H:%M:%S %z").astimezone(timezone.utc)
|
|
except Exception:
|
|
published_at = None
|
|
|
|
if title.strip():
|
|
items.append(
|
|
{
|
|
"title": title.strip(),
|
|
"approx_traffic": approx.strip() if approx else None,
|
|
"published_at": published_at,
|
|
"link": link,
|
|
}
|
|
)
|
|
|
|
return items
|
|
|