@qwen-code/arena-agent 0.0.9-dev.26 → 0.0.9-dev.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -33
- package/dist/audit.d.ts +14 -0
- package/dist/audit.js +31 -0
- package/dist/audit.js.map +1 -0
- package/dist/dashscope.d.ts +5 -0
- package/dist/dashscope.js +55 -0
- package/dist/dashscope.js.map +1 -0
- package/dist/fetch-page/aparat.d.ts +30 -0
- package/dist/fetch-page/aparat.js +209 -0
- package/dist/fetch-page/aparat.js.map +1 -0
- package/dist/fetch-page/json-path.d.ts +12 -0
- package/dist/fetch-page/json-path.js +111 -0
- package/dist/fetch-page/json-path.js.map +1 -0
- package/dist/fetch-page/sites.d.ts +26 -0
- package/dist/fetch-page/sites.js +39 -0
- package/dist/fetch-page/sites.js.map +1 -0
- package/dist/fetch-page/text.d.ts +5 -0
- package/dist/fetch-page/text.js +38 -0
- package/dist/fetch-page/text.js.map +1 -0
- package/dist/fetch-page/types.d.ts +17 -0
- package/dist/fetch-page/types.js +3 -0
- package/dist/fetch-page/types.js.map +1 -0
- package/dist/fetch-page/youtube.d.ts +35 -0
- package/dist/fetch-page/youtube.js +282 -0
- package/dist/fetch-page/youtube.js.map +1 -0
- package/dist/provider.js +72 -1
- package/dist/provider.js.map +1 -1
- package/dist/web-search.d.ts +5 -0
- package/dist/web-search.js +465 -0
- package/dist/web-search.js.map +1 -0
- package/package.json +4 -2
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { decodeText } from "./text.js";
|
|
2
|
+
/**
|
|
3
|
+
* Navigation helpers for the undocumented JSON blobs embedded in dynamic site
|
|
4
|
+
* pages. Every accessor is total: a missing or wrongly typed field yields an
|
|
5
|
+
* empty value rather than throwing, because these shapes change without notice.
|
|
6
|
+
*/
|
|
7
|
+
export function jsonObject(bytes, contentType) {
|
|
8
|
+
const value = JSON.parse(decodeText(bytes, contentType));
|
|
9
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
10
|
+
throw new Error("site adapter returned invalid JSON");
|
|
11
|
+
}
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
export function stringField(value, key) {
|
|
15
|
+
const field = value[key];
|
|
16
|
+
return typeof field === "string" || typeof field === "number"
|
|
17
|
+
? String(field)
|
|
18
|
+
: "";
|
|
19
|
+
}
|
|
20
|
+
export function recordValue(value) {
|
|
21
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
22
|
+
? value
|
|
23
|
+
: undefined;
|
|
24
|
+
}
|
|
25
|
+
export function recordArray(value) {
|
|
26
|
+
return Array.isArray(value)
|
|
27
|
+
? value.flatMap((item) => {
|
|
28
|
+
const record = recordValue(item);
|
|
29
|
+
return record ? [record] : [];
|
|
30
|
+
})
|
|
31
|
+
: [];
|
|
32
|
+
}
|
|
33
|
+
export function findNestedValue(value, key) {
|
|
34
|
+
const record = recordValue(value);
|
|
35
|
+
if (!record)
|
|
36
|
+
return undefined;
|
|
37
|
+
if (Object.hasOwn(record, key))
|
|
38
|
+
return record[key];
|
|
39
|
+
for (const child of Object.values(record)) {
|
|
40
|
+
if (Array.isArray(child)) {
|
|
41
|
+
for (const item of child) {
|
|
42
|
+
const found = findNestedValue(item, key);
|
|
43
|
+
if (found !== undefined)
|
|
44
|
+
return found;
|
|
45
|
+
}
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
const found = findNestedValue(child, key);
|
|
49
|
+
if (found !== undefined)
|
|
50
|
+
return found;
|
|
51
|
+
}
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
export function findNestedRecord(value, predicate) {
|
|
55
|
+
const record = recordValue(value);
|
|
56
|
+
if (!record)
|
|
57
|
+
return undefined;
|
|
58
|
+
if (predicate(record))
|
|
59
|
+
return record;
|
|
60
|
+
for (const child of Object.values(record)) {
|
|
61
|
+
if (Array.isArray(child)) {
|
|
62
|
+
for (const item of child) {
|
|
63
|
+
const found = findNestedRecord(item, predicate);
|
|
64
|
+
if (found)
|
|
65
|
+
return found;
|
|
66
|
+
}
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const found = findNestedRecord(child, predicate);
|
|
70
|
+
if (found)
|
|
71
|
+
return found;
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
export function extractAssignedJson(html, marker) {
|
|
76
|
+
const markerIndex = html.indexOf(marker);
|
|
77
|
+
if (markerIndex < 0)
|
|
78
|
+
return undefined;
|
|
79
|
+
const start = html.indexOf("{", markerIndex + marker.length);
|
|
80
|
+
if (start < 0)
|
|
81
|
+
return undefined;
|
|
82
|
+
let depth = 0;
|
|
83
|
+
let inString = false;
|
|
84
|
+
let escaped = false;
|
|
85
|
+
for (let index = start; index < html.length; index += 1) {
|
|
86
|
+
const character = html[index];
|
|
87
|
+
if (inString) {
|
|
88
|
+
if (escaped)
|
|
89
|
+
escaped = false;
|
|
90
|
+
else if (character === "\\")
|
|
91
|
+
escaped = true;
|
|
92
|
+
else if (character === '"')
|
|
93
|
+
inString = false;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (character === '"')
|
|
97
|
+
inString = true;
|
|
98
|
+
else if (character === "{")
|
|
99
|
+
depth += 1;
|
|
100
|
+
else if (character === "}" && --depth === 0) {
|
|
101
|
+
try {
|
|
102
|
+
return recordValue(JSON.parse(html.slice(start, index + 1)));
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=json-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-path.js","sourceRoot":"","sources":["../../src/fetch-page/json-path.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type AparatTarget } from "./aparat.js";
|
|
2
|
+
import type { ParsedPage, SiteAdapterContext } from "./types.js";
|
|
3
|
+
import { type YoutubeTarget } from "./youtube.js";
|
|
4
|
+
/**
|
|
5
|
+
* Site-adapter seam.
|
|
6
|
+
*
|
|
7
|
+
* The core `fetch_page` contract — seven fields, the 8,000 UTF-16 window, the
|
|
8
|
+
* error envelope, the post-redirect URL — is graded [G] against the golden
|
|
9
|
+
* corpus and must not drift. Everything reachable from here is [H]: a local
|
|
10
|
+
* choice about pages the generic extractor cannot read, built on undocumented
|
|
11
|
+
* site internals that change without notice. Keeping the two apart is what
|
|
12
|
+
* makes the distinction auditable rather than a matter of reading 1,600 lines.
|
|
13
|
+
*/
|
|
14
|
+
export type DynamicSiteTarget = YoutubeTarget | AparatTarget;
|
|
15
|
+
export declare function dynamicSiteTarget(value: string): DynamicSiteTarget | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Why the page cannot be read generically, when the site served a shell instead
|
|
18
|
+
* of content. Absent means the HTML is worth extracting normally.
|
|
19
|
+
*/
|
|
20
|
+
export declare function dynamicShellReason(html: string, target: DynamicSiteTarget | undefined): string | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Returns an adapted page, or undefined to fall through to generic extraction.
|
|
23
|
+
* Throws when the page is a shell no adapter could recover, so an unreadable
|
|
24
|
+
* response never reports success.
|
|
25
|
+
*/
|
|
26
|
+
export declare function loadDynamicSite(target: DynamicSiteTarget, ctx: SiteAdapterContext): Promise<ParsedPage | undefined>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { aparatShellReason, loadAparat, matchAparat, } from "./aparat.js";
|
|
2
|
+
import { loadYoutube, matchYoutube, youtubeShellReason, } from "./youtube.js";
|
|
3
|
+
export function dynamicSiteTarget(value) {
|
|
4
|
+
const url = new URL(value);
|
|
5
|
+
const hostname = url.hostname.toLowerCase().replace(/^www\./, "");
|
|
6
|
+
return matchYoutube(url, hostname) || matchAparat(url, hostname);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Why the page cannot be read generically, when the site served a shell instead
|
|
10
|
+
* of content. Absent means the HTML is worth extracting normally.
|
|
11
|
+
*/
|
|
12
|
+
export function dynamicShellReason(html, target) {
|
|
13
|
+
if (!target)
|
|
14
|
+
return undefined;
|
|
15
|
+
return target.kind === "youtube"
|
|
16
|
+
? youtubeShellReason(html)
|
|
17
|
+
: aparatShellReason(html);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Returns an adapted page, or undefined to fall through to generic extraction.
|
|
21
|
+
* Throws when the page is a shell no adapter could recover, so an unreadable
|
|
22
|
+
* response never reports success.
|
|
23
|
+
*/
|
|
24
|
+
export async function loadDynamicSite(target, ctx) {
|
|
25
|
+
const shellReason = dynamicShellReason(ctx.html, target);
|
|
26
|
+
// YouTube runs unconditionally: even a healthy watch page hides its metadata
|
|
27
|
+
// in embedded JSON. Aparat only runs once its shell has been detected.
|
|
28
|
+
if (target.kind !== "youtube" && !shellReason)
|
|
29
|
+
return undefined;
|
|
30
|
+
const adapted = target.kind === "youtube"
|
|
31
|
+
? await loadYoutube(target, ctx)
|
|
32
|
+
: await loadAparat(target, ctx);
|
|
33
|
+
if (adapted)
|
|
34
|
+
return adapted;
|
|
35
|
+
if (shellReason)
|
|
36
|
+
throw new Error(`Failed to fetch page: ${shellReason}`);
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=sites.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sites.js","sourceRoot":"","sources":["../../src/fetch-page/sites.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,iBAAiB,EACjB,UAAU,EACV,WAAW,GACZ,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,WAAW,EACX,YAAY,EAEZ,kBAAkB,GACnB,MAAM,cAAc,CAAC;AAetB,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAC3B,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAClE,OAAO,YAAY,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,WAAW,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AACnE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAAY,EACZ,MAAqC;IAErC,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,OAAO,MAAM,CAAC,IAAI,KAAK,SAAS;QAC9B,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC;QAC1B,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAyB,EACzB,GAAuB;IAEvB,MAAM,WAAW,GAAG,kBAAkB,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACzD,6EAA6E;IAC7E,uEAAuE;IACvE,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,WAAW;QAAE,OAAO,SAAS,CAAC;IAChE,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,KAAK,SAAS;QACvC,CAAC,CAAC,MAAM,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC;QAChC,CAAC,CAAC,MAAM,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAClC,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAC5B,IAAI,WAAW;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,WAAW,EAAE,CAAC,CAAC;IACzE,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Text helpers shared by the fetch_page core and its site adapters. */
|
|
2
|
+
export declare function decodeText(bytes: Uint8Array, contentType: string): string;
|
|
3
|
+
export declare function normalizeMarkdown(value: string): string;
|
|
4
|
+
export declare function decodeHtmlEntities(value: string): string;
|
|
5
|
+
export declare function requireReadableContent(markdown: string): string;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { parseHTML } from "linkedom";
|
|
2
|
+
/** Text helpers shared by the fetch_page core and its site adapters. */
|
|
3
|
+
export function decodeText(bytes, contentType) {
|
|
4
|
+
const charset = contentType.match(/charset\s*=\s*["']?([^;"'\s]+)/i)?.[1];
|
|
5
|
+
try {
|
|
6
|
+
return new TextDecoder(charset || "utf-8").decode(bytes);
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return new TextDecoder("utf-8").decode(bytes);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export function normalizeMarkdown(value) {
|
|
13
|
+
return value
|
|
14
|
+
.replace(/\r\n?/g, "\n")
|
|
15
|
+
.replace(/[ \t]+\n/g, "\n")
|
|
16
|
+
.replace(/\n{4,}/g, "\n\n\n")
|
|
17
|
+
.trim();
|
|
18
|
+
}
|
|
19
|
+
let htmlEntityDecoder;
|
|
20
|
+
export function decodeHtmlEntities(value) {
|
|
21
|
+
if (!value.includes("&"))
|
|
22
|
+
return value;
|
|
23
|
+
if (!htmlEntityDecoder) {
|
|
24
|
+
const { document } = parseHTML("<html><body><span></span></body></html>");
|
|
25
|
+
htmlEntityDecoder = document.querySelector("span") || undefined;
|
|
26
|
+
}
|
|
27
|
+
if (!htmlEntityDecoder)
|
|
28
|
+
return value;
|
|
29
|
+
htmlEntityDecoder.innerHTML = value;
|
|
30
|
+
return htmlEntityDecoder.textContent || "";
|
|
31
|
+
}
|
|
32
|
+
export function requireReadableContent(markdown) {
|
|
33
|
+
if (!markdown.trim()) {
|
|
34
|
+
throw new Error("Failed to fetch page: no readable content");
|
|
35
|
+
}
|
|
36
|
+
return markdown;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/fetch-page/text.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,wEAAwE;AAExE,MAAM,UAAU,UAAU,CAAC,KAAiB,EAAE,WAAmB;IAC/D,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,iCAAiC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC1E,IAAI,CAAC;QACH,OAAO,IAAI,WAAW,CAAC,OAAO,IAAI,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,OAAO,KAAK;SACT,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC;SACvB,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC;SAC1B,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC;SAC5B,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,IAAI,iBAAsC,CAAC;AAE3C,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,MAAM,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC,yCAAyC,CAAC,CAAC;QAC1E,iBAAiB,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC;IAClE,CAAC;IACD,IAAI,CAAC,iBAAiB;QAAE,OAAO,KAAK,CAAC;IACrC,iBAAiB,CAAC,SAAS,GAAG,KAAK,CAAC;IACpC,OAAO,iBAAiB,CAAC,WAAW,IAAI,EAAE,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,QAAgB;IACrD,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Shapes shared across the `fetch_page` modules. */
|
|
2
|
+
export interface ParsedPage {
|
|
3
|
+
finalUrl: string;
|
|
4
|
+
contentType: string;
|
|
5
|
+
markdown: string;
|
|
6
|
+
title?: string;
|
|
7
|
+
totalPages?: number;
|
|
8
|
+
pagesParsed?: number;
|
|
9
|
+
truncated?: boolean;
|
|
10
|
+
warning?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface DownloadedPage {
|
|
13
|
+
bytes: Uint8Array;
|
|
14
|
+
contentType: string;
|
|
15
|
+
finalUrl: string;
|
|
16
|
+
status: number;
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/fetch-page/types.ts"],"names":[],"mappings":"AAAA,qDAAqD"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ParsedPage, SiteAdapterContext } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* YouTube adapter.
|
|
4
|
+
*
|
|
5
|
+
* The watch page carries structured metadata the generic HTML extractor cannot
|
|
6
|
+
* see, so this adapter runs even on a healthy page rather than only on the bot
|
|
7
|
+
* shell. Everything it reads comes from the live response; nothing observed in
|
|
8
|
+
* the source history is hardcoded. Per the golden spec this is an [H] local
|
|
9
|
+
* choice, not a behavior the corpus proves the source tool implemented.
|
|
10
|
+
*/
|
|
11
|
+
export interface YoutubeTarget {
|
|
12
|
+
kind: "youtube";
|
|
13
|
+
canonicalUrl: string;
|
|
14
|
+
videoId: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function matchYoutube(url: URL, hostname: string): YoutubeTarget | undefined;
|
|
17
|
+
export declare function youtubeShellReason(html: string): string | undefined;
|
|
18
|
+
interface YoutubeMetadata {
|
|
19
|
+
title: string;
|
|
20
|
+
thumbnail: string;
|
|
21
|
+
thumbnailWidth: string;
|
|
22
|
+
thumbnailHeight: string;
|
|
23
|
+
author: string;
|
|
24
|
+
authorUrl: string;
|
|
25
|
+
uploadedAt: string;
|
|
26
|
+
length: string;
|
|
27
|
+
views: string;
|
|
28
|
+
likes: string;
|
|
29
|
+
category: string;
|
|
30
|
+
description: string;
|
|
31
|
+
transcript: string;
|
|
32
|
+
}
|
|
33
|
+
export declare function youtubePage(target: YoutubeTarget, metadata: YoutubeMetadata): ParsedPage | undefined;
|
|
34
|
+
export declare function loadYoutube(target: YoutubeTarget, ctx: SiteAdapterContext): Promise<ParsedPage | undefined>;
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { extractAssignedJson, findNestedRecord, findNestedValue, jsonObject, recordArray, recordValue, stringField, } from "./json-path.js";
|
|
2
|
+
import { decodeHtmlEntities, decodeText, normalizeMarkdown, requireReadableContent, } from "./text.js";
|
|
3
|
+
export function matchYoutube(url, hostname) {
|
|
4
|
+
if (hostname !== "youtube.com" || url.pathname !== "/watch")
|
|
5
|
+
return undefined;
|
|
6
|
+
const videoId = url.searchParams.get("v") || "";
|
|
7
|
+
if (!videoId)
|
|
8
|
+
return undefined;
|
|
9
|
+
return {
|
|
10
|
+
kind: "youtube",
|
|
11
|
+
canonicalUrl: `https://www.youtube.com/watch?v=${encodeURIComponent(videoId)}`,
|
|
12
|
+
videoId,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function youtubeShellReason(html) {
|
|
16
|
+
return /sign in to confirm you(?:'|’)?re not a bot/i.test(html) ||
|
|
17
|
+
/"status"\s*:\s*"LOGIN_REQUIRED"/.test(html)
|
|
18
|
+
? "bot verification required"
|
|
19
|
+
: undefined;
|
|
20
|
+
}
|
|
21
|
+
function youtubeText(value) {
|
|
22
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
23
|
+
return String(value);
|
|
24
|
+
}
|
|
25
|
+
const record = recordValue(value);
|
|
26
|
+
if (!record)
|
|
27
|
+
return "";
|
|
28
|
+
const simpleText = stringField(record, "simpleText");
|
|
29
|
+
if (simpleText)
|
|
30
|
+
return simpleText;
|
|
31
|
+
const content = stringField(record, "content");
|
|
32
|
+
if (content)
|
|
33
|
+
return content;
|
|
34
|
+
return recordArray(record.runs)
|
|
35
|
+
.map((run) => stringField(run, "text"))
|
|
36
|
+
.join("");
|
|
37
|
+
}
|
|
38
|
+
function numericText(value) {
|
|
39
|
+
return value.replace(/[^0-9]/g, "");
|
|
40
|
+
}
|
|
41
|
+
function isoDate(value) {
|
|
42
|
+
if (!value)
|
|
43
|
+
return "";
|
|
44
|
+
const parsed = new Date(`${value} 00:00:00 UTC`);
|
|
45
|
+
return Number.isNaN(parsed.valueOf()) ? value : parsed.toISOString().slice(0, 10);
|
|
46
|
+
}
|
|
47
|
+
function formatDuration(secondsValue) {
|
|
48
|
+
if (!secondsValue.trim())
|
|
49
|
+
return "";
|
|
50
|
+
const seconds = Number(secondsValue);
|
|
51
|
+
if (!Number.isFinite(seconds) || seconds < 0)
|
|
52
|
+
return "";
|
|
53
|
+
const whole = Math.floor(seconds);
|
|
54
|
+
const hours = Math.floor(whole / 3600);
|
|
55
|
+
const minutes = Math.floor((whole % 3600) / 60);
|
|
56
|
+
const remainder = whole % 60;
|
|
57
|
+
return hours
|
|
58
|
+
? [hours, minutes, remainder].map((part) => String(part).padStart(2, "0")).join(":")
|
|
59
|
+
: [minutes, remainder].map((part) => String(part).padStart(2, "0")).join(":");
|
|
60
|
+
}
|
|
61
|
+
function expandYoutubeDescription(value) {
|
|
62
|
+
const description = recordValue(value);
|
|
63
|
+
if (!description)
|
|
64
|
+
return youtubeText(value);
|
|
65
|
+
let content = youtubeText(description);
|
|
66
|
+
const replacements = recordArray(description.commandRuns)
|
|
67
|
+
.flatMap((run) => {
|
|
68
|
+
const startIndex = Number(run.startIndex);
|
|
69
|
+
const length = Number(run.length);
|
|
70
|
+
const metadata = recordValue(findNestedValue(run, "webCommandMetadata"));
|
|
71
|
+
const rawUrl = metadata ? stringField(metadata, "url") : "";
|
|
72
|
+
if (!Number.isSafeInteger(startIndex) || length <= 0 || !rawUrl)
|
|
73
|
+
return [];
|
|
74
|
+
try {
|
|
75
|
+
const target = new URL(rawUrl, "https://www.youtube.com");
|
|
76
|
+
const expanded = target.searchParams.get("q") || "";
|
|
77
|
+
return expanded ? [{ startIndex, length, expanded }] : [];
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return [];
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
.sort((left, right) => right.startIndex - left.startIndex);
|
|
84
|
+
for (const replacement of replacements) {
|
|
85
|
+
content =
|
|
86
|
+
content.slice(0, replacement.startIndex) +
|
|
87
|
+
replacement.expanded +
|
|
88
|
+
content.slice(replacement.startIndex + replacement.length);
|
|
89
|
+
}
|
|
90
|
+
return content;
|
|
91
|
+
}
|
|
92
|
+
function youtubeMetadataFromHtml(target, html) {
|
|
93
|
+
const initialData = extractAssignedJson(html, "var ytInitialData =") ||
|
|
94
|
+
extractAssignedJson(html, "window[\"ytInitialData\"] =");
|
|
95
|
+
const initialPlayer = extractAssignedJson(html, "var ytInitialPlayerResponse =") ||
|
|
96
|
+
extractAssignedJson(html, "ytInitialPlayerResponse =");
|
|
97
|
+
const primary = recordValue(findNestedValue(initialData, "videoPrimaryInfoRenderer"));
|
|
98
|
+
const secondary = recordValue(findNestedValue(initialData, "videoSecondaryInfoRenderer"));
|
|
99
|
+
const owner = recordValue(findNestedValue(secondary, "videoOwnerRenderer"));
|
|
100
|
+
const browse = recordValue(findNestedValue(owner, "browseEndpoint"));
|
|
101
|
+
const viewRenderer = recordValue(findNestedValue(primary, "videoViewCountRenderer"));
|
|
102
|
+
const likeButton = findNestedRecord(primary, (record) => record.iconName === "LIKE" && typeof record.title === "string");
|
|
103
|
+
const playerDetails = recordValue(initialPlayer?.videoDetails);
|
|
104
|
+
const microformat = recordValue(findNestedValue(initialPlayer, "playerMicroformatRenderer"));
|
|
105
|
+
const canonicalBase = browse ? stringField(browse, "canonicalBaseUrl") : "";
|
|
106
|
+
const authorUrl = canonicalBase
|
|
107
|
+
? new URL(canonicalBase, "https://www.youtube.com").href
|
|
108
|
+
: "";
|
|
109
|
+
return {
|
|
110
|
+
title: youtubeText(primary?.title) || stringField(playerDetails || {}, "title"),
|
|
111
|
+
thumbnail: `https://i.ytimg.com/vi/${encodeURIComponent(target.videoId)}/maxresdefault.jpg`,
|
|
112
|
+
thumbnailWidth: "1920",
|
|
113
|
+
thumbnailHeight: "1080",
|
|
114
|
+
author: youtubeText(owner?.title) || stringField(playerDetails || {}, "author"),
|
|
115
|
+
authorUrl,
|
|
116
|
+
uploadedAt: isoDate(youtubeText(primary?.dateText) || stringField(microformat || {}, "uploadDate")),
|
|
117
|
+
length: formatDuration(stringField(playerDetails || {}, "lengthSeconds")),
|
|
118
|
+
views: numericText(youtubeText(viewRenderer?.viewCount) || stringField(playerDetails || {}, "viewCount")),
|
|
119
|
+
likes: numericText(stringField(likeButton || {}, "title")),
|
|
120
|
+
category: stringField(microformat || {}, "category"),
|
|
121
|
+
description: expandYoutubeDescription(findNestedValue(initialData, "attributedDescriptionBodyText")) ||
|
|
122
|
+
stringField(playerDetails || {}, "shortDescription"),
|
|
123
|
+
transcript: "",
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function youtubeEmbedMetadata(html) {
|
|
127
|
+
const match = html.match(/"embedded_player_response":("(?:\\.|[^"\\])*")/);
|
|
128
|
+
if (!match?.[1])
|
|
129
|
+
return {};
|
|
130
|
+
try {
|
|
131
|
+
const response = recordValue(JSON.parse(JSON.parse(match[1])));
|
|
132
|
+
const preview = recordValue(response?.embedPreview);
|
|
133
|
+
const thumbnailRenderer = recordValue(findNestedValue(preview, "thumbnailPreviewRenderer"));
|
|
134
|
+
const thumbnails = recordArray(recordValue(thumbnailRenderer?.defaultThumbnail)?.thumbnails);
|
|
135
|
+
const thumbnail = thumbnails.at(-1);
|
|
136
|
+
const durationValue = findNestedValue(preview, "videoDurationSeconds");
|
|
137
|
+
const duration = typeof durationValue === "string" || typeof durationValue === "number"
|
|
138
|
+
? String(durationValue)
|
|
139
|
+
: "";
|
|
140
|
+
return {
|
|
141
|
+
...(duration ? { length: formatDuration(duration) } : {}),
|
|
142
|
+
...(thumbnail
|
|
143
|
+
? {
|
|
144
|
+
thumbnail: stringField(thumbnail, "url"),
|
|
145
|
+
thumbnailWidth: stringField(thumbnail, "width"),
|
|
146
|
+
thumbnailHeight: stringField(thumbnail, "height"),
|
|
147
|
+
}
|
|
148
|
+
: {}),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
return {};
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function youtubeOembedMetadata(value) {
|
|
156
|
+
return {
|
|
157
|
+
title: stringField(value, "title"),
|
|
158
|
+
thumbnail: stringField(value, "thumbnail_url"),
|
|
159
|
+
thumbnailWidth: stringField(value, "thumbnail_width"),
|
|
160
|
+
thumbnailHeight: stringField(value, "thumbnail_height"),
|
|
161
|
+
author: stringField(value, "author_name"),
|
|
162
|
+
authorUrl: stringField(value, "author_url"),
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function youtubeCaptionUrl(html) {
|
|
166
|
+
const initialPlayer = extractAssignedJson(html, "var ytInitialPlayerResponse =") ||
|
|
167
|
+
extractAssignedJson(html, "ytInitialPlayerResponse =");
|
|
168
|
+
const tracks = recordArray(findNestedValue(initialPlayer, "captionTracks"));
|
|
169
|
+
const selected = tracks.find((track) => stringField(track, "languageCode").startsWith("en")) ||
|
|
170
|
+
tracks[0];
|
|
171
|
+
return selected ? stringField(selected, "baseUrl") : "";
|
|
172
|
+
}
|
|
173
|
+
function youtubeTranscript(bytes, contentType) {
|
|
174
|
+
const text = decodeText(bytes, contentType);
|
|
175
|
+
try {
|
|
176
|
+
const value = JSON.parse(text);
|
|
177
|
+
const events = recordArray(recordValue(value)?.events);
|
|
178
|
+
const lines = events.flatMap((event) => {
|
|
179
|
+
const line = recordArray(event.segs)
|
|
180
|
+
.map((segment) => stringField(segment, "utf8"))
|
|
181
|
+
.join("")
|
|
182
|
+
.trim();
|
|
183
|
+
return line ? [line] : [];
|
|
184
|
+
});
|
|
185
|
+
if (lines.length)
|
|
186
|
+
return lines.join("\n");
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
// Timed-text endpoints also return XML; handle it below.
|
|
190
|
+
}
|
|
191
|
+
const lines = [...text.matchAll(/<text\b[^>]*>([\s\S]*?)<\/text>/gi)]
|
|
192
|
+
.map((match) => decodeHtmlEntities(match[1] || "").trim())
|
|
193
|
+
.filter(Boolean);
|
|
194
|
+
return lines.join("\n");
|
|
195
|
+
}
|
|
196
|
+
export function youtubePage(target, metadata) {
|
|
197
|
+
if (!metadata.title)
|
|
198
|
+
return undefined;
|
|
199
|
+
const thumbnailLabel = metadata.thumbnailWidth && metadata.thumbnailHeight
|
|
200
|
+
? `Thumbnail (${metadata.thumbnailWidth}x${metadata.thumbnailHeight})`
|
|
201
|
+
: "Thumbnail";
|
|
202
|
+
const lines = [
|
|
203
|
+
...(metadata.thumbnail
|
|
204
|
+
? [``]
|
|
205
|
+
: []),
|
|
206
|
+
`# [${metadata.title}](${target.canonicalUrl})`,
|
|
207
|
+
"",
|
|
208
|
+
`**Uploaded by**: ${metadata.authorUrl
|
|
209
|
+
? `[${metadata.author}](${metadata.authorUrl})`
|
|
210
|
+
: metadata.author}`,
|
|
211
|
+
`**Uploaded at**: ${metadata.uploadedAt}`,
|
|
212
|
+
"**Published at**: ",
|
|
213
|
+
`**Length**: ${metadata.length}`,
|
|
214
|
+
`**Views**: ${metadata.views}`,
|
|
215
|
+
`**Likes**: ${metadata.likes}`,
|
|
216
|
+
`**Category**: ${metadata.category}`,
|
|
217
|
+
];
|
|
218
|
+
if (metadata.description) {
|
|
219
|
+
lines.push("", "## Description", "", "```", metadata.description, "```");
|
|
220
|
+
}
|
|
221
|
+
if (metadata.transcript) {
|
|
222
|
+
lines.push("", "## Transcript", "", metadata.transcript);
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
finalUrl: target.canonicalUrl,
|
|
226
|
+
contentType: "text/html",
|
|
227
|
+
markdown: requireReadableContent(normalizeMarkdown(lines.join("\n"))),
|
|
228
|
+
title: `${metadata.title} - YouTube`,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
export async function loadYoutube(target, ctx) {
|
|
232
|
+
try {
|
|
233
|
+
let metadata = youtubeMetadataFromHtml(target, ctx.html);
|
|
234
|
+
const captionUrl = youtubeCaptionUrl(ctx.html);
|
|
235
|
+
if (captionUrl) {
|
|
236
|
+
try {
|
|
237
|
+
const separator = captionUrl.includes("?") ? "&" : "?";
|
|
238
|
+
const response = await ctx.download(`${captionUrl}${separator}fmt=json3`);
|
|
239
|
+
metadata.transcript = youtubeTranscript(response.bytes, response.contentType);
|
|
240
|
+
}
|
|
241
|
+
catch {
|
|
242
|
+
ctx.throwIfAborted();
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
if (metadata.title && !metadata.length) {
|
|
246
|
+
try {
|
|
247
|
+
const response = await ctx.download(`https://www.youtube.com/embed/${encodeURIComponent(target.videoId)}`, {
|
|
248
|
+
referer: "https://example.com/",
|
|
249
|
+
"user-agent": "Mozilla/5.0",
|
|
250
|
+
});
|
|
251
|
+
metadata = {
|
|
252
|
+
...metadata,
|
|
253
|
+
...youtubeEmbedMetadata(decodeText(response.bytes, response.contentType)),
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
catch {
|
|
257
|
+
ctx.throwIfAborted();
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if (!metadata.title || !metadata.author) {
|
|
261
|
+
const endpoint = "https://www.youtube.com/oembed?format=json&url=" +
|
|
262
|
+
encodeURIComponent(target.canonicalUrl);
|
|
263
|
+
const response = await ctx.download(endpoint);
|
|
264
|
+
const fallback = youtubeOembedMetadata(jsonObject(response.bytes, response.contentType));
|
|
265
|
+
metadata = {
|
|
266
|
+
...metadata,
|
|
267
|
+
title: metadata.title || fallback.title || "",
|
|
268
|
+
thumbnail: metadata.thumbnail || fallback.thumbnail || "",
|
|
269
|
+
thumbnailWidth: metadata.thumbnailWidth || fallback.thumbnailWidth || "",
|
|
270
|
+
thumbnailHeight: metadata.thumbnailHeight || fallback.thumbnailHeight || "",
|
|
271
|
+
author: metadata.author || fallback.author || "",
|
|
272
|
+
authorUrl: metadata.authorUrl || fallback.authorUrl || "",
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
return youtubePage(target, metadata);
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
ctx.throwIfAborted();
|
|
279
|
+
return undefined;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
//# sourceMappingURL=youtube.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"youtube.js","sourceRoot":"","sources":["../../src/fetch-page/youtube.ts"],"names":[],"mappings":"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"}
|