- 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
148 lines
8.0 KiB
Markdown
148 lines
8.0 KiB
Markdown
# 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`。
|