# we-mp-rss 运维笔记

## 调度器卡死

**症状**: we-mp-rss 进程正常运行数天，但文章停留在某个日期后不再更新。`ENABLE_JOB=True` 和 `SPAN_INTERVAL=600` 已配置。

**诊断**:
```bash
# 检查数据库最新文章的日期
python3 -c "
import sqlite3
db = sqlite3.connect('/path/to/we-mp-rss-data/db.db')
cur = db.cursor()
cur.execute('SELECT MAX(datetime(publish_time, \"unixepoch\", \"localtime\")) FROM articles')
print(cur.fetchone()[0])
"
```

如果日期停在几天前 → 调度器卡死。

**修复**: 重启 we-mp-rss
```bash
kill PID
# 重启（使用与旧进程完全相同的参数）
cd /path/to/we-mp-rss-main && source venv/bin/activate && \
  DB="sqlite:////path/to/we-mp-rss-data/db.db" \
  ENABLE_JOB=True PORT=8001 BROWSER_TYPE=firefox \
  SPAN_INTERVAL=600 SEND_CODE=False \
  python main.py -job True -init True &
```

重启后应立即看到 scheduler 启动日志：
```
添加任务: 定时采集
INFO:apscheduler.scheduler:Scheduler started
Adding cron job with expression: */5 * * * *
```

## API 端点路径

正确路径格式：`/api/v1/wx/{resource}`（注意复数形式）

| 资源 | 路径 |
|------|------|
| 文章列表 | `/api/v1/wx/articles?page=1&page_size=100` |
| 公众号列表 | `/api/v1/wx/mps` |
| 文章详情 | `/api/v1/wx/articles/{article_id}?content=true` |

认证头：`Authorization: AK-SK {access_key}:{secret_key}`

响应格式（成功）:
```json
{"code": 0, "message": "success", "data": {"list": [...], "page": {"total": N}}}
```

## WARNING

- fetch_articles.py 传入的 API 路径是 `/api/v1/wx/articles`（复数），不是 `/api/v1/wx/article`
- `.env` 文件中的 `source` 会因含注释的 cron 表达式（如 `DIGEST_CRON=0 8 * * *  # 备注`）导致 shell 报错。改用 `export $(grep ...)` 只导出需要的变量
- **`-init True` 坑**: 重启时加 `-init True` 会把数据库配置重置为级联模式（cascade），导致调度器跑「级联任务分发」而非「定时采集」。修复：删掉 `-init True`，只用 `python main.py -job True`
- **Session 过期**: 日志 `请先扫码登录公众号平台` 或 `Invalid Session` → 登录 Web UI（`admin` / 密码见数据库 users.password_hash），选中一个公众号点「刷新授权」扫码
- **浏览器依赖**: we-mp-rss 需要浏览器（Firefox / Chromium）抓取。Firefox 可能未安装。用 Playwright 安装 Chromium：
  ```bash
  PLAYWRIGHT_DOWNLOAD_HOST=https://npmmirror.com/mirrors/playwright/ playwright install chromium
  # 然后重启，改用 BROWSER_TYPE=chromium
  ```
- **密码重置**: users 表列名是 `password_hash` 不是 `password`，用 bcrypt 生成 hash：
  ```python
  import bcrypt, sqlite3
  db = sqlite3.connect('db.db')
  h = bcrypt.hashpw(b'admin', bcrypt.gensalt()).decode()
  db.execute("UPDATE users SET password_hash = ? WHERE username = 'admin'", (h,))
  db.commit()
  ```
