- sites/spiders: Haidan/HDDolby/RousiPro/SunnyPT/TNode/TorrentLeech/Yema (+mTorrent wrapper), specialized SiteAdapter, indirect download resolved at download time - sites/user-parsers: SiteParserBase + all 20 MP SiteSchema parsers (lxml XPath via xpath+xmldom), refreshSiteUserData with schema fallback - sites/definitions: zod SiteDefinition schemas, 23 MovieClaw v0.27.0 (MIT) definitions via scripts/mp-sync/movieclaw-import.mjs, registry getSiteDefinition/listSiteDefinitions, NOTICE - scripts/mp-sync: ledger.json (upstream sha256), check.mjs, build-ledger.mjs; docs/porting/mp-sync-ledger.md - license-and-provenance: add copied-mit kind, re-anchor MovieClaw rows to v0.27.0 Co-Authored-By: Claude Opus 5.5 <[email protected]>
51 lines
1.7 KiB
TypeScript
51 lines
1.7 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { createSiteRateLimiter } from "./rate-limit.ts";
|
|
import { parseSizeMp as parseSize } from "./spider/spider.ts";
|
|
import { parseCount, parseSiteTime } from "./util.ts";
|
|
|
|
describe("站点令牌桶", () => {
|
|
it("burst 内不等待,之后按间隔补充;penalize 顺延;并发按顺序排队", async () => {
|
|
let clock = 0;
|
|
const sleeps: number[] = [];
|
|
const l = createSiteRateLimiter({
|
|
minIntervalMs: 1000,
|
|
burst: 2,
|
|
now: () => clock,
|
|
sleep: async (ms) => {
|
|
sleeps.push(ms);
|
|
clock += ms;
|
|
},
|
|
});
|
|
await Promise.all([l.acquire(), l.acquire(), l.acquire()]);
|
|
expect(sleeps).toEqual([1000]);
|
|
l.penalize(5000);
|
|
expect(l.tryAcquire()).toBe(false);
|
|
await l.acquire();
|
|
expect(sleeps.at(-1)).toBe(5000);
|
|
});
|
|
|
|
it("取消等待", async () => {
|
|
const l = createSiteRateLimiter({ minIntervalMs: 60_000 });
|
|
await l.acquire();
|
|
const ac = new AbortController();
|
|
const p = l.acquire(ac.signal);
|
|
ac.abort(new Error("cancelled"));
|
|
await expect(p).rejects.toThrow("cancelled");
|
|
});
|
|
});
|
|
|
|
describe("解析辅助", () => {
|
|
it("parseSize/parseCount/parseSiteTime", () => {
|
|
expect(parseSize("78.42 GB")).toBe(84202833838);
|
|
expect(parseSize("850 KB")).toBe(870400);
|
|
expect(parseSize("n/a")).toBe(0);
|
|
expect(parseSize("1,234.56 MiB")).toBe(1294529987);
|
|
expect(parseSize("2.1 TB")).toBe(2308974418330);
|
|
expect(parseCount("1,204")).toBe(1204);
|
|
expect(parseCount("532 / 3")).toBe(532);
|
|
expect(parseCount("--")).toBeNull();
|
|
expect(parseSiteTime("2026-09-26 21:14:03", "+08:00")).toBe("2026-09-26T13:14:03.000Z");
|
|
expect(parseSiteTime("3小时前", "+08:00")).toBeNull();
|
|
});
|
|
});
|