Agent-Reach/agent_reach/channels/rss.py
Panniantong 5c62a21f32 rename: Agent Eyes → Agent Reach
全局重命名:
- 包名: agent_eyes → agent_reach
- CLI: agent-eyes → agent-reach
- 类名: AgentEyes → AgentReach
- 显示名: Agent Eyes → Agent Reach
- GitHub: Panniantong/agent-eyes → Panniantong/Agent-Reach

所有 36 个测试通过,CLI/doctor/read/search 全部正常。
2026-02-24 10:25:46 +01:00

57 lines
1.8 KiB
Python

# -*- coding: utf-8 -*-
"""RSS feeds — via feedparser (free, pip dependency).
Backend: feedparser (https://github.com/kurtmckee/feedparser)
Swap to: any RSS parser
"""
import feedparser
from urllib.parse import urlparse
from .base import Channel, ReadResult
class RSSChannel(Channel):
name = "rss"
description = "RSS/Atom 订阅源"
backends = ["feedparser"]
tier = 0
def can_handle(self, url: str) -> bool:
lower = url.lower()
domain = urlparse(url).netloc.lower()
return (lower.endswith(".xml") or "/rss" in lower or "/feed" in lower
or "/atom" in lower or "rss" in domain)
async def read(self, url: str, config=None) -> ReadResult:
feed = feedparser.parse(url)
if feed.bozo and not feed.entries:
raise ValueError(f"Failed to parse RSS feed: {url}")
if not feed.entries:
raise ValueError(f"No entries in RSS feed: {url}")
# Return latest entry
entry = feed.entries[0]
content = entry.get("summary", "") or entry.get("description", "")
# If multiple entries, summarize all
if len(feed.entries) > 1:
lines = [f"# {feed.feed.get('title', 'RSS Feed')}\n"]
for i, e in enumerate(feed.entries[:20], 1):
title = e.get("title", "Untitled")
link = e.get("link", "")
summary = e.get("summary", "")[:200]
lines.append(f"## {i}. {title}")
lines.append(f"🔗 {link}")
if summary:
lines.append(summary)
lines.append("")
content = "\n".join(lines)
return ReadResult(
title=feed.feed.get("title", entry.get("title", url)),
content=content,
url=url,
platform="rss",
)