1 Commits

Author SHA1 Message Date
wukko
d3c41db99a api/services/youtube: force player_id
temporary workaround
2025-09-27 21:09:52 +03:00
4 changed files with 27 additions and 59 deletions

View File

@@ -39,7 +39,7 @@
"set-cookie-parser": "2.6.0",
"undici": "^6.21.3",
"url-pattern": "1.0.3",
"youtubei.js": "16.0.0",
"youtubei.js": "15.1.1",
"zod": "^3.23.8"
},
"optionalDependencies": {

View File

@@ -9,10 +9,6 @@ const defaultAgent = new Agent();
let session;
const validateSession = (sessionResponse) => {
sessionResponse.visitor_data ??= sessionResponse.contentBinding;
sessionResponse.potoken ??= sessionResponse.poToken;
sessionResponse.updated ??= new Date().getTime();
if (!sessionResponse.potoken) {
throw "no poToken in session response";
}
@@ -37,11 +33,11 @@ const updateSession = (newSession) => {
const loadSession = async () => {
const sessionServerUrl = new URL(env.ytSessionServer);
sessionServerUrl.pathname = "/get_pot";
sessionServerUrl.pathname = "/token";
const newSession = await fetch(
sessionServerUrl,
{ method: 'POST', dispatcher: defaultAgent }
{ dispatcher: defaultAgent }
).then(a => a.json());
validateSession(newSession);

View File

@@ -1,29 +1,12 @@
import HLS from "hls-parser";
import { fetch, Request } from "undici";
import { Innertube, Platform, Session } from "youtubei.js";
import { fetch } from "undici";
import { Innertube, Session } from "youtubei.js";
import { env } from "../../config.js";
import { getCookie } from "../cookie/manager.js";
import { getYouTubeSession } from "../helpers/youtube-session.js";
// https://github.com/LuanRT/YouTube.js/pull/1052
Platform.shim.eval = async (data, env) => {
const properties = [];
if (env.n) {
properties.push(`n: exportedVars.nFunction("${env.n}")`)
}
if (env.sig) {
properties.push(`sig: exportedVars.sigFunction("${env.sig}")`)
}
const code = `${data.output}\nreturn { ${properties.join(', ')} }`;
return new Function(code)();
}
const PLAYER_REFRESH_PERIOD = 1000 * 60 * 15; // ms
let innertube, lastRefreshedAt;
@@ -83,6 +66,7 @@ const cloneInnertube = async (customFetch, useSession) => {
cookie,
po_token: useSession ? sessionTokens?.potoken : undefined,
visitor_data: useSession ? sessionTokens?.visitor_data : undefined,
player_id : "0004de42",
});
lastRefreshedAt = +new Date();
}
@@ -223,24 +207,10 @@ export default async function (o) {
let yt;
try {
yt = await cloneInnertube(
(input, init) => {
const url = typeof input === 'string'
? new URL(input)
: input instanceof URL
? input
: new URL(input.url);
const request = new Request(
url,
input instanceof Platform.shim.Request
? input : undefined
);
return fetch(request, {
...init,
dispatcher: o.dispatcher
});
},
(input, init) => fetch(input, {
...init,
dispatcher: o.dispatcher
}),
useSession
);
} catch (e) {
@@ -560,7 +530,7 @@ export default async function (o) {
}
if (!clientsWithNoCipher.includes(innertubeClient) && innertube) {
urls = await audio.decipher(innertube.session.player);
urls = audio.decipher(innertube.session.player);
}
let cover = `https://i.ytimg.com/vi/${o.id}/maxresdefault.jpg`;
@@ -607,8 +577,8 @@ export default async function (o) {
filenameAttributes.extension = o.container === "auto" ? codecList[codec].container : o.container;
if (!clientsWithNoCipher.includes(innertubeClient) && innertube) {
video = await video.decipher(innertube.session.player);
audio = await audio.decipher(innertube.session.player);
video = video.decipher(innertube.session.player);
audio = audio.decipher(innertube.session.player);
} else {
video = video.url;
audio = audio.url;

26
pnpm-lock.yaml generated
View File

@@ -59,8 +59,8 @@ importers:
specifier: 1.0.3
version: 1.0.3
youtubei.js:
specifier: 16.0.0
version: 16.0.0
specifier: 15.1.1
version: 15.1.1
zod:
specifier: ^3.23.8
version: 3.23.8
@@ -1447,6 +1447,9 @@ packages:
resolution: {integrity: sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==}
engines: {node: 20 || >=22}
jintr@3.3.1:
resolution: {integrity: sha512-nnOzyhf0SLpbWuZ270Omwbj5LcXUkTcZkVnK8/veJXtSZOiATM5gMZMdmzN75FmTyj+NVgrGaPdH12zIJ24oIA==}
joycon@3.1.1:
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
engines: {node: '>=10'}
@@ -1535,10 +1538,6 @@ packages:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
meriyah@6.1.4:
resolution: {integrity: sha512-Sz8FzjzI0kN13GK/6MVEsVzMZEPvOhnmmI1lU5+/1cGOiK3QUahntrNNtdVeihrO7t9JpoH75iMNXg6R6uWflQ==}
engines: {node: '>=18.0.0'}
methods@1.1.2:
resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==}
engines: {node: '>= 0.6'}
@@ -2187,8 +2186,8 @@ packages:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
youtubei.js@16.0.0:
resolution: {integrity: sha512-aMx+ulnrxzsgVsxTr7gbBVnIjti2NQUlMwCoo1/MzICCJS3iMLOPUFdo7bSpwskL6ljzQ/LxmmB4WQC3FtkBlA==}
youtubei.js@15.1.1:
resolution: {integrity: sha512-fuEDj9Ky6cAQg93BrRVCbr+GTYNZQAIFZrx/a3oDRuGc3Mf5bS0dQfoYwwgjtSV7sgAKQEEdGtzRdBzOc8g72Q==}
zimmerframe@1.1.2:
resolution: {integrity: sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==}
@@ -3389,6 +3388,10 @@ snapshots:
dependencies:
'@isaacs/cliui': 8.0.2
jintr@3.3.1:
dependencies:
acorn: 8.14.0
joycon@3.1.1: {}
js-yaml@3.14.1:
@@ -3461,8 +3464,6 @@ snapshots:
merge2@1.4.1: {}
meriyah@6.1.4: {}
methods@1.1.2: {}
micromatch@4.0.7:
@@ -4043,10 +4044,11 @@ snapshots:
yocto-queue@0.1.0: {}
youtubei.js@16.0.0:
youtubei.js@15.1.1:
dependencies:
'@bufbuild/protobuf': 2.2.5
meriyah: 6.1.4
jintr: 3.3.1
undici: 6.21.3
zimmerframe@1.1.2: {}