youtube-transcript-nodejs 0.1.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/LICENSE +21 -0
- package/README.md +337 -0
- package/dist/cjs/api/InnerTubeClient.js +236 -0
- package/dist/cjs/api/InnerTubeClient.js.map +1 -0
- package/dist/cjs/api/YouTubeTranscriptApi.js +160 -0
- package/dist/cjs/api/YouTubeTranscriptApi.js.map +1 -0
- package/dist/cjs/api/fetchStrategies.js +51 -0
- package/dist/cjs/api/fetchStrategies.js.map +1 -0
- package/dist/cjs/config/constants.js +34 -0
- package/dist/cjs/config/constants.js.map +1 -0
- package/dist/cjs/config/innerTubeContext.js +82 -0
- package/dist/cjs/config/innerTubeContext.js.map +1 -0
- package/dist/cjs/errors/BotDetected.js +20 -0
- package/dist/cjs/errors/BotDetected.js.map +1 -0
- package/dist/cjs/errors/FailedToCreateConsentCookie.js +17 -0
- package/dist/cjs/errors/FailedToCreateConsentCookie.js.map +1 -0
- package/dist/cjs/errors/InvalidVideoId.js +16 -0
- package/dist/cjs/errors/InvalidVideoId.js.map +1 -0
- package/dist/cjs/errors/IpBlocked.js +17 -0
- package/dist/cjs/errors/IpBlocked.js.map +1 -0
- package/dist/cjs/errors/NoTranscriptFound.js +23 -0
- package/dist/cjs/errors/NoTranscriptFound.js.map +1 -0
- package/dist/cjs/errors/NotTranslatable.js +15 -0
- package/dist/cjs/errors/NotTranslatable.js.map +1 -0
- package/dist/cjs/errors/PoTokenRequired.js +18 -0
- package/dist/cjs/errors/PoTokenRequired.js.map +1 -0
- package/dist/cjs/errors/TooManyRequests.js +19 -0
- package/dist/cjs/errors/TooManyRequests.js.map +1 -0
- package/dist/cjs/errors/TranscriptsDisabled.js +15 -0
- package/dist/cjs/errors/TranscriptsDisabled.js.map +1 -0
- package/dist/cjs/errors/TranslationLanguageNotAvailable.js +16 -0
- package/dist/cjs/errors/TranslationLanguageNotAvailable.js.map +1 -0
- package/dist/cjs/errors/VideoUnavailable.js +15 -0
- package/dist/cjs/errors/VideoUnavailable.js.map +1 -0
- package/dist/cjs/errors/VideoUnplayable.js +22 -0
- package/dist/cjs/errors/VideoUnplayable.js.map +1 -0
- package/dist/cjs/errors/YouTubeDataUnparsable.js +15 -0
- package/dist/cjs/errors/YouTubeDataUnparsable.js.map +1 -0
- package/dist/cjs/errors/YouTubeRequestFailed.js +18 -0
- package/dist/cjs/errors/YouTubeRequestFailed.js.map +1 -0
- package/dist/cjs/errors/YouTubeTranscriptError.js +19 -0
- package/dist/cjs/errors/YouTubeTranscriptError.js.map +1 -0
- package/dist/cjs/errors/index.js +34 -0
- package/dist/cjs/errors/index.js.map +1 -0
- package/dist/cjs/formatters/Formatter.js +3 -0
- package/dist/cjs/formatters/Formatter.js.map +1 -0
- package/dist/cjs/formatters/JSONFormatter.js +24 -0
- package/dist/cjs/formatters/JSONFormatter.js.map +1 -0
- package/dist/cjs/formatters/PrettyPrintFormatter.js +26 -0
- package/dist/cjs/formatters/PrettyPrintFormatter.js.map +1 -0
- package/dist/cjs/formatters/SRTFormatter.js +39 -0
- package/dist/cjs/formatters/SRTFormatter.js.map +1 -0
- package/dist/cjs/formatters/TextFormatter.js +20 -0
- package/dist/cjs/formatters/TextFormatter.js.map +1 -0
- package/dist/cjs/formatters/WebVTTFormatter.js +39 -0
- package/dist/cjs/formatters/WebVTTFormatter.js.map +1 -0
- package/dist/cjs/formatters/base.js +61 -0
- package/dist/cjs/formatters/base.js.map +1 -0
- package/dist/cjs/formatters/index.js +19 -0
- package/dist/cjs/formatters/index.js.map +1 -0
- package/dist/cjs/http/cookieJar.js +91 -0
- package/dist/cjs/http/cookieJar.js.map +1 -0
- package/dist/cjs/http/httpClient.js +228 -0
- package/dist/cjs/http/httpClient.js.map +1 -0
- package/dist/cjs/index.js +50 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/models/FetchedTranscript.js +80 -0
- package/dist/cjs/models/FetchedTranscript.js.map +1 -0
- package/dist/cjs/models/FetchedTranscriptSnippet.js +29 -0
- package/dist/cjs/models/FetchedTranscriptSnippet.js.map +1 -0
- package/dist/cjs/models/FormattedTranscript.js +3 -0
- package/dist/cjs/models/FormattedTranscript.js.map +1 -0
- package/dist/cjs/models/Transcript.js +75 -0
- package/dist/cjs/models/Transcript.js.map +1 -0
- package/dist/cjs/models/TranscriptList.js +84 -0
- package/dist/cjs/models/TranscriptList.js.map +1 -0
- package/dist/cjs/models/TranscriptMetadata.js +3 -0
- package/dist/cjs/models/TranscriptMetadata.js.map +1 -0
- package/dist/cjs/models/TranslationLanguage.js +3 -0
- package/dist/cjs/models/TranslationLanguage.js.map +1 -0
- package/dist/cjs/models/index.js +13 -0
- package/dist/cjs/models/index.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/parsers/captionTrackParser.js +96 -0
- package/dist/cjs/parsers/captionTrackParser.js.map +1 -0
- package/dist/cjs/parsers/videoIdParser.js +65 -0
- package/dist/cjs/parsers/videoIdParser.js.map +1 -0
- package/dist/cjs/parsers/watchHtmlParser.js +78 -0
- package/dist/cjs/parsers/watchHtmlParser.js.map +1 -0
- package/dist/cjs/parsers/xmlTranscriptParser.js +84 -0
- package/dist/cjs/parsers/xmlTranscriptParser.js.map +1 -0
- package/dist/cjs/potoken/AutoPoTokenProvider.js +203 -0
- package/dist/cjs/potoken/AutoPoTokenProvider.js.map +1 -0
- package/dist/cjs/potoken/HttpPoTokenProvider.js +105 -0
- package/dist/cjs/potoken/HttpPoTokenProvider.js.map +1 -0
- package/dist/cjs/potoken/NoopPoTokenProvider.js +18 -0
- package/dist/cjs/potoken/NoopPoTokenProvider.js.map +1 -0
- package/dist/cjs/potoken/baseScriptCache.js +41 -0
- package/dist/cjs/potoken/baseScriptCache.js.map +1 -0
- package/dist/cjs/potoken/index.js +14 -0
- package/dist/cjs/potoken/index.js.map +1 -0
- package/dist/cjs/potoken/types.js +10 -0
- package/dist/cjs/potoken/types.js.map +1 -0
- package/dist/cjs/util/htmlSanitizer.js +77 -0
- package/dist/cjs/util/htmlSanitizer.js.map +1 -0
- package/dist/cjs/util/proxyUrl.js +42 -0
- package/dist/cjs/util/proxyUrl.js.map +1 -0
- package/dist/cjs/util/retry.js +65 -0
- package/dist/cjs/util/retry.js.map +1 -0
- package/dist/esm/api/InnerTubeClient.d.ts +61 -0
- package/dist/esm/api/InnerTubeClient.d.ts.map +1 -0
- package/dist/esm/api/InnerTubeClient.js +198 -0
- package/dist/esm/api/InnerTubeClient.js.map +1 -0
- package/dist/esm/api/YouTubeTranscriptApi.d.ts +88 -0
- package/dist/esm/api/YouTubeTranscriptApi.d.ts.map +1 -0
- package/dist/esm/api/YouTubeTranscriptApi.js +157 -0
- package/dist/esm/api/YouTubeTranscriptApi.js.map +1 -0
- package/dist/esm/api/fetchStrategies.d.ts +20 -0
- package/dist/esm/api/fetchStrategies.d.ts.map +1 -0
- package/dist/esm/api/fetchStrategies.js +48 -0
- package/dist/esm/api/fetchStrategies.js.map +1 -0
- package/dist/esm/config/constants.d.ts +30 -0
- package/dist/esm/config/constants.d.ts.map +1 -0
- package/dist/esm/config/constants.js +31 -0
- package/dist/esm/config/constants.js.map +1 -0
- package/dist/esm/config/innerTubeContext.d.ts +47 -0
- package/dist/esm/config/innerTubeContext.d.ts.map +1 -0
- package/dist/esm/config/innerTubeContext.js +77 -0
- package/dist/esm/config/innerTubeContext.js.map +1 -0
- package/dist/esm/errors/BotDetected.d.ts +13 -0
- package/dist/esm/errors/BotDetected.d.ts.map +1 -0
- package/dist/esm/errors/BotDetected.js +16 -0
- package/dist/esm/errors/BotDetected.js.map +1 -0
- package/dist/esm/errors/FailedToCreateConsentCookie.d.ts +10 -0
- package/dist/esm/errors/FailedToCreateConsentCookie.d.ts.map +1 -0
- package/dist/esm/errors/FailedToCreateConsentCookie.js +13 -0
- package/dist/esm/errors/FailedToCreateConsentCookie.js.map +1 -0
- package/dist/esm/errors/InvalidVideoId.d.ts +9 -0
- package/dist/esm/errors/InvalidVideoId.d.ts.map +1 -0
- package/dist/esm/errors/InvalidVideoId.js +12 -0
- package/dist/esm/errors/InvalidVideoId.js.map +1 -0
- package/dist/esm/errors/IpBlocked.d.ts +10 -0
- package/dist/esm/errors/IpBlocked.d.ts.map +1 -0
- package/dist/esm/errors/IpBlocked.js +13 -0
- package/dist/esm/errors/IpBlocked.js.map +1 -0
- package/dist/esm/errors/NoTranscriptFound.d.ts +19 -0
- package/dist/esm/errors/NoTranscriptFound.d.ts.map +1 -0
- package/dist/esm/errors/NoTranscriptFound.js +19 -0
- package/dist/esm/errors/NoTranscriptFound.js.map +1 -0
- package/dist/esm/errors/NotTranslatable.d.ts +9 -0
- package/dist/esm/errors/NotTranslatable.d.ts.map +1 -0
- package/dist/esm/errors/NotTranslatable.js +11 -0
- package/dist/esm/errors/NotTranslatable.js.map +1 -0
- package/dist/esm/errors/PoTokenRequired.d.ts +10 -0
- package/dist/esm/errors/PoTokenRequired.d.ts.map +1 -0
- package/dist/esm/errors/PoTokenRequired.js +14 -0
- package/dist/esm/errors/PoTokenRequired.js.map +1 -0
- package/dist/esm/errors/TooManyRequests.d.ts +12 -0
- package/dist/esm/errors/TooManyRequests.d.ts.map +1 -0
- package/dist/esm/errors/TooManyRequests.js +15 -0
- package/dist/esm/errors/TooManyRequests.js.map +1 -0
- package/dist/esm/errors/TranscriptsDisabled.d.ts +9 -0
- package/dist/esm/errors/TranscriptsDisabled.d.ts.map +1 -0
- package/dist/esm/errors/TranscriptsDisabled.js +11 -0
- package/dist/esm/errors/TranscriptsDisabled.js.map +1 -0
- package/dist/esm/errors/TranslationLanguageNotAvailable.d.ts +9 -0
- package/dist/esm/errors/TranslationLanguageNotAvailable.d.ts.map +1 -0
- package/dist/esm/errors/TranslationLanguageNotAvailable.js +12 -0
- package/dist/esm/errors/TranslationLanguageNotAvailable.js.map +1 -0
- package/dist/esm/errors/VideoUnavailable.d.ts +9 -0
- package/dist/esm/errors/VideoUnavailable.d.ts.map +1 -0
- package/dist/esm/errors/VideoUnavailable.js +11 -0
- package/dist/esm/errors/VideoUnavailable.js.map +1 -0
- package/dist/esm/errors/VideoUnplayable.d.ts +12 -0
- package/dist/esm/errors/VideoUnplayable.d.ts.map +1 -0
- package/dist/esm/errors/VideoUnplayable.js +18 -0
- package/dist/esm/errors/VideoUnplayable.js.map +1 -0
- package/dist/esm/errors/YouTubeDataUnparsable.d.ts +9 -0
- package/dist/esm/errors/YouTubeDataUnparsable.d.ts.map +1 -0
- package/dist/esm/errors/YouTubeDataUnparsable.js +11 -0
- package/dist/esm/errors/YouTubeDataUnparsable.js.map +1 -0
- package/dist/esm/errors/YouTubeRequestFailed.d.ts +10 -0
- package/dist/esm/errors/YouTubeRequestFailed.d.ts.map +1 -0
- package/dist/esm/errors/YouTubeRequestFailed.js +14 -0
- package/dist/esm/errors/YouTubeRequestFailed.js.map +1 -0
- package/dist/esm/errors/YouTubeTranscriptError.d.ts +10 -0
- package/dist/esm/errors/YouTubeTranscriptError.d.ts.map +1 -0
- package/dist/esm/errors/YouTubeTranscriptError.js +15 -0
- package/dist/esm/errors/YouTubeTranscriptError.js.map +1 -0
- package/dist/esm/errors/index.d.ts +17 -0
- package/dist/esm/errors/index.d.ts.map +1 -0
- package/dist/esm/errors/index.js +16 -0
- package/dist/esm/errors/index.js.map +1 -0
- package/dist/esm/formatters/Formatter.d.ts +33 -0
- package/dist/esm/formatters/Formatter.d.ts.map +1 -0
- package/dist/esm/formatters/Formatter.js +2 -0
- package/dist/esm/formatters/Formatter.js.map +1 -0
- package/dist/esm/formatters/JSONFormatter.d.ts +10 -0
- package/dist/esm/formatters/JSONFormatter.d.ts.map +1 -0
- package/dist/esm/formatters/JSONFormatter.js +20 -0
- package/dist/esm/formatters/JSONFormatter.js.map +1 -0
- package/dist/esm/formatters/PrettyPrintFormatter.d.ts +15 -0
- package/dist/esm/formatters/PrettyPrintFormatter.d.ts.map +1 -0
- package/dist/esm/formatters/PrettyPrintFormatter.js +22 -0
- package/dist/esm/formatters/PrettyPrintFormatter.js.map +1 -0
- package/dist/esm/formatters/SRTFormatter.d.ts +22 -0
- package/dist/esm/formatters/SRTFormatter.d.ts.map +1 -0
- package/dist/esm/formatters/SRTFormatter.js +35 -0
- package/dist/esm/formatters/SRTFormatter.js.map +1 -0
- package/dist/esm/formatters/TextFormatter.d.ts +10 -0
- package/dist/esm/formatters/TextFormatter.d.ts.map +1 -0
- package/dist/esm/formatters/TextFormatter.js +16 -0
- package/dist/esm/formatters/TextFormatter.js.map +1 -0
- package/dist/esm/formatters/WebVTTFormatter.d.ts +22 -0
- package/dist/esm/formatters/WebVTTFormatter.d.ts.map +1 -0
- package/dist/esm/formatters/WebVTTFormatter.js +35 -0
- package/dist/esm/formatters/WebVTTFormatter.js.map +1 -0
- package/dist/esm/formatters/base.d.ts +25 -0
- package/dist/esm/formatters/base.d.ts.map +1 -0
- package/dist/esm/formatters/base.js +55 -0
- package/dist/esm/formatters/base.js.map +1 -0
- package/dist/esm/formatters/index.d.ts +8 -0
- package/dist/esm/formatters/index.d.ts.map +1 -0
- package/dist/esm/formatters/index.js +7 -0
- package/dist/esm/formatters/index.js.map +1 -0
- package/dist/esm/http/cookieJar.d.ts +39 -0
- package/dist/esm/http/cookieJar.d.ts.map +1 -0
- package/dist/esm/http/cookieJar.js +87 -0
- package/dist/esm/http/cookieJar.js.map +1 -0
- package/dist/esm/http/httpClient.d.ts +88 -0
- package/dist/esm/http/httpClient.d.ts.map +1 -0
- package/dist/esm/http/httpClient.js +191 -0
- package/dist/esm/http/httpClient.js.map +1 -0
- package/dist/esm/index.d.ts +19 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +14 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/models/FetchedTranscript.d.ts +49 -0
- package/dist/esm/models/FetchedTranscript.d.ts.map +1 -0
- package/dist/esm/models/FetchedTranscript.js +76 -0
- package/dist/esm/models/FetchedTranscript.js.map +1 -0
- package/dist/esm/models/FetchedTranscriptSnippet.d.ts +15 -0
- package/dist/esm/models/FetchedTranscriptSnippet.d.ts.map +1 -0
- package/dist/esm/models/FetchedTranscriptSnippet.js +25 -0
- package/dist/esm/models/FetchedTranscriptSnippet.js.map +1 -0
- package/dist/esm/models/FormattedTranscript.d.ts +9 -0
- package/dist/esm/models/FormattedTranscript.d.ts.map +1 -0
- package/dist/esm/models/FormattedTranscript.js +2 -0
- package/dist/esm/models/FormattedTranscript.js.map +1 -0
- package/dist/esm/models/Transcript.d.ts +36 -0
- package/dist/esm/models/Transcript.d.ts.map +1 -0
- package/dist/esm/models/Transcript.js +71 -0
- package/dist/esm/models/Transcript.js.map +1 -0
- package/dist/esm/models/TranscriptList.d.ts +48 -0
- package/dist/esm/models/TranscriptList.d.ts.map +1 -0
- package/dist/esm/models/TranscriptList.js +79 -0
- package/dist/esm/models/TranscriptList.js.map +1 -0
- package/dist/esm/models/TranscriptMetadata.d.ts +10 -0
- package/dist/esm/models/TranscriptMetadata.d.ts.map +1 -0
- package/dist/esm/models/TranscriptMetadata.js +2 -0
- package/dist/esm/models/TranscriptMetadata.js.map +1 -0
- package/dist/esm/models/TranslationLanguage.d.ts +8 -0
- package/dist/esm/models/TranslationLanguage.d.ts.map +1 -0
- package/dist/esm/models/TranslationLanguage.js +2 -0
- package/dist/esm/models/TranslationLanguage.js.map +1 -0
- package/dist/esm/models/index.d.ts +8 -0
- package/dist/esm/models/index.d.ts.map +1 -0
- package/dist/esm/models/index.js +5 -0
- package/dist/esm/models/index.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/parsers/captionTrackParser.d.ts +29 -0
- package/dist/esm/parsers/captionTrackParser.d.ts.map +1 -0
- package/dist/esm/parsers/captionTrackParser.js +91 -0
- package/dist/esm/parsers/captionTrackParser.js.map +1 -0
- package/dist/esm/parsers/videoIdParser.d.ts +11 -0
- package/dist/esm/parsers/videoIdParser.d.ts.map +1 -0
- package/dist/esm/parsers/videoIdParser.js +61 -0
- package/dist/esm/parsers/videoIdParser.js.map +1 -0
- package/dist/esm/parsers/watchHtmlParser.d.ts +33 -0
- package/dist/esm/parsers/watchHtmlParser.d.ts.map +1 -0
- package/dist/esm/parsers/watchHtmlParser.js +70 -0
- package/dist/esm/parsers/watchHtmlParser.js.map +1 -0
- package/dist/esm/parsers/xmlTranscriptParser.d.ts +17 -0
- package/dist/esm/parsers/xmlTranscriptParser.d.ts.map +1 -0
- package/dist/esm/parsers/xmlTranscriptParser.js +81 -0
- package/dist/esm/parsers/xmlTranscriptParser.js.map +1 -0
- package/dist/esm/potoken/AutoPoTokenProvider.d.ts +28 -0
- package/dist/esm/potoken/AutoPoTokenProvider.d.ts.map +1 -0
- package/dist/esm/potoken/AutoPoTokenProvider.js +166 -0
- package/dist/esm/potoken/AutoPoTokenProvider.js.map +1 -0
- package/dist/esm/potoken/HttpPoTokenProvider.d.ts +41 -0
- package/dist/esm/potoken/HttpPoTokenProvider.d.ts.map +1 -0
- package/dist/esm/potoken/HttpPoTokenProvider.js +101 -0
- package/dist/esm/potoken/HttpPoTokenProvider.js.map +1 -0
- package/dist/esm/potoken/NoopPoTokenProvider.d.ts +12 -0
- package/dist/esm/potoken/NoopPoTokenProvider.d.ts.map +1 -0
- package/dist/esm/potoken/NoopPoTokenProvider.js +14 -0
- package/dist/esm/potoken/NoopPoTokenProvider.js.map +1 -0
- package/dist/esm/potoken/baseScriptCache.d.ts +28 -0
- package/dist/esm/potoken/baseScriptCache.d.ts.map +1 -0
- package/dist/esm/potoken/baseScriptCache.js +37 -0
- package/dist/esm/potoken/baseScriptCache.js.map +1 -0
- package/dist/esm/potoken/index.d.ts +10 -0
- package/dist/esm/potoken/index.d.ts.map +1 -0
- package/dist/esm/potoken/index.js +6 -0
- package/dist/esm/potoken/index.js.map +1 -0
- package/dist/esm/potoken/types.d.ts +40 -0
- package/dist/esm/potoken/types.d.ts.map +1 -0
- package/dist/esm/potoken/types.js +7 -0
- package/dist/esm/potoken/types.js.map +1 -0
- package/dist/esm/util/htmlSanitizer.d.ts +21 -0
- package/dist/esm/util/htmlSanitizer.d.ts.map +1 -0
- package/dist/esm/util/htmlSanitizer.js +69 -0
- package/dist/esm/util/htmlSanitizer.js.map +1 -0
- package/dist/esm/util/proxyUrl.d.ts +22 -0
- package/dist/esm/util/proxyUrl.d.ts.map +1 -0
- package/dist/esm/util/proxyUrl.js +39 -0
- package/dist/esm/util/proxyUrl.js.map +1 -0
- package/dist/esm/util/retry.d.ts +37 -0
- package/dist/esm/util/retry.d.ts.map +1 -0
- package/dist/esm/util/retry.js +60 -0
- package/dist/esm/util/retry.js.map +1 -0
- package/package.json +111 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HttpPoTokenProvider.js","sourceRoot":"","sources":["../../../src/potoken/HttpPoTokenProvider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NoopPoTokenProvider = void 0;
|
|
4
|
+
const index_js_1 = require("../errors/index.js");
|
|
5
|
+
/**
|
|
6
|
+
* Default PoToken provider — always throws.
|
|
7
|
+
*
|
|
8
|
+
* This preserves Python-library behavior: ANDROID InnerTube is used as
|
|
9
|
+
* the primary path, and PoToken is only required if the user explicitly
|
|
10
|
+
* opts in via a real provider.
|
|
11
|
+
*/
|
|
12
|
+
class NoopPoTokenProvider {
|
|
13
|
+
async generateForVideo(_videoId) {
|
|
14
|
+
throw new index_js_1.PoTokenRequired(_videoId);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.NoopPoTokenProvider = NoopPoTokenProvider;
|
|
18
|
+
//# sourceMappingURL=NoopPoTokenProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NoopPoTokenProvider.js","sourceRoot":"","sources":["../../../src/potoken/NoopPoTokenProvider.ts"],"names":[],"mappings":";;;AAAA,iDAAqD;AAGrD;;;;;;GAMG;AACH,MAAa,mBAAmB;IAC9B,KAAK,CAAC,gBAAgB,CAAC,QAAgB;QACrC,MAAM,IAAI,0BAAe,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC;CACF;AAJD,kDAIC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BaseScriptCache = void 0;
|
|
4
|
+
class BaseScriptCache {
|
|
5
|
+
ttlMs;
|
|
6
|
+
fetchImpl;
|
|
7
|
+
cached = null;
|
|
8
|
+
constructor(opts = {}) {
|
|
9
|
+
this.ttlMs = opts.ttlMs ?? 5 * 60 * 1000;
|
|
10
|
+
const f = opts.fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
11
|
+
if (!f) {
|
|
12
|
+
throw new Error('No fetch implementation available');
|
|
13
|
+
}
|
|
14
|
+
this.fetchImpl = f;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Get base.js content. Re-downloads when cache is stale or missing.
|
|
18
|
+
*/
|
|
19
|
+
async get(baseJsUrl) {
|
|
20
|
+
if (this.cached && Date.now() - this.cached.fetchedAt < this.ttlMs) {
|
|
21
|
+
return this.cached.content;
|
|
22
|
+
}
|
|
23
|
+
const response = await this.fetchImpl(baseJsUrl);
|
|
24
|
+
if (!response.ok) {
|
|
25
|
+
throw new Error(`Failed to fetch base.js: ${response.status} ${response.statusText}`);
|
|
26
|
+
}
|
|
27
|
+
const content = await response.text();
|
|
28
|
+
this.cached = { content, fetchedAt: Date.now() };
|
|
29
|
+
return content;
|
|
30
|
+
}
|
|
31
|
+
/** Force the next `get()` to re-download. */
|
|
32
|
+
invalidate() {
|
|
33
|
+
this.cached = null;
|
|
34
|
+
}
|
|
35
|
+
/** Inspect cache state (for tests). */
|
|
36
|
+
isFresh() {
|
|
37
|
+
return this.cached !== null && Date.now() - this.cached.fetchedAt < this.ttlMs;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.BaseScriptCache = BaseScriptCache;
|
|
41
|
+
//# sourceMappingURL=baseScriptCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseScriptCache.js","sourceRoot":"","sources":["../../../src/potoken/baseScriptCache.ts"],"names":[],"mappings":";;;AAcA,MAAa,eAAe;IACT,KAAK,CAAS;IACd,SAAS,CAAe;IACjC,MAAM,GAAkD,IAAI,CAAC;IAErE,YAAY,OAA+B,EAAE;QAC3C,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;QACzC,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC9D,IAAI,CAAC,CAAC,EAAE,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACvD,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,GAAG,CAAC,SAAiB;QACzB,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;YACnE,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;QAC7B,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACjD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,4BAA4B,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QACxF,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACtC,IAAI,CAAC,MAAM,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QACjD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,6CAA6C;IAC7C,UAAU;QACR,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACrB,CAAC;IAED,uCAAuC;IACvC,OAAO;QACL,OAAO,IAAI,CAAC,MAAM,KAAK,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC;IACjF,CAAC;CACF;AAvCD,0CAuCC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isTokenFresh = exports.BaseScriptCache = exports.AutoPoTokenProvider = exports.HttpPoTokenProvider = exports.NoopPoTokenProvider = void 0;
|
|
4
|
+
var NoopPoTokenProvider_js_1 = require("./NoopPoTokenProvider.js");
|
|
5
|
+
Object.defineProperty(exports, "NoopPoTokenProvider", { enumerable: true, get: function () { return NoopPoTokenProvider_js_1.NoopPoTokenProvider; } });
|
|
6
|
+
var HttpPoTokenProvider_js_1 = require("./HttpPoTokenProvider.js");
|
|
7
|
+
Object.defineProperty(exports, "HttpPoTokenProvider", { enumerable: true, get: function () { return HttpPoTokenProvider_js_1.HttpPoTokenProvider; } });
|
|
8
|
+
var AutoPoTokenProvider_js_1 = require("./AutoPoTokenProvider.js");
|
|
9
|
+
Object.defineProperty(exports, "AutoPoTokenProvider", { enumerable: true, get: function () { return AutoPoTokenProvider_js_1.AutoPoTokenProvider; } });
|
|
10
|
+
var baseScriptCache_js_1 = require("./baseScriptCache.js");
|
|
11
|
+
Object.defineProperty(exports, "BaseScriptCache", { enumerable: true, get: function () { return baseScriptCache_js_1.BaseScriptCache; } });
|
|
12
|
+
var types_js_1 = require("./types.js");
|
|
13
|
+
Object.defineProperty(exports, "isTokenFresh", { enumerable: true, get: function () { return types_js_1.isTokenFresh; } });
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/potoken/index.ts"],"names":[],"mappings":";;;AAAA,mEAA+D;AAAtD,6HAAA,mBAAmB,OAAA;AAC5B,mEAA+D;AAAtD,6HAAA,mBAAmB,OAAA;AAE5B,mEAA+D;AAAtD,6HAAA,mBAAmB,OAAA;AAE5B,2DAAuD;AAA9C,qHAAA,eAAe,OAAA;AAExB,uCAA0C;AAAjC,wGAAA,YAAY,OAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isTokenFresh = isTokenFresh;
|
|
4
|
+
/**
|
|
5
|
+
* Internal: returns true if a token is still fresh (with a safety margin).
|
|
6
|
+
*/
|
|
7
|
+
function isTokenFresh(result, safetyMarginMs = 60_000) {
|
|
8
|
+
return result.expiresAt.getTime() - safetyMarginMs > Date.now();
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/potoken/types.ts"],"names":[],"mappings":";;AAyCA,oCAEC;AALD;;GAEG;AACH,SAAgB,YAAY,CAAC,MAAmB,EAAE,iBAAyB,MAAM;IAC/E,OAAO,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;AAClE,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PRESERVED_FORMATTING_TAGS = void 0;
|
|
7
|
+
exports.sanitizeTranscriptText = sanitizeTranscriptText;
|
|
8
|
+
exports.decodeHtmlEntities = decodeHtmlEntities;
|
|
9
|
+
const he_1 = __importDefault(require("he"));
|
|
10
|
+
/**
|
|
11
|
+
* HTML / formatting helpers for transcript text.
|
|
12
|
+
*
|
|
13
|
+
* Mirrors the Python library's `_TranscriptParser`:
|
|
14
|
+
* - `he.decode` (equivalent to Python's `html.unescape`) for entity resolution
|
|
15
|
+
* - `preserveFormatting=true` keeps a small set of formatting tags and
|
|
16
|
+
* strips everything else (via negative-lookahead regex from Python source)
|
|
17
|
+
* - `preserveFormatting=false` strips every tag
|
|
18
|
+
*/
|
|
19
|
+
const FORMATTING_TAGS = [
|
|
20
|
+
'strong',
|
|
21
|
+
'em',
|
|
22
|
+
'b',
|
|
23
|
+
'i',
|
|
24
|
+
'mark',
|
|
25
|
+
'small',
|
|
26
|
+
'del',
|
|
27
|
+
'ins',
|
|
28
|
+
'sub',
|
|
29
|
+
'sup',
|
|
30
|
+
];
|
|
31
|
+
/** Regex that strips all HTML tags. */
|
|
32
|
+
const STRIP_ALL_TAGS_REGEX = /<[^>]*>/g;
|
|
33
|
+
/**
|
|
34
|
+
* Regex that strips every tag EXCEPT a small set of formatting tags.
|
|
35
|
+
*
|
|
36
|
+
* Constructed once at module load. Note: `[^>]*?` keeps each match confined
|
|
37
|
+
* to a single tag, so adjacent tags (e.g. `<font>x</font>`) are stripped
|
|
38
|
+
* independently rather than swallowed together.
|
|
39
|
+
*/
|
|
40
|
+
const STRIP_BUT_FORMATTING_REGEX = (() => {
|
|
41
|
+
const alt = FORMATTING_TAGS.join('|');
|
|
42
|
+
// Negative lookahead: don't match open/close of the formatting tags.
|
|
43
|
+
return new RegExp(`<\\/?(?!\\/?(${alt})\\b)[^>]*>`, 'gi');
|
|
44
|
+
})();
|
|
45
|
+
/**
|
|
46
|
+
* Sanitize a piece of HTML-formatted transcript text into plain text
|
|
47
|
+
* with HTML entities decoded.
|
|
48
|
+
*
|
|
49
|
+
* YouTube occasionally double-encodes entities (`&#39;` instead of `'`),
|
|
50
|
+
* so we decode repeatedly until the string stabilises (capped at 5 passes
|
|
51
|
+
* to defend against pathological cases).
|
|
52
|
+
*
|
|
53
|
+
* @param raw raw `<text>` inner content from the timedtext XML
|
|
54
|
+
* @param preserveFormatting when true, retain formatting tags listed above
|
|
55
|
+
*/
|
|
56
|
+
function sanitizeTranscriptText(raw, preserveFormatting = false) {
|
|
57
|
+
let unescaped = raw;
|
|
58
|
+
for (let i = 0; i < 5; i++) {
|
|
59
|
+
const next = he_1.default.decode(unescaped);
|
|
60
|
+
if (next === unescaped)
|
|
61
|
+
break;
|
|
62
|
+
unescaped = next;
|
|
63
|
+
}
|
|
64
|
+
const regex = preserveFormatting ? STRIP_BUT_FORMATTING_REGEX : STRIP_ALL_TAGS_REGEX;
|
|
65
|
+
return unescaped.replace(regex, '');
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Decode HTML entities only (no tag stripping). Useful for diagnostics.
|
|
69
|
+
*/
|
|
70
|
+
function decodeHtmlEntities(text) {
|
|
71
|
+
return he_1.default.decode(text);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Tags retained when `preserveFormatting=true`. Exposed for tests.
|
|
75
|
+
*/
|
|
76
|
+
exports.PRESERVED_FORMATTING_TAGS = FORMATTING_TAGS;
|
|
77
|
+
//# sourceMappingURL=htmlSanitizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"htmlSanitizer.js","sourceRoot":"","sources":["../../../src/util/htmlSanitizer.ts"],"names":[],"mappings":";;;;;;AAoDA,wDASC;AAKD,gDAEC;AApED,4CAAoB;AAEpB;;;;;;;;GAQG;AAEH,MAAM,eAAe,GAAG;IACtB,QAAQ;IACR,IAAI;IACJ,GAAG;IACH,GAAG;IACH,MAAM;IACN,OAAO;IACP,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;CACG,CAAC;AAEX,uCAAuC;AACvC,MAAM,oBAAoB,GAAG,UAAU,CAAC;AAExC;;;;;;GAMG;AACH,MAAM,0BAA0B,GAAW,CAAC,GAAG,EAAE;IAC/C,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtC,qEAAqE;IACrE,OAAO,IAAI,MAAM,CAAC,gBAAgB,GAAG,aAAa,EAAE,IAAI,CAAC,CAAC;AAC5D,CAAC,CAAC,EAAE,CAAC;AAEL;;;;;;;;;;GAUG;AACH,SAAgB,sBAAsB,CAAC,GAAW,EAAE,qBAA8B,KAAK;IACrF,IAAI,SAAS,GAAG,GAAG,CAAC;IACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,YAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAClC,IAAI,IAAI,KAAK,SAAS;YAAE,MAAM;QAC9B,SAAS,GAAG,IAAI,CAAC;IACnB,CAAC;IACD,MAAM,KAAK,GAAG,kBAAkB,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,oBAAoB,CAAC;IACrF,OAAO,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB,CAAC,IAAY;IAC7C,OAAO,YAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED;;GAEG;AACU,QAAA,yBAAyB,GAAsB,eAAe,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseProxyUrl = parseProxyUrl;
|
|
4
|
+
// Require either a protocol prefix OR a port. A bare hostname without protocol
|
|
5
|
+
// or port is ambiguous (looks like a URL fragment) so we reject it.
|
|
6
|
+
const PROXY_REGEX = /^(?:(https?|socks4?|socks5):\/\/)?(?:([^:@]+)(?::([^@]*))?@)?([^:\/\s]+)(?::(\d+))?\/?$/i;
|
|
7
|
+
/**
|
|
8
|
+
* Parse a proxy URL like `http://user:pass@host:1080` or `socks5://host:1080`.
|
|
9
|
+
*
|
|
10
|
+
* Returns `null` if the URL is malformed.
|
|
11
|
+
*/
|
|
12
|
+
function parseProxyUrl(url) {
|
|
13
|
+
if (typeof url !== 'string') {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
const trimmed = url.trim();
|
|
17
|
+
if (trimmed.length === 0) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
const match = PROXY_REGEX.exec(trimmed);
|
|
21
|
+
if (!match) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const [, proto, user, pass, host, port] = match;
|
|
25
|
+
if (!host) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
// Require either an explicit protocol or a port to disambiguate from
|
|
29
|
+
// arbitrary host strings.
|
|
30
|
+
if (!proto && !port) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const result = {
|
|
34
|
+
protocol: (proto ?? 'http').toLowerCase(),
|
|
35
|
+
host,
|
|
36
|
+
username: user || undefined,
|
|
37
|
+
password: pass || undefined,
|
|
38
|
+
port: port ? Number.parseInt(port, 10) : undefined,
|
|
39
|
+
};
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=proxyUrl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxyUrl.js","sourceRoot":"","sources":["../../../src/util/proxyUrl.ts"],"names":[],"mappings":";;AA0BA,sCA6BC;AAvCD,+EAA+E;AAC/E,oEAAoE;AACpE,MAAM,WAAW,GACf,0FAA0F,CAAC;AAE7F;;;;GAIG;AACH,SAAgB,aAAa,CAAC,GAAW;IACvC,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACxC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC;IAChD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,IAAI,CAAC;IACd,CAAC;IACD,qEAAqE;IACrE,0BAA0B;IAC1B,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,MAAM,GAAmB;QAC7B,QAAQ,EAAE,CAAC,KAAK,IAAI,MAAM,CAAC,CAAC,WAAW,EAAE;QACzC,IAAI;QACJ,QAAQ,EAAE,IAAI,IAAI,SAAS;QAC3B,QAAQ,EAAE,IAAI,IAAI,SAAS;QAC3B,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;KACnD,CAAC;IACF,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Exponential backoff helpers for HTTP retries.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.computeBackoffDelay = computeBackoffDelay;
|
|
7
|
+
exports.sleep = sleep;
|
|
8
|
+
exports.withRetry = withRetry;
|
|
9
|
+
/**
|
|
10
|
+
* Compute the delay before retry attempt `attempt` (1-indexed).
|
|
11
|
+
*/
|
|
12
|
+
function computeBackoffDelay(attempt, opts = {}) {
|
|
13
|
+
const base = opts.baseDelayMs ?? 500;
|
|
14
|
+
const cap = opts.maxDelayMs ?? 8_000;
|
|
15
|
+
const jitter = opts.jitter ?? 0.2;
|
|
16
|
+
const exp = Math.min(cap, base * 2 ** (attempt - 1));
|
|
17
|
+
const rand = 1 - jitter + Math.random() * jitter * 2;
|
|
18
|
+
return Math.round(exp * rand);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Sleep for `ms` milliseconds, or until `signal` is aborted.
|
|
22
|
+
*/
|
|
23
|
+
function sleep(ms, signal) {
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
if (signal?.aborted) {
|
|
26
|
+
reject(new Error('Aborted'));
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const id = setTimeout(() => {
|
|
30
|
+
signal?.removeEventListener('abort', onAbort);
|
|
31
|
+
resolve();
|
|
32
|
+
}, ms);
|
|
33
|
+
const onAbort = () => {
|
|
34
|
+
clearTimeout(id);
|
|
35
|
+
reject(new Error('Aborted'));
|
|
36
|
+
};
|
|
37
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Run `fn` with exponential backoff. Throws if all attempts fail.
|
|
42
|
+
*
|
|
43
|
+
* `shouldRetry` lets the caller decide which errors are retryable; by
|
|
44
|
+
* default any error is retried.
|
|
45
|
+
*/
|
|
46
|
+
async function withRetry(fn, opts = { maxAttempts: 1 }) {
|
|
47
|
+
const max = Math.max(1, opts.maxAttempts);
|
|
48
|
+
const shouldRetry = opts.shouldRetry ?? (() => true);
|
|
49
|
+
let lastErr;
|
|
50
|
+
for (let attempt = 1; attempt <= max; attempt++) {
|
|
51
|
+
try {
|
|
52
|
+
return await fn(attempt);
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
lastErr = err;
|
|
56
|
+
if (attempt >= max || !shouldRetry(err) || opts.signal?.aborted) {
|
|
57
|
+
throw err;
|
|
58
|
+
}
|
|
59
|
+
const delay = computeBackoffDelay(attempt, opts);
|
|
60
|
+
await sleep(delay, opts.signal);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
throw lastErr;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../../src/util/retry.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAoBH,kDAUC;AAKD,sBAgBC;AAQD,8BAoBC;AA9DD;;GAEG;AACH,SAAgB,mBAAmB,CACjC,OAAe,EACf,OAAuE,EAAE;IAEzE,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,IAAI,GAAG,CAAC;IACrC,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,IAAI,KAAK,CAAC;IACrC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC;IAClC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,CAAC;IACrD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,SAAgB,KAAK,CAAC,EAAU,EAAE,MAAoB;IACpD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;YAC7B,OAAO;QACT,CAAC;QACD,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE;YACzB,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9C,OAAO,EAAE,CAAC;QACZ,CAAC,EAAE,EAAE,CAAC,CAAC;QACP,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,YAAY,CAAC,EAAE,CAAC,CAAC;YACjB,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;QAC/B,CAAC,CAAC;QACF,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,SAAS,CAC7B,EAAmC,EACnC,OAAqB,EAAE,WAAW,EAAE,CAAC,EAAE;IAEvC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IACrD,IAAI,OAAgB,CAAC;IACrB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC;QAChD,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,GAAG,GAAG,CAAC;YACd,IAAI,OAAO,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;gBAChE,MAAM,GAAG,CAAC;YACZ,CAAC;YACD,MAAM,KAAK,GAAG,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YACjD,MAAM,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IACD,MAAM,OAAO,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type InnerTubeContext } from '../config/innerTubeContext.js';
|
|
2
|
+
import type { HttpClient } from '../http/httpClient.js';
|
|
3
|
+
import type { CaptionTrackJson } from '../parsers/captionTrackParser.js';
|
|
4
|
+
export interface InnerTubeClientOptions {
|
|
5
|
+
http: HttpClient;
|
|
6
|
+
/** PoToken (optional). When provided, attached to the WEB client body. */
|
|
7
|
+
poToken?: string;
|
|
8
|
+
/** visitorData (optional). */
|
|
9
|
+
visitorData?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface CaptionTracksResult {
|
|
12
|
+
readonly captionTracks: readonly CaptionTrackJson[];
|
|
13
|
+
readonly translationLanguages: ReadonlyArray<{
|
|
14
|
+
languageCode: string;
|
|
15
|
+
languageName: string;
|
|
16
|
+
}>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Thin InnerTube client implementing the ANDROID-first strategy.
|
|
20
|
+
*
|
|
21
|
+
* Mirrors the Python library's `_transcripts.TranscriptListFetcher._fetch_innertube_data`
|
|
22
|
+
* but with explicit client selection.
|
|
23
|
+
*/
|
|
24
|
+
export declare class InnerTubeClient {
|
|
25
|
+
private readonly http;
|
|
26
|
+
constructor(opts: InnerTubeClientOptions);
|
|
27
|
+
/**
|
|
28
|
+
* Fetch the watch HTML for a video id, returning the raw HTML.
|
|
29
|
+
*
|
|
30
|
+
* Performs EU-consent gate handling: if the response is the consent
|
|
31
|
+
* page, parses out the `v` form value and retries once with the
|
|
32
|
+
* CONSENT cookie set.
|
|
33
|
+
*/
|
|
34
|
+
fetchWatchHtml(videoId: string): Promise<string>;
|
|
35
|
+
/**
|
|
36
|
+
* Extract INNERTUBE_API_KEY from watch HTML.
|
|
37
|
+
*/
|
|
38
|
+
extractApiKey(html: string, videoId: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Issue an InnerTube player request with the given client context.
|
|
41
|
+
*/
|
|
42
|
+
fetchPlayer(videoId: string, apiKey: string, ctx: InnerTubeContext): Promise<unknown>;
|
|
43
|
+
/**
|
|
44
|
+
* Validate the player response and extract caption tracks.
|
|
45
|
+
*/
|
|
46
|
+
extractCaptionTracks(playerJson: unknown, videoId: string): CaptionTracksResult;
|
|
47
|
+
/**
|
|
48
|
+
* Fetch the timedtext XML for a single caption track.
|
|
49
|
+
*/
|
|
50
|
+
fetchTranscriptXml(baseUrl: string, videoId: string): Promise<string>;
|
|
51
|
+
/**
|
|
52
|
+
* Append `tlang=...` to a baseUrl for translation.
|
|
53
|
+
*/
|
|
54
|
+
buildTranslateUrl(baseUrl: string, targetLang: string): string;
|
|
55
|
+
private assertPlayability;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Map a generic HTTP failure status (after retries) to a specific error.
|
|
59
|
+
*/
|
|
60
|
+
export declare function mapHttpStatusToError(videoId: string, status: number, statusText: string, url: string): Error;
|
|
61
|
+
//# sourceMappingURL=InnerTubeClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InnerTubeClient.d.ts","sourceRoot":"","sources":["../../../src/api/InnerTubeClient.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,KAAK,gBAAgB,EAGtB,MAAM,+BAA+B,CAAC;AAWvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAQxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAYzE,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,UAAU,CAAC;IACjB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,aAAa,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACpD,QAAQ,CAAC,oBAAoB,EAAE,aAAa,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC9F;AAED;;;;;GAKG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;gBAEtB,IAAI,EAAE,sBAAsB;IAIxC;;;;;;OAMG;IACG,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA6BtD;;OAEG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;IAIpD;;OAEG;IACG,WAAW,CACf,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,OAAO,CAAC;IA8BnB;;OAEG;IACH,oBAAoB,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,mBAAmB;IAuB/E;;OAEG;IACG,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAS3E;;OAEG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;IAK9D,OAAO,CAAC,iBAAiB;CAmC1B;AAqBD;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,GACV,KAAK,CAKP"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { INNERTUBE_API_URL, WATCH_URL, } from '../config/constants.js';
|
|
2
|
+
import { clientNameHeader, clientVersionHeader, } from '../config/innerTubeContext.js';
|
|
3
|
+
import { BotDetected, FailedToCreateConsentCookie, IpBlocked, TranscriptsDisabled, VideoUnavailable, VideoUnplayable, YouTubeDataUnparsable, YouTubeRequestFailed, } from '../errors/index.js';
|
|
4
|
+
import { buildConsentCookieValue, extractConsentFormValue, extractInnertubeApiKey, isConsentGate, } from '../parsers/watchHtmlParser.js';
|
|
5
|
+
import { parseCaptionTracklist } from '../parsers/captionTrackParser.js';
|
|
6
|
+
/**
|
|
7
|
+
* Reason sent by InnerTube when BotGuard blocks the request.
|
|
8
|
+
*
|
|
9
|
+
* NOTE: the apostrophe is a U+2019 "RIGHT SINGLE QUOTATION MARK", not
|
|
10
|
+
* ASCII. This is the exact string returned by YouTube.
|
|
11
|
+
*/
|
|
12
|
+
const BOT_DETECT_REASON = 'Sign in to confirm you’re not a bot';
|
|
13
|
+
const AGE_RESTRICTED_REASON = 'This video may be inappropriate for some users.';
|
|
14
|
+
const VIDEO_UNAVAILABLE_REASON = 'This video is unavailable';
|
|
15
|
+
/**
|
|
16
|
+
* Thin InnerTube client implementing the ANDROID-first strategy.
|
|
17
|
+
*
|
|
18
|
+
* Mirrors the Python library's `_transcripts.TranscriptListFetcher._fetch_innertube_data`
|
|
19
|
+
* but with explicit client selection.
|
|
20
|
+
*/
|
|
21
|
+
export class InnerTubeClient {
|
|
22
|
+
http;
|
|
23
|
+
constructor(opts) {
|
|
24
|
+
this.http = opts.http;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Fetch the watch HTML for a video id, returning the raw HTML.
|
|
28
|
+
*
|
|
29
|
+
* Performs EU-consent gate handling: if the response is the consent
|
|
30
|
+
* page, parses out the `v` form value and retries once with the
|
|
31
|
+
* CONSENT cookie set.
|
|
32
|
+
*/
|
|
33
|
+
async fetchWatchHtml(videoId) {
|
|
34
|
+
const url = WATCH_URL.replace('{video_id}', videoId);
|
|
35
|
+
let html = await (await this.http.get(url)).text();
|
|
36
|
+
if (isConsentGate(html)) {
|
|
37
|
+
const v = extractConsentFormValue(html);
|
|
38
|
+
if (!v) {
|
|
39
|
+
throw new FailedToCreateConsentCookie(videoId);
|
|
40
|
+
}
|
|
41
|
+
// Set CONSENT cookie and re-fetch.
|
|
42
|
+
const cookieValue = buildConsentCookieValue(v);
|
|
43
|
+
// We poke the underlying cookie jar via an extra request that
|
|
44
|
+
// triggers ingestion; HttpClient stores cookies from Set-Cookie
|
|
45
|
+
// headers. Here we simulate by setting a request header that
|
|
46
|
+
// YouTube recognises.
|
|
47
|
+
html = await (await this.http.get(url, {
|
|
48
|
+
headers: { Cookie: `CONSENT=${cookieValue}` },
|
|
49
|
+
})).text();
|
|
50
|
+
if (isConsentGate(html)) {
|
|
51
|
+
throw new FailedToCreateConsentCookie(videoId);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return html;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Extract INNERTUBE_API_KEY from watch HTML.
|
|
58
|
+
*/
|
|
59
|
+
extractApiKey(html, videoId) {
|
|
60
|
+
return extractInnertubeApiKey(html, videoId);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Issue an InnerTube player request with the given client context.
|
|
64
|
+
*/
|
|
65
|
+
async fetchPlayer(videoId, apiKey, ctx) {
|
|
66
|
+
const url = INNERTUBE_API_URL.replace('{api_key}', apiKey);
|
|
67
|
+
const body = {
|
|
68
|
+
context: {
|
|
69
|
+
client: {
|
|
70
|
+
clientName: ctx.client.clientName,
|
|
71
|
+
clientVersion: ctx.client.clientVersion,
|
|
72
|
+
hl: ctx.client.hl,
|
|
73
|
+
gl: ctx.client.gl,
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
videoId,
|
|
77
|
+
};
|
|
78
|
+
if (ctx.client.androidSdkVersion !== undefined) {
|
|
79
|
+
body['context']['client'] = {
|
|
80
|
+
...body['context']['client'],
|
|
81
|
+
androidSdkVersion: ctx.client.androidSdkVersion,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
const headers = {
|
|
85
|
+
'X-YouTube-Client-Name': clientNameHeader(ctx),
|
|
86
|
+
'X-YouTube-Client-Version': clientVersionHeader(ctx),
|
|
87
|
+
};
|
|
88
|
+
if (ctx.client.userAgent) {
|
|
89
|
+
headers['User-Agent'] = ctx.client.userAgent;
|
|
90
|
+
}
|
|
91
|
+
const response = await this.http.postJson(url, body, { headers });
|
|
92
|
+
return response.json();
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Validate the player response and extract caption tracks.
|
|
96
|
+
*/
|
|
97
|
+
extractCaptionTracks(playerJson, videoId) {
|
|
98
|
+
if (typeof playerJson !== 'object' || playerJson === null) {
|
|
99
|
+
throw new YouTubeDataUnparsable(videoId, 'InnerTube response is not an object');
|
|
100
|
+
}
|
|
101
|
+
const data = playerJson;
|
|
102
|
+
this.assertPlayability(data['playabilityStatus'], videoId);
|
|
103
|
+
const captions = data['captions'];
|
|
104
|
+
if (typeof captions !== 'object' || captions === null) {
|
|
105
|
+
throw new TranscriptsDisabled(videoId);
|
|
106
|
+
}
|
|
107
|
+
const tracklistJson = captions['playerCaptionsTracklistRenderer'];
|
|
108
|
+
const parsed = parseCaptionTracklist(tracklistJson);
|
|
109
|
+
if (!parsed) {
|
|
110
|
+
throw new TranscriptsDisabled(videoId);
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
captionTracks: parsed.captionTracks,
|
|
114
|
+
translationLanguages: parsed.translationLanguages ?? [],
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Fetch the timedtext XML for a single caption track.
|
|
119
|
+
*/
|
|
120
|
+
async fetchTranscriptXml(baseUrl, videoId) {
|
|
121
|
+
if (baseUrl.includes('&exp=xpe')) {
|
|
122
|
+
const { PoTokenRequired } = await import('../errors/index.js');
|
|
123
|
+
throw new PoTokenRequired(videoId);
|
|
124
|
+
}
|
|
125
|
+
const response = await this.http.get(baseUrl);
|
|
126
|
+
return response.text();
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Append `tlang=...` to a baseUrl for translation.
|
|
130
|
+
*/
|
|
131
|
+
buildTranslateUrl(baseUrl, targetLang) {
|
|
132
|
+
const sep = baseUrl.includes('?') ? '&' : '?';
|
|
133
|
+
return `${baseUrl}${sep}tlang=${encodeURIComponent(targetLang)}`;
|
|
134
|
+
}
|
|
135
|
+
assertPlayability(playabilityStatus, videoId) {
|
|
136
|
+
if (typeof playabilityStatus !== 'object' || playabilityStatus === null)
|
|
137
|
+
return;
|
|
138
|
+
const ps = playabilityStatus;
|
|
139
|
+
const status = ps['status'];
|
|
140
|
+
if (status === 'OK' || status === undefined)
|
|
141
|
+
return;
|
|
142
|
+
const reason = typeof ps['reason'] === 'string' ? ps['reason'] : undefined;
|
|
143
|
+
if (status === 'LOGIN_REQUIRED') {
|
|
144
|
+
if (reason === BOT_DETECT_REASON) {
|
|
145
|
+
throw new BotDetected(videoId);
|
|
146
|
+
}
|
|
147
|
+
if (reason === AGE_RESTRICTED_REASON) {
|
|
148
|
+
// We don't model AgeRestricted as a class; use VideoUnplayable.
|
|
149
|
+
throw new VideoUnplayable(videoId, reason, []);
|
|
150
|
+
}
|
|
151
|
+
throw new VideoUnplayable(videoId, reason, extractSubreasons(ps));
|
|
152
|
+
}
|
|
153
|
+
if (status === 'ERROR') {
|
|
154
|
+
if (reason === VIDEO_UNAVAILABLE_REASON) {
|
|
155
|
+
if (videoId.startsWith('http://') || videoId.startsWith('https://')) {
|
|
156
|
+
// URL passed in — looks like an invalid id case.
|
|
157
|
+
throw new YouTubeDataUnparsable(videoId, 'video id looks like a URL');
|
|
158
|
+
}
|
|
159
|
+
throw new VideoUnavailable(videoId);
|
|
160
|
+
}
|
|
161
|
+
throw new VideoUnplayable(videoId, reason, extractSubreasons(ps));
|
|
162
|
+
}
|
|
163
|
+
throw new VideoUnplayable(videoId, reason, extractSubreasons(ps));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
function extractSubreasons(playabilityStatus) {
|
|
167
|
+
const errorScreen = playabilityStatus['errorScreen'];
|
|
168
|
+
if (typeof errorScreen !== 'object' || errorScreen === null)
|
|
169
|
+
return [];
|
|
170
|
+
const playerErr = errorScreen['playerErrorMessageRenderer'];
|
|
171
|
+
if (typeof playerErr !== 'object' || playerErr === null)
|
|
172
|
+
return [];
|
|
173
|
+
const subreason = playerErr['subreason'];
|
|
174
|
+
if (typeof subreason !== 'object' || subreason === null)
|
|
175
|
+
return [];
|
|
176
|
+
const runs = subreason['runs'];
|
|
177
|
+
if (!Array.isArray(runs))
|
|
178
|
+
return [];
|
|
179
|
+
const texts = [];
|
|
180
|
+
for (const run of runs) {
|
|
181
|
+
if (typeof run === 'object' && run !== null) {
|
|
182
|
+
const t = run['text'];
|
|
183
|
+
if (typeof t === 'string')
|
|
184
|
+
texts.push(t);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return texts;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Map a generic HTTP failure status (after retries) to a specific error.
|
|
191
|
+
*/
|
|
192
|
+
export function mapHttpStatusToError(videoId, status, statusText, url) {
|
|
193
|
+
if (status === 429) {
|
|
194
|
+
return new IpBlocked(videoId, status);
|
|
195
|
+
}
|
|
196
|
+
return new YouTubeRequestFailed(videoId, status, statusText, url);
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=InnerTubeClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InnerTubeClient.js","sourceRoot":"","sources":["../../../src/api/InnerTubeClient.ts"],"names":[],"mappings":"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"}
|