已读完的书挪进「书籍」,抓取上限去掉(8 -> 整架 26 本)
抓取范围 - TOP_N 默认从 8 改成 0=不限制。原来那个 8 是我拍的「最近动过的前 8 本」, 不是接口限制;整架 26 本也就 1+26 个请求,完全够用 - --top N 仍可用,想只抓最近几本时加 分组调整 - 「最近在读」只留 progress < 100 的(20 本),进度条不再出现 100% - 新增「书籍」区底部的「微信读书 · 已读完」分组(6 本),卡片结构与手工 书单一致,左上角带「已读完」徽标;因为微信读书的数据没有书评/简介, 这一组点击直接跳 weread.qq.com,不弹窗 - 这一组带 data-weread-card + data-category="微信读书",所以搜索框和 「领域」筛选同样作用得到;领域筛选里会多出一个「微信读书」选项 - 筛选逻辑把 [data-book-card] 的选择器扩成 [data-book-card], [data-weread-card],分组计数也一并算上 实测数据分布(整架 26 本) - 已读完 6 / 在读中 16(1%-97%)/ 没开始 4(0%) 静态验证(dist/bookshelf/index.html) - 在读区 20 张卡片,进度条 30/0/77/28/13/97/0/5/16/3/10/1/4/13/4/0/1/10/6/0, 区内无「已读完」字样 - 已读完分组 6 张卡片,6 个徽标、6 个微信读书跳转链接,均带 data-weread-card - 手工书单 3 张卡片未受影响;领域筛选新增「微信读书」按钮
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* 用法:
|
||||
* pnpm reading 手动刷新(失败会 exit 1,明确报错)
|
||||
* pnpm reading --top 12 抓前 12 本,默认 8
|
||||
* pnpm reading --top 12 只抓最近动过的 12 本;不加则整架都抓(默认不限)
|
||||
* node scripts/fetch-reading.mjs --soft 失败时保留旧数据并 exit 0(构建流程用)
|
||||
*
|
||||
* 接口是腾讯官方的微信读书 Agent Gateway:
|
||||
@@ -25,14 +25,15 @@ const ENDPOINT = "https://i.weread.qq.com/api/agent/gateway"
|
||||
/** 与官方 SKILL.md 顶部的 version 保持一致;服务端会用它对版本 */
|
||||
const SKILL_VERSION = "1.0.4"
|
||||
const OUT_FILE = "src/data/reading.json"
|
||||
const DEFAULT_TOP = 8
|
||||
/** 0 = 不限制,整架都抓。书架一般也就几十本,1+N 个请求完全够用 */
|
||||
const DEFAULT_TOP = 0
|
||||
const REQUEST_TIMEOUT_MS = 15_000
|
||||
const DELAY_BETWEEN_CALLS_MS = 150
|
||||
|
||||
const args = process.argv.slice(2)
|
||||
const SOFT = args.includes("--soft")
|
||||
const topIndex = args.indexOf("--top")
|
||||
const TOP_N = topIndex >= 0 ? Number(args[topIndex + 1]) || DEFAULT_TOP : DEFAULT_TOP
|
||||
const TOP_N = topIndex >= 0 ? Number(args[topIndex + 1]) || DEFAULT_TOP : DEFAULT_TOP // 0 = 不限
|
||||
|
||||
// .env 已 gitignore;Node 22 自带 loadEnvFile,不需要 dotenv
|
||||
try {
|
||||
@@ -78,13 +79,15 @@ async function call(apiName, params = {}) {
|
||||
async function fetchReading() {
|
||||
const shelf = await call("/shelf/sync")
|
||||
|
||||
const candidates = (shelf.books ?? [])
|
||||
const sorted = (shelf.books ?? [])
|
||||
// 私密阅读(secret=1)不要发到公开网站上
|
||||
.filter((book) => book.secret !== 1)
|
||||
// readUpdateTime 为 0 表示从没打开过,不算「在读」
|
||||
.filter((book) => Number(book.readUpdateTime) > 0)
|
||||
.sort((a, b) => Number(b.readUpdateTime) - Number(a.readUpdateTime))
|
||||
.slice(0, TOP_N)
|
||||
|
||||
// TOP_N 为 0 时整架都取;页面再按「读完 / 在读」自己分组
|
||||
const candidates = TOP_N > 0 ? sorted.slice(0, TOP_N) : sorted
|
||||
|
||||
if (candidates.length === 0) {
|
||||
return { books: [], note: "书架里没有可展示的阅读记录" }
|
||||
|
||||
Reference in New Issue
Block a user