Cai
3 days ago c3cb8625712050247ccf17b4f60238304e1faf26
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import assert from "node:assert/strict";
import cryptoModule from "node:crypto";
import {pathToFileURL} from "node:url";
 
const protocol = await import(pathToFileURL(process.argv[2]));
const extractor = await import(pathToFileURL(process.argv[3]));
 
function stable(value) {
  if (Array.isArray(value)) return value.map(stable);
  if (value && typeof value === "object") return Object.fromEntries(Object.keys(value).sort().map((key) => [key, stable(value[key])]));
  return value;
}
function canonical(value) { return JSON.stringify(stable(value)); }
function signed(secret, value) {
  return {...value, hmac: cryptoModule.createHmac("sha256", Buffer.from(secret, "hex")).update(canonical(value)).digest("hex")};
}
 
const calls = {prepare: 0, dispatch: 0, observe: 0};
const api = {
  async prepare(action) { calls.prepare += 1; return {...action, tab_id: 7}; },
  async dispatch(prepared) { calls.dispatch += 1; return {action_id: prepared.action_id, tab_id: 7, url: prepared.url}; },
  async observe(result) { calls.observe += 1; return {schema_version: 1, final_url: result.url}; }
};
const hello = {extension_id: "gllihoanalkiollgpeggamfhajmmnmml", version: "1.0.0", manifest_name: "project-info Bilibili dynamic refresh trusted adapter"};
const session = new protocol.TrustedRuntimeSession(api, hello);
assert.equal(session.helloFrame().type, "EXTENSION_HELLO");
const secret = "11".repeat(32);
const challenge = signed(secret, {schema_version: 1, type: "HOST_CHALLENGE", run_id: "run", request_id: "request", sequence: 2, challenge_id: "challenge", secret});
const accepted = await session.accept(challenge);
assert.equal(accepted.type, "EXTENSION_CHALLENGE_ACCEPTED");
const prepare = signed(secret, {schema_version: 1, type: "HOST_ACTION_PREPARE", run_id: "run", request_id: "request", sequence: 4, action: {action_id: "action", kind: "reload", url: "https://space.bilibili.com/1420210197/dynamic"}});
const ready = await session.accept(prepare);
assert.equal(ready.type, "EXTENSION_READY_TO_DISPATCH");
assert.deepEqual(calls, {prepare: 1, dispatch: 0, observe: 0});
const permit = signed(secret, {schema_version: 1, type: "HOST_DISPATCH_PERMIT", run_id: "run", request_id: "request", sequence: 6, permit: {permit_id: "permit", action_id: "action", deadline_at: "2999-01-01T00:00:00Z"}});
const action = await session.accept(permit);
assert.equal(action.type, "EXTENSION_ACTION_RESULT");
assert.deepEqual(calls, {prepare: 1, dispatch: 1, observe: 0});
await assert.rejects(session.accept(permit), /E_SEQUENCE|E_PERMIT|E_REPLAY/u);
assert.deepEqual(calls, {prepare: 1, dispatch: 1, observe: 0});
const request = signed(secret, {schema_version: 1, type: "HOST_OBSERVATION_REQUEST", run_id: "run", request_id: "request", sequence: 8, action_id: "action"});
const observation = await session.accept(request);
assert.equal(observation.type, "EXTENSION_OBSERVATION");
assert.deepEqual(calls, {prepare: 1, dispatch: 1, observe: 1});
 
const target = "https://space.bilibili.com/1420210197/dynamic";
const normalized = extractor.canonicalizeSnapshot({
  final_url: "https://space.bilibili.com/1420210197/dynamic#x",
  page_title: " title ", ready_state: "complete", visibility_state: "visible",
  creator: {uid: "1420210197", name: "青枫浦上Q", profile_url: "https://space.bilibili.com/1420210197"},
  cards: [{dynamic_id: "123", published_at: "2026-08-14T00:00:00+08:00", text: " hello  world ", url: "https://space.bilibili.com/1420210197/dynamic/123"}],
  unparsed_nodes: 0, terminal_marker_text: "已经到底了"
}, target);
assert.equal(normalized.cards[0].text, "hello world");
assert.equal(normalized.coverage_complete, true);
await assert.rejects(async () => extractor.canonicalizeSnapshot({...normalized, cards: [normalized.cards[0], normalized.cards[0]]}, target), /E_CARD_DUPLICATE/u);
console.log(JSON.stringify({ok: true, calls, normalized_id: normalized.cards[0].dynamic_id}));