33import fs from 'fs/promises'
44import path from 'path'
55import os from 'os'
6- import { Innertube , UniversalCache , Log } from 'youtubei.js'
7- import { BG } from 'bgutils-js'
6+ import { Innertube , ProtoUtils , Utils , UniversalCache , Log } from 'youtubei.js'
7+ import { BG , USER_AGENT } from 'bgutils-js'
88import { JSDOM } from 'jsdom'
9- import electronFetch from 'electron-fetch'
10- const fetch = electronFetch . default
11-
12- const REQUEST_KEY = 'O43z0dpjhgX20SCx4KAo'
139
1410let cacheDir = null
1511let searchInnertube = null
1612let downloadInnertube = null
13+ let downloadPoToken = null
1714
1815const createYtCacheDir = async ( ) => {
1916 if ( cacheDir ) {
@@ -61,47 +58,16 @@ const setupDownloadInnertube = async () => {
6158 Log . setLevel ( Log . Level . WARNING )
6259 }
6360
64- const visitorData = searchInnertube . session . context . client . visitorData
65- if ( ! visitorData ) {
66- throw new Error ( 'Could not get visitorData' )
67- }
68-
69- const dom = new JSDOM ( )
70- Object . assign ( globalThis , {
71- window : dom . window ,
72- document : dom . window . document ,
73- } )
74-
75- const bgConfig = {
76- fetch,
77- globalObj : globalThis ,
78- identifier : visitorData ,
79- requestKey : REQUEST_KEY ,
80- }
81-
82- const bgChallenge = await BG . Challenge . create ( bgConfig )
83- if ( ! bgChallenge ) {
84- throw new Error ( 'Could not get challenge' )
85- }
86-
87- const interpreterJavascript =
88- bgChallenge . interpreterJavascript . privateDoNotAccessOrElseSafeScriptWrappedValue
89- if ( interpreterJavascript ) {
90- new Function ( interpreterJavascript ) ( )
91- } else {
92- throw new Error ( 'Could not load VM' )
93- }
94-
95- const poTokenResult = await BG . PoToken . generate ( {
96- program : bgChallenge . program ,
97- globalName : bgChallenge . globalName ,
98- bgConfig,
99- } )
61+ const visitorData = ProtoUtils . encodeVisitorData (
62+ Utils . generateRandomString ( 11 ) ,
63+ Math . floor ( Date . now ( ) / 1000 )
64+ )
65+ downloadPoToken = await getPo ( visitorData )
10066
10167 await createYtCacheDir ( )
10268
10369 downloadInnertube = await Innertube . create ( {
104- po_token : poTokenResult . poToken ,
70+ po_token : downloadPoToken ,
10571 visitor_data : visitorData ,
10672 cache : new UniversalCache ( true , cacheDir ) ,
10773 generate_session_locally : true ,
@@ -113,7 +79,6 @@ export const fetchYtStream = async (videoId) => {
11379
11480 const ytStream = await downloadInnertube . download ( videoId , {
11581 type : 'audio' ,
116- quality : 'best' ,
11782 } )
11883
11984 return ytStream
@@ -154,3 +119,55 @@ export const searchYt = async (query) => {
154119
155120 return plainResults
156121}
122+
123+ const getPo = async ( identifier ) => {
124+ const dom = new JSDOM (
125+ '<!DOCTYPE html><html lang="en"><head><title></title></head><body></body></html>' ,
126+ {
127+ url : 'https://www.youtube.com/' ,
128+ referrer : 'https://www.youtube.com/' ,
129+ userAgent : USER_AGENT ,
130+ }
131+ )
132+ Object . assign ( globalThis , {
133+ window : dom . window ,
134+ document : dom . window . document ,
135+ location : dom . window . location ,
136+ origin : dom . window . origin ,
137+ } )
138+ if ( ! Reflect . has ( globalThis , 'navigator' ) ) {
139+ Object . defineProperty ( globalThis , 'navigator' , { value : dom . window . navigator } )
140+ }
141+
142+ const requestKey = 'O43z0dpjhgX20SCx4KAo'
143+
144+ const bgConfig = {
145+ fetch,
146+ globalObj : globalThis ,
147+ requestKey,
148+ identifier,
149+ }
150+
151+ const bgChallenge = await BG . Challenge . create ( bgConfig )
152+
153+ if ( ! bgChallenge ) {
154+ throw new Error ( 'Could not get challenge' )
155+ }
156+
157+ const interpreterJavascript =
158+ bgChallenge . interpreterJavascript . privateDoNotAccessOrElseSafeScriptWrappedValue
159+
160+ if ( interpreterJavascript ) {
161+ new Function ( interpreterJavascript ) ( )
162+ } else {
163+ throw new Error ( 'Could not load VM' )
164+ }
165+
166+ const poTokenResult = await BG . PoToken . generate ( {
167+ program : bgChallenge . program ,
168+ globalName : bgChallenge . globalName ,
169+ bgConfig,
170+ } )
171+
172+ return poTokenResult . poToken
173+ }
0 commit comments