googlemaps-kit 0.6.0 → 0.7.0
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 +54 -2
- package/dist/books.d.ts +30 -0
- package/dist/books.d.ts.map +1 -0
- package/dist/books.js +77 -0
- package/dist/books.js.map +1 -0
- package/dist/client/http-client.d.ts +3 -1
- package/dist/client/http-client.d.ts.map +1 -1
- package/dist/client/http-client.js +14 -3
- package/dist/client/http-client.js.map +1 -1
- package/dist/client/namespaces.d.ts +1 -4
- package/dist/client/namespaces.d.ts.map +1 -1
- package/dist/client/namespaces.js +1 -5
- package/dist/client/namespaces.js.map +1 -1
- package/dist/finance/client.d.ts +19 -0
- package/dist/finance/client.d.ts.map +1 -0
- package/dist/finance/client.js +75 -0
- package/dist/finance/client.js.map +1 -0
- package/dist/finance/parsers.d.ts +13 -0
- package/dist/finance/parsers.d.ts.map +1 -0
- package/dist/finance/parsers.js +146 -0
- package/dist/finance/parsers.js.map +1 -0
- package/dist/finance/types.d.ts +76 -0
- package/dist/finance/types.d.ts.map +1 -0
- package/dist/finance/types.js +2 -0
- package/dist/finance/types.js.map +1 -0
- package/dist/finance.d.ts +5 -0
- package/dist/finance.d.ts.map +1 -0
- package/dist/finance.js +4 -0
- package/dist/finance.js.map +1 -0
- package/dist/flights/client.d.ts +9 -0
- package/dist/flights/client.d.ts.map +1 -0
- package/dist/flights/client.js +14 -0
- package/dist/flights/client.js.map +1 -0
- package/dist/flights/parsers.d.ts +11 -0
- package/dist/flights/parsers.d.ts.map +1 -0
- package/dist/flights/parsers.js +64 -0
- package/dist/flights/parsers.js.map +1 -0
- package/dist/flights/types.d.ts +52 -0
- package/dist/flights/types.d.ts.map +1 -0
- package/dist/flights/types.js +2 -0
- package/dist/flights/types.js.map +1 -0
- package/dist/flights.d.ts +5 -0
- package/dist/flights.d.ts.map +1 -0
- package/dist/flights.js +4 -0
- package/dist/flights.js.map +1 -0
- package/dist/gemini-web/client.d.ts +16 -0
- package/dist/gemini-web/client.d.ts.map +1 -0
- package/dist/gemini-web/client.js +110 -0
- package/dist/gemini-web/client.js.map +1 -0
- package/dist/gemini-web/parsers.d.ts +5 -0
- package/dist/gemini-web/parsers.d.ts.map +1 -0
- package/dist/gemini-web/parsers.js +62 -0
- package/dist/gemini-web/parsers.js.map +1 -0
- package/dist/gemini-web/types.d.ts +47 -0
- package/dist/gemini-web/types.d.ts.map +1 -0
- package/dist/gemini-web/types.js +2 -0
- package/dist/gemini-web/types.js.map +1 -0
- package/dist/gemini-web.d.ts +5 -0
- package/dist/gemini-web.d.ts.map +1 -0
- package/dist/gemini-web.js +4 -0
- package/dist/gemini-web.js.map +1 -0
- package/dist/google-search/client.d.ts +16 -0
- package/dist/google-search/client.d.ts.map +1 -0
- package/dist/google-search/client.js +117 -0
- package/dist/google-search/client.js.map +1 -0
- package/dist/google-search/errors.d.ts +8 -0
- package/dist/google-search/errors.d.ts.map +1 -0
- package/dist/google-search/errors.js +13 -0
- package/dist/google-search/errors.js.map +1 -0
- package/dist/google-search/html.d.ts +12 -0
- package/dist/google-search/html.d.ts.map +1 -0
- package/dist/google-search/html.js +135 -0
- package/dist/google-search/html.js.map +1 -0
- package/dist/google-search/parsers.d.ts +6 -0
- package/dist/google-search/parsers.d.ts.map +1 -0
- package/dist/google-search/parsers.js +177 -0
- package/dist/google-search/parsers.js.map +1 -0
- package/dist/google-search/types.d.ts +66 -0
- package/dist/google-search/types.d.ts.map +1 -0
- package/dist/google-search/types.js +2 -0
- package/dist/google-search/types.js.map +1 -0
- package/dist/google-search.d.ts +6 -0
- package/dist/google-search.d.ts.map +1 -0
- package/dist/google-search.js +4 -0
- package/dist/google-search.js.map +1 -0
- package/dist/hotels/client.d.ts +9 -0
- package/dist/hotels/client.d.ts.map +1 -0
- package/dist/hotels/client.js +14 -0
- package/dist/hotels/client.js.map +1 -0
- package/dist/hotels/parsers.d.ts +7 -0
- package/dist/hotels/parsers.d.ts.map +1 -0
- package/dist/hotels/parsers.js +74 -0
- package/dist/hotels/parsers.js.map +1 -0
- package/dist/hotels/types.d.ts +55 -0
- package/dist/hotels/types.d.ts.map +1 -0
- package/dist/hotels/types.js +2 -0
- package/dist/hotels/types.js.map +1 -0
- package/dist/hotels.d.ts +4 -0
- package/dist/hotels.d.ts.map +1 -0
- package/dist/hotels.js +3 -0
- package/dist/hotels.js.map +1 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/known-surfaces.d.ts +0 -6
- package/dist/known-surfaces.d.ts.map +1 -1
- package/dist/known-surfaces.js +0 -6
- package/dist/known-surfaces.js.map +1 -1
- package/dist/lens/client.d.ts +14 -0
- package/dist/lens/client.d.ts.map +1 -0
- package/dist/lens/client.js +116 -0
- package/dist/lens/client.js.map +1 -0
- package/dist/lens/errors.d.ts +8 -0
- package/dist/lens/errors.d.ts.map +1 -0
- package/dist/lens/errors.js +13 -0
- package/dist/lens/errors.js.map +1 -0
- package/dist/lens/types.d.ts +27 -0
- package/dist/lens/types.d.ts.map +1 -0
- package/dist/lens/types.js +2 -0
- package/dist/lens/types.js.map +1 -0
- package/dist/lens.d.ts +8 -0
- package/dist/lens.d.ts.map +1 -0
- package/dist/lens.js +5 -0
- package/dist/lens.js.map +1 -0
- package/dist/news.d.ts +46 -0
- package/dist/news.d.ts.map +1 -0
- package/dist/news.js +202 -0
- package/dist/news.js.map +1 -0
- package/dist/pagespeed/client.d.ts +28 -0
- package/dist/pagespeed/client.d.ts.map +1 -0
- package/dist/pagespeed/client.js +222 -0
- package/dist/pagespeed/client.js.map +1 -0
- package/dist/pagespeed/errors.d.ts +9 -0
- package/dist/pagespeed/errors.d.ts.map +1 -0
- package/dist/pagespeed/errors.js +15 -0
- package/dist/pagespeed/errors.js.map +1 -0
- package/dist/pagespeed/parsers.d.ts +7 -0
- package/dist/pagespeed/parsers.d.ts.map +1 -0
- package/dist/pagespeed/parsers.js +236 -0
- package/dist/pagespeed/parsers.js.map +1 -0
- package/dist/pagespeed/types.d.ts +156 -0
- package/dist/pagespeed/types.d.ts.map +1 -0
- package/dist/pagespeed/types.js +2 -0
- package/dist/pagespeed/types.js.map +1 -0
- package/dist/pagespeed/wire.d.ts +10 -0
- package/dist/pagespeed/wire.d.ts.map +1 -0
- package/dist/pagespeed/wire.js +96 -0
- package/dist/pagespeed/wire.js.map +1 -0
- package/dist/pagespeed.d.ts +6 -0
- package/dist/pagespeed.d.ts.map +1 -0
- package/dist/pagespeed.js +4 -0
- package/dist/pagespeed.js.map +1 -0
- package/dist/platform/catalog.d.ts.map +1 -1
- package/dist/platform/catalog.js +0 -9
- package/dist/platform/catalog.js.map +1 -1
- package/dist/services/environment/air-quality.d.ts.map +1 -1
- package/dist/services/environment/air-quality.js +3 -7
- package/dist/services/environment/air-quality.js.map +1 -1
- package/dist/services/environment/weather.d.ts +4 -1
- package/dist/services/environment/weather.d.ts.map +1 -1
- package/dist/services/environment/weather.js +12 -3
- package/dist/services/environment/weather.js.map +1 -1
- package/dist/services/reviews.d.ts.map +1 -1
- package/dist/services/reviews.js +4 -1
- package/dist/services/reviews.js.map +1 -1
- package/dist/translate.d.ts +75 -0
- package/dist/translate.d.ts.map +1 -0
- package/dist/translate.js +126 -0
- package/dist/translate.js.map +1 -0
- package/dist/travel-google/common.d.ts +24 -0
- package/dist/travel-google/common.d.ts.map +1 -0
- package/dist/travel-google/common.js +72 -0
- package/dist/travel-google/common.js.map +1 -0
- package/dist/trends/client.d.ts +17 -0
- package/dist/trends/client.d.ts.map +1 -0
- package/dist/trends/client.js +86 -0
- package/dist/trends/client.js.map +1 -0
- package/dist/trends/errors.d.ts +8 -0
- package/dist/trends/errors.d.ts.map +1 -0
- package/dist/trends/errors.js +13 -0
- package/dist/trends/errors.js.map +1 -0
- package/dist/trends/links.d.ts +8 -0
- package/dist/trends/links.d.ts.map +1 -0
- package/dist/trends/links.js +71 -0
- package/dist/trends/links.js.map +1 -0
- package/dist/trends/parsers.d.ts +5 -0
- package/dist/trends/parsers.d.ts.map +1 -0
- package/dist/trends/parsers.js +126 -0
- package/dist/trends/parsers.js.map +1 -0
- package/dist/trends/types.d.ts +71 -0
- package/dist/trends/types.d.ts.map +1 -0
- package/dist/trends/types.js +2 -0
- package/dist/trends/types.js.map +1 -0
- package/dist/trends.d.ts +9 -0
- package/dist/trends.d.ts.map +1 -0
- package/dist/trends.js +8 -0
- package/dist/trends.js.map +1 -0
- package/dist/types/common.d.ts +0 -2
- package/dist/types/common.d.ts.map +1 -1
- package/dist/types/common.js.map +1 -1
- package/dist/utils/google-web.d.ts +24 -0
- package/dist/utils/google-web.d.ts.map +1 -0
- package/dist/utils/google-web.js +150 -0
- package/dist/utils/google-web.js.map +1 -0
- package/dist/youtube/client.d.ts +19 -0
- package/dist/youtube/client.d.ts.map +1 -0
- package/dist/youtube/client.js +115 -0
- package/dist/youtube/client.js.map +1 -0
- package/dist/youtube/errors.d.ts +8 -0
- package/dist/youtube/errors.d.ts.map +1 -0
- package/dist/youtube/errors.js +13 -0
- package/dist/youtube/errors.js.map +1 -0
- package/dist/youtube/parsers.d.ts +9 -0
- package/dist/youtube/parsers.d.ts.map +1 -0
- package/dist/youtube/parsers.js +213 -0
- package/dist/youtube/parsers.js.map +1 -0
- package/dist/youtube/types.d.ts +90 -0
- package/dist/youtube/types.d.ts.map +1 -0
- package/dist/youtube/types.js +2 -0
- package/dist/youtube/types.js.map +1 -0
- package/dist/youtube.d.ts +9 -0
- package/dist/youtube.d.ts.map +1 -0
- package/dist/youtube.js +6 -0
- package/dist/youtube.js.map +1 -0
- package/docs/books.md +18 -0
- package/docs/environment-research.md +65 -0
- package/docs/finance-research.md +153 -0
- package/docs/finance.md +43 -0
- package/docs/gemini-web.md +36 -0
- package/docs/google-ai-books-research.md +53 -0
- package/docs/google-media-research.md +105 -0
- package/docs/google-search-research.md +36 -0
- package/docs/google-search.md +53 -0
- package/docs/google-services-research.md +135 -0
- package/docs/google-travel-research.md +86 -0
- package/docs/internal/reverse-engineering.md +85 -0
- package/docs/lens.md +54 -0
- package/docs/maps-revalidation.md +31 -0
- package/docs/news.md +35 -0
- package/docs/pagespeed-research.md +153 -0
- package/docs/pagespeed.md +135 -0
- package/docs/reviews-research.md +33 -0
- package/docs/translate.md +78 -0
- package/docs/trends-research.md +82 -0
- package/docs/trends.md +75 -0
- package/docs/youtube.md +72 -0
- package/package.json +77 -2
- package/dist/services/aerial-view.d.ts +0 -22
- package/dist/services/aerial-view.d.ts.map +0 -1
- package/dist/services/aerial-view.js +0 -107
- package/dist/services/aerial-view.js.map +0 -1
- package/dist/types/aerial-view.d.ts +0 -39
- package/dist/types/aerial-view.d.ts.map +0 -1
- package/dist/types/aerial-view.js +0 -2
- package/dist/types/aerial-view.js.map +0 -1
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { YouTubeError } from './errors.js';
|
|
2
|
+
import { extractYouTubeClient, extractYouTubeJson, parseSearch, parseVideo, parseYouTubeVideoId, youtubeObject } from './parsers.js';
|
|
3
|
+
/** Reads anonymous watch metadata, search results, continuations, and oEmbed responses. */
|
|
4
|
+
export class YouTubeClient {
|
|
5
|
+
fetcher;
|
|
6
|
+
locale;
|
|
7
|
+
region;
|
|
8
|
+
timeoutMs;
|
|
9
|
+
constructor(config = {}) {
|
|
10
|
+
this.fetcher = config.fetch ?? globalThis.fetch;
|
|
11
|
+
this.locale = config.locale ?? 'en';
|
|
12
|
+
this.region = config.region ?? 'US';
|
|
13
|
+
this.timeoutMs = config.timeoutMs ?? 30_000;
|
|
14
|
+
if (!Number.isFinite(this.timeoutMs) || this.timeoutMs <= 0 || this.timeoutMs > 2_147_483_647)
|
|
15
|
+
throw new RangeError('timeoutMs must be positive and no greater than 2147483647');
|
|
16
|
+
if (!/^[A-Za-z]{2}$/.test(this.region))
|
|
17
|
+
throw new TypeError('region must be a two-letter country code');
|
|
18
|
+
}
|
|
19
|
+
/** Returns metadata and explicit playability status; it never fetches audio or video streams. */
|
|
20
|
+
async video(idOrUrl, options = {}) {
|
|
21
|
+
const id = parseYouTubeVideoId(idOrUrl);
|
|
22
|
+
const url = this.webUrl('/watch');
|
|
23
|
+
url.searchParams.set('v', id);
|
|
24
|
+
const html = await this.request(url, options);
|
|
25
|
+
const raw = extractYouTubeJson(html, 'ytInitialPlayerResponse');
|
|
26
|
+
if (!raw)
|
|
27
|
+
throw new YouTubeError('YouTube did not provide a player response', 'parse');
|
|
28
|
+
return parseVideo(raw, id, extractYouTubeJson(html, 'ytInitialData'));
|
|
29
|
+
}
|
|
30
|
+
async search(query, options = {}) {
|
|
31
|
+
if (typeof query !== 'string' || query.trim().length === 0)
|
|
32
|
+
throw new TypeError('query must be a nonempty string');
|
|
33
|
+
const url = this.webUrl('/results');
|
|
34
|
+
url.searchParams.set('search_query', query);
|
|
35
|
+
const html = await this.request(url, options);
|
|
36
|
+
const raw = extractYouTubeJson(html, 'ytInitialData');
|
|
37
|
+
if (!raw)
|
|
38
|
+
throw new YouTubeError('YouTube did not provide search data', 'parse');
|
|
39
|
+
return parseSearch(raw, extractYouTubeClient(html));
|
|
40
|
+
}
|
|
41
|
+
/** Uses the opaque continuation and anonymous client context returned by search. */
|
|
42
|
+
async continueSearch(cursor, options = {}) {
|
|
43
|
+
if (!cursor || typeof cursor.token !== 'string' || cursor.token.length === 0 || !cursor.client || cursor.client.clientName !== 'WEB' || typeof cursor.client.clientVersion !== 'string' || !cursor.client.clientVersion)
|
|
44
|
+
throw new TypeError('A search continuation with its client context is required');
|
|
45
|
+
const client = { clientName: cursor.client.clientName, clientVersion: cursor.client.clientVersion, hl: cursor.client.hl, gl: cursor.client.gl, visitorData: cursor.client.visitorData };
|
|
46
|
+
const text = await this.request(new URL('https://www.youtube.com/youtubei/v1/search?prettyPrint=false'), options, {
|
|
47
|
+
method: 'POST',
|
|
48
|
+
headers: { 'Content-Type': 'application/json', 'X-Youtube-Client-Name': '1', 'X-Youtube-Client-Version': client.clientVersion },
|
|
49
|
+
body: JSON.stringify({ context: { client }, continuation: cursor.token }),
|
|
50
|
+
});
|
|
51
|
+
return parseSearch(this.json(text), client);
|
|
52
|
+
}
|
|
53
|
+
async oembed(idOrUrl, options = {}) {
|
|
54
|
+
const id = parseYouTubeVideoId(idOrUrl);
|
|
55
|
+
const url = new URL('https://www.youtube.com/oembed');
|
|
56
|
+
url.searchParams.set('url', `https://www.youtube.com/watch?v=${id}`);
|
|
57
|
+
url.searchParams.set('format', 'json');
|
|
58
|
+
const raw = this.json(await this.request(url, options));
|
|
59
|
+
if (!youtubeObject(raw) || ['title', 'author_name', 'author_url', 'type', 'version', 'provider_name', 'provider_url', 'thumbnail_url', 'html'].some(key => typeof raw[key] !== 'string') || ['height', 'width', 'thumbnail_height', 'thumbnail_width'].some(key => typeof raw[key] !== 'number' || !Number.isFinite(raw[key])))
|
|
60
|
+
throw new YouTubeError('Malformed YouTube oEmbed response', 'parse');
|
|
61
|
+
return raw;
|
|
62
|
+
}
|
|
63
|
+
webUrl(path) {
|
|
64
|
+
const url = new URL(path, 'https://www.youtube.com');
|
|
65
|
+
url.searchParams.set('hl', this.locale);
|
|
66
|
+
url.searchParams.set('gl', this.region.toUpperCase());
|
|
67
|
+
return url;
|
|
68
|
+
}
|
|
69
|
+
json(text) {
|
|
70
|
+
try {
|
|
71
|
+
return JSON.parse(text.replace(/^\)\]\}'\s*/, ''));
|
|
72
|
+
}
|
|
73
|
+
catch (cause) {
|
|
74
|
+
throw new YouTubeError('Malformed YouTube JSON response', 'parse', undefined, undefined, { cause });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async request(url, options, init = {}) {
|
|
78
|
+
if (options.signal?.aborted)
|
|
79
|
+
throw options.signal.reason ?? new DOMException('The operation was aborted', 'AbortError');
|
|
80
|
+
const controller = new AbortController();
|
|
81
|
+
const abort = () => controller.abort(options.signal?.reason ?? new DOMException('The operation was aborted', 'AbortError'));
|
|
82
|
+
options.signal?.addEventListener('abort', abort, { once: true });
|
|
83
|
+
const timer = setTimeout(() => controller.abort(new YouTubeError('YouTube request timed out', 'timeout')), this.timeoutMs);
|
|
84
|
+
timer.unref?.();
|
|
85
|
+
try {
|
|
86
|
+
const response = await this.fetcher(url.toString(), { ...init, signal: controller.signal });
|
|
87
|
+
const body = await response.text();
|
|
88
|
+
if (controller.signal.aborted)
|
|
89
|
+
throw controller.signal.reason;
|
|
90
|
+
const retry = response.headers.get('retry-after');
|
|
91
|
+
const retryAfterMs = retry && /^\d+(?:\.\d+)?$/.test(retry) ? Number(retry) * 1000 : retry && Number.isFinite(Date.parse(retry)) ? Math.max(0, Date.parse(retry) - Date.now()) : undefined;
|
|
92
|
+
if (response.status === 429)
|
|
93
|
+
throw new YouTubeError('YouTube rate limited this request', 'rate-limit', 429, retryAfterMs);
|
|
94
|
+
if (/\/sorry\/|consent\.youtube\.com|consent\.google\.com/.test(response.url) || /<(?:form|div)[^>]+(?:captcha|consent)|<title[^>]*>[^<]*(?:unusual traffic|consent)/i.test(body))
|
|
95
|
+
throw new YouTubeError('YouTube returned a consent or traffic challenge', 'blocked', response.status);
|
|
96
|
+
if (response.status === 401)
|
|
97
|
+
throw new YouTubeError('YouTube requires authentication', 'auth-required', 401);
|
|
98
|
+
if (!response.ok)
|
|
99
|
+
throw new YouTubeError(`YouTube returned HTTP ${response.status}`, 'http', response.status, retryAfterMs);
|
|
100
|
+
return body;
|
|
101
|
+
}
|
|
102
|
+
catch (cause) {
|
|
103
|
+
if (controller.signal.aborted)
|
|
104
|
+
throw controller.signal.reason;
|
|
105
|
+
if (cause instanceof YouTubeError)
|
|
106
|
+
throw cause;
|
|
107
|
+
throw new YouTubeError('YouTube request failed', 'network', undefined, undefined, { cause });
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
clearTimeout(timer);
|
|
111
|
+
options.signal?.removeEventListener('abort', abort);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/youtube/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type YouTubeErrorKind = 'http' | 'blocked' | 'auth-required' | 'rate-limit' | 'parse' | 'network' | 'timeout';
|
|
2
|
+
export declare class YouTubeError extends Error {
|
|
3
|
+
readonly kind: YouTubeErrorKind;
|
|
4
|
+
readonly status?: number | undefined;
|
|
5
|
+
readonly retryAfterMs?: number | undefined;
|
|
6
|
+
constructor(message: string, kind: YouTubeErrorKind, status?: number | undefined, retryAfterMs?: number | undefined, options?: ErrorOptions);
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/youtube/errors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,SAAS,GAAG,eAAe,GAAG,YAAY,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AACrH,qBAAa,YAAa,SAAQ,KAAK;IACR,QAAQ,CAAC,IAAI,EAAE,gBAAgB;IAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM;IAAE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM;gBAA1G,OAAO,EAAE,MAAM,EAAW,IAAI,EAAE,gBAAgB,EAAW,MAAM,CAAC,EAAE,MAAM,YAAA,EAAW,YAAY,CAAC,EAAE,MAAM,YAAA,EAAE,OAAO,CAAC,EAAE,YAAY;CAI/I"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export class YouTubeError extends Error {
|
|
2
|
+
kind;
|
|
3
|
+
status;
|
|
4
|
+
retryAfterMs;
|
|
5
|
+
constructor(message, kind, status, retryAfterMs, options) {
|
|
6
|
+
super(message, options);
|
|
7
|
+
this.kind = kind;
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.retryAfterMs = retryAfterMs;
|
|
10
|
+
this.name = 'YouTubeError';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/youtube/errors.ts"],"names":[],"mappings":"AACA,MAAM,OAAO,YAAa,SAAQ,KAAK;IACC;IAAiC;IAA0B;IAAjG,YAAY,OAAe,EAAW,IAAsB,EAAW,MAAe,EAAW,YAAqB,EAAE,OAAsB;QAC5I,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QADY,SAAI,GAAJ,IAAI,CAAkB;QAAW,WAAM,GAAN,MAAM,CAAS;QAAW,iBAAY,GAAZ,YAAY,CAAS;QAEpH,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { YouTubeSearchCursor, YouTubeSearchPage, YouTubeVideo } from './types.js';
|
|
2
|
+
export declare function youtubeObject(value: unknown): value is Record<string, unknown>;
|
|
3
|
+
export declare function youtubeText(value: unknown): string | undefined;
|
|
4
|
+
export declare function extractYouTubeJson(html: string, variable: string): Record<string, unknown> | undefined;
|
|
5
|
+
export declare function parseVideo(raw: unknown, id: string, initialData?: Record<string, unknown>): YouTubeVideo;
|
|
6
|
+
export declare function parseSearch(raw: unknown, client: YouTubeSearchCursor['client']): YouTubeSearchPage;
|
|
7
|
+
export declare function extractYouTubeClient(html: string): YouTubeSearchCursor['client'];
|
|
8
|
+
export declare function parseYouTubeVideoId(value: string): string;
|
|
9
|
+
//# sourceMappingURL=parsers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parsers.d.ts","sourceRoot":"","sources":["../../src/youtube/parsers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAuB,mBAAmB,EAAqB,iBAAiB,EAAoB,YAAY,EAAE,MAAM,YAAY,CAAC;AAEjJ,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE9E;AAUD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAM9D;AAOD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAwBtG;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,YAAY,CAqBxG;AA6CD,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,mBAAmB,CAAC,QAAQ,CAAC,GAAG,iBAAiB,CA+BlG;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAWhF;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAUzD"}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { YouTubeError } from './errors.js';
|
|
2
|
+
export function youtubeObject(value) {
|
|
3
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
4
|
+
}
|
|
5
|
+
function fail(label) { throw new YouTubeError(`Malformed YouTube ${label}`, 'parse'); }
|
|
6
|
+
function optionalString(value) { return typeof value === 'string' ? value : undefined; }
|
|
7
|
+
function requiredString(value, name) { return typeof value === 'string' && value.length > 0 ? value : fail(name); }
|
|
8
|
+
function numeric(value) {
|
|
9
|
+
const result = typeof value === 'string' && /^\d+$/.test(value) ? Number(value) : value;
|
|
10
|
+
return typeof result === 'number' && Number.isFinite(result) && result >= 0 ? result : undefined;
|
|
11
|
+
}
|
|
12
|
+
export function youtubeText(value) {
|
|
13
|
+
if (!youtubeObject(value))
|
|
14
|
+
return undefined;
|
|
15
|
+
if (typeof value.simpleText === 'string')
|
|
16
|
+
return value.simpleText;
|
|
17
|
+
if (Array.isArray(value.runs))
|
|
18
|
+
return value.runs.map(run => youtubeObject(run) && typeof run.text === 'string' ? run.text : '').join('');
|
|
19
|
+
if (typeof value.content === 'string')
|
|
20
|
+
return value.content;
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
function thumbnails(value) {
|
|
24
|
+
if (!youtubeObject(value) || !Array.isArray(value.thumbnails))
|
|
25
|
+
return [];
|
|
26
|
+
return value.thumbnails.flatMap(item => youtubeObject(item) && typeof item.url === 'string' ? [{ url: item.url.startsWith('//') ? `https:${item.url}` : item.url, width: numeric(item.width), height: numeric(item.height) }] : []);
|
|
27
|
+
}
|
|
28
|
+
export function extractYouTubeJson(html, variable) {
|
|
29
|
+
const escaped = variable.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
30
|
+
const pattern = new RegExp(`(?:var\\s+)?${escaped}\\s*=\\s*|window\\[["']${escaped}["']\\]\\s*=\\s*`, 'g');
|
|
31
|
+
let match;
|
|
32
|
+
while ((match = pattern.exec(html))) {
|
|
33
|
+
const start = pattern.lastIndex;
|
|
34
|
+
if (html[start] !== '{')
|
|
35
|
+
continue;
|
|
36
|
+
let depth = 0, quoted = false, escapedCharacter = false;
|
|
37
|
+
for (let index = start; index < html.length; index++) {
|
|
38
|
+
const character = html[index];
|
|
39
|
+
if (quoted) {
|
|
40
|
+
if (escapedCharacter)
|
|
41
|
+
escapedCharacter = false;
|
|
42
|
+
else if (character === '\\')
|
|
43
|
+
escapedCharacter = true;
|
|
44
|
+
else if (character === '"')
|
|
45
|
+
quoted = false;
|
|
46
|
+
}
|
|
47
|
+
else if (character === '"')
|
|
48
|
+
quoted = true;
|
|
49
|
+
else if (character === '{')
|
|
50
|
+
depth++;
|
|
51
|
+
else if (character === '}' && --depth === 0) {
|
|
52
|
+
try {
|
|
53
|
+
const value = JSON.parse(html.slice(start, index + 1));
|
|
54
|
+
return youtubeObject(value) ? value : fail(variable);
|
|
55
|
+
}
|
|
56
|
+
catch (cause) {
|
|
57
|
+
throw new YouTubeError(`Malformed YouTube ${variable} JSON`, 'parse', undefined, undefined, { cause });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return fail(variable);
|
|
62
|
+
}
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
export function parseVideo(raw, id, initialData) {
|
|
66
|
+
if (!youtubeObject(raw) || !youtubeObject(raw.playabilityStatus))
|
|
67
|
+
return fail('player response');
|
|
68
|
+
const playability = raw.playabilityStatus;
|
|
69
|
+
const details = youtubeObject(raw.videoDetails) ? raw.videoDetails : {};
|
|
70
|
+
if (details.videoId !== undefined && details.videoId !== id)
|
|
71
|
+
return fail('player video ID');
|
|
72
|
+
const captionContainer = youtubeObject(raw.captions) && youtubeObject(raw.captions.playerCaptionsTracklistRenderer) ? raw.captions.playerCaptionsTracklistRenderer : undefined;
|
|
73
|
+
const captions = !Array.isArray(captionContainer?.captionTracks) ? [] : captionContainer.captionTracks.map(value => {
|
|
74
|
+
if (!youtubeObject(value))
|
|
75
|
+
return fail('caption track');
|
|
76
|
+
return { languageCode: requiredString(value.languageCode, 'caption language'), name: youtubeText(value.name) ?? '', baseUrl: requiredString(value.baseUrl, 'caption URL'), kind: optionalString(value.kind), isTranslatable: typeof value.isTranslatable === 'boolean' ? value.isTranslatable : undefined, raw: value };
|
|
77
|
+
});
|
|
78
|
+
return {
|
|
79
|
+
id: optionalString(details.videoId) ?? id,
|
|
80
|
+
url: `https://www.youtube.com/watch?v=${id}`,
|
|
81
|
+
title: optionalString(details.title), author: optionalString(details.author), channelId: optionalString(details.channelId),
|
|
82
|
+
description: optionalString(details.shortDescription), lengthSeconds: numeric(details.lengthSeconds), viewCount: optionalString(details.viewCount),
|
|
83
|
+
keywords: Array.isArray(details.keywords) ? details.keywords.filter((value) => typeof value === 'string') : undefined,
|
|
84
|
+
isLiveContent: typeof details.isLiveContent === 'boolean' ? details.isLiveContent : undefined,
|
|
85
|
+
thumbnails: thumbnails(details.thumbnail),
|
|
86
|
+
playability: { status: requiredString(playability.status, 'playability status'), reason: optionalString(playability.reason), raw: playability },
|
|
87
|
+
captions, raw, initialData,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function ownerId(value) {
|
|
91
|
+
if (!youtubeObject(value) || !Array.isArray(value.runs))
|
|
92
|
+
return undefined;
|
|
93
|
+
for (const run of value.runs) {
|
|
94
|
+
if (youtubeObject(run) && youtubeObject(run.navigationEndpoint) && youtubeObject(run.navigationEndpoint.browseEndpoint))
|
|
95
|
+
return optionalString(run.navigationEndpoint.browseEndpoint.browseId);
|
|
96
|
+
}
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
function searchItem(type, raw) {
|
|
100
|
+
const id = requiredString(raw[type === 'video' ? 'videoId' : 'channelId'], 'search result ID');
|
|
101
|
+
const title = youtubeText(raw.title) ?? fail('search result title');
|
|
102
|
+
const owner = raw.ownerText ?? raw.longBylineText ?? raw.shortBylineText;
|
|
103
|
+
return {
|
|
104
|
+
type, id, title,
|
|
105
|
+
url: type === 'video' ? `https://www.youtube.com/watch?v=${id}` : `https://www.youtube.com/channel/${id}`,
|
|
106
|
+
description: youtubeText(raw.descriptionSnippet), author: youtubeText(owner), channelId: type === 'channel' ? id : ownerId(owner),
|
|
107
|
+
duration: youtubeText(raw.lengthText), viewCount: youtubeText(raw.viewCountText), publishedTime: youtubeText(raw.publishedTimeText),
|
|
108
|
+
thumbnails: thumbnails(raw.thumbnail ?? (Array.isArray(raw.thumbnails) ? raw.thumbnails[0] : undefined)), raw,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function path(value, ...keys) {
|
|
112
|
+
for (const key of keys)
|
|
113
|
+
value = typeof key === 'number' && Array.isArray(value) ? value[key] : typeof key === 'string' && youtubeObject(value) ? value[key] : undefined;
|
|
114
|
+
return value;
|
|
115
|
+
}
|
|
116
|
+
function playlistLockup(raw) {
|
|
117
|
+
const id = requiredString(raw.contentId, 'playlist ID');
|
|
118
|
+
const metadata = path(raw, 'metadata', 'lockupMetadataViewModel');
|
|
119
|
+
const rows = path(metadata, 'metadata', 'contentMetadataViewModel', 'metadataRows');
|
|
120
|
+
const byline = Array.isArray(rows) ? rows.find(row => path(row, 'lockupContentMetadataRowExtension', 'contentType') === 'METADATA_ROW_CONTENT_TYPE_BYLINE') : undefined;
|
|
121
|
+
const author = path(byline, 'metadataParts', 0, 'text');
|
|
122
|
+
return {
|
|
123
|
+
type: 'playlist', id,
|
|
124
|
+
title: requiredString(youtubeText(path(metadata, 'title')), 'playlist title'),
|
|
125
|
+
url: `https://www.youtube.com/playlist?list=${id}`,
|
|
126
|
+
author: youtubeText(author),
|
|
127
|
+
channelId: optionalString(path(author, 'commandRuns', 0, 'onTap', 'innertubeCommand', 'browseEndpoint', 'browseId')),
|
|
128
|
+
thumbnails: thumbnails({ thumbnails: path(raw, 'contentImage', 'collectionThumbnailViewModel', 'primaryThumbnail', 'thumbnailViewModel', 'image', 'sources') }),
|
|
129
|
+
raw,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
export function parseSearch(raw, client) {
|
|
133
|
+
if (!youtubeObject(raw))
|
|
134
|
+
return fail('search response');
|
|
135
|
+
const primary = youtubeObject(raw.contents) && youtubeObject(raw.contents.twoColumnSearchResultsRenderer) ? raw.contents.twoColumnSearchResultsRenderer.primaryContents : undefined;
|
|
136
|
+
const actions = raw.onResponseReceivedCommands ?? raw.onResponseReceivedActions;
|
|
137
|
+
if (!youtubeObject(primary) && !Array.isArray(actions))
|
|
138
|
+
return fail('search results');
|
|
139
|
+
const items = [];
|
|
140
|
+
const seen = new Set();
|
|
141
|
+
let token;
|
|
142
|
+
const stack = [primary ?? actions];
|
|
143
|
+
while (stack.length) {
|
|
144
|
+
const value = stack.pop();
|
|
145
|
+
if (Array.isArray(value)) {
|
|
146
|
+
for (let i = value.length - 1; i >= 0; i--)
|
|
147
|
+
stack.push(value[i]);
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
if (!youtubeObject(value))
|
|
151
|
+
continue;
|
|
152
|
+
if (youtubeObject(value.continuationCommand) && typeof value.continuationCommand.token === 'string')
|
|
153
|
+
token ??= value.continuationCommand.token;
|
|
154
|
+
if (youtubeObject(value.lockupViewModel) && value.lockupViewModel.contentType === 'LOCKUP_CONTENT_TYPE_PLAYLIST') {
|
|
155
|
+
const item = playlistLockup(value.lockupViewModel);
|
|
156
|
+
if (!seen.has(`playlist:${item.id}`)) {
|
|
157
|
+
items.push(item);
|
|
158
|
+
seen.add(`playlist:${item.id}`);
|
|
159
|
+
}
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
const entry = ['video', 'channel'].find(type => youtubeObject(value[`${type}Renderer`]));
|
|
163
|
+
if (entry) {
|
|
164
|
+
const item = searchItem(entry, value[`${entry}Renderer`]);
|
|
165
|
+
const key = `${entry}:${item.id}`;
|
|
166
|
+
if (!seen.has(key)) {
|
|
167
|
+
items.push(item);
|
|
168
|
+
seen.add(key);
|
|
169
|
+
}
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
for (const [key, child] of Object.entries(value).reverse()) {
|
|
173
|
+
if (!/adSlotRenderer|promotedSparklesWebRenderer|searchPyvRenderer|adMetadata|loggingDirectives|trackingParams/.test(key))
|
|
174
|
+
stack.push(child);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return { items, estimatedResults: optionalString(raw.estimatedResults), continuation: token ? { token, client } : undefined, raw };
|
|
178
|
+
}
|
|
179
|
+
export function extractYouTubeClient(html) {
|
|
180
|
+
const pattern = /ytcfg\.set\s*\(/g;
|
|
181
|
+
let match;
|
|
182
|
+
while ((match = pattern.exec(html))) {
|
|
183
|
+
const config = extractYouTubeJson(`config=${html.slice(pattern.lastIndex).trimStart()}`, 'config');
|
|
184
|
+
if (!config || !youtubeObject(config.INNERTUBE_CONTEXT) || !youtubeObject(config.INNERTUBE_CONTEXT.client))
|
|
185
|
+
continue;
|
|
186
|
+
const client = config.INNERTUBE_CONTEXT.client;
|
|
187
|
+
if (client.clientName !== 'WEB')
|
|
188
|
+
return fail('unsupported anonymous client');
|
|
189
|
+
return { clientName: 'WEB', clientVersion: requiredString(client.clientVersion, 'client version'), hl: optionalString(client.hl), gl: optionalString(client.gl), visitorData: optionalString(client.visitorData) };
|
|
190
|
+
}
|
|
191
|
+
return fail('anonymous client configuration');
|
|
192
|
+
}
|
|
193
|
+
export function parseYouTubeVideoId(value) {
|
|
194
|
+
if (typeof value !== 'string')
|
|
195
|
+
throw new TypeError('A YouTube video ID or URL is required');
|
|
196
|
+
if (/^[A-Za-z0-9_-]{11}$/.test(value))
|
|
197
|
+
return value;
|
|
198
|
+
let url;
|
|
199
|
+
try {
|
|
200
|
+
url = new URL(value);
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
throw new TypeError('Invalid YouTube video ID or URL');
|
|
204
|
+
}
|
|
205
|
+
if (!['https:', 'http:'].includes(url.protocol) || url.username || url.password || url.port)
|
|
206
|
+
throw new TypeError('Invalid YouTube video URL');
|
|
207
|
+
const host = url.hostname.toLowerCase();
|
|
208
|
+
const id = host === 'youtu.be' ? url.pathname.slice(1) : ['youtube.com', 'www.youtube.com', 'm.youtube.com', 'www.youtube-nocookie.com'].includes(host) ? url.pathname === '/watch' ? url.searchParams.get('v') : /^\/(?:shorts|embed|live)\/([A-Za-z0-9_-]{11})\/?$/.exec(url.pathname)?.[1] : undefined;
|
|
209
|
+
if (typeof id !== 'string' || !/^[A-Za-z0-9_-]{11}$/.test(id))
|
|
210
|
+
throw new TypeError('Invalid YouTube video URL');
|
|
211
|
+
return id;
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=parsers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parsers.js","sourceRoot":"","sources":["../../src/youtube/parsers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
export interface YouTubeConfig {
|
|
2
|
+
fetch?: typeof globalThis.fetch;
|
|
3
|
+
locale?: string;
|
|
4
|
+
region?: string;
|
|
5
|
+
timeoutMs?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface YouTubeRequestOptions {
|
|
8
|
+
signal?: AbortSignal;
|
|
9
|
+
}
|
|
10
|
+
export interface YouTubeThumbnail {
|
|
11
|
+
url: string;
|
|
12
|
+
width?: number;
|
|
13
|
+
height?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface YouTubeCaptionTrack {
|
|
16
|
+
languageCode: string;
|
|
17
|
+
name: string;
|
|
18
|
+
baseUrl: string;
|
|
19
|
+
kind?: string;
|
|
20
|
+
isTranslatable?: boolean;
|
|
21
|
+
raw: Record<string, unknown>;
|
|
22
|
+
}
|
|
23
|
+
export interface YouTubeVideo {
|
|
24
|
+
id: string;
|
|
25
|
+
url: string;
|
|
26
|
+
title?: string;
|
|
27
|
+
author?: string;
|
|
28
|
+
channelId?: string;
|
|
29
|
+
description?: string;
|
|
30
|
+
lengthSeconds?: number;
|
|
31
|
+
viewCount?: string;
|
|
32
|
+
keywords?: string[];
|
|
33
|
+
isLiveContent?: boolean;
|
|
34
|
+
thumbnails: YouTubeThumbnail[];
|
|
35
|
+
playability: {
|
|
36
|
+
status: string;
|
|
37
|
+
reason?: string;
|
|
38
|
+
raw: Record<string, unknown>;
|
|
39
|
+
};
|
|
40
|
+
captions: YouTubeCaptionTrack[];
|
|
41
|
+
raw: Record<string, unknown>;
|
|
42
|
+
initialData?: Record<string, unknown>;
|
|
43
|
+
}
|
|
44
|
+
export interface YouTubeSearchItem {
|
|
45
|
+
type: 'video' | 'channel' | 'playlist';
|
|
46
|
+
id: string;
|
|
47
|
+
title: string;
|
|
48
|
+
url: string;
|
|
49
|
+
description?: string;
|
|
50
|
+
author?: string;
|
|
51
|
+
channelId?: string;
|
|
52
|
+
duration?: string;
|
|
53
|
+
viewCount?: string;
|
|
54
|
+
publishedTime?: string;
|
|
55
|
+
thumbnails: YouTubeThumbnail[];
|
|
56
|
+
raw: Record<string, unknown>;
|
|
57
|
+
}
|
|
58
|
+
export interface YouTubeSearchCursor {
|
|
59
|
+
token: string;
|
|
60
|
+
client: {
|
|
61
|
+
clientName: 'WEB';
|
|
62
|
+
clientVersion: string;
|
|
63
|
+
hl?: string;
|
|
64
|
+
gl?: string;
|
|
65
|
+
visitorData?: string;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
export interface YouTubeSearchPage {
|
|
69
|
+
items: YouTubeSearchItem[];
|
|
70
|
+
estimatedResults?: string;
|
|
71
|
+
continuation?: YouTubeSearchCursor;
|
|
72
|
+
raw: Record<string, unknown>;
|
|
73
|
+
}
|
|
74
|
+
export interface YouTubeOEmbed {
|
|
75
|
+
title: string;
|
|
76
|
+
author_name: string;
|
|
77
|
+
author_url: string;
|
|
78
|
+
type: string;
|
|
79
|
+
height: number;
|
|
80
|
+
width: number;
|
|
81
|
+
version: string;
|
|
82
|
+
provider_name: string;
|
|
83
|
+
provider_url: string;
|
|
84
|
+
thumbnail_height: number;
|
|
85
|
+
thumbnail_width: number;
|
|
86
|
+
thumbnail_url: string;
|
|
87
|
+
html: string;
|
|
88
|
+
[key: string]: unknown;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/youtube/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/youtube/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { YouTubeClient } from './youtube/client.js';
|
|
2
|
+
export { YouTubeError } from './youtube/errors.js';
|
|
3
|
+
export type { YouTubeErrorKind } from './youtube/errors.js';
|
|
4
|
+
export { parseYouTubeVideoId } from './youtube/parsers.js';
|
|
5
|
+
export type * from './youtube/types.js';
|
|
6
|
+
import { YouTubeClient } from './youtube/client.js';
|
|
7
|
+
import type { YouTubeConfig } from './youtube/types.js';
|
|
8
|
+
export declare function youtube(config?: YouTubeConfig): YouTubeClient;
|
|
9
|
+
//# sourceMappingURL=youtube.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"youtube.d.ts","sourceRoot":"","sources":["../src/youtube.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,mBAAmB,oBAAoB,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,wBAAgB,OAAO,CAAC,MAAM,GAAE,aAAkB,GAAG,aAAa,CAAsC"}
|
package/dist/youtube.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { YouTubeClient } from './youtube/client.js';
|
|
2
|
+
export { YouTubeError } from './youtube/errors.js';
|
|
3
|
+
export { parseYouTubeVideoId } from './youtube/parsers.js';
|
|
4
|
+
import { YouTubeClient } from './youtube/client.js';
|
|
5
|
+
export function youtube(config = {}) { return new YouTubeClient(config); }
|
|
6
|
+
//# sourceMappingURL=youtube.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"youtube.js","sourceRoot":"","sources":["../src/youtube.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,MAAM,UAAU,OAAO,CAAC,SAAwB,EAAE,IAAmB,OAAO,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC"}
|
package/docs/books.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Google Books public metadata
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
import { googleBooks } from 'googlemaps-kit/books';
|
|
5
|
+
|
|
6
|
+
const book = await googleBooks().get('zyTCAlFPjgYC');
|
|
7
|
+
console.log(book.title, book.authors, book.identifiers, book.pageCount);
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
This client reads an observed public bibliographic page at `books.google.com/books?id=...&hl=en`. It returns the title, bibliographic title, authors, publisher/year, edition, ISBNs, page count, optional description, canonical link and original table values. Fields missing from the page remain undefined or empty. It does not retrieve book pages, full text, purchased content, account libraries or previews.
|
|
11
|
+
|
|
12
|
+
The web metadata request succeeded anonymously on October 29, 2026. The documented Books v1 search and volume endpoints returned HTTP 429 quota errors from the same environment. This module uses the verified web surface; it is not a wrapper presented as successful v1 API access. Search by query, browsing bookshelves, v1 API operations and broad pagination are outside the current implementation.
|
|
13
|
+
|
|
14
|
+
`googleBooks({ fetch?, timeoutMs? })` accepts an injected fetch and defaults to a 30-second request deadline including the response body. `get(id, { signal? })` accepts a Google volume ID, requests the English page, and makes no automatic retries. Unknown layouts, mismatched volume IDs and HTTP failures throw `GoogleWebError` rather than returning empty fabricated metadata. Regional redirects are handled by normal fetch behavior; bibliographic parsing is verified only for the captured page structure.
|
|
15
|
+
|
|
16
|
+
`parseGoogleBooksHtml(html, id)` exposes the same parser for saved HTML. It never executes scripts. Sanitized actual fixture provenance is in `tests/fixtures/books/README.md`.
|
|
17
|
+
|
|
18
|
+
See the [independent research ledger](./google-ai-books-research.md) for observed behavior and unresolved gaps.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Weather, Air Quality and Cloud Vision access boundaries
|
|
2
|
+
|
|
3
|
+
Audited on 2026-10-29. These products have supported Google APIs with project
|
|
4
|
+
identity and billing/quota rules. A public consumer widget is a different
|
|
5
|
+
contract from those APIs.
|
|
6
|
+
|
|
7
|
+
## Direct API observations
|
|
8
|
+
|
|
9
|
+
Requests deliberately supplied no API key, OAuth token or account cookies:
|
|
10
|
+
|
|
11
|
+
| API | Request | Observed result |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| Weather current conditions | `GET weather.googleapis.com/v1/currentConditions:lookup` with location | HTTP 403, `PERMISSION_DENIED`, consumer identity required |
|
|
14
|
+
| Air Quality current conditions | `POST airquality.googleapis.com/v1/currentConditions:lookup` with JSON location | HTTP 403, `PERMISSION_DENIED`, consumer identity required |
|
|
15
|
+
| Vision text detection | `POST vision.googleapis.com/v1/images:annotate` with Google's public logo URL | HTTP 403, `PERMISSION_DENIED`, consumer identity required |
|
|
16
|
+
|
|
17
|
+
These failures establish that the tested official routes do not accept
|
|
18
|
+
unregistered callers. They do not establish successful access to the protected
|
|
19
|
+
data. No project credential was borrowed or extracted and no supported API's
|
|
20
|
+
paid feature is claimed anonymously available.
|
|
21
|
+
|
|
22
|
+
## Existing consumer capabilities
|
|
23
|
+
|
|
24
|
+
`maps.environment.weather.getCurrentConditions` parses the weather chip from a
|
|
25
|
+
Maps viewport response. It requires a current in-page viewport `psi` supplied
|
|
26
|
+
by the caller or a `psiProvider`. It does not produce a full forecast. A bare
|
|
27
|
+
degree symbol has no established Celsius/Fahrenheit meaning, so the parser now
|
|
28
|
+
preserves the value/display while leaving `unit` unset unless C or F is explicit.
|
|
29
|
+
|
|
30
|
+
A fresh ordinary Maps viewport capture for HSR Layout on 2026-10-29 returned
|
|
31
|
+
the expected cache-metadata stub followed by two populated responses. The
|
|
32
|
+
existing parser extracted `HSR Layout`, `28°`, and `Sunny`. This revalidates the
|
|
33
|
+
bounded current-condition chip contract, not a forecast or numerical AQI API.
|
|
34
|
+
|
|
35
|
+
`maps.environment.airQuality.getHeatmapTile` reads the existing raster overlay
|
|
36
|
+
surface. A tile is not a numerical point AQI lookup, and a returned placeholder
|
|
37
|
+
does not prove meaningful overlay coverage. The existing batchexecute parser
|
|
38
|
+
remains a separate partially established, session-dependent interface.
|
|
39
|
+
|
|
40
|
+
## Corrected supported-API contracts
|
|
41
|
+
|
|
42
|
+
The audit identified two existing request bugs and added offline regressions:
|
|
43
|
+
|
|
44
|
+
- Air Quality `lookup` now sends Google's documented JSON POST location instead
|
|
45
|
+
of GET query parameters. It accepts only a caller-configured API key.
|
|
46
|
+
- Weather `lookupForecast` now calls `forecast/days:lookup`, returning actual
|
|
47
|
+
daily records rather than calling current conditions. It accepts `days` and
|
|
48
|
+
`pageSize` from 1 to 10 and an optional `pageToken`, preserving Google's
|
|
49
|
+
pagination response. It still requires the caller's API credential.
|
|
50
|
+
|
|
51
|
+
The shared Maps HTTP client now has `postJson`, which preserves scheduling,
|
|
52
|
+
authentication options, error handling and statistics while parsing ordinary
|
|
53
|
+
JSON objects. Automatic retries are disabled by default for JSON POSTs.
|
|
54
|
+
These request fixes were tested offline; a successful authenticated/billable
|
|
55
|
+
Weather/Air Quality response was not claimed or attempted in this pass.
|
|
56
|
+
|
|
57
|
+
References: [Weather daily forecast](https://developers.google.com/maps/documentation/weather/reference/rest/v1/forecast.days/lookup),
|
|
58
|
+
[Weather setup](https://developers.google.com/maps/documentation/weather/get-api-key),
|
|
59
|
+
[Air Quality current conditions](https://developers.google.com/maps/documentation/air-quality/reference/rest/v1/currentConditions/lookup),
|
|
60
|
+
[Air Quality authentication](https://developers.google.com/maps/documentation/air-quality/get-api-key),
|
|
61
|
+
[Vision pricing](https://cloud.google.com/vision/pricing).
|
|
62
|
+
|
|
63
|
+
Consumer Lens is investigated separately from Cloud Vision. Similar OCR or
|
|
64
|
+
visual-search capabilities do not establish identical output, licensed data,
|
|
65
|
+
throughput, model selection or paid API parity.
|