124 lines
4.5 KiB
Python
124 lines
4.5 KiB
Python
import os, subprocess, asyncio, json
|
|
|
|
async def nodeFetchInternal(url, data):
|
|
sp = await asyncio.create_subprocess_exec(
|
|
"node", "--disable-warning", "DEP0040", os.path.join(os.path.abspath(os.path.dirname(__file__)), "fetch-with-node/index.js"), url, data,
|
|
stdout=asyncio.subprocess.PIPE
|
|
)
|
|
|
|
out = await sp.stdout.read()
|
|
out = out.decode("utf-8").rstrip()
|
|
try:
|
|
asJson = json.loads(out)
|
|
except Exception:
|
|
print("ERROR")
|
|
print(out)
|
|
return None
|
|
return asJson
|
|
|
|
def nodeFetch(url, data):
|
|
return asyncio.run(nodeFetchInternal(url, data))
|
|
|
|
async def protodecInternal(input, flags):
|
|
sp = subprocess.Popen(
|
|
'echo \'' + input + '\' | ' + os.path.join(os.path.abspath(os.path.dirname(__file__)), "protodec") + ' ' + flags,
|
|
shell=True,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.STDOUT
|
|
)
|
|
|
|
out = sp.communicate()[0]
|
|
out = out.decode("utf-8").rstrip()
|
|
return out
|
|
|
|
def protodec(input, flags):
|
|
return asyncio.run(protodecInternal(input, flags))
|
|
|
|
###
|
|
|
|
defaultHeaders = {
|
|
"Accept-Encoding": "gzip, deflate, br",
|
|
"Accept-Language": "en-US,en;q=0.9",
|
|
"Content-Type": "application/json; charset=UTF-8",
|
|
"Cookie": "GPS=1; YSC=q6STb5ub1CU; VISITOR_INFO1_LIVE=Hbzrltf2qrk; VISITOR_PRIVACY_METADATA=CgJVUxIEGgAgCg%3D%3D; ",
|
|
"DNT": "1",
|
|
"Sec-Fetch-Dest": "document",
|
|
"Sec-Fetch-Mode": "navigate",
|
|
"Sec-Fetch-Site": "same-origin",
|
|
"User-Agent": "com.google.android.youtube/19.02.39 (Linux; U; Android 14) gzip",
|
|
#"x-goog-api-format-version" => "2",
|
|
#"x-youtube-client-name" => client_config.name_proto,
|
|
#"x-youtube-client-version" => client_config.version,
|
|
}
|
|
cachedInnertubeContent = {
|
|
"client": {
|
|
"hl":"en",
|
|
"gl":"US",
|
|
"remoteHost":"98.200.139.166",
|
|
"deviceMake":"",
|
|
"deviceModel":"",
|
|
"visitorData":"CgtIYnpybHRmMnFyayjf8s63BjIKCgJVUxIEGgAgCg%3D%3D",
|
|
"userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Firefox/102.0,gzip(gfe)",
|
|
"clientName":"WEB",
|
|
"clientVersion":"2.20240924.01.00",
|
|
"osName":"Windows",
|
|
"osVersion":"10.0",
|
|
"originalUrl":"https://www.youtube.com/",
|
|
"platform":"DESKTOP",
|
|
"clientFormFactor":"UNKNOWN_FORM_FACTOR",
|
|
"configInfo": {
|
|
"appInstallData":"CN_yzrcGEI3QsQUQ3-2wBRDh7LAFEMnmsAUQooGwBRCPw7EFEImnsQUQ6sOvBRCDvLEFEI2UsQUQws2xBRCI468FEJzRsQUQ782wBRCFp7EFEK7BsQUQ2cmvBRDvx7EFEJKusQUQxtCxBRCdprAFEO_LsQUQ7KixBRCEtrAFEIzNsQUQppKxBRCSwP8SEJ3QsAUQt-r-EhDwu7EFEJSJsQUQms6xBRComrAFENCNsAUQ49GwBRDbvrEFEKrYsAUQsO6wBRC9tq4FENPhrwUQppqwBRCinbEFEPirsQUQt--vBRCWlbAFEPSrsAUQhcOxBRDmz7EFEJmYsQUQ4tSuBRCNzLAFEP7XsAUQ47qxBRC9mbAFEMfUsQUQvYqwBRDW3bAFEOW5sQUQkMyxBRC8vrEFEIiHsAUQx8qxBRCHw7EFEN3o_hIQgsawBRD5zLEFEI_QsQUQieiuBRDRuLEFEOOVsAUQksuxBRDq0LEFENfprwUQr8exBRCKobEFEMX1sAUQydewBRDGpLEFEN6tsQUQ65mxBRDtubEFEMW_sQUQx-awBRDN17AFEMi_sQUQ86KxBRDM364FEJT-sAUQ9quwBRCBw7EFEKaTsQUQyfevBRDr6P4SENuvrwUQ28GxBRDiq7EFEPjGsQUQ_dGxBRD7rbEFEMvCsQUQ2dKxBRDszf8SENrNsQUqJENBTVNGeFVVcGIyd0ROemtCb096OUF2b3NRU3ctUTc1UWgwSA%3D%3D"
|
|
},
|
|
"userInterfaceTheme":"USER_INTERFACE_THEME_LIGHT",
|
|
"browserName":"Firefox",
|
|
"browserVersion":"102.0",
|
|
"acceptHeader":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
|
|
"deviceExperimentId":"ChxOelF4T0RRM05qZ3lPVE0zT0RBek16UTROZz09EN_yzrcGGN_yzrcG"
|
|
}
|
|
}
|
|
|
|
def browse(*kwargs, browseId=None, continuation=None, params=None):
|
|
data = {
|
|
"headers": defaultHeaders,
|
|
"referrer": "https://www.youtube.com/",
|
|
"referrerPolicy": "strict-origin-when-cross-origin",
|
|
"body": {
|
|
"context": cachedInnertubeContent
|
|
},
|
|
"method": "POST",
|
|
"mode": "cors"
|
|
}
|
|
|
|
if browseId is not None:
|
|
data["body"]["browseId"] = browseId
|
|
if continuation is not None:
|
|
data["body"]["continuation"] = continuation
|
|
if params is not None:
|
|
data["body"]["params"] = params
|
|
|
|
data["body"] = json.dumps(data["body"])
|
|
|
|
return nodeFetch("https://www.youtube.com/youtubei/v1/browse?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8", json.dumps(data))
|
|
|
|
def next(data=None, continuation=None):
|
|
newData = {
|
|
"headers": defaultHeaders,
|
|
"referrer": "https://www.youtube.com/",
|
|
"referrerPolicy": "strict-origin-when-cross-origin",
|
|
"body": {
|
|
"context": cachedInnertubeContent
|
|
},
|
|
"method": "POST",
|
|
"mode": "cors"
|
|
}
|
|
|
|
if data is not None:
|
|
for k in data:
|
|
newData["body"][k] = data[k]
|
|
if continuation is not None:
|
|
newData["body"]["continuation"] = continuation
|
|
|
|
newData["body"] = json.dumps(newData["body"])
|
|
|
|
return nodeFetch("https://www.youtube.com/youtubei/v1/next?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8", json.dumps(newData))
|