douyin
README.md
# dsh-douyin-scroll | 刷抖音
> [!WARNING]
> **用之前先想清楚(风险自担)**
> - 这个插件会把**你自己的抖音登录凭证(Cookie)**交给本机脚本,替你调用抖音的接口。这不是抖音官方功能 —— 属于**个人学习性质的自动化**,可能违反抖音的用户协议,**账号风险由你自己承担**。
> - Cookie 等同于登录态:**只存在本机**(`$DSH_HOME/douyin-duty/`,不进仓库、不上传任何服务器 —— 代码全是本地的,可自行审阅)。但请你**别把 Cookie 贴给任何人**,也别在公共电脑上用。
> - 私密分享默认开、**公开评论 / 自动回复默认关**,每一道发送都有每日上限(手动调用还有 `confirm` 闸)—— 请在**了解每一项开关做什么**之后再打开;在别人视频下发评论是**公开行为**。
> - 推荐流的筛选是**启发式**(互动比值 + 评论文本),不是内容理解 —— 它会误判,见「已知局限」。
> - 仅供个人学习研究,请勿用于商业用途或大规模账号操作。
> **先看五行**
> - 它不只是替你筛选,而是一只自己刷、自己学习、养出审美的小账号「**大肥鱼**」:刷到真心喜欢的才分享 / 评论 / 喊你。
> - 登录的是**你的 AI 小号(大肥鱼)**,你用**主号**接收分享、被 @ —— 两个号(`dmToId` / `commentSelfName` 标识)。
> - 它替你**刷一轮抖音**,把**值得看**的挑出来,写一份 Markdown 日报;并把真喜欢的**私信分享卡片**给你。
> - **看得更全、听得到台词**(v0.4.0;v0.4.1 每条最多 30 帧):每条入选视频按**时长自适应抽帧**(约 3 秒一帧、封顶 30、宽 640,需 ffmpeg,没有就只看高清封面),大肥鱼先看画面再判断;台词**优先用抖音官方字幕**,没字幕且装了可选 `faster-whisper` 时才本地转写,都没有就老实标「无台词」。
> - **🐟 自己收集、安全审核表情包**(v0.4.0;v0.4.1 图片/GIF 也能发):评论/聊天里看到的表情自动入库,大肥鱼逐张看图审核,只放行可爱/萌/抽象/搞笑/大肥鱼/治愈类,色情/暴力/血腥/恐怖/违法/涉政/辱骂/未成年向一律拦;平台贴纸走发布接口,图片/GIF 走上传(评论+私信,需该号有图片权限,没入口如实返回 `image_uploader`;默认关、受风控和每日上限)。
> - **私密分享默认开,公开行为默认关**:主动评论、自动回复默认关;回复只回善意、好回答的,**同一个人每天最多回 2 次**(硬规则)。
> - **私信只跟你(老大)一个人**:不接收、不回复任何陌生人;分享一律走抖音**官方分享卡片**,且带一句大肥鱼的看法。
> - **内置降封号风控**:拟人随机间隔、连做长休、夜间静默、每小时/每天上限、新号养号期、撞验证码自动熔断(见 v0.3.9)。
---
## 它做什么 / 不做什么
| ✅ 做 | ❌ 不做 |
|---|---|
| 用只读推荐流接口取候选(3 页 feed + 热榜) | 本地 Whisper 是**可选**重依赖(默认不装),没字幕且没开 Whisper 就只标「无台词」 |
| **自适应抽帧**(v0.4.0,v0.4.1 封顶 30;约 3 秒一帧/宽 640)+ 高清封面,让大肥鱼真的看画面 | 不做 OCR(不识别画面里的文字) |
| **官方字幕优先**(v0.4.0),可选本地 Whisper 转写台词 | 不长期留存视频,只短暂下载用于抽帧/提音频 |
| **图片/GIF 表情走上传**(v0.4.1,评论+私信),无入口三态 `image_uploader` | 需该号有图片评论/私信图片权限;找不到入口不硬试 |
| **代码层硬筛**:没文案、时长 <12 秒、文案太短且评论少 → 直接跳过 | 不做政治、色情等敏感内容的任何主动互动 |
| 拉**高赞评论**作为判断依据(前 5 条) | 陌生人私信一律不读、不回(只跟老大一个人) |
| 用「**画面帧** + 文案 + 标签 + **互动比值** + 高赞评论」判断喜不喜欢 | 不做关键词搜索(抖音 web 没有可用搜索接口) |
| 写 Markdown 日报到 `out/<日期>.md` | 不做私信自动投递(没有稳定接口;发信走工具,且要你点头) |
| 可选:Windows 通知 / webhook | 不代你登录、不上传任何凭证 |
| 可选:私信、分享卡片、回评论(**默认全关,且都要 `confirm`**) | 不保证判断准确(见下面「已知局限」) |
---
## v0.4.0 升级:自适应抽帧、语音识别、安全表情包
- **🎞️ 自适应抽帧**:不再固定 3 帧,按时长约每 `frameTargetSec`(默认 3 秒)抽一帧、每条封顶 `frameMax`(默认 12)、
帧宽 `frameWidth`(默认 640,可选 320/480/640/720)——长视频看得更全、token 又可控;`frameCount` 变"时长未知兜底"。
- **🎙️ 语音识别**:每条候选带 `spoken` / `spoken_kind`;**官方字幕优先**(`useOfficialSubtitle` 默认开),
没字幕且装了可选 `faster-whisper`、打开 `useAsr` 才本地转写(`asrModel` 默认 small、CPU int8);
`spokenMaxChars` 默认 600。doctor 新增第 11 项检测 Whisper。
- **🐟 表情包**:`douyin_comments` / `douyin_im_read` 自动收集(`collectSticker` 默认开);
新工具 `douyin_sticker_list` / `douyin_sticker_review` 看图审核(名称黑名单 + 视觉双保险,只放行健康的);
新工具 `douyin_comment_sticker` 发评论贴纸(`useSticker` 默认关、`stickerPerDay` 默认 5、只发 approved、过风控)。
面板新增「看画面/听台词」「表情包」两张设置卡。
## v0.3.9 升级:看画面、私信只认老大、降封号风控
- **看画面**:每条入选视频抓封面 + 关键帧(`watchFrames` 开、`frameCount` 默认 3),大肥鱼先 Read 画面再判断;
没 ffmpeg 自动降级只看封面(doctor 第 10 项会提示)。
- **私信铁闸**:`douyin_dm` / `douyin_share_card` / `douyin_im_read` 只认设置里的老大 `dmToId`,
其他人一律 `owner_only` 拦截;没配老大 `owner_not_set`。
- **官方卡片 + 必带评价**:视频只能用 `douyin_share_card` 官方卡片分享(贴文字链接拦 `use_share_card`),
卡片和 @ 都必须带一句大肥鱼对画面的看法(拦 `need_reason`)。
- **时间和条数**:面板新增「每轮最多刷几条」`maxPerRun`(1–30,默认 12);刷的时段、每天条数原本就可配。
- **称呼**:全链路叫你「**老大**」;评论区说"老大/老大/你家老大"都指你本人。
- **降封号风控**(`lib/ratelimit.mjs`,host 与 MCP 共用):随机间隔、连做 4 条长休、夜间 23:00–08:00 静默、
每小时 ≤8 / 每天 ≤20 个对外动作、新号养 7 天(间隔 ×1.8、配额 ×0.4)、撞验证码硬熔断 2h 起、
撞 403/429 冷却 10min 起;熔断后绝不重试,面板「🛡️ 降风险控」卡可看状态、手动「解除熔断」。
(刷视频/看评论不算对外动作,不受限;受限的只有发出去的评论/回复/@/私信/分享。)
---
## 大肥鱼自主行为(v0.3.8)
这版把它从「替老大筛选的秘书」改成**自己刷、自己学习、自己表达**的拟人小号。
所有动作都在设置页「🐟 大肥鱼自主行为」卡片里控制,**上限全可配、默认保守档**:
| 行为 | 开关 | 默认 | 每日上限(默认) | 说明 |
|---|---|---|---|---|
| 自主学习 | `autonomousLearn` | **开** | 每轮记 1–4 条 | 把真心喜欢的追加到 `tastes-inbox.jsonl`,下一轮自动注入「口味画像」,越刷越有审美 |
| 私信分享给老大 | `shareToOwner` | **开** | `sharePerDay` = 5 | 挑**自己最想安利**的发分享卡片,**不是每条都发** |
| 评论区 @ 老大 | `commentAtMe` | 关 | 每轮 1 条 | 那条视频下没有你的评论可回,只能 @ 把你叫来看(走 UI 真 @) |
| 主动评论 | `proactiveComment` | 关 | `proactiveCommentPerDay` = 3 | **不是每条都评**,只对真心想表达的发顶层普通评论(不带 @) |
| 自动回复评论 | `autoReply` | 关 | `replyPerDay` = 10 | 只回善意、好回答的;**同一个人每天最多回 `replyPerPerson`=2 次** |
| 只回善意 | `replyKindOnly` | 开 | — | 恶意 / 辱骂 / 抬杠 / 引战 / 引流 / 索要隐私 / 无意义一律不回 |
**硬规则不是只靠提示词**:`lib/engage.mjs` 是 host 工具和值班轮实际挂载的 MCP server **共用的同一本账**,
无论哪条调用路径都绕不过「每日上限 / 同人 ≤2 / 善意过滤」——超限会直接返回 `blocked`(`proactive_cap`
/ `share_cap` / `person_cap` / `daily_cap` / `unfriendly`),并自动把那条标记已读、不反复弹。
> 两账号:去刷的是**大肥鱼小号**;老大主号在「私信发给谁」(`dmToId` 稳定 ID) 与「评论区 @ 谁」
> (`commentSelfName` 昵称) 里填。**值班轮自动跑**时在开关与上限内直接发(工具带 `confirm:true`);
> 手动对话里让它发,仍会先给草稿等你点头。
---
## 三条路(2026-10-21 定型,别再自己加第四条)
| 干什么 | 怎么走 | 需要登录? |
|---|---|---|
| 取候选 / 出清单 | **不签名**的只读接口 `tab/feed` + `hot/search` | 要(Cookie) |
| 读评论 / 读通知(含「评论区 @ 我」) | **签名只读**(`tools/dy-signer.mjs` 出 a_bogus) | 要 |
| 发私信 / 发卡片 / 发评论 | **无头 Chrome** 里跑抖音自己的前端 | 要 |
- ⚠️ 可见浏览器只在**扫码登录**时用一次;其余全是无头 Chrome 或纯 HTTP。
- ⚠️ 扫码 / 私信 / 卡片 / 评论这几个脚本只找 `chrome.exe`(不找 Edge)。
没装 Chrome 不影响「取候选 + 写日报」,但上面这几个动作会失败。
- ⚠️ **发任何东西前必须先问使用者**(`confirm: true` 闸,不传只回草稿)。
---
## 判断是怎么做的(这是最核心的部分)
抖音**没有字幕轨**可白拿(B站 有),所以不能"读原文",只能**读观众反应**:
```
第 0 层 硬过滤(纯代码,0 token)
没文案 ⇒ 跳过|时长 <12 秒 ⇒ 跳过|文案太短 且 评论少 ⇒ 跳过
(两个阈值在设置页可调,默认 12 字 / 3 条;两个条件同时成立才丢)
⚠️ 太旧、带货、标题党 **没有自动筛**,交给模型逐条判断
第 1 层 互动结构打分(纯数值,0 token)
关键不是点赞绝对值,而是比值:
收藏/点赞 高 ⇒ 有保存价值(教程/攻略/美食)
转发/点赞 高 ⇒ 想转给别人(好笑/共鸣)
评论/点赞 高 ⇒ 引发讨论
⚠️ 播放量对别人的视频经常是 0 ⇒ 完全不参与计算
第 2 层 语义判断(模型)
输入是**压缩过的证据包**,不是原始 JSON:
文案 / 作者 / 时长 / 发布时间 / 互动四件套 / 三个比值 / 高赞评论 top5
模型必须**引用具体证据**(哪条评论、哪个比值),禁止"感觉有趣"
第 3 层 不确定就不推
证据不够 ⇒ 进「判断不了」区,**不出现在推荐里**
```
**能区分的几类**(各自判据不同):😂好笑 · 🛠有实用 · 💡涨知识 · 💗共鸣 · 🐱萌。
**会主动降权**:评论出现「被骗了/标题党」· 文案模板化 · 昵称带「测评/推荐」· 纯颜值 BGM(点赞高但评论空洞)。
> ⚠️ **诚实说**:这套比 B站 版弱一档。B站 读字幕全文,抖音只能读观众反应。
> 它做不到"条条精准",但能做到"扫一眼报告,大部分值得点开"。策略是**宽松召回 + 严格推荐**:
> 点错成本很低(划过去就行),漏掉才是真损失。
---
## 装
```bash
# 先跑预检(不用装 DSH;克隆下来后在本目录跑)
git clone https://github.com/hhc2939526265-sudo/dsh-douyin-scroll.git
cd dsh-douyin-scroll
node selfcheck.mjs # 全部通过再装
# 安装(本地目录链接,开发/自用)
dsh plugin --profile web add link:D:\aiagent\deepseek\dsh-douyin-scroll
```
⚠️ 装完**必须重启一次 dsh**(bundle 层要重启才组装)。然后进 **设置 → 刷抖音**。
### 已经装过的,怎么升级到新版本
```bash
cd dsh-douyin-scroll
git pull # 拉最新
node selfcheck.mjs # 确认预检全过
dsh plugin --profile web add link:<本目录绝对路径> # 重新指一次(幂等)
```
然后**重启一次 dsh**,设置页里「关于」那行版本号变了就是升上了。
配置和聊天记忆都放在插件家目录(不随仓库走),升级不动它们。
> 0.3.x 各版本的变化看 [CHANGELOG.md](CHANGELOG.md)。
---
## 首次使用(三步,约 2 分钟)
### 第 1 步:装主依赖
设置页点「**装主依赖**」。它会在插件家目录建一个**独立 venv**、装 `curl_cffi` + `httpx`(走国内镜像,通常 30 秒)。
进度看 `install.log`,**不卡页面**。
### 第 2 步:登录
两条路,任选一条:
```bash
# A. 扫码(唯一会开可见浏览器的场景)
node tools/qr-login.mjs start
```
```
B. 设置页 → 抖音 Cookie / 登录 → 把浏览器里已登录抖音的 Cookie 请求头粘进去
```
Cookie 只落在本机 `<家目录>/douyin_cookie.txt`(Windows 上 ACL 收不紧,但目录在你自己 profile 下),
**不进日志、不进报告、不上传**。日志里只出现脱敏后的 key 名。
### 第 3 步:填「刷什么」
- **关注关键词**:一行一个,例如 `搞笑`、`美食`、`猫`
- **推荐流分类**:例如 `游戏`、`游戏解说`
- **指定作者**:作者主页链接或 `sec_uid`(可选)
- **每天最多挑几条**(默认 5)、**每次最多筛选几个**(默认 12)
⚠️ **关键词 / 分类在采集侧不起作用**:抖音 web 没有可用的关键词搜索接口,
这些词只会写进报告当标注。真正取候选的是推荐流 + 热榜。
然后点「**现在跑一轮**」。
---
## 报告长什么样
写到 `<DSH_HOME>/douyin-duty/out/<日期>.md`:
```markdown
# 刷抖音 · 2026-10-21
> 本轮:证据包 10 条 → 逐条看过 10 条 → 推荐 4 条 · 顺带一提 4 条 · 判断不了 2 条
> 因「没文案」跳过 2 条,因「时长<12 秒」跳过 2 条
> ⚠️ 太旧、带货、标题党这些没有自动筛,靠逐条判断
## 值得看
### 7401234567890123401
**加班到凌晨三点回家,猫以为我死了** · @两只猫的铲屎官 · 12 秒 · 8 小时前
🔗 https://www.douyin.com/video/7401234567890123401
📊 赞 12.8万 · 评 8600 · 藏 9000 · 转 2.1万
**为什么值得**:高赞评论 3 条都在说"笑死/绷不住",转发/点赞 0.16 明显偏高 ⇒ 是那种会想转给朋友看的段子。
**一句话**:养猫的人看了会心一笑。
## 顺带一提(证据不够,没算进推荐)
- 7401234567890123456 · 某个美食教程 · 收藏比不错但评论太少,先记着
## 没把握 / 判断不了
- 7401234567890123457 · 文案只有「嗯」,评论 1 条 —— **没有判断依据,不硬猜**
```
⚠️ **`### <纯数字视频ID>` 这一行是宿主数配额用的** —— 这一行数 = 今天挑了几条。
「顺带一提」「判断不了」里**不要**加这种标题,加了会吃掉当天额度。
---
## 我需要你提供什么(清单)
| 项 | 必须? | 怎么给 |
|---|---|---|
| **抖音 Cookie** | 必须 | 设置页粘贴,或 `node tools/qr-login.mjs start` 扫码(**不上传**) |
| **关键词 / 分类** | 建议填 | 设置页,一行一个(只当报告标注,不参与采集) |
| **运行时间** | 可选 | 开「峰谷时段自动刷」→ 午间 12:00–14:00 / 夜间 18:00–09:00 |
| **每天几条** | 可选 | 默认 5,填 0 = 不自动刷(仍可手动跑) |
| **通知方式** | 可选,默认 **Windows 通知** | 默认就会弹;想换群/机器人就 `notifyMode=webhook` + 你的 webhook 地址 |
| **要 @ 谁** | 只在开评论时需要 | 设置页填抖音昵称;**留空 = 不发评论** |
**你不需要提供**:任何 API key、账号密码、抖音开发者资质、bb-browser、Playwright。
---
## 如何测试
```bash
# ① 不装 DSH 就能跑的判断层自检
python tools/smoke.py
# → 会打印"硬筛原因 + 证据包 + 粗分类",你能直接看出它怎么判断的
# ② 全套本地预检(不联网、不起浏览器)
node selfcheck.mjs
# ③ 装进 DSH 后
# 设置页「测一下」= 查会话 + 试取一次候选 → 回答"能不能用"
```
---
## 设置项
| 项 | 默认 | 说明 |
|---|---|---|
| 每天最多挑几条 | 5 | **全天总量**;0 = 不自动刷 |
| 每次最多筛选几个 | 12 | 证据包上限(传给 `forward-pick.py --limit`,最多 30) |
| 中午谷时 / 晚上谷时 | 开 / 开 | 12:00–14:00 / 18:00–次日 09:00 |
| **自定义时段** | 空 | 想加几个加几个(`09:00–11:00`、跨零点的 `23:00–02:00` 都行);**跟上面两个叠加**,任意一个命中就跑,每个时段每天一次 |
| 关键词 / 分类 / 作者 | 空 | 一行一个;**只当报告标注**,采集侧不按词搜 |
| 文案太短阈值 / 评论少阈值 | 12 / 3 | **两个条件同时成立**才跳过 |
| 自动评论并 @ | 关 | 危险,默认关 |
| 每轮 / 每天最多评论 | 1 / 0 | `commentPerDay=0` ⇒ 一条都不会发 |
| 🐟 自主学习 | 开 | 把喜欢的记进口味画像,越刷越有审美 |
| 🐟 私信分享给老大 / 每天条数 | 开 / 5 | 挑最爱的发卡片,不是每条都发;0 = 关 |
| 🐟 主动评论 / 每天条数 | 关 / 3 | 非每条都评,只发顶层普通评论 |
| 🐟 自动回复 / 每天条数 | 关 / 10 | 只回善意好回答的 |
| 🐟 同人每天最多回 / 只回善意 | 2 / 开 | 同一人每天≤2 次(硬规则);恶意抬杠引流不回 |
| 👀 抓封面+关键帧 | 开 | 需 ffmpeg,没有就只看高清封面 |
| 🎞️ 抽帧密度(秒/帧)/ 上限 / 帧宽 | 3 / 30 / 640 | 按时长自适应;密度 2–8 秒、上限 4–30、宽 320/480/640/720;时长未知兜底帧 2–30 |
| 🎙️ 官方字幕 / 本地 Whisper | 开 / 关 | 字幕优先;Whisper 需装可选 `faster-whisper`,没字幕才转写,模型默认 small |
| 🐟 表情收集 / 允许发表情 / 只发安全 / 每天几个 | 开 / 关 / 开 / 5 | 先收集审核;发默认关;只发 approved;贴纸数 0–30 |
| 🛡️ 拟人节奏 | 开 | 随机间隔、连做 4 条自动长休,像真人 |
| 🛡️ 夜间静默 / 起止 | 开 / 23:00–08:00 | 深夜不主动对外发;起止可改 |
| 🛡️ 每小时 / 每天动作上限 | 8 / 20 | 对外动作(评论/回复/@/私信/分享)硬上限 |
| 🛡️ 新号养号 / 天数 | 开 / 7 | 养号期间隔 ×1.8、配额 ×0.4;面板可解除熔断 |
| 通知方式 | toast | toast / file / webhook / both |
| 日报写多细 | full | full / brief(薄)/ off(不写) |
| pythonPath / dshBin | 自动 | 一般不用改 |
| 发私信给谁(昵称 / 稳定 ID) | 空 | `dmTo` 只显示;`dmToId` 才决定发给谁 |
| 更新地址 `updateUrl` | 空 | 留空 = 自动查 npm / GitHub;填了就只查这一个 |
> 2026-10-21 删掉了「采集来源」和「工作区」两项:前者只剩一条路(只读推荐流),
> 后者是"读外部 AGENTS.md 当人设"的口子,已封死 —— 人设只读插件自带的 `prompts/persona.md`。
---
## 消息怎么到你手上
一轮跑完,结果要**真的推到你面前**,不能只是躺在文件夹里。默认走 **Windows 通知**,零配置:
| 方式 | 行为 | 要准备什么 |
|---|---|---|
| `toast`(**默认**) | 屏幕右下角弹一条:挑到几条 + 前两条值不值得看;留在通知中心(Win+N) | **什么都不用** |
| `file` | 不额外提醒,报告落在 `out/<日期>.md` | — |
| `webhook` | 推到企业微信 / 飞书 / 钉钉群,或任意 URL(`custom`) | 一个机器人 webhook 地址 |
| `both` | 弹通知 + 推 webhook | 同上 |
设置页「通知 → **发一条测试消息**」点一下就知道通不通 —— 通了会**当场**弹到你屏幕上。
> **为什么不做「抖音私信发给我」**:发私信要签名和登录态,且风险高;插件里虽然有
> `douyin_dm` / `douyin_share_card`,但它们**只在会话里由模型调用,且必须你点头**,
> 不会自动把日报私信给你。
---
## 发评论 / 私信 / 卡片(默认全关)
### 评论:三重保障,任何一重关着都不会发
1. **设置里「自动评论」关着**(默认)→ 工具层直接拒绝
2. **评论执行器 = `off`**(默认)→ 即使开关开着也不会发
3. **「要 @ 谁」留空** → 不会发(评论的意义就是那一下 @)
| 执行器 | 行为 | 状态 |
|---|---|---|
| `off` | 不发(**默认**) | ✅ |
| `builtin` | 走抖音评论提交接口 | ❌ 不可用(要验签票据)——调用会如实报错 |
| `browser` | 在真实页面上填评论,**但不点发送** | ⚠️ 半自动(刻意保守) |
| `http` | 转发给你自己部署的服务 | ✅ 你有自己通道时用 |
🔴 **风险(必须知道)**:
- 抖音评论区**「@ 自己」是否成立未经验证**;
- 评论以**你本人账号**名义发出;
- 频繁评论会**触发风控/限流**,可能影响你正常刷抖音。
### 私信 / 分享卡片
- 🔴 两个工具(`douyin_dm` / `douyin_share_card`)都**必须传 `confirm: true`**,否则只回草稿。
- 🔴 **先卡片,后文字**:既要发卡片又要发文字时,**永远先卡片、隔几秒再文字**。
`douyin_share_card` 给了 `reason` 会自动按这个顺序办(卡片 → 回读 → 隔 N 秒 → 理由),
**不要**再补一次 `douyin_dm`。
- ⚠️ **纯文本网址在抖音里点不开**,只有**分享卡片**能点 —— 所以用卡片,不要拼文本链接。
- ⚠️ 回读能证明「发出去了」,**证明不了「对方已读」**。
---
## 已知局限(不掩饰)
1. **判断准确率低于 B站 版** —— 没有字幕,只能读观众反应。
2. **「文案极简 + 评论少」的视频一定会漏** —— 这是刻意的:没依据就不硬猜。
3. **播放量不可用** —— 对非作者的视频经常返回 0,所以判据里完全不用它。
4. **关键词搜索不可用** —— 抖音 web 的 `general/search` 被 2483 挡住;只有推荐流。
5. **推荐流每轮不一样** —— 同一时间跑两次可能拿到不同候选;报告里会标注每个采集源新增了几条。
6. **评论可能拉不到** —— 签名失效 / 风控 / 接口变更都会让某几条没有评论区证据;报告会如实写。
---
## 排障
| 现象 | 看哪里 |
|---|---|
| 设置页不出现「刷抖音」 | 重启 dsh;看日志有没有 `1 entry did not activate` |
| 拿不到候选 | `health.json` / `duty.log` / `forward-pick.json` 的 `meta`(每个源的 `new` 和 `status`) |
| 报告是空的 | 宿主会补一份「占位报告」并贴日志尾部;完整日志在 `duty.log` |
| 判断太保守/太激进 | 调「文案太短阈值 / 评论少阈值」和「每次最多筛选几个」 |
| 一轮跑太久 | 降证据包条数(前 5 条才拉评论,拉评论是最慢的一步) |
| 昨天挑的今天还算配额 | 不会:配额按 `out/<今天>.md` 里的 `### ID` 数,跨天自然归零 |
**数据都在**:`<DSH_HOME>/douyin-duty/`(`config.json` / `collector.json` / `forward-pick.json` /
`round-evidence.json` / `duty.md` / `out/` / `inbox/` / `duty.log` / `health.json`)。
---
## 目录结构
```
dsh-douyin-scroll/
├── package.json / cordis.patch.yml # 插件声明(entry id 必须 = douyin-scroll)
├── index.js # 宿主半端:配置/工具/定时器/证据包/headless 跑一轮/HTTP
├── client.js # 设置页(非 ESM 自注册脚本)
├── AI-USAGE.md # ⭐ 给别的 AI 看的使用说明(MCP 接入 + 安全红线)
├── selfcheck.mjs # 本地预检(300 项)
├── tools/
│ ├── mcp-server.mjs # ⭐ 标准 MCP server(stdio,零依赖)—— 别的 agent 工具接进来
│ ├── panel-render-check.mjs # ⭐ 设置页真渲染一遍(抓白屏,语法检查查不出)
│ ├── doctor.mjs # ⭐ 环境体检(纯 Node,不依赖 Python)
│ ├── forward-pick.py # ⭐ 取候选 + 硬筛 + 打分 + dropped 计数
│ ├── forward-run.mjs # 命令行一键:拉候选 + 弹通知
│ ├── api-comments.py # 签名拉评论
│ ├── notice-read.py # 签名读通知(含 @ 我)
│ ├── api-reply.py # 签名回评论(只读先通才写)
│ ├── comment-api.mjs # 无头页面里发评论/回复
│ ├── comment-mention-ui.mjs # 真 @ 提及(只有 UI 点选才算数)
│ ├── comment-delete.mjs # 删自己的评论(页面里 POST /comment/delete/)
│ ├── comment-reply.mjs # 真实 UI 回某条评论(保守方案)
│ ├── comment-read-dom.mjs # 从评论区 DOM 读(绕开"只翻前 80 条"的接口盲区)
│ ├── card-share.mjs # 分享卡片(无头页面点「分享给朋友」)
│ ├── im-send.mjs # 私信发送 + 回读(头像左右判发送方)
│ ├── mk-msg.mjs # 把清单拼成私信正文
│ ├── qr-login.mjs # 扫码登录(唯一可见浏览器)
│ ├── cdp.mjs # CDP 小工具
│ ├── dy-signer.mjs # 抖音 web 签名器(纯 Node + jsdom)
│ ├── session-guard.py # 会话保险丝(坏签名别打写接口)
│ └── smoke.py # 判断层自检(离线)
├── lib/
│ ├── hostdeps.mjs # 三级兜底取宿主依赖
│ ├── paths.mjs # ⭐ 家目录/插件目录的唯一来源(不写死盘符)
│ ├── chrome.mjs # 无头浏览器(找不到 Chrome 就找 Edge/Chromium)
│ ├── state.mjs # 家目录 / 谷时窗口 / 章程记账 / Cookie 脱敏
│ ├── credential.mjs # Cookie 存取
│ ├── notify.mjs # webhook + 报告摘要 + URL 脱敏
│ ├── toast.mjs # Windows 通知(默认)
│ ├── uvfetch.mjs # 机器上没有 uv/python 时自动下一份
│ ├── engage.mjs # ⭐ 自主互动账本(每日上限 / 同人≤2 / 善意分类),host 与 MCP 共用
│ └── tastes.mjs # ⭐ 大肥鱼的口味画像(自己刷、自己学,越刷越有审美)
├── prompts/
│ ├── duty.md # 一轮的章程(判据 + 红线 + 报告格式)
│ ├── persona.default.md # 中性默认人设(随包发布)
│ └── sample-candidates.json # 内置示例(离线演示用)
└── requirements.txt # 只有 curl_cffi + httpx
```
---
## 给别的 AI 用(MCP)
插件自带一个**标准 MCP server**(`tools/mcp-server.mjs`,stdio,**零依赖**)。
Claude Code / Cursor / Cline / 另一个 DSH 都能接:
```json
{
"mcpServers": {
"douyin": {
"command": "node",
"args": ["<插件目录>/tools/mcp-server.mjs"],
"env": { "DOUYIN_HOME": "<插件家目录>" }
}
}
}
```
设置页「**给别的 AI 用 → 看接入方式**」里有一键复制(路径按你这台机器算好)。
完整说明见 [AI-USAGE.md](AI-USAGE.md),或者直接让那个 AI 调 `douyin_guide`。
> 为什么不做成"任何 AI 都能直接装":MCP 是各家通用的接口,但**它只解决"能调工具"**。
> 「按点刷一轮 → 写日报」那条值班链路仍然在 DSH 里(要 headless 会话 + 定时器)。
> 两件事分开:**能力走 MCP,值班走 DSH 插件。**
---
## 许可证
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues