docs(skills): reddit-reading spells out that no login is needed and OAuth is app-only
The default backend needs no Reddit account, login, cookie or API key; the optional upgrade is a free 'script' app registration using the app-only client_credentials grant, never a user login. Said in the skill's Prerequisites (with a comparison table), Procedure, Pitfalls, the runtime doctor/thread notes, and a delimited .env.example block.
This commit is contained in:
@@ -533,3 +533,12 @@ IMAGE_TOOLS_DEBUG=false
|
|||||||
# GOOGLE_CHAT_ALLOW_ALL_USERS=false # Set true to skip the allowlist
|
# GOOGLE_CHAT_ALLOW_ALL_USERS=false # Set true to skip the allowlist
|
||||||
# GOOGLE_CHAT_HOME_CHANNEL= # Default space (spaces/XXXX) for cron delivery
|
# GOOGLE_CHAT_HOME_CHANNEL= # Default space (spaces/XXXX) for cron delivery
|
||||||
# GOOGLE_CHAT_HOME_CHANNEL_NAME= # Display name for the home channel
|
# GOOGLE_CHAT_HOME_CHANNEL_NAME= # Display name for the home channel
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# reddit-reading skill (optional) — app-only credentials, NOT a user login
|
||||||
|
# =============================================================================
|
||||||
|
# The skill works with no credentials via Reddit's public feeds (~1 request/minute).
|
||||||
|
# For faster access with scores and nested comments, register a free "script" app
|
||||||
|
# at https://www.reddit.com/prefs/apps and paste its id and secret here.
|
||||||
|
# REDDIT_CLIENT_ID=
|
||||||
|
# REDDIT_CLIENT_SECRET=
|
||||||
|
|||||||
@@ -29,18 +29,32 @@ backend routing in [Agent Reach](https://github.com/Panniantong/Agent-Reach).
|
|||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
None for the anonymous path. For anything beyond a handful of calls per task, create
|
**None.** No Reddit account, login, cookie, or API key is needed. The default backend is
|
||||||
a free Reddit "script" app at https://www.reddit.com/prefs/apps and put the two values
|
Reddit's public Atom feeds (`.rss` endpoints), the only unauthenticated route Reddit still
|
||||||
in `~/.hermes/.env`:
|
serves to non-residential IPs. It is throttled to about one request per minute per IP and
|
||||||
|
returns thinner data (no scores, top-level comments only), which is fine for a few calls.
|
||||||
|
|
||||||
|
**Optional upgrade (app credentials, still no user login):** for sustained use or full
|
||||||
|
data, register a free "script" type app at https://www.reddit.com/prefs/apps and put its
|
||||||
|
two values in `~/.hermes/.env`:
|
||||||
|
|
||||||
```
|
```
|
||||||
REDDIT_CLIENT_ID=...
|
REDDIT_CLIENT_ID=...
|
||||||
REDDIT_CLIENT_SECRET=...
|
REDDIT_CLIENT_SECRET=...
|
||||||
```
|
```
|
||||||
|
|
||||||
The script picks the OAuth backend automatically when both are set (~100 requests per
|
This is an application registration, not a login: the script uses the app-only
|
||||||
minute, scores, comment nesting, `num_comments`). Without them it uses Reddit's Atom
|
`client_credentials` grant, never a username, password, or browser cookie, and never
|
||||||
feeds, which are the only unauthenticated endpoints still served to non-residential IPs.
|
acts as the user. With both values set it switches to the OAuth API automatically
|
||||||
|
(~100 requests per minute, scores, nested comments, `num_comments`); if they are
|
||||||
|
missing or rejected it falls back to the anonymous feeds and says so on stderr.
|
||||||
|
|
||||||
|
| | Anonymous feeds (default) | OAuth app credentials |
|
||||||
|
|---|---|---|
|
||||||
|
| Setup | nothing | 1-minute app registration, two `.env` values |
|
||||||
|
| Rate limit | ~1 request / minute / IP | ~100 requests / minute |
|
||||||
|
| Thread data | post + top-level comments, no scores | nested comments, scores, comment counts |
|
||||||
|
| Acts as a user | no | no |
|
||||||
|
|
||||||
## How to Run
|
## How to Run
|
||||||
|
|
||||||
@@ -57,6 +71,8 @@ python3 scripts/reddit.py --json search "topic" # machine-reada
|
|||||||
|
|
||||||
## Quick Reference
|
## Quick Reference
|
||||||
|
|
||||||
|
Every command works on both backends; the script chooses the backend, you never pass a flag.
|
||||||
|
|
||||||
| Need | Command | Anonymous | OAuth |
|
| Need | Command | Anonymous | OAuth |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| Subreddit front page | `sub NAME --sort hot\|new\|top\|rising [--time week]` | ✔ | ✔ |
|
| Subreddit front page | `sub NAME --sort hot\|new\|top\|rising [--time week]` | ✔ | ✔ |
|
||||||
@@ -83,7 +99,9 @@ than stopping at titles; the listing only carries the first ~300 characters of e
|
|||||||
`grounded-citations` registers these URLs like any other source.
|
`grounded-citations` registers these URLs like any other source.
|
||||||
|
|
||||||
⑤ If the user needs sustained Reddit access (monitoring, more than ~10 calls), stop and
|
⑤ If the user needs sustained Reddit access (monitoring, more than ~10 calls), stop and
|
||||||
ask them to add the OAuth credentials rather than grinding through the throttle.
|
ask them to register the app credentials (Prerequisites) rather than grinding through the
|
||||||
|
throttle. Tell them plainly: it is a free app registration, not logging Hermes into their
|
||||||
|
account. Never ask for a Reddit password or browser cookies.
|
||||||
|
|
||||||
## Pitfalls
|
## Pitfalls
|
||||||
|
|
||||||
@@ -98,6 +116,9 @@ ask them to add the OAuth credentials rather than grinding through the throttle.
|
|||||||
- Reddit's `limit` on feeds is advisory — expect 5–25 entries regardless of what you ask.
|
- Reddit's `limit` on feeds is advisory — expect 5–25 entries regardless of what you ask.
|
||||||
- Never paste `REDDIT_CLIENT_SECRET` into a chat or log; the script reads it from the
|
- Never paste `REDDIT_CLIENT_SECRET` into a chat or log; the script reads it from the
|
||||||
environment only.
|
environment only.
|
||||||
|
- Do not "fix" a 429 by retrying in a loop or adding a proxy; the throttle is per IP and
|
||||||
|
the script already waits out the window once. More than one 429 in a row means the
|
||||||
|
task needs the app credentials.
|
||||||
|
|
||||||
## Verification
|
## Verification
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,10 @@
|
|||||||
Two backends, chosen automatically:
|
Two backends, chosen automatically:
|
||||||
|
|
||||||
* **OAuth API** (preferred when ``REDDIT_CLIENT_ID`` + ``REDDIT_CLIENT_SECRET`` are set):
|
* **OAuth API** (preferred when ``REDDIT_CLIENT_ID`` + ``REDDIT_CLIENT_SECRET`` are set):
|
||||||
a free "script" app from https://www.reddit.com/prefs/apps; ~100 requests/minute,
|
app-only ``client_credentials`` grant for a free "script" app registered at
|
||||||
full JSON including scores and nested comments.
|
https://www.reddit.com/prefs/apps. No username, password or cookie is ever used and
|
||||||
|
the script never acts as a user. ~100 requests/minute, full JSON including scores
|
||||||
|
and nested comments.
|
||||||
* **Anonymous Atom feeds** (``.rss`` endpoints): the only unauthenticated path Reddit
|
* **Anonymous Atom feeds** (``.rss`` endpoints): the only unauthenticated path Reddit
|
||||||
still serves to server IPs (``.json`` and old.reddit return 403 / an empty shell).
|
still serves to server IPs (``.json`` and old.reddit return 403 / an empty shell).
|
||||||
Roughly ONE request per minute per IP; the script sleeps until the window resets
|
Roughly ONE request per minute per IP; the script sleeps until the window resets
|
||||||
@@ -181,7 +183,8 @@ def atom_thread(sub: str, post_id: str, limit: int) -> dict:
|
|||||||
raise SystemExit("thread feed returned no entries")
|
raise SystemExit("thread feed returned no entries")
|
||||||
post, comments = entries[0], entries[1:]
|
post, comments = entries[0], entries[1:]
|
||||||
post["comments"] = [{"author": c["author"], "created": c["created"], "body": c["body"], "url": c["url"]} for c in comments]
|
post["comments"] = [{"author": c["author"], "created": c["created"], "body": c["body"], "url": c["url"]} for c in comments]
|
||||||
post["note"] = "anonymous feed: scores and nesting unavailable; set REDDIT_CLIENT_ID/SECRET for full data"
|
post["note"] = ("anonymous feed: scores and nesting unavailable; register a free Reddit script app and set "
|
||||||
|
"REDDIT_CLIENT_ID/REDDIT_CLIENT_SECRET (no user login) for full data")
|
||||||
return post
|
return post
|
||||||
|
|
||||||
|
|
||||||
@@ -241,9 +244,10 @@ def cmd_doctor(a, token):
|
|||||||
except urllib.error.HTTPError as exc:
|
except urllib.error.HTTPError as exc:
|
||||||
report["anonymous_feed"] = f"HTTP {exc.code}"
|
report["anonymous_feed"] = f"HTTP {exc.code}"
|
||||||
report["notes"] = [
|
report["notes"] = [
|
||||||
"anonymous .rss: ~1 request/minute per IP (x-ratelimit-remaining drops to 0 after each call)",
|
"anonymous .rss needs no account, login, cookie or key; ~1 request/minute per IP",
|
||||||
"www.reddit.com .json, api.reddit.com and old.reddit are 403 / an empty shell for server IPs",
|
"www.reddit.com .json, api.reddit.com and old.reddit are 403 / an empty shell for server IPs",
|
||||||
"for more than a few calls per task create a free script app and export REDDIT_CLIENT_ID/SECRET",
|
"for more than a few calls per task register a free 'script' app at reddit.com/prefs/apps and set "
|
||||||
|
"REDDIT_CLIENT_ID/REDDIT_CLIENT_SECRET in .env (app-only credentials; Hermes never logs in as the user)",
|
||||||
]
|
]
|
||||||
return report
|
return report
|
||||||
|
|
||||||
|
|||||||
@@ -47,18 +47,32 @@ backend routing in [Agent Reach](https://github.com/Panniantong/Agent-Reach).
|
|||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
None for the anonymous path. For anything beyond a handful of calls per task, create
|
**None.** No Reddit account, login, cookie, or API key is needed. The default backend is
|
||||||
a free Reddit "script" app at https://www.reddit.com/prefs/apps and put the two values
|
Reddit's public Atom feeds (`.rss` endpoints), the only unauthenticated route Reddit still
|
||||||
in `~/.hermes/.env`:
|
serves to non-residential IPs. It is throttled to about one request per minute per IP and
|
||||||
|
returns thinner data (no scores, top-level comments only), which is fine for a few calls.
|
||||||
|
|
||||||
|
**Optional upgrade (app credentials, still no user login):** for sustained use or full
|
||||||
|
data, register a free "script" type app at https://www.reddit.com/prefs/apps and put its
|
||||||
|
two values in `~/.hermes/.env`:
|
||||||
|
|
||||||
```
|
```
|
||||||
REDDIT_CLIENT_ID=...
|
REDDIT_CLIENT_ID=...
|
||||||
REDDIT_CLIENT_SECRET=...
|
REDDIT_CLIENT_SECRET=...
|
||||||
```
|
```
|
||||||
|
|
||||||
The script picks the OAuth backend automatically when both are set (~100 requests per
|
This is an application registration, not a login: the script uses the app-only
|
||||||
minute, scores, comment nesting, `num_comments`). Without them it uses Reddit's Atom
|
`client_credentials` grant, never a username, password, or browser cookie, and never
|
||||||
feeds, which are the only unauthenticated endpoints still served to non-residential IPs.
|
acts as the user. With both values set it switches to the OAuth API automatically
|
||||||
|
(~100 requests per minute, scores, nested comments, `num_comments`); if they are
|
||||||
|
missing or rejected it falls back to the anonymous feeds and says so on stderr.
|
||||||
|
|
||||||
|
| | Anonymous feeds (default) | OAuth app credentials |
|
||||||
|
|---|---|---|
|
||||||
|
| Setup | nothing | 1-minute app registration, two `.env` values |
|
||||||
|
| Rate limit | ~1 request / minute / IP | ~100 requests / minute |
|
||||||
|
| Thread data | post + top-level comments, no scores | nested comments, scores, comment counts |
|
||||||
|
| Acts as a user | no | no |
|
||||||
|
|
||||||
## How to Run
|
## How to Run
|
||||||
|
|
||||||
@@ -75,6 +89,8 @@ python3 scripts/reddit.py --json search "topic" # machine-reada
|
|||||||
|
|
||||||
## Quick Reference
|
## Quick Reference
|
||||||
|
|
||||||
|
Every command works on both backends; the script chooses the backend, you never pass a flag.
|
||||||
|
|
||||||
| Need | Command | Anonymous | OAuth |
|
| Need | Command | Anonymous | OAuth |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| Subreddit front page | `sub NAME --sort hot\|new\|top\|rising [--time week]` | ✔ | ✔ |
|
| Subreddit front page | `sub NAME --sort hot\|new\|top\|rising [--time week]` | ✔ | ✔ |
|
||||||
@@ -101,7 +117,9 @@ than stopping at titles; the listing only carries the first ~300 characters of e
|
|||||||
`grounded-citations` registers these URLs like any other source.
|
`grounded-citations` registers these URLs like any other source.
|
||||||
|
|
||||||
⑤ If the user needs sustained Reddit access (monitoring, more than ~10 calls), stop and
|
⑤ If the user needs sustained Reddit access (monitoring, more than ~10 calls), stop and
|
||||||
ask them to add the OAuth credentials rather than grinding through the throttle.
|
ask them to register the app credentials (Prerequisites) rather than grinding through the
|
||||||
|
throttle. Tell them plainly: it is a free app registration, not logging Hermes into their
|
||||||
|
account. Never ask for a Reddit password or browser cookies.
|
||||||
|
|
||||||
## Pitfalls
|
## Pitfalls
|
||||||
|
|
||||||
@@ -116,6 +134,9 @@ ask them to add the OAuth credentials rather than grinding through the throttle.
|
|||||||
- Reddit's `limit` on feeds is advisory — expect 5–25 entries regardless of what you ask.
|
- Reddit's `limit` on feeds is advisory — expect 5–25 entries regardless of what you ask.
|
||||||
- Never paste `REDDIT_CLIENT_SECRET` into a chat or log; the script reads it from the
|
- Never paste `REDDIT_CLIENT_SECRET` into a chat or log; the script reads it from the
|
||||||
environment only.
|
environment only.
|
||||||
|
- Do not "fix" a 429 by retrying in a loop or adding a proxy; the throttle is per IP and
|
||||||
|
the script already waits out the window once. More than one 429 in a row means the
|
||||||
|
task needs the app credentials.
|
||||||
|
|
||||||
## Verification
|
## Verification
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user