更新脚本和技能

This commit is contained in:
2026-08-30 07:42:25 +08:00
parent d1df3a607c
commit 146350565c
2 changed files with 421 additions and 49 deletions

View File

@@ -1,12 +1,12 @@
---
name: blogwatcher-daily
description: RSS 订阅监控 + 文章导出。使用 RSSHub + feedparser 抓取 31 个订阅,自动去重并存入 SQLite;可将文章按 txt/markdown/html 三种格式导出。
version: 1.3
description: RSS 订阅监控 + 文章管理 + 导出。使用 RSSHub + feedparser 抓取订阅,自动去重入库 SQLite;支持按单个订阅更新/查看/标记已读/删除文章,可将文章按 txt/markdown/html 导出。附「自然语言操作指南」,AI 智能体可直接把用户口语映射到 CLI 命令。
version: 1.4
category: custom
tags: [rss, blog, monitoring, automation, export]
metadata:
author: Hermes Agent
last_updated: 2026-08-29
last_updated: 2026-08-30
platform: macos, ubuntu
custom_skill_path: /Users/weishen/.hermes/skills/custom/
installation_note: "blogwatcher-daily 脚本在 Mac mini 本地运行(依赖 feedparser)。需要 RSSHub 服务(http://192.168.3.45:1200)访问 YouTube/Bilibili 等被墙源。"
@@ -103,12 +103,107 @@ python3 ~/.hermes/skills/custom/blogwatcher-daily/scripts/blogwatcher-daily.py -
- 每频道最多10篇
- 用途:历史内容回扫、测试订阅状态
### 标记已读
### 更新单个订阅(`--update SUB`)
只抓某一个订阅,不动其它源。SUB 可传订阅名或 `--list` 中的序号(详见下方「订阅标识(SUB)」)。
```bash
python3 ~/.hermes/skills/custom/blogwatcher-daily/scripts/blogwatcher-daily.py --mark-read
# 按名字更新
python3 ~/.hermes/skills/custom/blogwatcher-daily/scripts/blogwatcher-daily.py \
--update "Tech With Tim"
# 按 --list 里的序号更新(例如第 3 个订阅)
python3 ~/.hermes/skills/custom/blogwatcher-daily/scripts/blogwatcher-daily.py --update 3
# 强制回扫单个订阅最新 10 篇(叠加 --all)
python3 ~/.hermes/skills/custom/blogwatcher-daily/scripts/blogwatcher-daily.py \
--update 3 --all
```
- 抓取失败 → 打印错误、退出 0(不打断脚本管道)
- 订阅未找到 → 退出 1
### 查看某订阅的文章(`--articles SUB`)
从数据库读文章(不联网),可选只看未读:
```bash
# 该订阅全部文章(按 fetched_at 降序)
python3 ~/.hermes/skills/custom/blogwatcher-daily/scripts/blogwatcher-daily.py \
--articles "Engadget"
# 只看未读
python3 ~/.hermes/skills/custom/blogwatcher-daily/scripts/blogwatcher-daily.py \
--articles "Engadget" --unread
# 也可用序号
python3 ~/.hermes/skills/custom/blogwatcher-daily/scripts/blogwatcher-daily.py \
--articles 22 --unread
```
输出示例:
```
📄 [Engadget] 未读文章 (244 篇):
[1] 🆕 How long is a new Fire TV Stick actually supposed to last?
🔗 https://www.engadget.com/...
📅 Sat, 30 Aug 2026 12:00:00 GMT
...
```
- 已读用 `📖`,未读用 `🆕`
- 每篇左侧的 `[N]` 是**订阅内 1-based 序号**,可直接用于下方 `--delete --article-id N`
### 标记已读(`--mark-read [SUB]`)
不带参数 → 全库标记;带 SUB → 只标记指定订阅。
```bash
# 全库标记为已读
python3 ~/.hermes/skills/custom/blogwatcher-daily/scripts/blogwatcher-daily.py --mark-read
# 只标记某个订阅
python3 ~/.hermes/skills/custom/blogwatcher-daily/scripts/blogwatcher-daily.py \
--mark-read "Tech With Tim"
python3 ~/.hermes/skills/custom/blogwatcher-daily/scripts/blogwatcher-daily.py \
--mark-read 3
```
### 删除文章(`--delete SUB [--article-id N]`)
删除该订阅下**所有文章**或**单篇**。序号 N 与 `--articles` 显示顺序一致。
```bash
# 删除某订阅下所有文章
python3 ~/.hermes/skills/custom/blogwatcher-daily/scripts/blogwatcher-daily.py \
--delete "Jon Law"
# 删除某订阅下第 2 篇(先用 --articles 查序号)
python3 ~/.hermes/skills/custom/blogwatcher-daily/scripts/blogwatcher-daily.py \
--delete "Jon Law" --article-id 2
# 序号也支持
python3 ~/.hermes/skills/custom/blogwatcher-daily/scripts/blogwatcher-daily.py \
--delete 2 --article-id 1
```
- 空库删除是幂等 no-op,退出 0
- 序号越界 → 退出 1,不改动 DB
- 删除**不可撤销**,请配合 `--articles SUB` 先看清再删
### 订阅标识(SUB)
`--update / --articles / --mark-read / --delete` 的 SUB 参数按以下顺序匹配:
1. 数字 → 视为 `--list` 中的 1-based 序号
2. 精确名称(区分大小写)
3. 忽略大小写精确匹配
4. 忽略大小写子串匹配
匹配到多条时脚本报错并列出候选:AI 智能体应向用户回问「你指的是 X 还是 Y?」或改用序号消歧。
### 导出文章(`--export`)
从 SQLite 里读取文章并输出到 stdout,格式通过 `--export {txt,markdown,html}` 选择:
@@ -154,6 +249,98 @@ python3 ~/.hermes/skills/custom/blogwatcher-daily/scripts/blogwatcher-daily.py \
- `markdown`:`## 【频道】` + `- [title](link)` + 描述引用块
- `html`:完整 `<!DOCTYPE html>` 单文件,内嵌简洁 CSS,标题/URL/描述全部经 `html.escape` 转义(防 XSS)
## 自然语言操作指南(AI 智能体路由表)
用户通常不会记 CLI 参数。下面是常见口语意图 → 应执行命令的映射,AI 智能体应据此选择命令。
命令前缀统一是:
```
python3 ~/.hermes/skills/custom/blogwatcher-daily/scripts/blogwatcher-daily.py
```
下表省略前缀,只列参数。
### 1. 抓取 / 更新
| 用户可能说 | 命令 | 备注 |
|---|---|---|
| "刷新所有博客"、"扫一下今天有什么新的"、"跑一下每日抓取"、"更新一下" | *(无参数)* | 全量扫描所有订阅 |
| "更新 Tech With Tim"、"抓一下 Engadget 最新的"、"看看第 3 个订阅有没有更新" | `--update "SUB"` | SUB = 名字或序号 |
| "强制回扫 X 最新 10 篇"、"忽略已读重新抓 X"、"重新拉 X 全部" | `--update "SUB" --all` | 忽略去重、强抓 10 篇 |
| "强制回扫所有订阅"、"忽略已读全部重抓" | `--all` | 全量强抓 |
### 2. 查看订阅
| 用户可能说 | 命令 |
|---|---|
| "列出所有订阅"、"我订了哪些博客"、"有哪些频道"、"看订阅列表" | `--list` |
### 3. 查看文章
| 用户可能说 | 命令 |
|---|---|
| "看看 Engadget 里都有什么文章"、"X 的所有文章"、"列出 X 的文章" | `--articles "SUB"` |
| "X 还没看的"、"X 有哪些未读"、"X 的未读列表"、"哪些没读过" | `--articles "SUB" --unread` |
| "第 3 个订阅有什么文章" | `--articles 3` |
> AI 智能体判断"未读"意图的关键词:**未读 / 没看 / 还没读 / 新的 / unread / 待看**。
### 4. 标记已读
| 用户可能说 | 命令 |
|---|---|
| "全部标为已读"、"清一下未读"、"我都看过了"、"全部当作看过" | `--mark-read` |
| "把 X 都当作看过了"、"X 全部标为已读"、"这个频道我不感兴趣了先标已读" | `--mark-read "SUB"` |
### 5. 删除文章
| 用户可能说 | 命令 | 危险度 |
|---|---|---|
| "删掉 X 的所有文章"、"清空 X 的历史"、"重置 X" | `--delete "SUB"` | 高 — 建议先 `--articles SUB` 确认 |
| "删除 X 里第 3 篇"、"把 X 的第 2 条去掉"、"X 的 [5] 号删了" | `--delete "SUB" --article-id N` | 中 — 序号来自 `--articles` 输出 |
> **重要**:删除不可逆。AI 智能体收到"删除 / 清空 / 移除"类意图时,除非用户明确肯定,应先执行 `--articles SUB` 展示待删内容再回问一次。
### 6. 添加订阅
| 用户可能说 | 命令 |
|---|---|
| "订阅 X"、"添加频道 X"、"加个 RSS"、"帮我关注 X"(附 URL) | `--add "NAME" "URL"` |
- YouTube URL、RSSHub URL、原生 RSS URL 都直接传,脚本内部自动路由。
### 7. 导出
| 用户可能说 | 命令 |
|---|---|
| "把今天的文章导出成 markdown"、"生成今日摘要 md" | `--export markdown` |
| "导出 2026-08-28 的 HTML"、"我要那天的网页版" | `--export html --date 2026-08-28` |
| "最新 20 篇导出为 txt"、"给我全库最新 20 篇" | `--export txt --limit 20` |
| "今天的文章导 html 到桌面" | `--export html > ~/Desktop/$(date +%Y-%m-%d).html` |
### 订阅标识(SUB)如何解析
`--update / --articles / --mark-read / --delete` 的 SUB 参数按下列顺序匹配:
1. **数字** → 视为 `--list` 中的 1-based 序号
2. **精确名称**(区分大小写)
3. **忽略大小写精确**
4. **忽略大小写子串**
匹配到多条时脚本会打印候选并退出 1。此时 AI 智能体应:
- 向用户回问「你指的是 X 还是 Y?」
- 或改用 `--list` 里的序号做无歧义定位
匹配不到时也退出 1。
### AI 智能体决策要点
1. **看/查询类**(无副作用):`--list`、`--articles`。可直接执行。
2. **抓取类**(可能改 DB):`--update`、无参扫描、`--all`。安全,直接跑。
3. **写入类**(会改 DB):`--mark-read`、`--add`。可直接执行,但结束后简报结果。
4. **删除类**(不可逆):`--delete`。**先展示要删的内容再执行**,除非用户在同一轮明确肯定。
5. **导出类**(只读):`--export`。stdout 输出,AI 应帮用户决定重定向到哪个文件。
6. **SUB 消歧**:能用序号就优先用序号(`--list` 是廉价的),避免多义。
## 添加订阅示例
### YouTube 频道