1- // This file is partially copied from: https://github.com/LuanRT/BgUtils/blob/main/examples/node/index.ts
1+ import { Innertube } from 'youtubei.js'
22
3- import fs from 'fs/promises'
4- import path from 'path'
5- import os from 'os'
6- import { Innertube , ProtoUtils , Utils , UniversalCache , Log } from 'youtubei.js'
7- import { BG , USER_AGENT } from 'bgutils-js'
8- import { JSDOM } from 'jsdom'
9-
10- let cacheDir = null
113let searchInnertube = null
12- let downloadInnertube = null
13- let downloadPoToken = null
14-
15- const createYtCacheDir = async ( ) => {
16- if ( cacheDir ) {
17- return
18- }
19-
20- cacheDir = await fs . mkdtemp ( path . join ( os . tmpdir ( ) , 'StemRoller-cache-' ) )
21- }
22-
23- export const deleteYtCacheDir = async ( ) => {
24- if ( ! cacheDir ) {
25- return
26- }
27-
28- try {
29- await fs . rm ( cacheDir , {
30- recursive : true ,
31- maxRetries : 5 ,
32- retryDelay : 1000 ,
33- } )
34- console . log ( `Deleted cache folder "${ cacheDir } "` )
35- } catch ( error ) {
36- console . trace ( error )
37- }
38- }
394
405const setupSearchInnertube = async ( ) => {
416 if ( searchInnertube ) {
@@ -45,46 +10,6 @@ const setupSearchInnertube = async () => {
4510 searchInnertube = await Innertube . create ( { retrieve_player : false } )
4611}
4712
48- const setupDownloadInnertube = async ( ) => {
49- if ( downloadInnertube ) {
50- return
51- }
52-
53- await setupSearchInnertube ( )
54-
55- if ( process . env . NODE_ENV === 'dev' ) {
56- Log . setLevel ( Log . Level . INFO )
57- } else {
58- Log . setLevel ( Log . Level . WARNING )
59- }
60-
61- const visitorData = ProtoUtils . encodeVisitorData (
62- Utils . generateRandomString ( 11 ) ,
63- Math . floor ( Date . now ( ) / 1000 )
64- )
65- downloadPoToken = await getPo ( visitorData )
66-
67- await createYtCacheDir ( )
68-
69- downloadInnertube = await Innertube . create ( {
70- po_token : downloadPoToken ,
71- visitor_data : visitorData ,
72- cache : new UniversalCache ( true , cacheDir ) ,
73- generate_session_locally : true ,
74- player_id : '0004de42' , // https://github.com/LuanRT/YouTube.js/issues/1043#issuecomment-3328154175
75- } )
76- }
77-
78- export const fetchYtStream = async ( videoId ) => {
79- await setupDownloadInnertube ( )
80-
81- const ytStream = await downloadInnertube . download ( videoId , {
82- type : 'audio' ,
83- } )
84-
85- return ytStream
86- }
87-
8813export const searchYt = async ( query ) => {
8914 await setupSearchInnertube ( )
9015
@@ -121,54 +46,8 @@ export const searchYt = async (query) => {
12146 return plainResults
12247}
12348
124- const getPo = async ( identifier ) => {
125- const dom = new JSDOM (
126- '<!DOCTYPE html><html lang="en"><head><title></title></head><body></body></html>' ,
127- {
128- url : 'https://www.youtube.com/' ,
129- referrer : 'https://www.youtube.com/' ,
130- userAgent : USER_AGENT ,
131- }
132- )
133- Object . assign ( globalThis , {
134- window : dom . window ,
135- document : dom . window . document ,
136- location : dom . window . location ,
137- origin : dom . window . origin ,
138- } )
139- if ( ! Reflect . has ( globalThis , 'navigator' ) ) {
140- Object . defineProperty ( globalThis , 'navigator' , { value : dom . window . navigator } )
141- }
142-
143- const requestKey = 'O43z0dpjhgX20SCx4KAo'
144-
145- const bgConfig = {
146- fetch,
147- globalObj : globalThis ,
148- requestKey,
149- identifier,
150- }
151-
152- const bgChallenge = await BG . Challenge . create ( bgConfig )
153-
154- if ( ! bgChallenge ) {
155- throw new Error ( 'Could not get challenge' )
156- }
157-
158- const interpreterJavascript =
159- bgChallenge . interpreterJavascript . privateDoNotAccessOrElseSafeScriptWrappedValue
160-
161- if ( interpreterJavascript ) {
162- new Function ( interpreterJavascript ) ( )
163- } else {
164- throw new Error ( 'Could not load VM' )
165- }
166-
167- const poTokenResult = await BG . PoToken . generate ( {
168- program : bgChallenge . program ,
169- globalName : bgChallenge . globalName ,
170- bgConfig,
171- } )
172-
173- return poTokenResult . poToken
49+ export const fetchYtStream = async ( videoId ) => {
50+ //
51+ // TODO
52+ //
17453}
0 commit comments