Files
dsh-acfun/README.zh.md
T
tamakyi 97825f020d feat: QR login, AcFun settings panel, and 动态 (moment) tools
- scan.acfun.cn QR flow (start -> long-poll scanResult -> acceptResult) with
  rotated-signature handling, background poller, durable session in the Host
  credential service, and cookie handoff to the provider
- Client half: Settings -> AcFun page (status, QR code, poll, logout) over a
  same-origin /acfun-panel JSON API with cross-origin rejection
- acfun_moment / acfun_moment_comments / acfun_topic read tools, moment_like /
  moment_unlike / moment_banana actions, and comment posting on moments
- acfun_account status tool; docs for the QR contract, the 广场/动态 research
  verdict, and the client-composition restart requirement
2026-10-27 11:50:44 +08:00

148 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# dsh-plugin-acfun
给 **DeepSeek Harness** 用的 **AcFun(A站)** 插件:搜索视频、读取视频详情、
评论、弹幕、日/周排行榜、播放地址和**动态(moment)**;可在
**“设置 → AcFun”里扫码登录**;开启写操作后可用自己的账号点赞、投蕉、收藏、
关注、评论(含动态)。
## 工具
| 工具 | 类型 | 作用 |
| --- | --- | --- |
| `acfun_search` | 读 | 关键词搜索视频;`sort: "views"` 按播放量(A 站只返回固定第一页 30 条)。 |
| `acfun_video` | 读 | 单个视频完整信息:UP 主、分区、标签、播放/点赞/收藏/投蕉/评论/弹幕数、发布时间、封面。 |
| `acfun_comments` | 读 | 视频评论(按楼层序)的一页。 |
| `acfun_danmaku` | 读 | 视频弹幕一批,按视频内时间排序,支持 `cursor` 翻页。 |
| `acfun_rank` | 读 | 日榜 / 周榜,`channelId: 0` 为全站。 |
| `acfun_playurl` | 读 | m3u8 清晰度列表(1080P+ / 1080P / 720P / 540P / 360P)。 |
| `acfun_moment` | 读 | 按 id 读取一条动态:正文、话题、图片、作者、计数、官方分享链接。 |
| `acfun_moment_comments` | 读 | 动态评论区一页(动态使用独立的评论枚举)。 |
| `acfun_topic` | 读 | 社区圈话题页(尽力解析,最多 15 条)——目前唯一可公开发现动态 id 的入口。 |
| `acfun_interact` | 写 | 视频:`like`、`unlike`、`banana`、`favorite`、`unfavorite`、`follow`、`unfollow`;动态:`moment_like`、`moment_unlike`、`moment_banana`。 |
| `acfun_post_comment` | 写 | 给视频(`acId`)或动态(`momentId`)发表评论或回复。 |
| `acfun_account` | 读 | 登录状态、凭据来源、写操作是否开启、下一步操作提示。 |
插件还附带面向模型的技能文件 `skills/plugin-tool-acfun/SKILL.md`,说明调用顺序、
写操作安全规则和动态相关限制。
## 安装
把工作区目录作为 bundle 安装:
```
plugin_manager action=install_bundle target=C:\path\to\dsh-acfun
```
插件会插入两行:`acfun`(工具、面板接口、扫码登录)与
`acfun-skill-filesystem`(把本包的 `skills/` 暴露给 Agent)。本地目录是链接
安装,修改插件代码后需要重启 Harness 才能加载新的模块实例。
卸载:`plugin_manager action=remove_bundle target=dsh-plugin-acfun`。
## 扫码登录与 Web UI 面板
插件自带 Client 半(`client.js`),在 **设置 → AcFun** 增加一页:显示登录状态、
凭据来源、写操作是否开启,渲染二维码并轮询直到手机确认。
流程全部在 Host 侧(`lib/qr-flow.js`):
1. `GET https://scan.acfun.cn/rest/pc-direct/qr/start?type=WEB_LOGIN` 返回 base64
PNG 以及 `qrLoginToken`、`qrLoginSignature`、`expireTime`(120 秒)。
2. `scanResult` 是 A 站保持的一次长轮询,直到手机扫码或二维码过期;扫码成功时
返回**轮换后的新签名**。
3. 用新签名调用 `acceptResult`,A 站通过 `Set-Cookie` 下发会话;插件捕获 Cookie,
经 Host 凭据服务持久化为 `acfun-session` 记录,并把 provider 切到该会话。
面板通过同源 `/acfun-panel/*` JSON 接口访问 Host,跨源请求会被拒绝。扫码确认这
一步插件无法自行验证,只有真实手机扫码才会走到确认分支。
**需要重启一次:** 如果某个包在 Host 已经扫描过之后才新增 Client 半,则需要重启
一次 Harness,再刷新页面,**设置 → AcFun** 才会出现(Boot 图是在启动时按当时的
Loader 条目组合的)。可用 `GET /acfun-panel/state` 的 `client.path`(必须非空)或
`GET /acfun-panel/diagnose` 判断,细节与证据见
[`docs/client-panel.md`](docs/client-panel.md)。
## 配置
配置位于 `cordis.patch.yml` 的 `acfun` 行,所有键都可省略。
| 键 | 默认值 | 含义 |
| --- | --- | --- |
| `cookie` | `''` | 完整的 AcFun `Cookie` 请求头。推荐用环境变量,避免密钥写进 patch。 |
| `cookieEnv` | `ACFUN_COOKIE` | `cookie` 为空时读取的环境变量名。 |
| `allowWriteActions` | `false` | `acfun_interact` / `acfun_post_comment` 的总开关。 |
| `requestTimeoutMs` | `30000` | 单次 HTTP 请求超时。 |
| `timeoutMs` | `45000` | 单次工具调用的协作式预算(写操作至少 60 秒)。 |
面板扫码得到的 Cookie 以凭据记录保存,优先于 `cookie`/`ACFUN_COOKIE`;在面板退出
登录后回退到配置值。
### 不用面板时手动获取 Cookie
1. 在桌面浏览器登录 <https://www.acfun.cn/>。
2. 打开开发者工具 → Network,刷新任意 acfun.cn 页面,复制文档请求的完整
`Cookie` 请求头(包含 `auth_key`、`acPasstoken`、`_did` 等)。
3. 粘贴到 `cookie` 或 `ACFUN_COOKIE`。
这串 Cookie 等同于账号密码,插件不会写进日志。
## 安全设计
- 读取类工具不会修改任何内容,也不需要 Cookie。
- 写操作必须同时具备 `allowWriteActions: true` 与登录状态;只满足其一时返回
`WRITE_DISABLED` / `LOGIN_REQUIRED`,不会发出写请求。
- 写工具声明为非并发安全,Harness 不会并行执行两个账号操作。
- AcFun 返回人机验证要求(`result` 400001–410999)时报告 `CAPTCHA_REQUIRED`,
绝不尝试绕过。
## 验证情况
2026-10-27 对 acfun.cn 实测(匿名):
- 九个读取工具(`acfun_search` 含 `sort: "views"`、`acfun_video`、
`acfun_comments`、`acfun_danmaku`、`acfun_rank`、`acfun_playurl`、
`acfun_moment`、`acfun_moment_comments`、`acfun_topic`)返回真实数据并通过
输出 schema 校验与渲染(`node scripts/live-check.mjs`)。
- 扫码登录的二维码下发、等待与中止路径已实测(真实 ticket + PNG;未扫码时保持长
轮询到 120 秒过期,然后报告 expired)。
- 十二个工具通过模拟 Cordis 上下文注册,面板接口在本地 HTTP 服务器上验证
(含跨源拒绝、登出),写操作守卫正确失败关闭
(`node scripts/self-check.mjs`)。
- 写接口路由存在,匿名调用返回 `{"result":-401}`;但**未**验证登录后的成功路径
(包括扫码最后一步和动态写操作),因为本次没有可用账号。首次使用时请以 A 站
页面上的实际结果为准,不要在结果不明时重复调用。
## 已知限制
- A 站的 pc-direct 搜索接口忽略 `page`/`pageSize`,永远只返回第一页 30 条;只有
`sort` 有效。
- 不支持番剧(bangumi)与文章页面——`acfun_video` 会返回
`UNSUPPORTED_RESOURCE`。
- **没有公开的“广场”列表接口。** 约 560 条路径探测后,各站点都没有公开的
广场/推荐动态列表;动态 id 只能通过 `acfun_topic`(SSR 页面,最多 15 条,无分页)
或分享链接获得,动态列表类接口都需要登录。
- 发布、删除、转发、投票动态只能在 App 内完成(需要签名 token),Web 插件做不了。
- 动态的点赞/投蕉/评论契约来自站点自身代码,只验证到 `401` 未登录,属于实验性
功能。
- 弹幕翻页依赖 A 站不透明的 `pcursor`,通过 `cursor`/`nextCursor` 透传。
- 播放地址是带签名的临时 m3u8,过期需重新调用;下载/合并流媒体不在范围内。
- 插件只调用 acfun.cn 的公开 Web 接口,属于非官方实现,A 站改版后可能失效。
## 开发
```
node scripts/self-check.mjs # 离线:导出、工具 schema、扫码状态机、面板 HTTP
node scripts/live-check.mjs # 在线:真实读取、二维码下发、schema 校验与渲染
```
无构建步骤、无运行时依赖。`lib/` 与 `client.js` 都是只依赖 Node/浏览器内置能力的
纯 JS。插件故意不导出 `Config` schema:工作区链接安装的 bundle 无法解析
`@deepseek-ai/*` 包,所以由 `lib/config.js` 校验配置并带告警地回退默认值。
接口笔记:`docs/acfun-api.md`(视频/评论/弹幕/排行)、`docs/acfun-login.md`
(扫码登录)、`docs/acfun-moment.md`(广场/动态调研与结论)。
## 许可证
MIT,见 `LICENSE`。