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.
Files changed (323) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +337 -0
  3. package/dist/cjs/api/InnerTubeClient.js +236 -0
  4. package/dist/cjs/api/InnerTubeClient.js.map +1 -0
  5. package/dist/cjs/api/YouTubeTranscriptApi.js +160 -0
  6. package/dist/cjs/api/YouTubeTranscriptApi.js.map +1 -0
  7. package/dist/cjs/api/fetchStrategies.js +51 -0
  8. package/dist/cjs/api/fetchStrategies.js.map +1 -0
  9. package/dist/cjs/config/constants.js +34 -0
  10. package/dist/cjs/config/constants.js.map +1 -0
  11. package/dist/cjs/config/innerTubeContext.js +82 -0
  12. package/dist/cjs/config/innerTubeContext.js.map +1 -0
  13. package/dist/cjs/errors/BotDetected.js +20 -0
  14. package/dist/cjs/errors/BotDetected.js.map +1 -0
  15. package/dist/cjs/errors/FailedToCreateConsentCookie.js +17 -0
  16. package/dist/cjs/errors/FailedToCreateConsentCookie.js.map +1 -0
  17. package/dist/cjs/errors/InvalidVideoId.js +16 -0
  18. package/dist/cjs/errors/InvalidVideoId.js.map +1 -0
  19. package/dist/cjs/errors/IpBlocked.js +17 -0
  20. package/dist/cjs/errors/IpBlocked.js.map +1 -0
  21. package/dist/cjs/errors/NoTranscriptFound.js +23 -0
  22. package/dist/cjs/errors/NoTranscriptFound.js.map +1 -0
  23. package/dist/cjs/errors/NotTranslatable.js +15 -0
  24. package/dist/cjs/errors/NotTranslatable.js.map +1 -0
  25. package/dist/cjs/errors/PoTokenRequired.js +18 -0
  26. package/dist/cjs/errors/PoTokenRequired.js.map +1 -0
  27. package/dist/cjs/errors/TooManyRequests.js +19 -0
  28. package/dist/cjs/errors/TooManyRequests.js.map +1 -0
  29. package/dist/cjs/errors/TranscriptsDisabled.js +15 -0
  30. package/dist/cjs/errors/TranscriptsDisabled.js.map +1 -0
  31. package/dist/cjs/errors/TranslationLanguageNotAvailable.js +16 -0
  32. package/dist/cjs/errors/TranslationLanguageNotAvailable.js.map +1 -0
  33. package/dist/cjs/errors/VideoUnavailable.js +15 -0
  34. package/dist/cjs/errors/VideoUnavailable.js.map +1 -0
  35. package/dist/cjs/errors/VideoUnplayable.js +22 -0
  36. package/dist/cjs/errors/VideoUnplayable.js.map +1 -0
  37. package/dist/cjs/errors/YouTubeDataUnparsable.js +15 -0
  38. package/dist/cjs/errors/YouTubeDataUnparsable.js.map +1 -0
  39. package/dist/cjs/errors/YouTubeRequestFailed.js +18 -0
  40. package/dist/cjs/errors/YouTubeRequestFailed.js.map +1 -0
  41. package/dist/cjs/errors/YouTubeTranscriptError.js +19 -0
  42. package/dist/cjs/errors/YouTubeTranscriptError.js.map +1 -0
  43. package/dist/cjs/errors/index.js +34 -0
  44. package/dist/cjs/errors/index.js.map +1 -0
  45. package/dist/cjs/formatters/Formatter.js +3 -0
  46. package/dist/cjs/formatters/Formatter.js.map +1 -0
  47. package/dist/cjs/formatters/JSONFormatter.js +24 -0
  48. package/dist/cjs/formatters/JSONFormatter.js.map +1 -0
  49. package/dist/cjs/formatters/PrettyPrintFormatter.js +26 -0
  50. package/dist/cjs/formatters/PrettyPrintFormatter.js.map +1 -0
  51. package/dist/cjs/formatters/SRTFormatter.js +39 -0
  52. package/dist/cjs/formatters/SRTFormatter.js.map +1 -0
  53. package/dist/cjs/formatters/TextFormatter.js +20 -0
  54. package/dist/cjs/formatters/TextFormatter.js.map +1 -0
  55. package/dist/cjs/formatters/WebVTTFormatter.js +39 -0
  56. package/dist/cjs/formatters/WebVTTFormatter.js.map +1 -0
  57. package/dist/cjs/formatters/base.js +61 -0
  58. package/dist/cjs/formatters/base.js.map +1 -0
  59. package/dist/cjs/formatters/index.js +19 -0
  60. package/dist/cjs/formatters/index.js.map +1 -0
  61. package/dist/cjs/http/cookieJar.js +91 -0
  62. package/dist/cjs/http/cookieJar.js.map +1 -0
  63. package/dist/cjs/http/httpClient.js +228 -0
  64. package/dist/cjs/http/httpClient.js.map +1 -0
  65. package/dist/cjs/index.js +50 -0
  66. package/dist/cjs/index.js.map +1 -0
  67. package/dist/cjs/models/FetchedTranscript.js +80 -0
  68. package/dist/cjs/models/FetchedTranscript.js.map +1 -0
  69. package/dist/cjs/models/FetchedTranscriptSnippet.js +29 -0
  70. package/dist/cjs/models/FetchedTranscriptSnippet.js.map +1 -0
  71. package/dist/cjs/models/FormattedTranscript.js +3 -0
  72. package/dist/cjs/models/FormattedTranscript.js.map +1 -0
  73. package/dist/cjs/models/Transcript.js +75 -0
  74. package/dist/cjs/models/Transcript.js.map +1 -0
  75. package/dist/cjs/models/TranscriptList.js +84 -0
  76. package/dist/cjs/models/TranscriptList.js.map +1 -0
  77. package/dist/cjs/models/TranscriptMetadata.js +3 -0
  78. package/dist/cjs/models/TranscriptMetadata.js.map +1 -0
  79. package/dist/cjs/models/TranslationLanguage.js +3 -0
  80. package/dist/cjs/models/TranslationLanguage.js.map +1 -0
  81. package/dist/cjs/models/index.js +13 -0
  82. package/dist/cjs/models/index.js.map +1 -0
  83. package/dist/cjs/package.json +1 -0
  84. package/dist/cjs/parsers/captionTrackParser.js +96 -0
  85. package/dist/cjs/parsers/captionTrackParser.js.map +1 -0
  86. package/dist/cjs/parsers/videoIdParser.js +65 -0
  87. package/dist/cjs/parsers/videoIdParser.js.map +1 -0
  88. package/dist/cjs/parsers/watchHtmlParser.js +78 -0
  89. package/dist/cjs/parsers/watchHtmlParser.js.map +1 -0
  90. package/dist/cjs/parsers/xmlTranscriptParser.js +84 -0
  91. package/dist/cjs/parsers/xmlTranscriptParser.js.map +1 -0
  92. package/dist/cjs/potoken/AutoPoTokenProvider.js +203 -0
  93. package/dist/cjs/potoken/AutoPoTokenProvider.js.map +1 -0
  94. package/dist/cjs/potoken/HttpPoTokenProvider.js +105 -0
  95. package/dist/cjs/potoken/HttpPoTokenProvider.js.map +1 -0
  96. package/dist/cjs/potoken/NoopPoTokenProvider.js +18 -0
  97. package/dist/cjs/potoken/NoopPoTokenProvider.js.map +1 -0
  98. package/dist/cjs/potoken/baseScriptCache.js +41 -0
  99. package/dist/cjs/potoken/baseScriptCache.js.map +1 -0
  100. package/dist/cjs/potoken/index.js +14 -0
  101. package/dist/cjs/potoken/index.js.map +1 -0
  102. package/dist/cjs/potoken/types.js +10 -0
  103. package/dist/cjs/potoken/types.js.map +1 -0
  104. package/dist/cjs/util/htmlSanitizer.js +77 -0
  105. package/dist/cjs/util/htmlSanitizer.js.map +1 -0
  106. package/dist/cjs/util/proxyUrl.js +42 -0
  107. package/dist/cjs/util/proxyUrl.js.map +1 -0
  108. package/dist/cjs/util/retry.js +65 -0
  109. package/dist/cjs/util/retry.js.map +1 -0
  110. package/dist/esm/api/InnerTubeClient.d.ts +61 -0
  111. package/dist/esm/api/InnerTubeClient.d.ts.map +1 -0
  112. package/dist/esm/api/InnerTubeClient.js +198 -0
  113. package/dist/esm/api/InnerTubeClient.js.map +1 -0
  114. package/dist/esm/api/YouTubeTranscriptApi.d.ts +88 -0
  115. package/dist/esm/api/YouTubeTranscriptApi.d.ts.map +1 -0
  116. package/dist/esm/api/YouTubeTranscriptApi.js +157 -0
  117. package/dist/esm/api/YouTubeTranscriptApi.js.map +1 -0
  118. package/dist/esm/api/fetchStrategies.d.ts +20 -0
  119. package/dist/esm/api/fetchStrategies.d.ts.map +1 -0
  120. package/dist/esm/api/fetchStrategies.js +48 -0
  121. package/dist/esm/api/fetchStrategies.js.map +1 -0
  122. package/dist/esm/config/constants.d.ts +30 -0
  123. package/dist/esm/config/constants.d.ts.map +1 -0
  124. package/dist/esm/config/constants.js +31 -0
  125. package/dist/esm/config/constants.js.map +1 -0
  126. package/dist/esm/config/innerTubeContext.d.ts +47 -0
  127. package/dist/esm/config/innerTubeContext.d.ts.map +1 -0
  128. package/dist/esm/config/innerTubeContext.js +77 -0
  129. package/dist/esm/config/innerTubeContext.js.map +1 -0
  130. package/dist/esm/errors/BotDetected.d.ts +13 -0
  131. package/dist/esm/errors/BotDetected.d.ts.map +1 -0
  132. package/dist/esm/errors/BotDetected.js +16 -0
  133. package/dist/esm/errors/BotDetected.js.map +1 -0
  134. package/dist/esm/errors/FailedToCreateConsentCookie.d.ts +10 -0
  135. package/dist/esm/errors/FailedToCreateConsentCookie.d.ts.map +1 -0
  136. package/dist/esm/errors/FailedToCreateConsentCookie.js +13 -0
  137. package/dist/esm/errors/FailedToCreateConsentCookie.js.map +1 -0
  138. package/dist/esm/errors/InvalidVideoId.d.ts +9 -0
  139. package/dist/esm/errors/InvalidVideoId.d.ts.map +1 -0
  140. package/dist/esm/errors/InvalidVideoId.js +12 -0
  141. package/dist/esm/errors/InvalidVideoId.js.map +1 -0
  142. package/dist/esm/errors/IpBlocked.d.ts +10 -0
  143. package/dist/esm/errors/IpBlocked.d.ts.map +1 -0
  144. package/dist/esm/errors/IpBlocked.js +13 -0
  145. package/dist/esm/errors/IpBlocked.js.map +1 -0
  146. package/dist/esm/errors/NoTranscriptFound.d.ts +19 -0
  147. package/dist/esm/errors/NoTranscriptFound.d.ts.map +1 -0
  148. package/dist/esm/errors/NoTranscriptFound.js +19 -0
  149. package/dist/esm/errors/NoTranscriptFound.js.map +1 -0
  150. package/dist/esm/errors/NotTranslatable.d.ts +9 -0
  151. package/dist/esm/errors/NotTranslatable.d.ts.map +1 -0
  152. package/dist/esm/errors/NotTranslatable.js +11 -0
  153. package/dist/esm/errors/NotTranslatable.js.map +1 -0
  154. package/dist/esm/errors/PoTokenRequired.d.ts +10 -0
  155. package/dist/esm/errors/PoTokenRequired.d.ts.map +1 -0
  156. package/dist/esm/errors/PoTokenRequired.js +14 -0
  157. package/dist/esm/errors/PoTokenRequired.js.map +1 -0
  158. package/dist/esm/errors/TooManyRequests.d.ts +12 -0
  159. package/dist/esm/errors/TooManyRequests.d.ts.map +1 -0
  160. package/dist/esm/errors/TooManyRequests.js +15 -0
  161. package/dist/esm/errors/TooManyRequests.js.map +1 -0
  162. package/dist/esm/errors/TranscriptsDisabled.d.ts +9 -0
  163. package/dist/esm/errors/TranscriptsDisabled.d.ts.map +1 -0
  164. package/dist/esm/errors/TranscriptsDisabled.js +11 -0
  165. package/dist/esm/errors/TranscriptsDisabled.js.map +1 -0
  166. package/dist/esm/errors/TranslationLanguageNotAvailable.d.ts +9 -0
  167. package/dist/esm/errors/TranslationLanguageNotAvailable.d.ts.map +1 -0
  168. package/dist/esm/errors/TranslationLanguageNotAvailable.js +12 -0
  169. package/dist/esm/errors/TranslationLanguageNotAvailable.js.map +1 -0
  170. package/dist/esm/errors/VideoUnavailable.d.ts +9 -0
  171. package/dist/esm/errors/VideoUnavailable.d.ts.map +1 -0
  172. package/dist/esm/errors/VideoUnavailable.js +11 -0
  173. package/dist/esm/errors/VideoUnavailable.js.map +1 -0
  174. package/dist/esm/errors/VideoUnplayable.d.ts +12 -0
  175. package/dist/esm/errors/VideoUnplayable.d.ts.map +1 -0
  176. package/dist/esm/errors/VideoUnplayable.js +18 -0
  177. package/dist/esm/errors/VideoUnplayable.js.map +1 -0
  178. package/dist/esm/errors/YouTubeDataUnparsable.d.ts +9 -0
  179. package/dist/esm/errors/YouTubeDataUnparsable.d.ts.map +1 -0
  180. package/dist/esm/errors/YouTubeDataUnparsable.js +11 -0
  181. package/dist/esm/errors/YouTubeDataUnparsable.js.map +1 -0
  182. package/dist/esm/errors/YouTubeRequestFailed.d.ts +10 -0
  183. package/dist/esm/errors/YouTubeRequestFailed.d.ts.map +1 -0
  184. package/dist/esm/errors/YouTubeRequestFailed.js +14 -0
  185. package/dist/esm/errors/YouTubeRequestFailed.js.map +1 -0
  186. package/dist/esm/errors/YouTubeTranscriptError.d.ts +10 -0
  187. package/dist/esm/errors/YouTubeTranscriptError.d.ts.map +1 -0
  188. package/dist/esm/errors/YouTubeTranscriptError.js +15 -0
  189. package/dist/esm/errors/YouTubeTranscriptError.js.map +1 -0
  190. package/dist/esm/errors/index.d.ts +17 -0
  191. package/dist/esm/errors/index.d.ts.map +1 -0
  192. package/dist/esm/errors/index.js +16 -0
  193. package/dist/esm/errors/index.js.map +1 -0
  194. package/dist/esm/formatters/Formatter.d.ts +33 -0
  195. package/dist/esm/formatters/Formatter.d.ts.map +1 -0
  196. package/dist/esm/formatters/Formatter.js +2 -0
  197. package/dist/esm/formatters/Formatter.js.map +1 -0
  198. package/dist/esm/formatters/JSONFormatter.d.ts +10 -0
  199. package/dist/esm/formatters/JSONFormatter.d.ts.map +1 -0
  200. package/dist/esm/formatters/JSONFormatter.js +20 -0
  201. package/dist/esm/formatters/JSONFormatter.js.map +1 -0
  202. package/dist/esm/formatters/PrettyPrintFormatter.d.ts +15 -0
  203. package/dist/esm/formatters/PrettyPrintFormatter.d.ts.map +1 -0
  204. package/dist/esm/formatters/PrettyPrintFormatter.js +22 -0
  205. package/dist/esm/formatters/PrettyPrintFormatter.js.map +1 -0
  206. package/dist/esm/formatters/SRTFormatter.d.ts +22 -0
  207. package/dist/esm/formatters/SRTFormatter.d.ts.map +1 -0
  208. package/dist/esm/formatters/SRTFormatter.js +35 -0
  209. package/dist/esm/formatters/SRTFormatter.js.map +1 -0
  210. package/dist/esm/formatters/TextFormatter.d.ts +10 -0
  211. package/dist/esm/formatters/TextFormatter.d.ts.map +1 -0
  212. package/dist/esm/formatters/TextFormatter.js +16 -0
  213. package/dist/esm/formatters/TextFormatter.js.map +1 -0
  214. package/dist/esm/formatters/WebVTTFormatter.d.ts +22 -0
  215. package/dist/esm/formatters/WebVTTFormatter.d.ts.map +1 -0
  216. package/dist/esm/formatters/WebVTTFormatter.js +35 -0
  217. package/dist/esm/formatters/WebVTTFormatter.js.map +1 -0
  218. package/dist/esm/formatters/base.d.ts +25 -0
  219. package/dist/esm/formatters/base.d.ts.map +1 -0
  220. package/dist/esm/formatters/base.js +55 -0
  221. package/dist/esm/formatters/base.js.map +1 -0
  222. package/dist/esm/formatters/index.d.ts +8 -0
  223. package/dist/esm/formatters/index.d.ts.map +1 -0
  224. package/dist/esm/formatters/index.js +7 -0
  225. package/dist/esm/formatters/index.js.map +1 -0
  226. package/dist/esm/http/cookieJar.d.ts +39 -0
  227. package/dist/esm/http/cookieJar.d.ts.map +1 -0
  228. package/dist/esm/http/cookieJar.js +87 -0
  229. package/dist/esm/http/cookieJar.js.map +1 -0
  230. package/dist/esm/http/httpClient.d.ts +88 -0
  231. package/dist/esm/http/httpClient.d.ts.map +1 -0
  232. package/dist/esm/http/httpClient.js +191 -0
  233. package/dist/esm/http/httpClient.js.map +1 -0
  234. package/dist/esm/index.d.ts +19 -0
  235. package/dist/esm/index.d.ts.map +1 -0
  236. package/dist/esm/index.js +14 -0
  237. package/dist/esm/index.js.map +1 -0
  238. package/dist/esm/models/FetchedTranscript.d.ts +49 -0
  239. package/dist/esm/models/FetchedTranscript.d.ts.map +1 -0
  240. package/dist/esm/models/FetchedTranscript.js +76 -0
  241. package/dist/esm/models/FetchedTranscript.js.map +1 -0
  242. package/dist/esm/models/FetchedTranscriptSnippet.d.ts +15 -0
  243. package/dist/esm/models/FetchedTranscriptSnippet.d.ts.map +1 -0
  244. package/dist/esm/models/FetchedTranscriptSnippet.js +25 -0
  245. package/dist/esm/models/FetchedTranscriptSnippet.js.map +1 -0
  246. package/dist/esm/models/FormattedTranscript.d.ts +9 -0
  247. package/dist/esm/models/FormattedTranscript.d.ts.map +1 -0
  248. package/dist/esm/models/FormattedTranscript.js +2 -0
  249. package/dist/esm/models/FormattedTranscript.js.map +1 -0
  250. package/dist/esm/models/Transcript.d.ts +36 -0
  251. package/dist/esm/models/Transcript.d.ts.map +1 -0
  252. package/dist/esm/models/Transcript.js +71 -0
  253. package/dist/esm/models/Transcript.js.map +1 -0
  254. package/dist/esm/models/TranscriptList.d.ts +48 -0
  255. package/dist/esm/models/TranscriptList.d.ts.map +1 -0
  256. package/dist/esm/models/TranscriptList.js +79 -0
  257. package/dist/esm/models/TranscriptList.js.map +1 -0
  258. package/dist/esm/models/TranscriptMetadata.d.ts +10 -0
  259. package/dist/esm/models/TranscriptMetadata.d.ts.map +1 -0
  260. package/dist/esm/models/TranscriptMetadata.js +2 -0
  261. package/dist/esm/models/TranscriptMetadata.js.map +1 -0
  262. package/dist/esm/models/TranslationLanguage.d.ts +8 -0
  263. package/dist/esm/models/TranslationLanguage.d.ts.map +1 -0
  264. package/dist/esm/models/TranslationLanguage.js +2 -0
  265. package/dist/esm/models/TranslationLanguage.js.map +1 -0
  266. package/dist/esm/models/index.d.ts +8 -0
  267. package/dist/esm/models/index.d.ts.map +1 -0
  268. package/dist/esm/models/index.js +5 -0
  269. package/dist/esm/models/index.js.map +1 -0
  270. package/dist/esm/package.json +1 -0
  271. package/dist/esm/parsers/captionTrackParser.d.ts +29 -0
  272. package/dist/esm/parsers/captionTrackParser.d.ts.map +1 -0
  273. package/dist/esm/parsers/captionTrackParser.js +91 -0
  274. package/dist/esm/parsers/captionTrackParser.js.map +1 -0
  275. package/dist/esm/parsers/videoIdParser.d.ts +11 -0
  276. package/dist/esm/parsers/videoIdParser.d.ts.map +1 -0
  277. package/dist/esm/parsers/videoIdParser.js +61 -0
  278. package/dist/esm/parsers/videoIdParser.js.map +1 -0
  279. package/dist/esm/parsers/watchHtmlParser.d.ts +33 -0
  280. package/dist/esm/parsers/watchHtmlParser.d.ts.map +1 -0
  281. package/dist/esm/parsers/watchHtmlParser.js +70 -0
  282. package/dist/esm/parsers/watchHtmlParser.js.map +1 -0
  283. package/dist/esm/parsers/xmlTranscriptParser.d.ts +17 -0
  284. package/dist/esm/parsers/xmlTranscriptParser.d.ts.map +1 -0
  285. package/dist/esm/parsers/xmlTranscriptParser.js +81 -0
  286. package/dist/esm/parsers/xmlTranscriptParser.js.map +1 -0
  287. package/dist/esm/potoken/AutoPoTokenProvider.d.ts +28 -0
  288. package/dist/esm/potoken/AutoPoTokenProvider.d.ts.map +1 -0
  289. package/dist/esm/potoken/AutoPoTokenProvider.js +166 -0
  290. package/dist/esm/potoken/AutoPoTokenProvider.js.map +1 -0
  291. package/dist/esm/potoken/HttpPoTokenProvider.d.ts +41 -0
  292. package/dist/esm/potoken/HttpPoTokenProvider.d.ts.map +1 -0
  293. package/dist/esm/potoken/HttpPoTokenProvider.js +101 -0
  294. package/dist/esm/potoken/HttpPoTokenProvider.js.map +1 -0
  295. package/dist/esm/potoken/NoopPoTokenProvider.d.ts +12 -0
  296. package/dist/esm/potoken/NoopPoTokenProvider.d.ts.map +1 -0
  297. package/dist/esm/potoken/NoopPoTokenProvider.js +14 -0
  298. package/dist/esm/potoken/NoopPoTokenProvider.js.map +1 -0
  299. package/dist/esm/potoken/baseScriptCache.d.ts +28 -0
  300. package/dist/esm/potoken/baseScriptCache.d.ts.map +1 -0
  301. package/dist/esm/potoken/baseScriptCache.js +37 -0
  302. package/dist/esm/potoken/baseScriptCache.js.map +1 -0
  303. package/dist/esm/potoken/index.d.ts +10 -0
  304. package/dist/esm/potoken/index.d.ts.map +1 -0
  305. package/dist/esm/potoken/index.js +6 -0
  306. package/dist/esm/potoken/index.js.map +1 -0
  307. package/dist/esm/potoken/types.d.ts +40 -0
  308. package/dist/esm/potoken/types.d.ts.map +1 -0
  309. package/dist/esm/potoken/types.js +7 -0
  310. package/dist/esm/potoken/types.js.map +1 -0
  311. package/dist/esm/util/htmlSanitizer.d.ts +21 -0
  312. package/dist/esm/util/htmlSanitizer.d.ts.map +1 -0
  313. package/dist/esm/util/htmlSanitizer.js +69 -0
  314. package/dist/esm/util/htmlSanitizer.js.map +1 -0
  315. package/dist/esm/util/proxyUrl.d.ts +22 -0
  316. package/dist/esm/util/proxyUrl.d.ts.map +1 -0
  317. package/dist/esm/util/proxyUrl.js +39 -0
  318. package/dist/esm/util/proxyUrl.js.map +1 -0
  319. package/dist/esm/util/retry.d.ts +37 -0
  320. package/dist/esm/util/retry.d.ts.map +1 -0
  321. package/dist/esm/util/retry.js +60 -0
  322. package/dist/esm/util/retry.js.map +1 -0
  323. package/package.json +111 -0
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseCaptionTrack = parseCaptionTrack;
4
+ exports.parseTranslationLanguage = parseTranslationLanguage;
5
+ exports.parseCaptionTracklist = parseCaptionTracklist;
6
+ /**
7
+ * Helpers to convert the InnerTube `playerCaptionsTracklistRenderer` JSON
8
+ * into clean JS values.
9
+ *
10
+ * Mirrors the Python library's `TranscriptList.build`.
11
+ */
12
+ function readNameRuns(nameField) {
13
+ if (typeof nameField !== 'object' || nameField === null) {
14
+ return '';
15
+ }
16
+ const rec = nameField;
17
+ const runs = rec['runs'];
18
+ if (Array.isArray(runs) && runs.length > 0) {
19
+ const first = runs[0];
20
+ if (typeof first === 'object' && first !== null) {
21
+ const text = first['text'];
22
+ if (typeof text === 'string') {
23
+ return text;
24
+ }
25
+ }
26
+ }
27
+ const simpleText = rec['simpleText'];
28
+ if (typeof simpleText === 'string') {
29
+ return simpleText;
30
+ }
31
+ return '';
32
+ }
33
+ function parseCaptionTrack(node) {
34
+ if (typeof node !== 'object' || node === null)
35
+ return null;
36
+ const rec = node;
37
+ const baseUrl = rec['baseUrl'];
38
+ const languageCode = rec['languageCode'];
39
+ const vssId = rec['vssId'];
40
+ if (typeof baseUrl !== 'string' || typeof languageCode !== 'string' || typeof vssId !== 'string') {
41
+ return null;
42
+ }
43
+ // Strip the &fmt=srv3 flag so the response defaults to XML (mirrors Python).
44
+ const cleanBaseUrl = baseUrl.replace(/&fmt=srv3/g, '');
45
+ const kindRaw = rec['kind'];
46
+ const kind = kindRaw === 'asr' ? 'asr' : '';
47
+ return {
48
+ baseUrl: cleanBaseUrl,
49
+ languageCode,
50
+ name: readNameRuns(rec['name']),
51
+ kind,
52
+ isTranslatable: rec['isTranslatable'] === true,
53
+ vssId,
54
+ };
55
+ }
56
+ function parseTranslationLanguage(node) {
57
+ if (typeof node !== 'object' || node === null)
58
+ return null;
59
+ const rec = node;
60
+ const languageCode = rec['languageCode'];
61
+ if (typeof languageCode !== 'string')
62
+ return null;
63
+ return {
64
+ languageCode,
65
+ languageName: readNameRuns(rec['languageName']),
66
+ };
67
+ }
68
+ function parseCaptionTracklist(node) {
69
+ if (typeof node !== 'object' || node === null)
70
+ return null;
71
+ const rec = node;
72
+ const captionTracksRaw = rec['captionTracks'];
73
+ if (!Array.isArray(captionTracksRaw))
74
+ return null;
75
+ const captionTracks = [];
76
+ for (const ct of captionTracksRaw) {
77
+ const parsed = parseCaptionTrack(ct);
78
+ if (parsed)
79
+ captionTracks.push(parsed);
80
+ }
81
+ if (captionTracks.length === 0)
82
+ return null;
83
+ const translationLanguagesRaw = rec['translationLanguages'];
84
+ let translationLanguages = [];
85
+ if (Array.isArray(translationLanguagesRaw)) {
86
+ const list = [];
87
+ for (const tl of translationLanguagesRaw) {
88
+ const parsed = parseTranslationLanguage(tl);
89
+ if (parsed)
90
+ list.push(parsed);
91
+ }
92
+ translationLanguages = list;
93
+ }
94
+ return { captionTracks, translationLanguages };
95
+ }
96
+ //# sourceMappingURL=captionTrackParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"captionTrackParser.js","sourceRoot":"","sources":["../../../src/parsers/captionTrackParser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractVideoId = extractVideoId;
4
+ exports.tryExtractVideoId = tryExtractVideoId;
5
+ const constants_js_1 = require("../config/constants.js");
6
+ const index_js_1 = require("../errors/index.js");
7
+ /**
8
+ * Extract a YouTube video id from a string that is either:
9
+ * - a raw 11-character id
10
+ * - any common YouTube URL form (watch?v=, youtu.be/, /shorts/, /embed/, etc.)
11
+ *
12
+ * Mirrors the Python library's regex set (added in PR #282 by Tesla2000).
13
+ */
14
+ const URL_PATTERNS = [
15
+ // youtu.be/<id>
16
+ /(?:youtu\.be\/)([A-Za-z0-9_-]{11})/,
17
+ // youtube.com/shorts/<id>
18
+ /(?:youtube\.com\/shorts\/)([A-Za-z0-9_-]{11})/,
19
+ // youtube.com/embed/<id>
20
+ /(?:youtube\.com\/embed\/)([A-Za-z0-9_-]{11})/,
21
+ // youtube.com/v/<id>
22
+ /(?:youtube\.com\/v\/)([A-Za-z0-9_-]{11})/,
23
+ // music.youtube.com/watch?v=<id>
24
+ /(?:music\.youtube\.com\/watch\?v=)([A-Za-z0-9_-]{11})/,
25
+ // generic ?v=<id> or &v=<id>
26
+ /(?:\?v=|\&v=)([A-Za-z0-9_-]{11})/,
27
+ ];
28
+ /**
29
+ * Try to extract a video id from `input`.
30
+ *
31
+ * @throws InvalidVideoId if `input` is not a valid YouTube id or URL.
32
+ */
33
+ function extractVideoId(input) {
34
+ if (typeof input !== 'string') {
35
+ throw new index_js_1.InvalidVideoId(String(input));
36
+ }
37
+ const trimmed = input.trim();
38
+ if (trimmed.length === 0) {
39
+ throw new index_js_1.InvalidVideoId(input);
40
+ }
41
+ // Fast path: already a canonical id.
42
+ if (constants_js_1.VIDEO_ID_REGEX.test(trimmed)) {
43
+ return trimmed;
44
+ }
45
+ // Try URL patterns.
46
+ for (const re of URL_PATTERNS) {
47
+ const m = re.exec(trimmed);
48
+ if (m && m[1]) {
49
+ return m[1];
50
+ }
51
+ }
52
+ throw new index_js_1.InvalidVideoId(input);
53
+ }
54
+ /**
55
+ * Non-throwing variant of `extractVideoId`. Returns `null` on failure.
56
+ */
57
+ function tryExtractVideoId(input) {
58
+ try {
59
+ return extractVideoId(input);
60
+ }
61
+ catch {
62
+ return null;
63
+ }
64
+ }
65
+ //# sourceMappingURL=videoIdParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"videoIdParser.js","sourceRoot":"","sources":["../../../src/parsers/videoIdParser.ts"],"names":[],"mappings":";;AA8BA,wCAoBC;AAKD,8CAMC;AA7DD,yDAAwD;AACxD,iDAAoD;AAEpD;;;;;;GAMG;AACH,MAAM,YAAY,GAAsB;IACtC,gBAAgB;IAChB,oCAAoC;IACpC,0BAA0B;IAC1B,+CAA+C;IAC/C,yBAAyB;IACzB,8CAA8C;IAC9C,qBAAqB;IACrB,0CAA0C;IAC1C,iCAAiC;IACjC,uDAAuD;IACvD,6BAA6B;IAC7B,kCAAkC;CACnC,CAAC;AAEF;;;;GAIG;AACH,SAAgB,cAAc,CAAC,KAAa;IAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,yBAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1C,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,yBAAc,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;IACD,qCAAqC;IACrC,IAAI,6BAAc,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACjC,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,oBAAoB;IACpB,KAAK,MAAM,EAAE,IAAI,YAAY,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3B,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACd,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACd,CAAC;IACH,CAAC;IACD,MAAM,IAAI,yBAAc,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,SAAgB,iBAAiB,CAAC,KAAa;IAC7C,IAAI,CAAC;QACH,OAAO,cAAc,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CONSENT_FORM_VALUE_REGEX = exports.CONSENT_GATE_MARKER = void 0;
4
+ exports.isConsentGate = isConsentGate;
5
+ exports.isCaptchaGate = isCaptchaGate;
6
+ exports.extractInnertubeApiKey = extractInnertubeApiKey;
7
+ exports.extractConsentFormValue = extractConsentFormValue;
8
+ exports.buildConsentCookieValue = buildConsentCookieValue;
9
+ const index_js_1 = require("../errors/index.js");
10
+ /**
11
+ * Parse the YouTube watch HTML to extract the `INNERTUBE_API_KEY` and
12
+ * (optionally) the EU-consent gate parameters.
13
+ *
14
+ * Mirrors the Python library's `_extract_innertube_api_key`:
15
+ *
16
+ * pattern = r'"INNERTUBE_API_KEY":\s*"([a-zA-Z0-9_-]+)"'
17
+ *
18
+ * We also keep a couple of fallback patterns to make the parser resilient
19
+ * to YouTube's occasional A/B variations.
20
+ */
21
+ const API_KEY_PATTERNS = [
22
+ /"INNERTUBE_API_KEY":\s*"([A-Za-z0-9_-]+)"/,
23
+ /"innertubeApiKey":\s*"([A-Za-z0-9_-]+)"/,
24
+ /"key":\s*"([A-Za-z0-9_-]{20,})"/,
25
+ ];
26
+ /** Marker that indicates the EU consent gate is present. */
27
+ exports.CONSENT_GATE_MARKER = 'action="https://consent.youtube.com/s"';
28
+ /** Regex extracting the `v` form value used to mint the CONSENT cookie. */
29
+ exports.CONSENT_FORM_VALUE_REGEX = /name="v" value="([^"]+)"/;
30
+ /**
31
+ * Detect whether the watch HTML is the EU consent gate.
32
+ */
33
+ function isConsentGate(html) {
34
+ return html.includes(exports.CONSENT_GATE_MARKER);
35
+ }
36
+ /**
37
+ * Detect whether the watch HTML is a CAPTCHA / bot-detect page.
38
+ *
39
+ * Python library checks for `class="g-recaptcha"`; we extend slightly.
40
+ */
41
+ function isCaptchaGate(html) {
42
+ return html.includes('class="g-recaptcha"') || html.includes('class="rc-imageselect"');
43
+ }
44
+ /**
45
+ * Extract the `INNERTUBE_API_KEY` from watch HTML.
46
+ *
47
+ * @throws YouTubeDataUnparsable if no key is found.
48
+ * @throws IpBlocked (with statusCode undefined) if a CAPTCHA gate is detected.
49
+ */
50
+ function extractInnertubeApiKey(html, videoId) {
51
+ if (isCaptchaGate(html)) {
52
+ throw new index_js_1.IpBlocked(videoId);
53
+ }
54
+ for (const re of API_KEY_PATTERNS) {
55
+ const m = re.exec(html);
56
+ if (m && m[1]) {
57
+ return m[1];
58
+ }
59
+ }
60
+ throw new index_js_1.YouTubeDataUnparsable(videoId, 'INNERTUBE_API_KEY not found in watch HTML (YouTube may have changed the page format).');
61
+ }
62
+ /**
63
+ * Extract the `v` parameter from the EU consent form.
64
+ *
65
+ * @returns the raw `v` value, or `null` if not found.
66
+ */
67
+ function extractConsentFormValue(html) {
68
+ const m = exports.CONSENT_FORM_VALUE_REGEX.exec(html);
69
+ return m && m[1] ? m[1] : null;
70
+ }
71
+ /**
72
+ * Build a CONSENT cookie value in the format YouTube expects:
73
+ * `YES+<v>`
74
+ */
75
+ function buildConsentCookieValue(v) {
76
+ return `YES+${v}`;
77
+ }
78
+ //# sourceMappingURL=watchHtmlParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watchHtmlParser.js","sourceRoot":"","sources":["../../../src/parsers/watchHtmlParser.ts"],"names":[],"mappings":";;;AA6BA,sCAEC;AAOD,sCAEC;AAQD,wDAcC;AAOD,0DAGC;AAMD,0DAEC;AAhFD,iDAAsE;AAEtE;;;;;;;;;;GAUG;AAEH,MAAM,gBAAgB,GAAsB;IAC1C,2CAA2C;IAC3C,yCAAyC;IACzC,iCAAiC;CAClC,CAAC;AAEF,4DAA4D;AAC/C,QAAA,mBAAmB,GAAG,wCAAwC,CAAC;AAE5E,2EAA2E;AAC9D,QAAA,wBAAwB,GAAG,0BAA0B,CAAC;AAEnE;;GAEG;AACH,SAAgB,aAAa,CAAC,IAAY;IACxC,OAAO,IAAI,CAAC,QAAQ,CAAC,2BAAmB,CAAC,CAAC;AAC5C,CAAC;AAED;;;;GAIG;AACH,SAAgB,aAAa,CAAC,IAAY;IACxC,OAAO,IAAI,CAAC,QAAQ,CAAC,qBAAqB,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAC;AACzF,CAAC;AAED;;;;;GAKG;AACH,SAAgB,sBAAsB,CAAC,IAAY,EAAE,OAAe;IAClE,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,oBAAS,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IACD,KAAK,MAAM,EAAE,IAAI,gBAAgB,EAAE,CAAC;QAClC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACd,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACd,CAAC;IACH,CAAC;IACD,MAAM,IAAI,gCAAqB,CAC7B,OAAO,EACP,uFAAuF,CACxF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,uBAAuB,CAAC,IAAY;IAClD,MAAM,CAAC,GAAG,gCAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACjC,CAAC;AAED;;;GAGG;AACH,SAAgB,uBAAuB,CAAC,CAAS;IAC/C,OAAO,OAAO,CAAC,EAAE,CAAC;AACpB,CAAC"}
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseTranscriptXml = parseTranscriptXml;
4
+ const htmlSanitizer_js_1 = require("../util/htmlSanitizer.js");
5
+ /**
6
+ * Parse timedtext XML into a list of cues.
7
+ *
8
+ * Note on parsing strategy: timedtext XML uses HTML-like markup INSIDE
9
+ * the `<text>` element (e.g. `<text><b>bold</b></text>`). A strict XML
10
+ * parser would treat the inner `<b>` as a nested element and lose the
11
+ * mixed-content ordering. The Python library uses defusedxml, which has
12
+ * the same limitation; the sanitizer layer below strips tags afterward.
13
+ *
14
+ * To avoid that pitfall, we extract `<text>` elements with a regex,
15
+ * which preserves the inner HTML verbatim for the sanitizer to handle.
16
+ *
17
+ * Expected input shape:
18
+ *
19
+ * <transcript>
20
+ * <text start="0.0" dur="1.54">Hello</text>
21
+ * <text start="1.54" dur="2.0">With <b>bold</b></text>
22
+ * </transcript>
23
+ */
24
+ const TEXT_ELEMENT_REGEX = /<text\b([^>]*?)\/?>([\s\S]*?)<\/text>|<text\b([^>]*?)\/>/gi;
25
+ const ATTR_REGEX = /([a-zA-Z_][\w:-]*)\s*=\s*"([^"]*)"/g;
26
+ /**
27
+ * Parse the timedtext XML response body.
28
+ *
29
+ * @throws Error if the input is not a string with at least one `<text>` element.
30
+ */
31
+ function parseTranscriptXml(rawXml, opts = {}) {
32
+ if (typeof rawXml !== 'string' || rawXml.length === 0) {
33
+ throw new Error('Empty transcript XML');
34
+ }
35
+ // Sanity: must contain at least one <text tag; otherwise we treat as malformed.
36
+ if (!/<text\b/i.test(rawXml)) {
37
+ throw new Error('Transcript XML contains no <text> elements');
38
+ }
39
+ const preserveFormatting = opts.preserveFormatting === true;
40
+ const cues = [];
41
+ // Reset lastIndex to be safe.
42
+ TEXT_ELEMENT_REGEX.lastIndex = 0;
43
+ let match;
44
+ while ((match = TEXT_ELEMENT_REGEX.exec(rawXml)) !== null) {
45
+ // The regex captures either:
46
+ // match[1] = attrs, match[2] = inner content (paired <text>...</text>)
47
+ // or:
48
+ // match[3] = attrs (self-closing <text ... />)
49
+ const attrs = match[1] ?? match[3] ?? '';
50
+ const innerHtml = match[2] ?? '';
51
+ if (innerHtml.length === 0)
52
+ continue;
53
+ const { start, duration } = parseAttributes(attrs);
54
+ if (!Number.isFinite(start))
55
+ continue;
56
+ cues.push({
57
+ text: (0, htmlSanitizer_js_1.sanitizeTranscriptText)(innerHtml, preserveFormatting),
58
+ start,
59
+ duration,
60
+ });
61
+ }
62
+ return cues;
63
+ }
64
+ function parseAttributes(attrString) {
65
+ const map = {};
66
+ ATTR_REGEX.lastIndex = 0;
67
+ let m;
68
+ while ((m = ATTR_REGEX.exec(attrString)) !== null) {
69
+ const name = m[1];
70
+ const value = m[2];
71
+ if (name && value !== undefined) {
72
+ map[name] = value;
73
+ }
74
+ }
75
+ const startStr = map['start'];
76
+ const durStr = map['dur'];
77
+ const start = startStr !== undefined ? Number.parseFloat(startStr) : 0;
78
+ const duration = durStr !== undefined ? Number.parseFloat(durStr) : 0;
79
+ return {
80
+ start: Number.isFinite(start) ? start : 0,
81
+ duration: Number.isFinite(duration) ? duration : 0,
82
+ };
83
+ }
84
+ //# sourceMappingURL=xmlTranscriptParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xmlTranscriptParser.js","sourceRoot":"","sources":["../../../src/parsers/xmlTranscriptParser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,203 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.AutoPoTokenProvider = void 0;
37
+ const index_js_1 = require("../errors/index.js");
38
+ const types_js_1 = require("./types.js");
39
+ /**
40
+ * Self-contained PoToken provider.
41
+ *
42
+ * Uses `bgutils-js` (an optional dependency) to drive YouTube's BotGuard
43
+ * VM and mint PoTokens locally. No external service required.
44
+ *
45
+ * The visitorData is derived from the video id by default; pass a real
46
+ * one via `setVisitorData()` for stronger session-bound guarantees.
47
+ *
48
+ * Note: this provider requires the optional `bgutils-js` dependency. If
49
+ * it is not installed, generation throws `BotDetected`.
50
+ */
51
+ const WAA_API_KEY = 'AIzaSyDyT5W0Jh49F30Pqqtyfdf7pDLFKLJoAnw';
52
+ const REQUEST_KEY = 'O43z0dpjhgX20SCx4KAo';
53
+ const CHALLENGE_URL = 'https://jnn-pa.googleapis.com/$rpc/google.internal.waa.v1.Waa/Create';
54
+ /**
55
+ * Lazy import of bgutils-js. Throws if the package is not installed.
56
+ */
57
+ async function importBg() {
58
+ try {
59
+ const mod = (await Promise.resolve().then(() => __importStar(require('bgutils-js'))));
60
+ return mod.BG ?? mod;
61
+ }
62
+ catch {
63
+ return null;
64
+ }
65
+ }
66
+ class AutoPoTokenProvider {
67
+ fetchImpl;
68
+ ttlMs;
69
+ challengeTtlMs;
70
+ visitorData;
71
+ cache = null;
72
+ constructor(opts = {}) {
73
+ const f = opts.fetchImpl ?? globalThis.fetch.bind(globalThis);
74
+ if (!f) {
75
+ throw new Error('No fetch implementation available');
76
+ }
77
+ this.fetchImpl = f;
78
+ this.ttlMs = opts.ttlMs ?? 12 * 60 * 60 * 1000;
79
+ this.challengeTtlMs = opts.challengeTtlMs ?? 5 * 60 * 1000;
80
+ this.visitorData = opts.visitorData;
81
+ }
82
+ setVisitorData(visitorData) {
83
+ this.visitorData = visitorData;
84
+ }
85
+ /**
86
+ * Whether bgutils-js is installed and the provider is usable.
87
+ */
88
+ isAvailable() {
89
+ // Synchronous check via require cache is unreliable; the real check
90
+ // happens lazily in generateForVideo().
91
+ try {
92
+ require.resolve('bgutils-js');
93
+ return true;
94
+ }
95
+ catch {
96
+ return false;
97
+ }
98
+ }
99
+ async generateForVideo(videoId) {
100
+ if (this.cache?.lastVideoId === videoId &&
101
+ this.cache.lastTokenResult &&
102
+ (0, types_js_1.isTokenFresh)(this.cache.lastTokenResult, 60_000)) {
103
+ return this.cache.lastTokenResult;
104
+ }
105
+ const bg = await importBg();
106
+ if (!bg) {
107
+ throw new index_js_1.BotDetected(videoId);
108
+ }
109
+ const visitorData = this.visitorData ?? videoId;
110
+ try {
111
+ const challengeEntry = await this.getOrLoadChallenge(bg);
112
+ const botguard = await bg.BotGuardClient.create({
113
+ program: challengeEntry.challenge.program,
114
+ globalName: challengeEntry.challenge.globalName,
115
+ globalObj: challengeEntry.globalObj,
116
+ });
117
+ const result = await bg.PoToken.generate({
118
+ program: challengeEntry.challenge.program,
119
+ globalName: challengeEntry.challenge.globalName,
120
+ bgConfig: {
121
+ fetch: this.fetchImpl.bind(globalThis),
122
+ globalObj: challengeEntry.globalObj,
123
+ identifier: visitorData,
124
+ requestKey: REQUEST_KEY,
125
+ },
126
+ });
127
+ const tokenResult = {
128
+ poToken: result.poToken,
129
+ visitorData,
130
+ expiresAt: new Date(Date.now() + this.ttlMs),
131
+ };
132
+ this.cache = {
133
+ ...challengeEntry,
134
+ botguard,
135
+ lastVideoId: videoId,
136
+ lastTokenResult: tokenResult,
137
+ };
138
+ return tokenResult;
139
+ }
140
+ catch (err) {
141
+ if (err instanceof index_js_1.BotDetected)
142
+ throw err;
143
+ throw new index_js_1.BotDetected(videoId);
144
+ }
145
+ }
146
+ async dispose() {
147
+ if (this.cache?.botguard?.shutdown) {
148
+ try {
149
+ await this.cache.botguard.shutdown();
150
+ }
151
+ catch {
152
+ // ignore
153
+ }
154
+ }
155
+ this.cache = null;
156
+ }
157
+ async getOrLoadChallenge(bg) {
158
+ if (this.cache && Date.now() - this.cache.fetchedAt < this.challengeTtlMs) {
159
+ return this.cache;
160
+ }
161
+ const response = await this.fetchImpl(CHALLENGE_URL, {
162
+ method: 'POST',
163
+ headers: {
164
+ 'Content-Type': 'application/json+protobuf',
165
+ 'x-goog-api-key': WAA_API_KEY,
166
+ 'x-user-agent': 'grpc-web-javascript/0.1',
167
+ },
168
+ body: JSON.stringify([REQUEST_KEY]),
169
+ });
170
+ if (!response.ok) {
171
+ throw new index_js_1.BotDetected('__challenge__');
172
+ }
173
+ const rawData = (await response.json());
174
+ const parsed = bg.Challenge.parseChallengeData
175
+ ? bg.Challenge.parseChallengeData(rawData)
176
+ : rawData;
177
+ const challenge = parsed;
178
+ if (!challenge?.program || !challenge?.globalName) {
179
+ throw new index_js_1.BotDetected('__challenge__');
180
+ }
181
+ // Execute interpreter script to populate globalObj[globalName].
182
+ const globalObj = globalThis ?? {};
183
+ const script = challenge.interpreterJavascript.privateDoNotAccessOrElseSafeScriptWrappedValue;
184
+ if (typeof script === 'string' && script.length > 0 && !globalObj[challenge.globalName]) {
185
+ try {
186
+ new Function(script)();
187
+ }
188
+ catch {
189
+ throw new index_js_1.BotDetected('__challenge__');
190
+ }
191
+ }
192
+ const entry = {
193
+ challenge,
194
+ globalObj,
195
+ botguard: null,
196
+ fetchedAt: Date.now(),
197
+ };
198
+ this.cache = entry;
199
+ return entry;
200
+ }
201
+ }
202
+ exports.AutoPoTokenProvider = AutoPoTokenProvider;
203
+ //# sourceMappingURL=AutoPoTokenProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AutoPoTokenProvider.js","sourceRoot":"","sources":["../../../src/potoken/AutoPoTokenProvider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HttpPoTokenProvider = void 0;
4
+ const index_js_1 = require("../errors/index.js");
5
+ const types_js_1 = require("./types.js");
6
+ /**
7
+ * Talks to a `bgutil-ytdlp-pot-provider`-compatible HTTP endpoint to fetch
8
+ * PoTokens. Useful for users who already run the provider as a sidecar.
9
+ *
10
+ * Protocol (compatible with bgutil-ytdlp-pot-provider):
11
+ *
12
+ * POST {baseUrl}/get_pot
13
+ * Content-Type: application/json
14
+ * Body: { video_id, visitor_data? }
15
+ * → 200 { po_token, visitor_data, expiration? }
16
+ *
17
+ * If the server returns no token, throws `BotDetected`.
18
+ */
19
+ class HttpPoTokenProvider {
20
+ baseUrl;
21
+ timeoutMs;
22
+ fetchImpl;
23
+ ttlMs;
24
+ cache = null;
25
+ signal;
26
+ constructor(opts) {
27
+ if (!opts.baseUrl) {
28
+ throw new Error('HttpPoTokenProvider requires baseUrl');
29
+ }
30
+ this.baseUrl = opts.baseUrl.replace(/\/+$/, '');
31
+ this.timeoutMs = opts.timeoutMs ?? 30_000;
32
+ const f = opts.fetchImpl ?? globalThis.fetch.bind(globalThis);
33
+ if (!f) {
34
+ throw new Error('No fetch implementation available');
35
+ }
36
+ this.fetchImpl = f;
37
+ this.ttlMs = opts.ttlMs ?? 12 * 60 * 60 * 1000; // 12h default
38
+ this.signal = opts.signal;
39
+ }
40
+ async generateForVideo(videoId) {
41
+ if (this.cache && this.cache.videoId === videoId && (0, types_js_1.isTokenFresh)(this.cache.result)) {
42
+ return this.cache.result;
43
+ }
44
+ const controller = new AbortController();
45
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
46
+ this.signal?.addEventListener('abort', () => controller.abort(), { once: true });
47
+ try {
48
+ const response = await this.fetchImpl(`${this.baseUrl}/get_pot`, {
49
+ method: 'POST',
50
+ headers: { 'Content-Type': 'application/json' },
51
+ body: JSON.stringify({ video_id: videoId }),
52
+ signal: controller.signal,
53
+ });
54
+ if (!response.ok) {
55
+ throw new index_js_1.BotDetected(videoId);
56
+ }
57
+ const data = (await response.json());
58
+ if (!data.po_token || !data.visitor_data) {
59
+ throw new index_js_1.BotDetected(videoId);
60
+ }
61
+ const expiresAt = parseExpiration(data.expiration, this.ttlMs);
62
+ const result = {
63
+ poToken: data.po_token,
64
+ visitorData: data.visitor_data,
65
+ expiresAt,
66
+ };
67
+ this.cache = { videoId, result };
68
+ return result;
69
+ }
70
+ catch (err) {
71
+ if (err instanceof index_js_1.BotDetected)
72
+ throw err;
73
+ // Re-throw AbortError directly so tests / callers can distinguish
74
+ // timeout from other failures.
75
+ if (err instanceof Error && err.name === 'AbortError') {
76
+ throw new Error(`PoToken request timed out for video "${videoId}"`);
77
+ }
78
+ // Wrap network errors as BotDetected since they likely indicate the
79
+ // provider is down or unreachable.
80
+ if (process.env['DEBUG_POT']) {
81
+ console.error('[HttpPoTokenProvider] fetch failed:', err);
82
+ }
83
+ throw new index_js_1.BotDetected(videoId);
84
+ }
85
+ finally {
86
+ clearTimeout(timer);
87
+ }
88
+ }
89
+ async dispose() {
90
+ this.cache = null;
91
+ }
92
+ }
93
+ exports.HttpPoTokenProvider = HttpPoTokenProvider;
94
+ function parseExpiration(value, fallbackMs) {
95
+ if (typeof value === 'number') {
96
+ return new Date(value > 1e12 ? value : Date.now() + value);
97
+ }
98
+ if (typeof value === 'string') {
99
+ const parsed = Date.parse(value);
100
+ if (Number.isFinite(parsed))
101
+ return new Date(parsed);
102
+ }
103
+ return new Date(Date.now() + fallbackMs);
104
+ }
105
+ //# sourceMappingURL=HttpPoTokenProvider.js.map