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
This commit is contained in:
+79
-47
@@ -1,28 +1,29 @@
|
||||
# dsh-plugin-acfun
|
||||
|
||||
给 **DeepSeek Harness** 用的 **AcFun(A站)** 插件:搜索视频、读取视频详情、
|
||||
评论、弹幕、日/周排行榜和可播放的 m3u8 地址;只有在你主动开启后,才能用自己
|
||||
的账号进行互动(点赞、投蕉、收藏、关注、发评论)。
|
||||
|
||||
这是社区 B 站工具插件在 A 站上的对应实现。读取类工具默认匿名可用;所有写操作
|
||||
必须同时满足 `allowWriteActions: true` **和** AcFun 登录 Cookie,因此装好插件
|
||||
并不会悄悄把账号的写权限交给模型。
|
||||
评论、弹幕、日/周排行榜、播放地址和**动态(moment)**;可在
|
||||
**“设置 → AcFun”里扫码登录**;开启写操作后可用自己的账号点赞、投蕉、收藏、
|
||||
关注、评论(含动态)。
|
||||
|
||||
## 工具
|
||||
|
||||
| 工具 | 类型 | 作用 |
|
||||
| --- | --- | --- |
|
||||
| `acfun_search` | 读 | 关键词搜索视频;`sort: "views"` 按播放量排序(A 站只返回固定第一页,最多 30 条)。 |
|
||||
| `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_interact` | 写 | `like`、`unlike`、`banana`(投蕉)、`favorite`、`unfavorite`、`follow`、`unfollow`。 |
|
||||
| `acfun_post_comment` | 写 | 发表评论或回复某条评论。 |
|
||||
| `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`,说明工具
|
||||
调用顺序和写操作的安全规则。
|
||||
插件还附带面向模型的技能文件 `skills/plugin-tool-acfun/SKILL.md`,说明调用顺序、
|
||||
写操作安全规则和动态相关限制。
|
||||
|
||||
## 安装
|
||||
|
||||
@@ -32,11 +33,35 @@
|
||||
plugin_manager action=install_bundle target=C:\path\to\dsh-acfun
|
||||
```
|
||||
|
||||
插件会向 Loader 插入一行(`id: acfun`)。本地目录是链接安装,修改插件代码后
|
||||
需要重启 Harness 才能加载新的模块实例。
|
||||
插件会插入两行:`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` 行,所有键都可省略。
|
||||
@@ -49,66 +74,73 @@ plugin_manager action=install_bundle target=C:\path\to\dsh-acfun
|
||||
| `requestTimeoutMs` | `30000` | 单次 HTTP 请求超时。 |
|
||||
| `timeoutMs` | `45000` | 单次工具调用的协作式预算(写操作至少 60 秒)。 |
|
||||
|
||||
使用环境变量的例子:
|
||||
面板扫码得到的 Cookie 以凭据记录保存,优先于 `cookie`/`ACFUN_COOKIE`;在面板退出
|
||||
登录后回退到配置值。
|
||||
|
||||
```powershell
|
||||
$env:ACFUN_COOKIE = 'auth_key=...; acPasstoken=...; _did=...'
|
||||
```
|
||||
|
||||
### 获取 Cookie
|
||||
### 不用面板时手动获取 Cookie
|
||||
|
||||
1. 在桌面浏览器登录 <https://www.acfun.cn/>。
|
||||
2. 打开开发者工具 → Network,刷新任意 acfun.cn 页面,复制文档请求的完整
|
||||
`Cookie` 请求头(包含 `auth_key`、`acPasstoken`、`_did` 等会话值)。
|
||||
3. 把整行粘贴到 `cookie` 或 `ACFUN_COOKIE`。
|
||||
`Cookie` 请求头(包含 `auth_key`、`acPasstoken`、`_did` 等)。
|
||||
3. 粘贴到 `cookie` 或 `ACFUN_COOKIE`。
|
||||
|
||||
这串 Cookie 等同于账号密码,插件不会把它写进日志。
|
||||
这串 Cookie 等同于账号密码,插件不会写进日志。
|
||||
|
||||
## 安全设计
|
||||
|
||||
- 读取类工具不会修改任何内容,也不需要 Cookie。
|
||||
- 写操作必须同时具备 `allowWriteActions: true` 与 Cookie;只满足其一时工具会
|
||||
返回 `WRITE_DISABLED` / `LOGIN_REQUIRED`,并且不会发出任何写请求。
|
||||
- 写操作必须同时具备 `allowWriteActions: true` 与登录状态;只满足其一时返回
|
||||
`WRITE_DISABLED` / `LOGIN_REQUIRED`,不会发出写请求。
|
||||
- 写工具声明为非并发安全,Harness 不会并行执行两个账号操作。
|
||||
- AcFun 返回人机验证/身份验证要求(`result` 400001–410999)时,插件以
|
||||
`CAPTCHA_REQUIRED` 报告,绝不尝试绕过验证码。
|
||||
- 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`)都返回真实
|
||||
数据,并通过输出 schema 校验与渲染(`node scripts/live-check.mjs`)。
|
||||
- 八个工具通过模拟 Cordis 上下文完成注册,写操作守卫正确失败关闭
|
||||
- 九个读取工具(`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}`;但本次没有 AcFun 账号
|
||||
Cookie,**未**验证登录后的成功路径。首次使用时请以 A 站页面上的实际结果为准,
|
||||
不要在结果不明时重复调用。
|
||||
- 写接口路由存在,匿名调用返回 `{"result":-401}`;但**未**验证登录后的成功路径
|
||||
(包括扫码最后一步和动态写操作),因为本次没有可用账号。首次使用时请以 A 站
|
||||
页面上的实际结果为准,不要在结果不明时重复调用。
|
||||
|
||||
## 已知限制
|
||||
|
||||
- A 站的 pc-direct 搜索接口忽略 `page`/`pageSize`,永远只返回第一页 30 条,
|
||||
因此 `acfun_search` 无法翻页;排序只有 `sort` 一个有效参数。
|
||||
- 不支持番剧(bangumi)与文章页面——`acfun_video` 会返回 `UNSUPPORTED_RESOURCE`,
|
||||
不会瞎猜。
|
||||
- 弹幕翻页依赖 A 站不透明的 `pcursor`,插件通过 `cursor`/`nextCursor` 透传。
|
||||
- 播放地址是带签名的临时 m3u8 链接,过期后重新调用 `acfun_playurl`;下载/合并
|
||||
流媒体不在本插件范围内。
|
||||
- 插件只调用 acfun.cn 的公开 Web 接口,属于非官方实现,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、写操作守卫
|
||||
node scripts/live-check.mjs # 在线:真实读取 + schema 校验 + 渲染
|
||||
node scripts/self-check.mjs # 离线:导出、工具 schema、扫码状态机、面板 HTTP
|
||||
node scripts/live-check.mjs # 在线:真实读取、二维码下发、schema 校验与渲染
|
||||
```
|
||||
|
||||
无构建步骤、无运行时依赖。`lib/` 下全部是只依赖 Node 内置能力的纯 ESM。插件
|
||||
故意不导出 `Config` schema:工作区链接安装的 bundle 无法解析 `@deepseek-ai/*`
|
||||
包,所以由 `lib/config.js` 校验配置并带告警地回退到默认值。
|
||||
无构建步骤、无运行时依赖。`lib/` 与 `client.js` 都是只依赖 Node/浏览器内置能力的
|
||||
纯 JS。插件故意不导出 `Config` schema:工作区链接安装的 bundle 无法解析
|
||||
`@deepseek-ai/*` 包,所以由 `lib/config.js` 校验配置并带告警地回退默认值。
|
||||
|
||||
接口逆向笔记见 [docs/acfun-api.md](docs/acfun-api.md)。
|
||||
接口笔记:`docs/acfun-api.md`(视频/评论/弹幕/排行)、`docs/acfun-login.md`
|
||||
(扫码登录)、`docs/acfun-moment.md`(广场/动态调研与结论)。
|
||||
|
||||
## 许可证
|
||||
|
||||
|
||||
Reference in New Issue
Block a user