From 5d046ecb614293ff098e97a277287668f46d7572 Mon Sep 17 00:00:00 2001 From: Pnant <73925474+Panniantong@users.noreply.github.com> Date: Tue, 31 Mar 2026 14:21:31 +0800 Subject: [PATCH] fix(reddit): switch to Exa-only for search and read, remove proxy dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reddit blocks nearly all non-browser access at IP level (including ISP proxies). Switch Reddit channel to use Exa exclusively: - Search: web_search_exa with includeDomains: ["reddit.com"] - Read: crawling_exa for full post + comments - check() now verifies Exa availability instead of probing Reddit API - tier changed from 1 (needs config) to 0 (zero config) - Removed reddit_proxy from config, CLI, and setup guide - Updated all docs (README, README_en, install.md, SKILL.md, references) - Fixed xreach→bird references in references/social.md Fixes #218, Fixes #222, Fixes #221 Co-Authored-By: Claude Opus 4.6 (1M context) --- README.md | 10 ++-- agent_reach/channels/reddit.py | 46 ++++++++-------- agent_reach/cli.py | 43 +++------------ agent_reach/config.py | 1 - agent_reach/guides/setup-reddit.md | 73 ++++++++++---------------- agent_reach/skill/SKILL.md | 6 +++ agent_reach/skill/references/social.md | 31 ++++++----- docs/README_en.md | 14 ++--- docs/install.md | 2 +- tests/test_config.py | 5 -- 10 files changed, 95 insertions(+), 136 deletions(-) diff --git a/README.md b/README.md index 25affd2..5148960 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ AI Agent 已经能帮你写代码、改文档、管项目——但你让它去 | 📦 **GitHub** | 读公开仓库 + 搜索 | 私有仓库、提 Issue/PR、Fork | 告诉 Agent「帮我登录 GitHub」 | | 🐦 **Twitter/X** | 读单条推文 | 搜索推文、浏览时间线、发推 | 告诉 Agent「帮我配 Twitter」 | | 📺 **B站** | 本地:字幕提取 + 搜索 | 服务器也能用 | 告诉 Agent「帮我配代理」 | -| 📖 **Reddit** | 搜索(通过 Exa 免费) | 读帖子和评论 | 告诉 Agent「帮我配代理」 | +| 📖 **Reddit** | 搜索 + 读帖子和评论(通过 Exa) | — | 无需配置(自动通过 Exa) | | 📕 **小红书** | — | 阅读、搜索、发帖、评论、点赞 | 告诉 Agent「帮我配小红书」 | | 🎵 **抖音** | — | 视频解析、无水印下载链接获取 | 告诉 Agent「帮我配抖音」 | | 💼 **LinkedIn** | Jina Reader 读公开页面 | Profile 详情、公司页面、职位搜索 | 告诉 Agent「帮我配 LinkedIn」 | @@ -173,7 +173,7 @@ channels/ ├── youtube.py → yt-dlp ← 可以换成 YouTube API、Whisper…… ├── github.py → gh CLI ← 可以换成 REST API、PyGithub…… ├── bilibili.py → yt-dlp ← 可以换成 bilibili-api…… -├── reddit.py → JSON API + Exa ← 可以换成 PRAW、Pushshift…… +├── reddit.py → Exa ← 搜索+阅读,无需代理 ├── xiaohongshu.py → mcporter MCP ← 可以换成其他 XHS 工具…… ├── douyin.py → mcporter MCP ← 可以换成其他抖音工具…… ├── linkedin.py → linkedin-mcp ← 可以换成 LinkedIn API…… @@ -293,9 +293,9 @@ Agent Reach uses the bird CLI with cookie auth — zero API fees. After installi
-Reddit 返回 403 / 服务器 IP 被封怎么办? +Reddit 返回 403 怎么办? -Reddit 封锁数据中心 IP。配置一个住宅代理即可解决:`agent-reach configure proxy http://user:pass@ip:port`。推荐 Webshare ($1/月)。本地电脑一般不会遇到这个问题。 +Agent Reach 已改为通过 Exa 搜索和阅读 Reddit 内容,完全绕过 Reddit API 的 IP 封锁。无需代理,无需额外配置。运行 `agent-reach install --env=auto` 自动安装 Exa。
@@ -327,7 +327,7 @@ Yes! Agent Reach is an installer + configuration tool — any AI coding agent th
Is this free? Any API costs? -100% free. All backends are open-source tools (bird CLI, yt-dlp, Jina Reader, Exa, etc.) that don't require paid API keys. The only optional cost is a residential proxy (~$1/month) if you need Reddit/Bilibili access from a server. +100% free. All backends are open-source tools (bird CLI, yt-dlp, Jina Reader, Exa, etc.) that don't require paid API keys. The only optional cost is a residential proxy (~$1/month) if you need Bilibili access from a server. Reddit now works free via Exa without any proxy.
--- diff --git a/agent_reach/channels/reddit.py b/agent_reach/channels/reddit.py index a307fe8..2dc0684 100644 --- a/agent_reach/channels/reddit.py +++ b/agent_reach/channels/reddit.py @@ -1,30 +1,31 @@ # -*- coding: utf-8 -*- -"""Reddit — check connectivity and proxy configuration.""" +"""Reddit — search and read via Exa (no direct Reddit API needed).""" -import os -import urllib.request +import shutil +import subprocess from .base import Channel -_UA = "agent-reach/1.0" -_TIMEOUT = 10 - -def _reddit_reachable() -> bool: - """Return True if Reddit JSON API responds with 200 (带 User-Agent).""" - url = "https://www.reddit.com/r/linux.json?limit=1" - req = urllib.request.Request(url, headers={"User-Agent": _UA}) +def _exa_available() -> bool: + """Return True if mcporter is installed and Exa MCP is configured.""" + mcporter = shutil.which("mcporter") + if not mcporter: + return False try: - with urllib.request.urlopen(req, timeout=_TIMEOUT) as resp: - return resp.status == 200 + r = subprocess.run( + [mcporter, "config", "list"], capture_output=True, + encoding="utf-8", errors="replace", timeout=5 + ) + return "exa" in r.stdout.lower() except Exception: return False class RedditChannel(Channel): name = "reddit" - description = "Reddit 帖子和评论" - backends = ["JSON API", "Exa"] - tier = 1 + description = "Reddit 帖子和评论(通过 Exa 搜索和阅读)" + backends = ["Exa via mcporter"] + tier = 0 def can_handle(self, url: str) -> bool: from urllib.parse import urlparse @@ -32,13 +33,10 @@ class RedditChannel(Channel): return "reddit.com" in d or "redd.it" in d def check(self, config=None): - proxy = (config.get("reddit_proxy") if config else None) or os.environ.get("REDDIT_PROXY") - if proxy: - return "ok", "代理已配置,可读取帖子。搜索走 Exa" - # 实际探测连通性(带 User-Agent,符合 Reddit API 要求) - if _reddit_reachable(): - return "ok", "直连可用(JSON API 响应正常)。搜索走 Exa" - return "warn", ( - "无代理且 Reddit JSON API 无响应。服务器 IP 可能被封锁。配置代理:\n" - " agent-reach configure proxy http://user:pass@ip:port" + if _exa_available(): + return "ok", "通过 Exa 搜索和阅读 Reddit 内容(免费,无需代理)" + return "off", ( + "需要 mcporter + Exa MCP。安装:\n" + " npm install -g mcporter\n" + " mcporter config add exa https://mcp.exa.ai/mcp" ) diff --git a/agent_reach/cli.py b/agent_reach/cli.py index 2cb4727..1c368d4 100644 --- a/agent_reach/cli.py +++ b/agent_reach/cli.py @@ -186,11 +186,10 @@ def _cmd_install(args): # Apply explicit flags if args.proxy: if dry_run: - print(f"[dry-run] Would configure proxy for Reddit + Bilibili") + print(f"[dry-run] Would configure proxy for Bilibili") else: - config.set("reddit_proxy", args.proxy) config.set("bilibili_proxy", args.proxy) - print(f"✅ Proxy configured for Reddit + Bilibili") + print(f"✅ Proxy configured for Bilibili") # ── Install system dependencies ── print() @@ -987,26 +986,9 @@ def _cmd_configure(args): return if args.key == "proxy": - config.set("reddit_proxy", value) config.set("bilibili_proxy", value) - print(f"✅ Proxy configured for Reddit + Bilibili!") - - # Auto-test - print("Testing Reddit access...", end=" ") - try: - import requests - resp = requests.get( - "https://www.reddit.com/r/test.json?limit=1", - headers={"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"}, - proxies={"http": value, "https": value}, - timeout=10, - ) - if resp.status_code == 200: - print("✅ Reddit works!") - else: - print(f"[!] Reddit returned {resp.status_code}") - except Exception as e: - print(f"[X] Failed: {e}") + print(f"✅ Proxy configured for Bilibili!") + print(" Note: Reddit 已改为通过 Exa 访问,无需代理。") elif args.key == "twitter-cookies": # Accept two formats: @@ -1466,20 +1448,9 @@ def _cmd_setup(): print(" 跳过。公开 API 也能用") print() - # Step 3: Reddit proxy - print("【可选】Reddit 代理 — 完整阅读 Reddit 帖子+评论") - print(" Reddit 封锁很多 IP,需要 ISP 代理才能直接访问") - print(" 格式: http://用户名:密码@IP:端口") - current = config.get("reddit_proxy") - if current: - print(f" 当前状态: ✅ 已配置") - else: - proxy = input(" REDDIT_PROXY (回车跳过): ").strip() - if proxy: - config.set("reddit_proxy", proxy) - print(" ✅ Reddit 完整阅读已开启!") - else: - print(" 跳过。仍可通过搜索获取 Reddit 内容") + # Step 3: Reddit — no config needed (uses Exa) + print("【信息】Reddit — 通过 Exa 搜索和阅读,无需配置") + print(" 搜索和阅读 Reddit 内容已通过 Exa 自动完成,免费无需代理。") print() # Step 4: Groq (Whisper) diff --git a/agent_reach/config.py b/agent_reach/config.py index a70f6f8..963ef88 100644 --- a/agent_reach/config.py +++ b/agent_reach/config.py @@ -21,7 +21,6 @@ class Config: # Feature → required config keys FEATURE_REQUIREMENTS = { "exa_search": ["exa_api_key"], - "reddit_proxy": ["reddit_proxy"], "twitter_xreach": ["twitter_auth_token", "twitter_ct0"], # legacy key name; used by bird CLI "groq_whisper": ["groq_api_key"], "github_token": ["github_token"], diff --git a/agent_reach/guides/setup-reddit.md b/agent_reach/guides/setup-reddit.md index e3a4e29..022e5d5 100644 --- a/agent_reach/guides/setup-reddit.md +++ b/agent_reach/guides/setup-reddit.md @@ -1,60 +1,45 @@ -# Reddit 代理配置指南 +# Reddit 配置指南 ## 功能说明 -Reddit 封锁了大量服务器 IP,直接访问会返回 403。需要 ISP 代理(Residential/ISP Proxy)才能读取完整的 Reddit 帖子和评论。 -**注意**:即使没有代理,也可以通过 Exa 搜索找到 Reddit 内容(只需要配 Exa API key)。代理只是用于读取完整帖子+评论。 +Reddit 封锁了几乎所有非浏览器的直接访问(包括数据中心和 ISP 代理 IP),JSON API 返回 403。 + +Agent Reach 通过 **Exa** 实现 Reddit 的搜索和阅读功能: +- **搜索**:`web_search_exa` + `includeDomains: ["reddit.com"]` +- **阅读完整帖子+评论**:`crawling_exa` 读取 Reddit URL 的缓存内容 + +免费,无需代理,无需 API Key。 ## Agent 可自动完成的步骤 -1. 检查当前状态: +1. 检查 Exa 是否可用: ```bash -agent-reach doctor | grep "Reddit" +agent-reach doctor | grep -E "Reddit|Exa" ``` -2. 如果用户提供了代理,测试连通性: +2. 如果 Exa 未安装,自动安装: ```bash -curl -s --proxy "用户提供的代理" \ - -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36" \ - "https://www.reddit.com/r/test.json?limit=1" \ - -o /dev/null -w "%{http_code}" +npm install -g mcporter +mcporter config add exa https://mcp.exa.ai/mcp ``` -返回 200 = 可用,403 = 代理被封,其他 = 配置错误 -3. 写入配置: -```python -from agent_reach.config import Config -c = Config() -c.set("reddit_proxy", "http://用户名:密码@IP:端口") +或一键安装: +```bash +agent-reach install --env=auto +``` + +## 使用示例 + +搜索 Reddit 内容: +```bash +mcporter call 'exa.web_search_exa(query: "python best practices", numResults: 5, includeDomains: ["reddit.com"])' +``` + +阅读完整帖子和评论: +```bash +mcporter call 'exa.crawling_exa(urls: ["https://www.reddit.com/r/python/comments/xxx/"], maxCharacters: 10000)' ``` ## 需要用户手动做的步骤 -请告诉用户: - -> 要完整阅读 Reddit 帖子和评论,需要一个 ISP 代理(约 $3-10/月)。 -> -> 推荐代理服务商(选一个就行): -> 1. **Smartproxy** (https://smartproxy.com) — ISP 代理,按流量计费 -> 2. **Bright Data** (https://brightdata.com) — 大厂,ISP 代理 -> 3. **IPRoyal** (https://iproyal.com) — 便宜,适合入门 -> 4. **ProxyEmpire** (https://proxyempire.io) — 有 Reddit 专用代理 -> -> 购买时选择: -> - 类型:**ISP Proxy**(不要选 Datacenter,会被封) -> - 地区:**美国** -> - 协议:**HTTP** -> -> 购买后你会得到一个代理地址,格式类似: -> `http://用户名:密码@IP地址:端口号` -> -> 把这个地址发给我就行。 -> -> ⚠️ 如果不想花钱,可以跳过。我仍然可以通过搜索引擎找到 Reddit 上的内容,只是不能读完整的帖子和评论。 - -## Agent 收到代理后的操作 - -1. 测试代理:用 curl 测试 reddit.com 是否返回 200 -2. 如果成功,写入配置:`config.set("reddit_proxy", proxy_url)` -3. 反馈:"✅ Reddit 完整阅读已开启!现在我可以读取 Reddit 帖子和所有评论了。" -4. 如果失败,告诉用户:"❌ 这个代理无法访问 Reddit,请检查代理是否有效,或换一个试试。" +无。Exa 通过 `agent-reach install --env=auto` 自动配置。 diff --git a/agent_reach/skill/SKILL.md b/agent_reach/skill/SKILL.md index 95807f0..d070160 100644 --- a/agent_reach/skill/SKILL.md +++ b/agent_reach/skill/SKILL.md @@ -63,6 +63,12 @@ bird search "query" -n 10 # YouTube/B站字幕 yt-dlp --write-sub --skip-download -o "/tmp/%(id)s" "URL" +# Reddit 搜索(通过 Exa,免费无需代理) +mcporter call 'exa.web_search_exa(query: "query", numResults: 5, includeDomains: ["reddit.com"])' + +# Reddit 读帖(通过 Exa) +mcporter call 'exa.crawling_exa(urls: ["https://www.reddit.com/r/.../comments/.../"], maxCharacters: 10000)' + # V2EX 热门 curl -s "https://www.v2ex.com/api/topics/hot.json" -H "User-Agent: agent-reach/1.0" ``` diff --git a/agent_reach/skill/references/social.md b/agent_reach/skill/references/social.md index 79ad98c..3a9802c 100644 --- a/agent_reach/skill/references/social.md +++ b/agent_reach/skill/references/social.md @@ -35,24 +35,23 @@ mcporter call 'douyin.extract_douyin_text(share_link: "https://v.douyin.com/xxx/ > **无需登录** -## Twitter/X (xreach CLI) +## Twitter/X (bird CLI) ```bash # 搜索推文 -xreach search "query" -n 10 --json +bird search "query" -n 10 # 读取单条推文 (支持 /status/ 和 /article/ URL) -xreach tweet URL_OR_ID --json +bird read URL_OR_ID # 用户时间线 -xreach tweets @username -n 20 --json +bird user-tweets @username -n 20 # 读取完整 thread -xreach thread URL_OR_ID --json +bird thread URL_OR_ID ``` > **需要配置**: `agent-reach configure twitter-auth ...` 或通过环境变量配置。 -> 如果 fetch 失败,确保安装了 undici: `npm install -g undici` ## 微博 / Weibo @@ -136,14 +135,20 @@ user = ch.get_user("Livid") > **节点列表**: https://www.v2ex.com/planes -## Reddit (公开 API) +## Reddit (通过 Exa) + +Reddit 封锁了几乎所有非浏览器访问(包括代理 IP)。搜索和阅读全部通过 Exa 完成,免费且无需代理。 + +### 搜索 Reddit 内容 ```bash -# 获取 subreddit 热门帖子 -curl -s "https://www.reddit.com/r/SUBREDDIT/hot.json?limit=10" -H "User-Agent: agent-reach/1.0" - -# 搜索 -curl -s "https://www.reddit.com/search.json?q=QUERY&limit=10" -H "User-Agent: agent-reach/1.0" +mcporter call 'exa.web_search_exa(query: "your search query", numResults: 5, includeDomains: ["reddit.com"])' ``` -> **注意**: 服务器 IP 可能遇到 403 错误。搜索建议使用 Exa 代替,或配置代理。 +### 阅读完整帖子和评论 + +```bash +mcporter call 'exa.crawling_exa(urls: ["https://www.reddit.com/r/SUBREDDIT/comments/POST_ID/TITLE/"], maxCharacters: 10000)' +``` + +> **零配置**: 只需安装 Exa MCP(`agent-reach install --env=auto` 自动完成)。无需代理,无需 API Key。 diff --git a/docs/README_en.md b/docs/README_en.md index 3f2d49c..af66fb8 100644 --- a/docs/README_en.md +++ b/docs/README_en.md @@ -76,7 +76,7 @@ Update Agent Reach: https://raw.githubusercontent.com/Panniantong/agent-reach/ma | 📺 **YouTube** | Read · **Search** | Zero config | Subtitles + search across 1800+ video sites ([yt-dlp](https://github.com/yt-dlp/yt-dlp) ⭐148K) | | 📺 **Bilibili** | Read · **Search** | Zero config / Proxy | Video info + subtitles + search. Local works directly, servers need a proxy ([yt-dlp](https://github.com/yt-dlp/yt-dlp)) | | 📡 **RSS** | Read | Zero config | Any RSS/Atom feed ([feedparser](https://github.com/kurtmckee/feedparser) ⭐2.3K) | -| 📖 **Reddit** | Search · Read | Free / Proxy | Search via Exa (free). Reading posts needs a proxy on servers | +| 📖 **Reddit** | Search · Read | Zero config | Search and read via Exa (free, no proxy needed) | > **Setup levels:** Zero config = install and go · Auto-configured = handled during install · mcporter = needs MCP service · Cookie = export from browser · Proxy = $1/month @@ -145,9 +145,9 @@ Tell your Agent "help me configure Twitter cookies" — it'll guide you through ### 🌐 Proxy — $1/month, servers only -Reddit and Bilibili block server IPs. Get a proxy ([Webshare](https://webshare.io) recommended, $1/month) and send the address to your Agent. +Bilibili blocks server IPs. Get a proxy ([Webshare](https://webshare.io) recommended, $1/month) and send the address to your Agent. -> Local computers don't need a proxy. Reddit search works free via Exa even without one. +> Reddit now works free via Exa without any proxy. Local computers don't need a proxy for Bilibili either. --- @@ -171,7 +171,7 @@ $ agent-reach doctor ⬜ Web semantic search — sign up at exa.ai for free key 🔧 Configurable: - ⬜ Reddit posts and comments — search via Exa (free). Reading needs proxy + ✅ Reddit posts and comments — search and read via Exa (free, no proxy) ⬜ XiaoHongShu notes — needs cookie. Export from browser Status: 6/9 channels available @@ -200,7 +200,7 @@ channels/ ├── youtube.py → yt-dlp ← swap to YouTube API, Whisper… ├── github.py → gh CLI ← swap to REST API, PyGithub… ├── bilibili.py → yt-dlp ← swap to bilibili-api… -├── reddit.py → JSON API + Exa ← swap to PRAW, Pushshift… +├── reddit.py → Exa ← search + read, no proxy needed ├── xiaohongshu.py → mcporter MCP ← swap to other XHS tools… ├── douyin.py → mcporter MCP ← swap to other Douyin tools… ├── linkedin.py → linkedin-mcp ← swap to LinkedIn API… @@ -261,7 +261,7 @@ Agent Reach uses the [bird CLI](https://www.npmjs.com/package/@steipete/bird) wi
Reddit returns 403 from server / datacenter IP blocked? -Reddit blocks datacenter IPs. Configure a residential proxy: `agent-reach configure proxy http://user:pass@ip:port`. Recommended: Webshare (~$1/month). Local machines typically don't have this issue. +Agent Reach now uses Exa to search and read Reddit content, completely bypassing Reddit's IP blocks. No proxy needed. Run `agent-reach install --env=auto` to set up Exa automatically.
@@ -273,7 +273,7 @@ Yes! Agent Reach is an installer + configuration tool. Any AI coding agent that
Is Agent Reach free? Any API costs? -100% free and open source. All backends (bird CLI, yt-dlp, Jina Reader, Exa) are free tools that don't require paid API keys. The only optional cost is a residential proxy (~$1/month) if you need Reddit/Bilibili access from a server. +100% free and open source. All backends (bird CLI, yt-dlp, Jina Reader, Exa) are free tools that don't require paid API keys. The only optional cost is a residential proxy (~$1/month) if you need Bilibili access from a server. Reddit works free via Exa without any proxy.
diff --git a/docs/install.md b/docs/install.md index e4323eb..c2a9f1b 100644 --- a/docs/install.md +++ b/docs/install.md @@ -336,7 +336,7 @@ After installation, use upstream tools directly. See SKILL.md for the full comma | Twitter/X | `bird` | `bird search "query" -n 10` | | YouTube | `yt-dlp` | `yt-dlp --dump-json URL` | | Bilibili | `yt-dlp` | `yt-dlp --dump-json URL` | -| Reddit | `curl` | `curl -s "https://reddit.com/r/xxx.json"` | +| Reddit | `mcporter` (Exa) | `mcporter call 'exa.web_search_exa(query: "...", includeDomains: ["reddit.com"])'` | | GitHub | `gh` | `gh search repos "query"` | | Web | `curl` + Jina | `curl -s "https://r.jina.ai/URL"` | | Exa Search | `mcporter` | `mcporter call 'exa.web_search_exa(...)'` | diff --git a/tests/test_config.py b/tests/test_config.py index b6e37d0..a7bb2a4 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -61,11 +61,6 @@ class TestConfig: tmp_config.set("exa_api_key", "test-key") assert tmp_config.is_configured("exa_search") - def test_is_configured_reddit(self, tmp_config): - assert not tmp_config.is_configured("reddit_proxy") - tmp_config.set("reddit_proxy", "http://user:pass@ip:port") - assert tmp_config.is_configured("reddit_proxy") - def test_get_configured_features(self, tmp_config): features = tmp_config.get_configured_features() assert isinstance(features, dict)