npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mr-quin/dango-manifests

v0.6.0

Published

Built-in dango manifests for danmaku sources

Downloads

149

Readme

@mr-quin/dango-manifests

Built-in dango manifests for a curated set of danmaku sources. Each manifest is a JSON file declaring the search/episodes/danmaku pipelines a @mr-quin/dango ManifestRunner interprets at runtime, with no per-source TypeScript fetching code.

This package is data, not code. There is no index.ts: consumers import each manifest JSON directly via the ./manifests/* subpath export.

Shipped manifests

| Id | Endpoint | Notes | | ------------ | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | dandanplay | baseUrl (default api.dandanplay.net) | Unified DDP source. Default official; optional appId/appSecret signing, auth headers, or none (proxy). baseUrl overrides the endpoint (proxy / self-hosted). | | bilibili | api.bilibili.com | Parallel media_bangumi + media_ft search; xml + protobuf danmaku variants. | | tencent | pbaccess.video.qq.com + dm.video.qq.com | POST bodies, page-cursor episode pagination via forEach breakOn, two-phase danmaku (segment index then per-segment fetch). | | hanjutv | hxqapi.hiyun.tv + hxqapi.zmdcq.com | Korean-drama source; search, detail-driven episodes, per-segment danmaku. | | mango | *.mgtv.com + *.hitv.com | Mango TV; source=imgo search, two-stage showlist episodes, per-minute CDN danmaku shards. | | migu | *.migu.cn + *.miguvideo.com | Migu Video; content-info lookup, episodes list, segmented danmaku. | | youku | *.youku.com + log.mmstat.com | Youku; HTML-stripped search, openapi episodes, signed per-minute danmaku POSTs (cna guid + _m_h5_tk token). | | iqiyi | *.iqiyi.com + mesh.if.iqiyi.com | iQIYI; /v_ watch-page search, signed base_info episodes, zlib-deflated XML bullet shards. | | aiyifan | yfsp.tv + rankv21.tripdata.app | Aiyifan; homepage-scraped pub/priv keys sign each JSON request; getBarrage danmaku. | | bahamut | api.gamer.com.tw | Bahamut Anime (Traditional Chinese); single danmu.php fetch, time in tenths of a second. | | maiduidui | mob.mddcloud.com.cn | Maiduidui; nested search, listVodSactions episodes, per-minute vodBarrage shards. | | renren | api.gorafie.com + static-dm.qwdjapp.com | Renren (foreign drama); array-rooted danmaku with CSV p strings. | | sohu | *.sohu.com | Sohu TV; site=1 search, album episodes, paginated dmListAll danmaku (decimal/hex color handling). |

Layout

src/
  manifests/
    aiyifan.json
    bahamut.json
    bilibili.json
    dandanplay.json
    hanjutv.json
    iqiyi.json
    maiduidui.json
    mango.json
    migu.json
    renren.json
    sohu.json
    tencent.json
    youku.json
  __tests__/
    *.test.ts                           # per-manifest pipeline tests
    fixtures/                           # captured representative responses
    mockFetcher.ts                      # shared test fetcher (string + Uint8Array bodies)
scripts/
  smoke-test.ts                         # manual end-to-end test against the real API

Usage

import { ManifestRunner, zManifest } from '@mr-quin/dango'
import builtinDandanplay from '@mr-quin/dango-manifests/manifests/dandanplay.json' with { type: 'json' }

const manifest = zManifest.parse(builtinDandanplay)
const runner = new ManifestRunner(manifest, { fetcher })

const results = await runner.runSearch({ q: 'frieren' })
const episodes = await runner.runEpisodes({
  bangumiId: results[0].providerIds.bangumiId,
})
const danmaku = await runner.runDanmaku({
  episodeId: episodes[0].providerIds.episodeId,
})

CDN consumption

A host can discover and fetch manifests over a CDN without bundling this package at build time. jsDelivr and unpkg serve the published package files, so a host reads catalog.json for the index, then fetches each entry's file path.

https://cdn.jsdelivr.net/npm/@mr-quin/dango-manifests@<version>/catalog.json
https://cdn.jsdelivr.net/npm/@mr-quin/dango-manifests@<version>/<file>

catalog.json is generated from the manifests on disk and ships with the package:

{
  "packageVersion": "0.4.0",
  "manifests": [
    {
      "id": "bilibili",
      "name": "Bilibili",
      "version": "0.4.0",
      "apiVersion": 1,
      "file": "src/manifests/bilibili.json",
    },
    // ...
  ],
}

Each file is the in-package path to fetch, e.g.:

https://cdn.jsdelivr.net/npm/@mr-quin/[email protected]/src/manifests/bilibili.json

unpkg works the same way (https://unpkg.com/@mr-quin/dango-manifests@<version>/...). Pin a <version> for reproducibility; omit it to track the latest published release.

catalog.json is regenerated as part of bun run build; bun run check fails if the committed copy is stale (run bun run catalog and commit the result).

Routing notes

DanDanPlay (dandanplay) is one manifest for every DDP endpoint over the /api/v2 paths. baseUrl (config) defaults to the official api.dandanplay.net; point it at a proxy or self-hosted server to override. Auth is picked by config: appId + appSecret sign each request (X-Signature: Base64(SHA256(appId + timestamp + path + appSecret)), secret never sent); else auth.enabled + auth.headers attach custom headers; else no auth (for a proxy that signs server-side). The official API is just the case with no baseUrl and credentials set.

Bilibili and Tencent call their public APIs directly. Both rely on rewriteHeaders for Origin / Referer, which a browser host's FetchLike applies via a request-header rewrite mechanism such as chrome.declarativeNetRequest. The smoke script merges those headers in directly since Node fetch lets you set them.

Smoke testing

bun run smoke <source> [keyword] walks search → first result → episodes → first episode → danmaku against the real API. Not in CI; useful when adding a manifest or verifying after an upstream change.

| Source | Command | Status | | -------- | ------------------------------- | -------------------------------------------------------- | | ddp | bun run smoke ddp Frieren | needs DDP_APP_ID / DDP_APP_SECRET env (official API) | | bilibili | bun run smoke bilibili Naruto | works (after a cookie warm-up via www.bilibili.com) | | tencent | bun run smoke tencent 庆余年 | works |

The smoke fetcher keeps a per-host cookie jar so bilibili's anti-bot wall lets us through, and it merges rewriteHeaders into the outgoing request (Node has no Origin/Referer restriction). The default ddp smoke hits the official API and needs DDP_APP_ID / DDP_APP_SECRET.

Adding a new manifest

  1. Drop the JSON file in src/manifests/. Use id: '<source>'.
  2. Capture representative responses from the source's API to src/__tests__/fixtures/.
  3. Write a per-manifest test that:
    • Parses the manifest against zManifest (catches schema drift)
    • Runs each pipeline with a mocked FetchLike against the captured fixtures
    • Asserts the canonical shape the engine emits
  4. (Optional) Add a section to scripts/smoke-test.ts to exercise the new manifest against a live endpoint.

Each manifest's tests own their own fixtures, don't share fixtures across manifests.

Trust model

Manifests in this package are vetted at PR review time and shipped as built-ins. They are not user-installable. User-installed manifests are a separate concern a host may add with explicit consent UX. See dango's trust model for the engine-level invariants that apply regardless of where a manifest comes from.

Scripts

| Command | Description | | ------------------------ | -------------------------------------------------------------- | | bun test | bun test, fixture-backed pipeline tests | | bun run smoke <source> | Live end-to-end test against the real API (manual, not CI) | | bun run type-check | tsc --noEmit | | bun run catalog | Regenerate catalog.json from the manifests on disk | | bun run catalog:check | Fail if the committed catalog.json is stale |