newleaf/tools/invidious_ported.py

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))