Adjust for yt-dlp changes

This commit is contained in:
Simon Sawicki
2025-09-10 23:27:55 +02:00
parent 4d20e9a3a6
commit d7bb4cc0cb
8 changed files with 181 additions and 52 deletions

View File

@@ -3,9 +3,9 @@ requires = ["hatchling", "hatch-build-scripts"]
build-backend = "hatchling.build"
[project]
name = "yt-dlp-jsc-deno"
name = "yt-dlp-jsc"
version = "0.0.1"
description = "JavaScript Challenge Provider for yt-dlp using Deno"
description = "JavaScript Challenge Provider for yt-dlp supporting many runtimes"
readme = "README.md"
requires-python = ">=3.9"
license = "Unlicense"
@@ -16,7 +16,6 @@ authors = [
classifiers = [
"Development Status :: 4 - Beta",
"Programming Language :: Python",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
@@ -29,16 +28,18 @@ classifiers = [
dependencies = []
[project.urls]
Documentation = "https://github.com/yt-dlp/yt-dlp-jsc-deno#readme"
Issues = "https://github.com/yt-dlp/yt-dlp-jsc-deno/issues"
Source = "https://github.com/yt-dlp/yt-dlp-jsc-deno"
Documentation = "https://github.com/yt-dlp/yt-dlp-jsc#readme"
Issues = "https://github.com/yt-dlp/yt-dlp-jsc/issues"
Source = "https://github.com/yt-dlp/yt-dlp-jsc"
[[tool.hatch.build.hooks.build-scripts.scripts]]
work_dir = "dist"
out_dir = "yt_dlp_jsc_deno"
out_dir = "yt_dlp_jsc"
commands = [
"deno install",
"deno task bundle",
]
artifacts = [
"jsc-deno.js",
"jsc.min.js",
"lib.min.js",
]

View File

@@ -8,32 +8,30 @@ export default function main(input: Input): Output {
const solvers = getFromPrepared(preprocessedPlayer);
const responses = input.requests.map(
(request): JsChallengeProviderResponse => {
if (!isOneOf(request.type, "nsig", "sig")) {
(input): Response => {
if (!isOneOf(input.type, "nsig", "sig")) {
return {
type: "error",
request,
error: `Unknown request type: ${request.type}`,
error: `Unknown request type: ${input.type}`,
};
}
const solver = solvers[request.type];
const solver = solvers[input.type];
if (!solver) {
return {
type: "error",
request,
error: `Failed to extract ${request.type} function`,
error: `Failed to extract ${input.type} function`,
};
}
try {
return {
type: "result",
request,
response: solver(request.challenge),
data: Object.fromEntries(
input.challenges.map((challenge) => [challenge, solver(challenge)]),
),
};
} catch (error) {
return {
type: "error",
request,
error: error instanceof Error
? `${error.message}\n${error.stack}`
: `${error}`,
@@ -56,31 +54,27 @@ export type Input =
| {
type: "player";
player: string;
requests: JsChallengeRequest[];
requests: Request[];
output_preprocessed: boolean;
}
| {
type: "preprocessed";
preprocessed_player: string;
requests: JsChallengeRequest[];
requests: Request[];
};
type JsChallengeRequest = {
type: string;
challenge: string;
player_url: string;
video_id: string | null;
type Request = {
type: "nsig" | "sig";
challenges: string[];
};
type JsChallengeProviderResponse =
type Response =
| {
type: "result";
request: JsChallengeRequest;
response: string;
data: Record<string, string>;
}
| {
type: "error";
request: JsChallengeRequest;
error: string;
};
@@ -88,7 +82,7 @@ export type Output =
| {
type: "result";
preprocessed_player?: string;
responses: JsChallengeProviderResponse[];
responses: Response[];
}
| {
type: "error";

View File

@@ -25,14 +25,19 @@ export async function getIO(): Promise<IO> {
async function _getIO(): Promise<IO> {
if (globalThis.process?.release?.name === "node") {
// Assume node compatibility
const { readFile, writeFile, access } = await import("node:fs/promises");
const { access, readFile } = await import("node:fs/promises");
const { deepStrictEqual } = await import("node:assert");
const assert: Assert = {
equal: deepStrictEqual,
};
let test: Test;
let writeFile: (
file: string,
data: ReadableStream<Uint8Array>,
) => Promise<void>;
if (typeof globalThis.Deno !== "undefined") {
// deno does not like `node:test` for some reason
// Except for Deno, which does its own thing
writeFile = Deno.writeFile;
test = (name, func) => {
Deno.test(name, (t) => {
return func(assert, async (name, func): Promise<void> => {
@@ -44,6 +49,7 @@ async function _getIO(): Promise<IO> {
return Promise.resolve();
};
} else {
writeFile = (await import("node:fs/promises"))["writeFile"];
const { suite, test: subtest } = await import("node:test");
test = (name, func) => {
suite(name, () => {

View File

@@ -83,6 +83,126 @@ export const tests: {
},
],
},
{
// tce causes exception even in browser
player: "3752a005",
variants: ["main", "tcc", "es5", "es6", "tv", "tv_es6", "phone", "tablet"],
nsig: [
// Synthetic test
{ input: "0eRGgQWJGfT5rFHFj", expected: "j22ZtsqVsR0Dn" },
],
sig: [
// Synthetic test
{
input:
"MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
expected:
"ZJM_ucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHG6S7uYq4TGjQXSD4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
},
],
},
{
// tce causes exception even in browser
player: "afc7785b",
variants: ["main", "tcc", "es5", "es6", "tv", "tv_es6", "phone", "tablet"],
nsig: [
// Synthetic test
{ input: "0eRGgQWJGfT5rFHFj", expected: "j22ZtsqVsR0Dn" },
],
sig: [
// Synthetic test
{
input:
"MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
expected:
"ZJM_ucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHG6S7uYq4TGjQXSD4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
},
],
},
{
// tce causes exception even in browser
player: "b9645327",
variants: ["main", "tcc", "es5", "es6", "tv", "tv_es6", "phone", "tablet"],
nsig: [
// Synthetic test
{ input: "0eRGgQWJGfT5rFHFj", expected: "j22ZtsqVsR0Dn" },
],
sig: [
// Synthetic test
{
input:
"MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
expected:
"ZJM_ucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHG6S7uYq4TGjQXSD4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
},
],
},
{
// tce causes exception even in browser
player: "035b9195",
variants: ["main", "tcc", "es5", "es6", "tv", "tv_es6", "phone", "tablet"],
nsig: [
// Synthetic test
{ input: "0eRGgQWJGfT5rFHFj", expected: "j22ZtsqVsR0Dn" },
],
sig: [
// Synthetic test
{
input:
"MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
expected:
"ZJM_ucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHG6S7uYq4TGjQXSD4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
},
],
},
{
player: "6740c111",
nsig: [
// Synthetic test
{ input: "0eRGgQWJGfT5rFHFj", expected: "AVsXYE0uE1k8e" },
],
sig: [
// Synthetic test
{
input:
"MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
expected:
"JfQdSswRAIgMVVvrovTbw6UNh99kPa4D_XQjGT4qYu7S6SHM8EjoCACIEQnz-MKN5RgG6iUTnNJC58csYPSrnS_SzricuUMJZGn",
},
],
},
{
player: "f6a4f3bc",
nsig: [
// Synthetic test
{ input: "0eRGgQWJGfT5rFHFj", expected: "H1NKYFbhlqZ" },
],
sig: [
// Synthetic test
{
input:
"MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
expected:
"JfQdSswRAIgMVVvrovTbw6UNh99kPa4D_XQjGT4qYM7S6SHM8EjoCACIEQnz-nKM5RgG6iUTnNJC58cNYPSrnS_SzricuUMJZGu",
},
],
},
{
player: "b66835e2",
nsig: [
// Synthetic test
{ input: "0eRGgQWJGfT5rFHFj", expected: "H1NKYFbhlqZ" },
],
sig: [
// Synthetic test
{
input:
"MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
expected:
"JfQdSswRAIgMVVvrovTbw6UNh99kPa4D_XQjGT4qYM7S6SHM8EjoCACIEQnz-nKM5RgG6iUTnNJC58cNYPSrnS_SzricuUMJZGu",
},
],
},
];
export const players = new Map(

26
yt_dlp_jsc/__init__.py Normal file
View File

@@ -0,0 +1,26 @@
import importlib.resources
import importlib.metadata
import yt_dlp_jsc
version = importlib.metadata.version(yt_dlp_jsc.__name__)
def jsc() -> str:
"""
Read the contents of the JavaScript jsc bundle as string.
"""
return importlib.resources.read_text(yt_dlp_jsc, 'jsc.min.js')
def lib() -> str:
"""
Read the contents of the JavaScript library bundle as string.
"""
return importlib.resources.read_text(yt_dlp_jsc, 'lib.min.js')
__all__ = [
"jsc",
"lib",
"version",
]

1
yt_dlp_jsc/jsc.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
yt_dlp_jsc/lib.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,20 +0,0 @@
import importlib.resources
import importlib.metadata
import yt_dlp_jsc_deno
_name = "jsc-deno.js"
version = importlib.metadata.version(yt_dlp_jsc_deno.__name__)
def exists() -> bool:
return importlib.resources.is_resource(yt_dlp_jsc_deno, _name)
def read() -> str:
return importlib.resources.read_text(yt_dlp_jsc_deno, _name)
def path():
return importlib.resources.path(yt_dlp_jsc_deno, _name)