🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

B站日报 lll-77777777/dsh-bili-scroll

DeepSeek Harnessv0.1.7
lll-7777777713 天前有提交已提供中文文档扫描:含敏感能力

DSH 插件:每天替你刷一轮 B站 —— 读字幕原文挑出值得的、写一份日报,值得的就 @ 你

32.2/100
综合分
3
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/22 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

自动兼容检查有告警:npm 同名包「dsh-bili-scroll」归属 c1overzz/dsh-bili-scroll,装到的可能不是本插件。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add lll-77777777/dsh-bili-scroll
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · platform
装得上吗
本站已在 dsh 0.2.1-rc.2 下真实安装成功
非静态推断
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 13 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意

npm 同名包「dsh-bili-scroll」归属 c1overzz/dsh-bili-scroll,装到的可能不是本插件

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-bili-scroll @ 0.1.7
✓Node 引擎要求 >=22 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/22 11:43:19

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 113 处,展示前 80 条)
  • 读取本地文件
    index.js:151
    try { myVer = String(JSON.parse(readFileSync(join(pluginDir, 'package.json'), 'utf8')).version || '') } catch { myVer = '' }
  • 读取本地文件
    index.js:170
    try { const s = statSync(join(pluginDir, 'index.js')); return `${s.size}:${Math.round(s.mtimeMs)}` }
  • 读取本地文件
    index.js:179
    if (existsSync(win)) return win
  • 读取本地文件
    index.js:182
    for (const d of readdirSync(lib)) {
  • 读取本地文件
    index.js:185
    if (existsSync(p)) return p
  • 读取本地文件
    index.js:191
    try { return readdirSync(sitePkgs(venvRoot)).some((n) => n.startsWith(prefix)) } catch { return false }
  • 写入本地文件
    index.js:198
    mkdirSync(outDir, { recursive: true })
  • 写入本地文件
    index.js:202
    try { appendFileSync(logFile, line + '\n', 'utf8') } catch { }
  • 写入本地文件
    index.js:965
    try { writeFileSync(file, yml, 'utf8'); return file } catch (e) { log(`写 overlay 失败:${e?.message ?? e}`); return null }
  • 写入本地文件
    index.js:1005
    writeFileSync(f, [
  • 写入本地文件
    index.js:1037
    writeFileSync(inboxFile, `# 谁在等你回话 · ${new Date().toISOString()}\n\n${inbox.text || '(没人在等)'}\n`, 'utf8')
  • 执行外部命令来自配置/变量
    index.js:1067
    const child = spawn(dsh.command, args, {
  • 写入本地文件
    index.js:1076
    const pick = (buf) => appendFileSync(logFile, String(buf), 'utf8')
  • 执行外部命令固定命令
    index.js:1231
    const c = spawn('uv', ['--version'], { windowsHide: true, stdio: 'ignore' })
  • 执行外部命令来自配置/变量
    index.js:1242
    const c = spawn(cmd, ['--version'], { windowsHide: true, stdio: 'ignore' })
  • 执行外部命令来自配置/变量
    index.js:1251
    try { c = spawn(cmd, args, { cwd: stateDir, windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'], env: pyEnv() }) }
  • 执行外部命令来自配置/变量
    index.js:1308
    c = spawn(cmd, args, { cwd: stateDir, windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'],
  • 执行外部命令来自配置/变量
    index.js:1606
    try { child = spawn(cmd, args, { detached: true, stdio: 'ignore' }) } catch (e) { resolve(String(e?.message ?? e)); return }
  • 请求外部主机registry.npmjs.org
    index.js:1628
    const r = await fetch('https://registry.npmjs.org/dsh-bili-scroll/latest', { signal: ctrl.signal })
  • 发起网络请求
    index.js:1628
    const r = await fetch('https://registry.npmjs.org/dsh-bili-scroll/latest', { signal: ctrl.signal })
  • 发起网络请求
    client.js:35
    const jget = async (p) => (await fetch(API + p, { credentials: 'same-origin' })).json()
  • 发起网络请求
    client.js:36
    const jpost = async (p, body) => (await fetch(API + p, {
  • 写入剪贴板
    client.js:214
    await navigator.clipboard.writeText(v)
  • 读取本地文件
    lib/hostdeps.mjs:40
    for (const n of readdirSync(join(npm, '@deepseek-ai'))) {
  • 读取本地文件
    lib/hostdeps.mjs:53
    for (const p of readdirSync(join(dshHome, 'profiles'))) {
  • 读取本地文件
    lib/hostdeps.mjs:68
    if (!existsSync(pkgFile)) return null
  • 读取本地文件
    lib/hostdeps.mjs:69
    const pkg = JSON.parse(readFileSync(pkgFile, 'utf8'))
  • 读取本地文件
    lib/hostdeps.mjs:76
    return existsSync(file) ? pathToFileURL(file).href : null
  • 执行外部命令来自配置/变量
    lib/mcp.mjs:32
    this.proc = spawn(command, args, {
  • 读取本地文件
    lib/verify.mjs:114
    if (!existsSync(seenFile)) return { checked: [], skipped: 0, text: '⚠️ 判重表还没生成,没什么可复核的' }
  • 读取本地文件
    lib/verify.mjs:118
    const rows = parseSeen(readFileSync(seenFile, 'utf8'))
  • 读取本地文件
    lib/verify.mjs:124
    try { state = JSON.parse(readFileSync(stateFile, 'utf8')) } catch { }
  • 写入本地文件
    lib/verify.mjs:146
    try { writeFileSync(stateFile, JSON.stringify(state, null, 2), 'utf8') } catch { }
  • 读取本地文件
    lib/verify.mjs:162
    if (!existsSync(f)) return null
  • 读取本地文件
    lib/verify.mjs:163
    writeFileSync(f, readFileSync(f, 'utf8').replace(/ *$/, '') + '\n' + text + '\n', 'utf8')
  • 写入本地文件
    lib/verify.mjs:163
    writeFileSync(f, readFileSync(f, 'utf8').replace(/ *$/, '') + '\n' + text + '\n', 'utf8')
  • 读取本地文件
    lib/threads.mjs:43
    const j = JSON.parse(readFileSync(conversationFileOf(stateDir), 'utf8'))
  • 写入本地文件
    lib/threads.mjs:57
    try { writeFileSync(conversationFileOf(stateDir), JSON.stringify(led, null, 2), 'utf8') } catch { }
  • 读取本地文件
    lib/threads.mjs:296
    const rows = existsSync(seenFile) ? parseSeen(readFileSync(seenFile, 'utf8')) : []
  • 读取本地文件
    lib/threads.mjs:296
    const rows = existsSync(seenFile) ? parseSeen(readFileSync(seenFile, 'utf8')) : []
  • 读取本地文件
    lib/bili-api.mjs:29
    if (!existsSync(f)) return null
  • 读取本地文件
    lib/bili-api.mjs:31
    const c = JSON.parse(readFileSync(f, 'utf8'))
  • 发起网络请求
    lib/bili-api.mjs:48
    const r = await fetch(url, { headers })
  • 写入本地文件
    lib/state.mjs:46
    mkdirSync(dir, { recursive: true })
  • 读取本地文件
    lib/state.mjs:51
    try { return JSON.parse(readFileSync(file, 'utf8')) } catch { return fallback }
  • 写入本地文件
    lib/state.mjs:55
    writeFileSync(file, JSON.stringify(value, null, 2), 'utf8')
  • 读取本地文件
    lib/state.mjs:67
    if (!existsSync(from)) { log(`缺文件:${from}`); continue }
  • 读取本地文件
    lib/state.mjs:68
    if (!overwrite && existsSync(to)) continue
  • 读取本地文件
    lib/state.mjs:69
    if (overwrite && existsSync(to) && readFileSync(from, 'utf8') === readFileSync(to, 'utf8')) continue
  • 读取本地文件
    lib/state.mjs:69
    if (overwrite && existsSync(to) && readFileSync(from, 'utf8') === readFileSync(to, 'utf8')) continue
  • 写入本地文件
    lib/state.mjs:70
    copyFileSync(from, to)
  • 发起网络请求
    lib/login.mjs:45
    const r = await fetch(SPI, { headers: { 'User-Agent': UA } })
  • 发起网络请求
    lib/login.mjs:54
    const r = await fetch(GEN, { headers: { 'User-Agent': UA } })
  • 发起网络请求
    lib/login.mjs:63
    const res = await fetch(pollUrl(key), { headers: { 'User-Agent': UA }, redirect: 'manual' })
  • 写入本地文件
    lib/login.mjs:79
    mkdirSync(stateDir, { recursive: true })
  • 写入本地文件
    lib/login.mjs:81
    writeFileSync(file, JSON.stringify({
  • 执行外部命令来自配置/变量
    lib/login.mjs:97
    child = spawn(pythonPath || 'python', ['-c', code, url, png], { cwd: stateDir, windowsHide: true })
  • 读取本地文件
    lib/login.mjs:99
    const done = () => { try { resolve(existsSync(png) ? png : null) } catch { resolve(null) } }
  • 读取本地文件
    lib/uvfetch.mjs:33
    return createHash('sha256').update(readFileSync(file)).digest('hex')
  • 发起网络请求
    lib/uvfetch.mjs:45
    const r = await fetch(source.url + '.sha256')
  • 读取本地文件
    lib/uvfetch.mjs:55
    try { entries = readdirSync(dir, { withFileTypes: true }) } catch { return null }
  • 执行外部命令来自配置/变量
    lib/uvfetch.mjs:69
    const r = spawnSync(cmd, args, { stdio: 'ignore' })
  • 读取本地文件
    lib/uvfetch.mjs:83
    if (existsSync(target)) return target
  • 写入本地文件
    lib/uvfetch.mjs:85
    mkdirSync(dir, { recursive: true })
  • 删除本地文件递归
    lib/uvfetch.mjs:87
    rmSync(tmp, { recursive: true, force: true })
  • 写入本地文件
    lib/uvfetch.mjs:88
    mkdirSync(tmp, { recursive: true })
  • 请求外部主机pypi.tuna.tsinghua.edu.cn
    lib/uvfetch.mjs:100
    const r = await fetch('https://pypi.tuna.tsinghua.edu.cn/pypi/uv/json')
  • 发起网络请求
    lib/uvfetch.mjs:100
    const r = await fetch('https://pypi.tuna.tsinghua.edu.cn/pypi/uv/json')
  • 发起网络请求
    lib/uvfetch.mjs:124
    const res = await fetch(s.url)
  • 写入本地文件
    lib/uvfetch.mjs:126
    await pipeline(Readable.fromWeb(res.body), createWriteStream(s.file))
  • 读取本地文件
    lib/uvfetch.mjs:127
    const mb = (statSync(s.file).size / 1048576).toFixed(1)
  • 写入本地文件
    lib/uvfetch.mjs:144
    copyFileSync(hit, target)
  • 写入本地文件
    lib/uvfetch.mjs:145
    try { chmodSync(target, 0o755) } catch { }
  • 执行外部命令来自配置/变量
    lib/uvfetch.mjs:147
    const r = spawnSync(target, ['--version'], { stdio: 'ignore' })
  • 删除本地文件递归
    lib/uvfetch.mjs:150
    rmSync(tmp, { recursive: true, force: true })
  • 删除本地文件递归
    lib/uvfetch.mjs:158
    rmSync(tmp, { recursive: true, force: true })
  • 删除本地文件递归
    selfcheck.mjs:45
    try { rmSync(SANDBOX_HOME, { recursive: true, force: true }) } catch { }
  • 写入本地文件
    selfcheck.mjs:46
    mkdirSync(SANDBOX_HOME, { recursive: true })
  • 读取本地文件
    selfcheck.mjs:58
    const pkg = JSON.parse(readFileSync('./package.json', 'utf8'))
  • 删除本地文件递归
    selfcheck.mjs:245
    try { rmSync(SANDBOX_HOME, { recursive: true, force: true }) } catch { }
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
涉及外部主机:registry.npmjs.org、pypi.tuna.tsinghua.edu.cn

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/schemastery@deepseek-ai/dsh-llm@deepseek-ai/dsh-tools
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

README

由 DeepSeek 最新模型翻译生成
dsh-bili-scroll | 刷B站 先看三行 - 需要 dsh ≥ 0.1.7-rc.1(本机是 0.1.7-rc.2)。⚠️ 版本不满足时,内核会静默跳过这个插件 —— 装了跟没装一样,不会报错。 - 空间:不装「本地转写」约 84 MB;装了转写约 1 GB(其中 Whisper 模型 538 MB,可在设置里换更小的模型)。 - 装完必须重启一次 dsh(插件在 bundle 层组装)。 - ⚠️ 桌面版 DSH(NEXT / 0.2.x):0.1.3 及以前的版本在桌面版上装不起来 —— 插件整条不激活, DSH 只留一句 warning: 1 entry did not activate … failed to import(根因是宿主半 import 的两个包在桌面版 profile 里没被安装,详见下面「装不上」那节的第 5 条)。0.1.4 起已修 ✓。 另有用户反馈桌面版上「自动跑那一轮会卡住」—— 卡住就先只用设置页的「现在跑一轮」手动跑(那条稳)。 ⚠️ 装的是旧版吗?
展开完整文档(README 剩余 1 节)
dsh-bili-scroll | 刷B站

先看三行
- 需要 dsh ≥ 0.1.7-rc.1(本机是 0.1.7-rc.2)。⚠️ 版本不满足时,内核会静默跳过这个插件 —— 装了跟没装一样,不会报错。
- 空间:不装「本地转写」约 84 MB;装了转写约 1 GB(其中 Whisper 模型 538 MB,可在设置里换更小的模型)。
- 装完必须重启一次 dsh(插件在 bundle 层组装)。
- ⚠️ 桌面版 DSH(NEXT / 0.2.x):0.1.3 及以前的版本在桌面版上装不起来 —— 插件整条不激活, DSH 只留一句 warning: 1 entry did not activate … failed to import(根因是宿主半 import 的两个包在桌面版 profile 里没被安装,详见下面「装不上」那节的第 5 条)。0.1.4 起已修 ✓。
另有用户反馈桌面版上「自动跑那一轮会卡住」—— 卡住就先只用设置页的「现在跑一轮」手动跑(那条稳)。

⚠️ 装的是旧版吗? 如果设置页里那个按钮写的是「重装依赖」(而不是「重装主依赖」),说明你装的是 0.1.0 ——跑一次 dsh plugin --profile web add dsh-bili-scroll 升级就好(那一版建 Python 环境时缺一个参数,依赖装不上、二维码也画不出来,重装多少次都一样)。

DSH 插件:每天替你刷一轮 B站 —— 它自己搜、读字幕原文判断、把值得的写成报告,特别值得的会留一条评论 @ 你。
你收到的每一条 @,都是它先筛过一遍的。

它做什么

- 按你填的关键词(留空则用内置那几组)搜近几天的视频
- 逐条读字幕原文再判断(不看摘要);没字幕的直接跳过 —— 除非你开了「本地转写」
- 写一份 Markdown 报告到 out/<日期>.md:每条含「为什么值得」+「它自己的一句话」
- 开着「自动评论」时,每轮最多发一条评论、@ 你一次
- 可以在峰谷时段自动跑(DeepSeek 的优惠时段),省 token
- ⭐ 评论区能跟你来回说话(0.1.6 新加):你在它那条评论下面回一句,它下一轮就接一句;你还能再回、它再接 —— 直到同一条串到达来回上限(默认 5 轮)或你不再说话。
想让它立刻接话,设置页有「现在回话」(只看消息、不刷视频,很快)。
- ⭐⭐ 在任意视频的评论区 @ 它,它也会出来(0.1.6):打一句 @<它这个账号的昵称> 想说的话(昵称在设置页里会显示出来),它就会看到并在你那条评论下面回你—— 靠的是 B站 自带的「收到的@」消息流,不是去全网扫评论 ✓
· ⚠️ 它永远不新开一层:只在你那条评论下面回(楼中楼),不会在别人视频底下留新的顶层评论 ✓

评论区「来回对话」怎么算的(0.1.6)

- ⭐⭐ 默认只跟你说话:名单里只有你(就是「要 @ 谁」那个人)的留言 —— 别人回复到它那条评论下面、或者在别处 @ 它,一律不理 ✓。想改成"回所有人",把设置里那个开关关掉即可。
· 认人先按 UID、再按昵称认第一次:第一次按昵称认出你之后就把 UID 认死 ⇒ 以后别人改成同一个昵称也冒充不了 ✓(你哪天改名了,照样认得出 ✓)
· ⚠️ 要是你把「要 @ 谁」填成了插件登录的那个账号,设置页会当场说清楚 ——那样它分不清"自己说的"和"你说的",对话根本转不起来
· 🔒 这条规矩有机器闸,不靠它自觉(0.1.6):发出去那一下还会再去核一遍「要回的那条是谁写的」, 不是你就直接拒发(认不出来也一样不发)—— 就算它哪一轮判断失误,也说不出一句给别人的话 ✓ ⚠️ 只有你亲手关掉「只回我 @ 的那个人」,这道闸才会放开(因为这条规矩是你定的)✓
- 两种来源,一个名单:
· 你回它那条评论 ⇒ 那一串的楼中楼(它自己发过的评论,账本里记着)
· 你在别的评论区 @ 它 ⇒ 从 B站 的「收到的@」里读出来,就在你那条评论下面回
- 谁最后说话谁是"轮到的人":最后一句是你说的 ⇒ 它接;最后一句是它说的 ⇒ 它闭嘴等着(所以它不会自问自答、不会追问、不会刷屏)
- 有来回上限:设置页「同一条串最多来回几轮」。到顶就收住 —— 这是"不拉锯"的机器级保证,不是建议
- 同一条你发的评论只回一次,哪怕它正被审核、页面上还看不见 ✓
- ⚠️ 它只认"账本里记着的评论":如果哪条评论是旧版本发的(那时还没有账本),它不知道"那条是我的" ⇒ 那下面的回复它看不到。
⇒ 用设置页的「认领一条旧评论」:在 B站 App 里对着那条评论点「复制链接」,粘进去即可 ✓
- 🔴 永远不新开一层:它只在"你评论的下面"说话,从不在任何视频下发新的顶层评论 ✓
- ⭐ 它记的是"自己真发出去过什么"(家目录里的 conversation.json,宿主在发出去那一刻自己记的)—— 不是靠"那一轮记得去写"(实测:模型经常忘了写判重表)

装之前(一条前提,30 秒)

机器上要有 Python 3.10+ 或 uv —— 有一个就够:

- 有 uv 最好:单个 ~32 MB 的 exe,解压就能用、不用管理员、不用进 PATH,而且它还能自己把 Python 拉下来;
- 只有 Python 也行(装官方安装器时记得勾 Add to PATH);
- ⭐ 两个都没有?也没关系:点「装依赖」时插件会自己下一份 uv 放到自己的家目录 (单文件、约 15MB、免管理员、不用进 PATH ✓),之后全程自动 ✓
· 它会先直连 GitHub,不通就走国内加速代理,还配了 PyPI 镜像兜底 ✓
· 下载完会核对官方 sha256(对不上就丢弃换下一个源 ✓)—— 因为它下来的东西是要被执行的
· ⚠️ 如果杀软 / Windows Defender 报这个下载:把插件家目录 %USERPROFILE%\.dsh\bili-duty\bin\ 加白即可;不想加白也行,自己装一份 uv 或 Python 3.10+ 就绕过去了 ✓ ✅ 已经做到了(v0.1.1 起):插件会自己把 uv 下到自己的家目录 ⇒ 这条前提不用你操心,也不用管理员权限。
⚠️ 万一它自己也下不动(有用户反馈桌面版上这条链路经常不通):手动放一份 uv.exe 到 <家目录>\bin\ 就行 ——插件优先用那里那一份,会跳过下载。

自己改代码 / 手动拷了插件文件之后(一条坑,30 秒看完)

DSH 的插件是两半:浏览器那半刷新页面就换新,宿主那半要完全退出 DSH 再打开才换新。
只刷新页面 ⇒ 页面是新的、宿主还是旧的 ⇒ 新加的开关点了不会有反应(而且以前什么都不说)。

- ✅ 改完/拷完文件,完全退出 DSH(不是刷新页面),再打开。
- ✅ 现在这件事会自己说:设置页顶部会顶一条「磁盘上的插件代码比正在跑的这一份新」;改设置时如果宿主不认识那个字段,也会直接告诉你"多半是没重启"。
- ⭐ 想少踩这个坑:别手拷文件,让 DSH 直接装你这个目录(改完只需重启一次):
dsh plugin --profile desktop add link:<仓库目录的绝对路径>

装

dsh plugin --profile web add dsh-bili-scroll # 从 npm
dsh plugin --profile web add github:c1overzz/dsh-bili-scroll # 备选:直接从 GitHub
(⭐ 最省事的一条:把仓库链接贴给你自己的 dsh,说「帮我装这个插件」,它会自己装。)

⚠️ 装完必须重启一次 dsh(bundle 层要重启才组装)。然后进 设置 → 刷B站。

自动跑失败?先看这一条(headless 凭据)

如果手动点「现在跑一轮」能成、自动跑那一轮却几秒钟就退出,duty.log 里反复出现:

dsh: MISSING_CREDENTIAL: llm-deepseek: no API key for provider route "deepseek-official"

那不是插件的问题 —— 是 --profile headless 的 profile 把 deepseek-account 和 credentials 两项关掉了,子进程只能用环境变量 DEEPSEEK_API_KEY。修法:在 C:\Users\<你>\.dsh\profiles\headless\cordis.patch.yml 里写

- id: deepseek-account
disabled: false
- id: credentials
disabled: false

改完不用重启 dsh,新起的子进程会重新 compose profile。验证:

"<DSH目录>/DeepSeek Harness.exe" "<DSH目录>/dsh/node_modules/@deepseek-ai/dsh/lib/bin.js" \
headless "Reply with exactly: OK"

打出 OK 就成了。

装不上 / 卡住时,先看这四条(都是用户实测撞过的)

1. 桌面版(DSH NEXT / 0.2.x)上"自动跑"会卡住 —— 有用户反馈:它起那一轮用的是 dsh --profile headless …,桌面版上容易卡在那儿。⇒ 先用设置页的「现在跑一轮」手动跑(那条是稳的);能不能自动跑,等你确认过自己那台桌面版的版本与 profile 再说。
2. 「装依赖」卡住、或者扫码时一直不出二维码 —— 大概率是 0.1.0 那版(见开头那个按钮指纹,跑一次 add 就升级了)。
不想升级也行,救急一句:<家>\.venv\Scripts\python.exe -m ensurepip --upgrade,再点一次「重装主依赖」。
3. 它下不动 uv(桌面版上这条链路经常不通)⇒ 自己放一份 uv.exe 到 <家目录>\bin\,插件会优先用它、跳过下载。
4. 「本地转写」是两段式的 —— 只打开开关不够,还得点它下面那个「装转写依赖」。
没装的时候,没字幕的视频会被跳过(报告里现在会写「因无字幕跳过 N 条」,你能一眼看出漏了几条)。
5. ⭐ 桌面版:装完设置页里根本不出现「刷B站」,日志只有一句 1 entry did not activate … failed to import ——这是 0.1.3 及以前在桌面版上的一个真 bug:插件宿主半 import 的两个包是 optional peer,而桌面版 profile(autoInstallPeers: false)不会装它们 ⇒ 插件整条不激活。
0.1.4 起已修(不再裸 import 那两个包)。⇒ 升级一次就好:dsh plugin --profile desktop add dsh-bili-scroll。
⚠️ 我们自己也只在 npm 0.1.7-rc.x + web profile 上实测过;桌面版这条路靠用户反馈修好的 ——装完还是不行的话,把 duty.log 里那几行发来(里面会写清楚"宿主依赖是从哪儿取的")。

首次使用(两步)

1. 装主依赖 —— 设置页点「装主依赖」:在插件自己的家目录建一个独立 venv,装 3 个包(bilibili-api-python / mcp<2 / qrcode)。走国内镜像 + uv,通常几十秒(进度写 install.log,不卡页面)。
2. 扫码登录 —— 点「扫码登录」,用手机 B站 扫页面上那张码。
⚠️ 确认时选「记住我 / 长期」那张(选 24 小时的话,明天就得重扫)。
凭证只落在你本机的插件家目录:<DSH_HOME>/bili-duty/bili_credential.json,不上传任何地方。

设置页里有什么

| 项 | 说明 |
| 峰谷时段自动刷 | 总开关;打开之后才展开「中午谷时 12:00–14:00」「晚上/夜间谷时 18:00–09:00」两个子开关,以及「自定义时间段」(默认关)。依据 DeepSeek 官方定价:工作日 9:00–12:00、14:00–18:00 是高峰,其余(含整个周末)都是谷时 |
| 每天最多看几条 | 数字自己填;填 0 = 不自动刷(但还能手动跑)。⭐ 这个额度会摊成几轮、随机排在时段里 —— 不会开窗就一次看完 |
| 每轮最多看几条 | 一轮 = 一次会话。默认 2:填 1 更「细水长流」但会话更多(更费),填太大就又变成「一股脑」了 |
| 自动评论并 @ 你 | 默认关;打开后展开两栏:最多 @ 我几条(⭐ 至多,不是任务 —— 没意思的可以不 @;填 0 = 一条都不 @)、要 @ 谁(B站 昵称) —— ⚠️ 留空就不发评论(评论的意义就是 @ 那一下) |
| 本地转写没字幕的视频 | 默认关 —— 要在本机装 Whisper、下几百 MB 模型 |
| 关注关键词 | 一行一个;留空用内置那几组 |
| 工作区 | 它按这里的 AGENTS.md 认「设定」⇒ 你有设定就按你的来 |
| 评论区来回对话(只回楼中楼) | 默认关;开了之后展开六栏:每轮最多回几条、同一条串最多来回几轮、只回我 @ 的那个人(默认开 —— 别人回它一律不理)、在别人的评论区 @ 它也能叫它出来(默认开)、认领一条旧评论(把以前发过、它账本里没有的评论收进来),以及「现在回话」「看谁在等我回话」两个按钮 |
| 日报写多细 | 完整 / 薄版 / 不写;薄版每条一两行(输出比输入贵 200 倍,薄版省的是真钱) |
| 现在跑一轮 / 装主依赖 / 扫码登录 / 看今天的报告 / 打开报告文件夹 | 版本号就在这一行上面(点「检查更新」可以看有没有新版) |

红线(写死在提示词里,不靠自觉)

- 不透露你的隐私:账号、机器路径、你聊过的话 —— 一个字都不进评论
- 每轮最多一条评论;同一视频只评论一次;不刷屏、不吵架
- ⭐ 来回也有限度:同一条串最多来回几轮(设置里能改),到顶就收住;同一条你发的评论只回一次
- ⭐⭐ 默认只跟你说话:名单里只有你;别人回复到它那条评论下面、或者 @ 它,一律不理(想改成回所有人,关掉那个开关)
· 🔒 而且发出去那一下还有一道机器闸:不是本人写的评论,bili_reply 直接拒发(认不出来也拒)✓
· 「本人当场让你发」(force)只放行这一次、这一条 —— 不会把整道闸关掉 ✓
- 🔴 永远不新开一层:只在你评论的下面说话(楼中楼),从不在任何视频下发新的顶层评论 ✓
- 不确定的事不编(报告里如实写「没查到」)

它是怎么跑的

- 插件内部起一个 Python MCP(下面那个开源项目,已内置),把它的能力注册成 DSH 工具
- 定时到点 → 起一个 headless dsh 会话,把 prompts/duty.md(它一轮要做的事)+ 当天设置交给它
- 那一轮的工作目录 = 插件自己的家目录(它被沙箱关着,只写得了自己那一亩三分地); ⭐ 你填的工作区里的 AGENTS.md 由插件读进来、内联进提示词 ⇒ 它按你的设定说话,而不是用一套通用人格
- ⭐ 「谁在等我回话」由插件自己去拉,不交给那一轮去翻(0.1.6):插件读 conversation.json(自己真发出去过的评论)
+ 判重表,去 B站 把每条串的楼中楼读一遍,算出「最后一句是对方说的」那些,写进 inbox.md 并内联进提示词。
这样它不用在几百条评论里翻(翻不全、还费钱),只要照着名单说话。
- ⭐ 两种轮次:刷一轮(搜视频 + 写日报)和 只回话(只看名单 + 说话,不搜视频、不写日报)。
后者就是设置页那个「现在回话」按钮 → POST /api/bili-duty/chat;没人在等 ⇒ 不起会话(不白花钱)。
- ⭐⭐ 一个时段 = 一次窗口实例,额度摊成几轮随机排(0.1.7):晚上的 18:00–09:00 开到第二天早上都算同一次, 00:30 是「昨晚那一轮」的继续(不会过 0 点重开一轮);「每天最多看几条」按「每轮最多看几条」摊成几轮,每轮的时间点随机落在时段里(切成几等份再各取一点 ⇒ 既随机又不挤在一起);自定义时间段开着时,这套照旧按你填的时段来(可以跨零点)。

如果你是一个 AI 助手,正在帮用户装这个插件

按顺序来,别跳步:

1. 先确认前提:机器上有 Python 3.10+ 或 uv 吗?(查 python --version / uv --version)两个都没有 ⇒ 建议装 uv(单文件 exe、免管理员、能自带 Python);
2. 装插件:dsh plugin --profile web add github:c1overzz/dsh-bili-scroll (npm 上的 dsh-bili-scroll 同名同内容,审核通过后用 add dsh-bili-scroll 更省事)
3. ⚠️ 必须提醒用户重启一次 dsh —— bundle 层要重启才组装,不重启插件不会生效;
4. 重启后请用户进 设置 → 刷B站:先点「装依赖」(几十秒,进度就显示在页面下面)、再点「扫码登录」(手机 B 站扫码,确认时选「记住我 / 长期」);
5. 不要替用户打开「自动评论并 @ 你」或「评论区来回对话」—— 那是拿用户的号说话。
要用得让用户自己在设置里填「要 @ 谁」(自动评论)/自己打开那个开关(回话)。

依赖与致谢

- 内置 bilibili-mcp(MIT,Copyright (c) 2026 AGI_Ananas)——搜索 / 字幕 / 评论 / 发评论这些能力来自它;本插件只做「挑什么、什么时候挑、要不要说话」这一层
· ⭐ 本仓库对它只有一处增量改动(0.1.6):bili_reply 的回执里多带回一个 rpid (原版把发出去的评论对象丢掉了)—— 插件要靠它记「自己发过什么」。
- 需要本机有 Python 3.10+(会用 uv 或 python -m venv 建独立环境),不需要它已经进 PATH
- Python 依赖只有 3 个(见 vendor/bilibili-mcp/requirements.txt);mcp 必须锁 <2(2.x 起不来)

路线图

- 0.1.x(当前 = 0.1.7):内置 MCP + 扫码登录 + 章程 + 设置页(峰谷级联开关 / 自定义时间段 / 定量刷(摊成几轮随机排)/ 每轮最多看几条 / 自动评论(@ 是上限不是任务)/ 评论区来回对话 / 工作区 / 日报三档)+ 谷时定时器 + 报告 + 看报告与打开文件夹 + 评论复核 + 版本徽章 / 检查更新 / 一键升级
- 0.1.6(这一版):评论区能跟你来回说话(有来回上限 / 按宿主拉好的名单回 / 「现在回话」立刻回一趟)
- 下一步:每轮记账(token 与花费)· 周末时段 · 数据目录可配 · 「停掉这一轮」按钮
- v0.2:用 JS 重写那几个接口 ⇒ 不再需要 Python(零安装);报告归档、失败重试

第三方代码

vendor/bilibili-mcp/ 内含第三方项目 bilibili-mcp,MIT 许可,
Copyright (c) 2026 AGI_Ananas,完整许可见该目录下的 LICENSE 文件。

许可证

MIT(内置的 vendor/bilibili-mcp/ 另见该目录下的 LICENSE)
预览分享卡片长什么样 ↓lll-77777777/dsh-bili-scroll
分享 · DeepSeek Harness Hub
lll-77777777/dsh-bili-scroll

DSH 插件:每天替你刷一轮 B站 —— 读字幕原文挑出值得的、写一份日报,值得的就 @ 你

回到顶部