shangjian2023/dsh-rss-daily ↗★ 0
dsh-rss-daily
dsh plugin: daily RSS news digest from 46 curated sources, LLM-edited via the model already configured in dsh, delivered to your IM via webhook (ServerChan / PushDeer / WeCom / Telegram / Bark / gotify / custom).
安装
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:shangjian2023/dsh-rss-daily说明文档
阅读完整 README ↗dsh-rss-daily
A dsh plugin that brings you a daily news digest — every morning, in your IM, from 46 curated RSS sources across tech / science / world / finance / humanities / dev.
What makes it different from a plain RSS reader:
- Editor, not aggregator. A candidate pool of ~20 items is scored (source tier × recency × signal words), deduplicated (Jaccard + MD5 history), cross-checked against a multi-source event graph (newsflash, ≥3 independent outlets), then handed to the model already configured in your dsh for editorial selection: merge same-event reports, drop PR filler and weekly roundups, balance topics (max 2 per tag), and write one concrete fact line per item (≤45 chars, Chinese rendering for English news).
- Zero extra LLM credentials. The editorial pass goes through
ctx.llm— whatever model your dsh already uses. If the model call fails, it degrades to a deterministic rule-based selection, so the digest never misses a day. - Delivered where you read. Webhook push to ServerChan / PushDeer / WeCom bot / Telegram / Bark / gotify / any custom JSON endpoint.
- Production-grade pipeline. Ported from a personal pipeline that has run daily since June 2026 through 9 revisions: per-source health tracking with adaptive timeouts, feed charset-mojibake repair, full-text enrichment for thin summaries, a 420s hard budget, idempotent two-phase send (fetch → outbox → deliver → confirm), and a 14-day dedup window.
Requirements
- dsh with the
web(or any long-running) profile - Python 3.9+ with
feedparser:pip install feedparser - Node.js ≥ 18 (bundled with dsh)
Install
One command — dsh plugin add installs the package via pnpm and appends it to the profile's dsh.profile.bundles; the row itself comes from this package's cordis.patch.yml:
dsh plugin --profile web add github:shangjian2023/dsh-rss-daily
Restart dsh web and the schedule is live. For development from a local checkout: dsh plugin --profile web add /absolute/path/to/dsh-rss-daily (pnpm links it; run pnpm install in the checkout once).
Configure
Tune config by overlaying the row from the profile's patch layer ($DSH_HOME/profiles/web/cordis.patch.yml):
- insert:
- id: rss-daily
name: dsh-rss-daily
config:
time: "08:00" # local time, daily
targets:
- type: serverchan # ServerChan sendkey
key: SCTxxxxxxxx
- type: telegram
token: "123456:ABC..."
chatId: "-1001234567890"
| Key | Default | Meaning |
|---|---|---|
enabled | true | daily schedule on/off (agent tool stays) |
time | "08:00" | local HH:MM to run; a boot-time catch-up runs if missed by <12h |
stateDir | $DSH_HOME/rss-daily | sources / dedup history / outbox live here |
sourcesFile | stateDir/sources.json | your source list; seeded from the bundled 46-source default on first run |
digestItems | 8 | max items per digest |
llmMode | harness | harness (use dsh's model) or none (rule-based only) |
llmProvider / llmModel | first available | override which harness model edits the digest |
footer | "" | custom footer line |
targets[] | [] | delivery targets; delivered = at least one succeeded |
Source entry shape (sources.json): { "name", "url", "category", "tier" (1–3) }. The bundled list was reachability-tested from mainland China; add sources freely — unhealthy ones auto-degrade for 24h after 3 consecutive failures and rotate back in.
Use
- Automatic: every day at
time, the digest is generated and pushed. Missed runs are caught up on boot. - In chat: ask the agent — it has an
rss_dailytool (run/status/redo/deliver), e.g. "generate today's news digest now". - Headless / system cron: run the pipeline directly with any OpenAI-compatible endpoint:
python py/daily.py --state-dir ~/.rss-daily # one-shot full run (rule mode)
RSS_LLM_ENDPOINT=https://api.deepseek.com/v1 \
RSS_LLM_KEY=sk-... RSS_LLM_MODEL=deepseek-chat \
python py/daily.py --state-dir ~/.rss-daily # with LLM editing
python py/daily.py --stage confirm --state-dir ~/.rss-daily # after delivery succeeded
Pipeline stages (advanced)
py/daily.py is independently scriptable and speaks single-line JSON on stdout:
python py/daily.py --stage fetch --state-dir DIR # → {"status":"READY","prompt":...}
python py/daily.py --stage finalize --llm-reply FILE --state-dir DIR
python py/daily.py --stage confirm --state-dir DIR
python py/daily.py --stage status --state-dir DIR
The plugin itself uses exactly these stages: fetch produces the editor prompt, the plugin streams it through ctx.llm, finalize parses the reply (falling back to rule mode on garbage), then the plugin delivers and confirm marks the day done. Never confirm before successful delivery — confirmed items enter the 14-day dedup window permanently.
License
MIT