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

8.0 KiB
Raw Blame History

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。

配置

配置位于 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;在面板退出 登录后回退到配置值。

  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。