# dsh-plugin-acfun DeepSeek Harness plugin for **AcFun (A站, acfun.cn)**: search videos, read video metadata, comment threads, danmaku (弹幕), the day/week ranking and playable stream URLs, and — only when you opt in — interact with your own account (like, tip bananas, favorite, follow, post comments). This is the AcFun counterpart of the community Bilibili tool plugins. Reads are anonymous and work out of the box; every mutating call is gated behind `allowWriteActions: true` **and** an AcFun login cookie, so installing the bundle never silently gives the model write access to an account. ## Tools | Tool | Kind | What it does | | --- | --- | --- | | `acfun_search` | read | Keyword video search; `sort: "views"` orders by play count (AcFun returns one fixed first page of up to 30). | | `acfun_video` | read | Full metadata for one video: author, channel, tags, stats, publish time, cover. | | `acfun_comments` | read | One page of a video's comment thread, in floor order. | | `acfun_danmaku` | read | One batch of a video's 弹幕, ordered by in-video position, with cursor paging. | | `acfun_rank` | read | Day or week ranking, all channels or one `channelId`. | | `acfun_playurl` | read | m3u8 quality ladder (1080P+ / 1080P / 720P / 540P / 360P). | | `acfun_interact` | write | `like`, `unlike`, `banana`, `favorite`, `unfavorite`, `follow`, `unfollow`. | | `acfun_post_comment` | write | Post a top-level comment or a reply. | A model-facing skill (`skills/plugin-tool-acfun/SKILL.md`) teaches the tool sequence and the write-safety rules. ## Install Install the workspace directory as a profile bundle: ``` plugin_manager action=install_bundle target=C:\path\to\dsh-acfun ``` The bundle inserts one Loader row (`id: acfun`) with the config below. A local directory is linked, so edits to the plugin need a Harness restart to load a fresh module generation. To remove it, use `plugin_manager action=remove_bundle target=dsh-plugin-acfun`. ## Configuration The row config lives in `cordis.patch.yml`; every key is optional. | Key | Default | Meaning | | --- | --- | --- | | `cookie` | `''` | Full AcFun `Cookie` header value. Prefer the environment variable so the secret does not enter the patch. | | `cookieEnv` | `ACFUN_COOKIE` | Environment variable read when `cookie` is empty. | | `allowWriteActions` | `false` | Master switch for `acfun_interact` and `acfun_post_comment`. | | `requestTimeoutMs` | `30000` | Per-HTTP-request timeout. | | `timeoutMs` | `45000` | Cooperative per-tool-call budget (write calls use at least 60 s). | Example with the environment variable: ```powershell $env:ACFUN_COOKIE = 'auth_key=...; acPasstoken=...; _did=...' ``` ### Getting the cookie 1. Sign in to in a desktop browser. 2. Open DevTools → Network, reload any acfun.cn page, and copy the complete `Cookie` request header of the document request (it contains `auth_key`, `acPasstoken`, `_did`, and other session values). 3. Paste it as one line into `cookie` or `ACFUN_COOKIE`. Treat that string like a password: it grants full access to the account. The plugin never logs it. ## Safety model - Reads cannot mutate anything and need no cookie. - Writes require both `allowWriteActions: true` and a cookie. With only one of them the tools return `WRITE_DISABLED` / `LOGIN_REQUIRED` and perform no HTTP write request. - Write tools are declared non-concurrency-safe so the harness will not run two account mutations in parallel. - A CAPTCHA/identity-verification challenge from AcFun (`result` 400001–410999) is surfaced as `CAPTCHA_REQUIRED`; the plugin never tries to solve it. ## Verification status Verified live on 2026-10-27 against acfun.cn (anonymous): - All six read tools — `acfun_search` (including `sort: "views"`), `acfun_video`, `acfun_comments`, `acfun_danmaku`, `acfun_rank`, `acfun_playurl` — return real API data and pass output-schema validation plus rendering (`node scripts/live-check.mjs`). - All eight tools register through a mock Cordis context and the write guard fails closed (`node scripts/self-check.mjs`). - Write routes exist and reject anonymous requests with `{"result":-401}`. The authenticated happy path was **not** exercised here because no AcFun account/cookie was available. Treat first use as a live test: check the result in the AcFun UI instead of retrying blindly. ## Known limitations - AcFun's pc-direct search endpoint ignores `page`/`pageSize` and always returns its first page (30 entries), so `acfun_search` cannot paginate. `sort` is the only ordering control AcFun honours. - Bangumi (番剧) and article pages are not supported — `acfun_video` reports `UNSUPPORTED_RESOURCE` instead of guessing. - Danmaku paging beyond the first batch depends on AcFun's opaque `pcursor`; `acfun_danmaku` passes it through as `cursor`/`nextCursor`. - Play URLs are time-limited signed m3u8 links; re-run `acfun_playurl` when one expires. Downloading/merging streams is out of scope. - This plugin only talks to acfun.cn's public web endpoints; it is unofficial and can break when AcFun changes them. ## Development ``` node scripts/self-check.mjs # offline: exports, tool schemas, write guard node scripts/live-check.mjs # online: real reads + schema validation + render ``` No build step, no runtime dependencies. Everything under `lib/` is plain ESM that imports only Node built-ins/globals. The bundle intentionally exports no `Config` schema: a workspace-linked bundle cannot resolve `@deepseek-ai/*` packages, so `lib/config.js` validates the row config and falls back to defaults with warnings instead of using schemastery. See `docs/acfun-api.md` for the endpoint notes this plugin is based on. ## License MIT — see `LICENSE`.