From 04d6974f502bbdfaed72c624344f262e30ad9708 Mon Sep 17 00:00:00 2001 From: bashonly <88596187+bashonly@users.noreply.github.com> Date: Tue, 17 Mar 2026 18:17:34 -0500 Subject: [PATCH] [ie/youtube] Update ejs to 0.8.0 (#16269) * Also default to `main` for `player_js_variant` extractor-arg Closes #16256 Authored by: bashonly, Grub4K Co-authored-by: Simon Sawicki --- Makefile | 6 +- README.md | 2 +- pyproject.toml | 2 +- test/test_jsc/test_ejs_integration.py | 60 ++++++++++++------- yt_dlp/extractor/youtube/_video.py | 2 +- .../youtube/jsc/_builtin/vendor/_info.py | 6 +- .../jsc/_builtin/vendor/yt.solver.core.js | 2 +- 7 files changed, 48 insertions(+), 32 deletions(-) diff --git a/Makefile b/Makefile index b4daeb88a4..de3eabd13b 100644 --- a/Makefile +++ b/Makefile @@ -202,9 +202,9 @@ CONTRIBUTORS: Changelog.md # The following EJS_-prefixed variables are auto-generated by devscripts/update_ejs.py # DO NOT EDIT! -EJS_VERSION = 0.7.0 -EJS_WHEEL_NAME = yt_dlp_ejs-0.7.0-py3-none-any.whl -EJS_WHEEL_HASH = sha256:967e9cbe114ddfd046ff4668af18b1827b4597e2e47a83deea668a355828c798 +EJS_VERSION = 0.8.0 +EJS_WHEEL_NAME = yt_dlp_ejs-0.8.0-py3-none-any.whl +EJS_WHEEL_HASH = sha256:79300e5fca7f937a1eeede11f0456862c1b41107ce1d726871e0207424f4bdb4 EJS_PY_FOLDERS = yt_dlp_ejs yt_dlp_ejs/yt yt_dlp_ejs/yt/solver EJS_PY_FILES = yt_dlp_ejs/__init__.py yt_dlp_ejs/_version.py yt_dlp_ejs/yt/__init__.py yt_dlp_ejs/yt/solver/__init__.py EJS_JS_FOLDERS = yt_dlp_ejs/yt/solver diff --git a/README.md b/README.md index b404c277f5..ec64c029ed 100644 --- a/README.md +++ b/README.md @@ -1865,7 +1865,7 @@ The following extractors use this feature: * `webpage_skip`: Skip extraction of embedded webpage data. One or both of `player_response`, `initial_data`. These options are for testing purposes and don't skip any network requests. Neither is skipped by default; however, if a `player_js_version` value other than `actual` is used, then `webpage_skip=player_response` is implied * `webpage_client`: Client to use for the video webpage request. One of `web` or `web_safari` (default) * `player_params`: YouTube player parameters to use for player requests. Will overwrite any default ones set by yt-dlp. -* `player_js_variant`: The player javascript variant to use for n/sig deciphering. The known variants are: `main`, `tcc`, `tce`, `es5`, `es6`, `es6_tcc`, `es6_tce`, `tv`, `tv_es6`, `phone`, `house`. The default is `tv`, and the others are for debugging purposes. You can use `actual` to go with what is prescribed by the site +* `player_js_variant`: The player javascript variant to use for n/sig deciphering. The known variants are: `main`, `tcc`, `tce`, `es5`, `es6`, `es6_tcc`, `es6_tce`, `tv`, `tv_es6`, `phone`, `house`. The default is `main`, and the others are for debugging purposes. You can use `actual` to go with what is prescribed by the site * `player_js_version`: The player javascript version to use for n/sig deciphering, in the format of `signature_timestamp@hash` (e.g. `20348@0004de42`). The default is to use what is prescribed by the site, and can be selected with `actual`. Using any other value will imply `webpage_skip=player_response` * `comment_sort`: `top` or `new` (default) - choose comment sorting mode (on YouTube's side) * `max_comments`: Limit the amount of comments to gather. Comma-separated list of integers representing `max-comments,max-parents,max-replies,max-replies-per-thread,max-depth`. Default is `all,all,all,all,all` diff --git a/pyproject.toml b/pyproject.toml index 8c8371f783..7feb739096 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,7 +55,7 @@ default = [ "requests>=2.32.2,<3", "urllib3>=2.0.2,<3", "websockets>=13.0", - "yt-dlp-ejs==0.7.0", + "yt-dlp-ejs==0.8.0", ] curl-cffi = [ "curl-cffi>=0.5.10,!=0.6.*,!=0.7.*,!=0.8.*,!=0.9.*,<0.15; implementation_name=='cpython'", diff --git a/test/test_jsc/test_ejs_integration.py b/test/test_jsc/test_ejs_integration.py index 30aee1b694..b2150e369e 100644 --- a/test/test_jsc/test_ejs_integration.py +++ b/test/test_jsc/test_ejs_integration.py @@ -53,50 +53,66 @@ class Challenge: CHALLENGES: list[Challenge] = [ - # 20518 - Challenge('edc3ba07', Variant.tv, JsChallengeType.N, { - 'BQoJvGBkC2nj1ZZLK-': '-m-se9fQVnvEofLx', - }), - Challenge('edc3ba07', Variant.tv, JsChallengeType.SIG, { - 'NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz': - 'zwg=wgwCHlydB9zg7PMegXoVzaoAXXB8woPSNZqRUC3Pe7vAEiApVSCMlh5mt5OX-8MB=tRPyyEdAM9MPM-kPfjgTxEK0IAhIgRwE0jiz', - }), - # 20521 - Challenge('316b61b4', Variant.tv, JsChallengeType.N, { - 'IlLiA21ny7gqA2m4p37': 'GchRcsUC_WmnhOUVGV', - }), - Challenge('316b61b4', Variant.tv, JsChallengeType.SIG, { - 'NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz': - 'tJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRN=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwz', - }), # 20522 - Challenge('74edf1a3', Variant.tv, JsChallengeType.N, { + Challenge('74edf1a3', Variant.main, JsChallengeType.N, { 'IlLiA21ny7gqA2m4p37': '9nRTxrbM1f0yHg', 'eabGFpsUKuWHXGh6FR4': 'izmYqDEY6kl7Sg', 'eabGF/ps%UK=uWHXGh6FR4': 'LACmqlhaBpiPlgE-a', }), - Challenge('74edf1a3', Variant.tv, JsChallengeType.SIG, { + Challenge('74edf1a3', Variant.main, JsChallengeType.SIG, { 'NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz': 'NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hzMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzl', '\x00\x01\x02%\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49': '\x00\x01\x02%\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x40\x41\x42\x49\x44\x45\x46\x47\x48\x43', }), # 20523 - Challenge('901741ab', Variant.tv, JsChallengeType.N, { + Challenge('901741ab', Variant.main, JsChallengeType.N, { 'BQoJvGBkC2nj1ZZLK-': 'UMPovvBZRh-sjb', }), - Challenge('901741ab', Variant.tv, JsChallengeType.SIG, { + Challenge('901741ab', Variant.main, JsChallengeType.SIG, { 'NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz': 'wgwCHlydB9Hg7PMegXoVzaoAXXB8woPSNZqRUC3Pe7vAEiApVSCMlhwmt5ON-8MB=5RPyyzdAM9MPM-kPfjgTxEK0IAhIgRwE0jiEJA', }), # 20524 - Challenge('e7573094', Variant.tv, JsChallengeType.N, { + Challenge('e7573094', Variant.main, JsChallengeType.N, { 'IlLiA21ny7gqA2m4p37': '3KuQ3235dojTSjo4', }), - Challenge('e7573094', Variant.tv, JsChallengeType.SIG, { + Challenge('e7573094', Variant.main, JsChallengeType.SIG, { 'NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz': 'yEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyNPRt=BM8-XO5tm5hlMCSVNAiEAvpeP3CURqZJSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=g', }), + # 20525 + Challenge('9fcf08e8', Variant.main, JsChallengeType.N, { + 'Dyc5ALyWiO0VqwCiT': 'H2PLmmAmJsYjKA', + }), + Challenge('9fcf08e8', Variant.main, JsChallengeType.SIG, { + '\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a': + '\x6a\x69\x68\x67\x66\x65\x64\x63\x62\x61\x60\x5f\x5e\x5d\x5c\x5b\x5a\x59\x58\x57\x56\x55\x54\x53\x52\x51\x50\x4f\x4e\x4d\x4c\x4b\x4a\x49\x48\x47\x46\x45\x44\x43\x42\x41\x40\x3f\x3e\x3d\x3c\x3b\x3a\x39\x38\x37\x36\x35\x34\x33\x32\x31\x30\x2f\x2e\x2d\x2c\x2b\x2a\x29\x28\x27\x26\x25\x24\x23\x22\x21\x20\x1f\x1e\x1d\x1c\x1b\x1a\x19\x18\x17\x16\x15\x14\x13\x12\x11\x10\x0f\x0e\x0d\x0c\x0b\x03\x09\x08\x07\x06\x05\x04\x0a', + }), + # 20527 + Challenge('21cd2156', Variant.main, JsChallengeType.N, { + 'CiOxDbW1WEE8Ti4w': 'ZcBE4klItiC4rQ', + }), + Challenge('21cd2156', Variant.main, JsChallengeType.SIG, { + '\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a': + '\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x00\x46\x47\x48\x49\x4a\x4b\x6a\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x4c', + }), + # 20528 + Challenge('5e55da5a', Variant.tv, JsChallengeType.N, { + 'FgTvzyq4jKv482R7': 'l26nyYSotkzDxg', + }), + Challenge('5e55da5a', Variant.tv, JsChallengeType.SIG, { + '\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a': + '\x46\x66\x65\x64\x63\x62\x61\x60\x5f\x5e\x67\x6a\x5b\x5a\x59\x58\x57\x56\x55\x54\x53\x52\x51\x50\x4f\x4e\x4d\x4c\x4b\x4a\x49\x48\x47\x2c\x45\x44\x43\x42\x41\x40\x3f\x3e\x3d\x3c\x3b\x3a\x39\x38\x13\x36\x35\x34\x33\x32\x31\x30\x2f\x2e\x2d\x5d\x2b\x2a\x29\x28\x27\x26\x25\x24\x23\x22\x21\x20\x1f\x1e\x1d\x1c\x1b\x1a\x19\x18\x17\x16\x15\x14\x0c\x12\x11\x10\x0f\x0e\x0d\x00\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x37', + }), + # 20529 + Challenge('631d3938', Variant.main, JsChallengeType.N, { + 'KBx1qz7jMhxELa8c': 'ttPvh7WIptsgSw', + }), + Challenge('631d3938', Variant.main, JsChallengeType.SIG, { + '\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66': + '\x19\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x00\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63', + }), ] requests: list[JsChallengeRequest] = [] diff --git a/yt_dlp/extractor/youtube/_video.py b/yt_dlp/extractor/youtube/_video.py index 174be95471..f12636d8cf 100644 --- a/yt_dlp/extractor/youtube/_video.py +++ b/yt_dlp/extractor/youtube/_video.py @@ -1876,7 +1876,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor): }] _DEFAULT_PLAYER_JS_VERSION = 'actual' - _DEFAULT_PLAYER_JS_VARIANT = 'tv' + _DEFAULT_PLAYER_JS_VARIANT = 'main' _PLAYER_JS_VARIANT_MAP = { 'main': 'player_ias.vflset/en_US/base.js', 'tcc': 'player_ias_tcc.vflset/en_US/base.js', diff --git a/yt_dlp/extractor/youtube/jsc/_builtin/vendor/_info.py b/yt_dlp/extractor/youtube/jsc/_builtin/vendor/_info.py index e23738eb28..087543974b 100644 --- a/yt_dlp/extractor/youtube/jsc/_builtin/vendor/_info.py +++ b/yt_dlp/extractor/youtube/jsc/_builtin/vendor/_info.py @@ -1,10 +1,10 @@ # This file is generated by devscripts/update_ejs.py. DO NOT MODIFY! -VERSION = '0.7.0' +VERSION = '0.8.0' HASHES = { 'yt.solver.bun.lib.js': '6ff45e94de9f0ea936a183c48173cfa9ce526ee4b7544cd556428427c1dd53c8073ef0174e79b320252bf0e7c64b0032cc1cf9c4358f3fda59033b7caa01c241', - 'yt.solver.core.js': '84e91a8ae91684272d11f1ef0970c757e9fec9ab277fb415b976c156163dde6ae2a9857c19c1ee21c9dcd01e2f89071098a1de2dc3072cf3ceeded84537db5e4', - 'yt.solver.core.min.js': 'd965ec01dcf44a0a9dea43f5935141c788471de9e8def5bf70d0b88ca656b79ca983d3e595f84b788d921dc98b900b7bf7380e9775ccb3b70a87c865482c71e3', + 'yt.solver.core.js': 'c163a6f376db6ce3da47d516a28a8f2a0554ae95c58dc766f0a6e2b3894f2cef1ee07fa84beb442fa471aac4f300985added1657c7c94c4d1cfefe68920ab599', + 'yt.solver.core.min.js': 'ee5b307d07f55e91e4723edf5ac205cc877a474187849d757dc1322e38427b157a9d706d510c1723d3670f98e5a3f8cbcde77874a80406bd7204bc9fea30f283', 'yt.solver.deno.lib.js': '9c8ee3ab6c23e443a5a951e3ac73c6b8c1c8fb34335e7058a07bf99d349be5573611de00536dcd03ecd3cf34014c4e9b536081de37af3637c5390c6a6fd6a0f0', 'yt.solver.lib.js': '1ee3753a8222fc855f5c39db30a9ccbb7967dbe1fb810e86dc9a89aa073a0907f294c720e9b65427d560a35aa1ce6af19ef854d9126a05ca00afe03f72047733', 'yt.solver.lib.min.js': '8420c259ad16e99ce004e4651ac1bcabb53b4457bf5668a97a9359be9a998a789fee8ab124ee17f91a2ea8fd84e0f2b2fc8eabcaf0b16a186ba734cf422ad053', diff --git a/yt_dlp/extractor/youtube/jsc/_builtin/vendor/yt.solver.core.js b/yt_dlp/extractor/youtube/jsc/_builtin/vendor/yt.solver.core.js index 31a20a0ff6..bbf5555dbf 100644 --- a/yt_dlp/extractor/youtube/jsc/_builtin/vendor/yt.solver.core.js +++ b/yt_dlp/extractor/youtube/jsc/_builtin/vendor/yt.solver.core.js @@ -175,7 +175,7 @@ var jsc = (function (meriyah, astring) { ); } const setupNodes = meriyah.parse( - `\nif (typeof globalThis.XMLHttpRequest === "undefined") {\n globalThis.XMLHttpRequest = { prototype: {} };\n}\nconst window = Object.create(null);\nif (typeof URL === "undefined") {\n window.location = {\n hash: "",\n host: "www.youtube.com",\n hostname: "www.youtube.com",\n href: "https://www.youtube.com/watch?v=yt-dlp-wins",\n origin: "https://www.youtube.com",\n password: "",\n pathname: "/watch",\n port: "",\n protocol: "https:",\n search: "?v=yt-dlp-wins",\n username: "",\n };\n} else {\n window.location = new URL("https://www.youtube.com/watch?v=yt-dlp-wins");\n}\nif (typeof globalThis.document === "undefined") {\n globalThis.document = Object.create(null);\n}\nif (typeof globalThis.navigator === "undefined") {\n globalThis.navigator = Object.create(null);\n}\nif (typeof globalThis.self === "undefined") {\n globalThis.self = globalThis;\n}\n`, + `\nif (typeof globalThis.XMLHttpRequest === "undefined") {\n globalThis.XMLHttpRequest = { prototype: {} };\n}\nif (typeof URL === "undefined") {\n globalThis.location = {\n hash: "",\n host: "www.youtube.com",\n hostname: "www.youtube.com",\n href: "https://www.youtube.com/watch?v=yt-dlp-wins",\n origin: "https://www.youtube.com",\n password: "",\n pathname: "/watch",\n port: "",\n protocol: "https:",\n search: "?v=yt-dlp-wins",\n username: "",\n };\n} else {\n globalThis.location = new URL("https://www.youtube.com/watch?v=yt-dlp-wins");\n}\nif (typeof globalThis.document === "undefined") {\n globalThis.document = Object.create(null);\n}\nif (typeof globalThis.navigator === "undefined") {\n globalThis.navigator = Object.create(null);\n}\nif (typeof globalThis.self === "undefined") {\n globalThis.self = globalThis;\n}\nif (typeof globalThis.window === "undefined") {\n globalThis.window = globalThis;\n}\n`, ).body; function _optionalChain(ops) { let lastAccessLHS = undefined;