mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2026-04-02 15:12:45 +00:00
Compare commits
3 Commits
3e36cf9cdb
...
990fdf36dd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
990fdf36dd | ||
|
|
92f1d99dbe | ||
|
|
db62e438a1 |
@ -874,3 +874,6 @@ LordMZTE
|
|||||||
regulad
|
regulad
|
||||||
stastix
|
stastix
|
||||||
syphyr
|
syphyr
|
||||||
|
FriederHannenheim
|
||||||
|
Peter-Devine
|
||||||
|
SparseOrnament15
|
||||||
|
|||||||
14
Changelog.md
14
Changelog.md
@ -4,6 +4,20 @@
|
|||||||
# To create a release, dispatch the https://github.com/yt-dlp/yt-dlp/actions/workflows/release.yml workflow on master
|
# To create a release, dispatch the https://github.com/yt-dlp/yt-dlp/actions/workflows/release.yml workflow on master
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
### 2026.03.13
|
||||||
|
|
||||||
|
#### Extractor changes
|
||||||
|
- **tiktok**: [Fix challenge solving](https://github.com/yt-dlp/yt-dlp/commit/db62e438a15743b156ca5ebfc6dbe160e9bc1662) ([#16223](https://github.com/yt-dlp/yt-dlp/issues/16223)) by [bashonly](https://github.com/bashonly)
|
||||||
|
- **youtube**
|
||||||
|
- [Fix `android_vr` player client](https://github.com/yt-dlp/yt-dlp/commit/ff459e5fc04b1a061212672626b7bfa23ff3cdcd) ([#16168](https://github.com/yt-dlp/yt-dlp/issues/16168)) by [gamer191](https://github.com/gamer191)
|
||||||
|
- [Fix `use_ad_playback_context` extractor-arg](https://github.com/yt-dlp/yt-dlp/commit/7e145ac1cae8f891e18c9375fa23097f1dfa0b19) ([#16196](https://github.com/yt-dlp/yt-dlp/issues/16196)) by [bashonly](https://github.com/bashonly)
|
||||||
|
- [Fix `web_embedded` player client](https://github.com/yt-dlp/yt-dlp/commit/f2bd3202c0ffa3f0c0069c44ca53b625dca568bc) ([#16177](https://github.com/yt-dlp/yt-dlp/issues/16177)) by [bashonly](https://github.com/bashonly), [SparseOrnament15](https://github.com/SparseOrnament15)
|
||||||
|
- [Request `web_safari` & `web_creator` client configs](https://github.com/yt-dlp/yt-dlp/commit/48a61d0f38b156785d24df628d42892441e008c4) ([#16198](https://github.com/yt-dlp/yt-dlp/issues/16198)) by [bashonly](https://github.com/bashonly)
|
||||||
|
- [Update ejs to 0.7.0](https://github.com/yt-dlp/yt-dlp/commit/92f1d99dbe1e10d942ef0963f625dbc5bc0768aa) ([#16231](https://github.com/yt-dlp/yt-dlp/issues/16231)) by [bashonly](https://github.com/bashonly), [Grub4K](https://github.com/Grub4K)
|
||||||
|
- tab
|
||||||
|
- [Fix album extraction](https://github.com/yt-dlp/yt-dlp/commit/ae025da02364f4d085953f41fd0d32ade3c4afb9) ([#16041](https://github.com/yt-dlp/yt-dlp/issues/16041)) by [FriederHannenheim](https://github.com/FriederHannenheim)
|
||||||
|
- [Improve description extraction](https://github.com/yt-dlp/yt-dlp/commit/3e36cf9cdb12ef566416c5620a1a95b5a0221017) ([#16057](https://github.com/yt-dlp/yt-dlp/issues/16057)) by [Peter-Devine](https://github.com/Peter-Devine)
|
||||||
|
|
||||||
### 2026.03.03
|
### 2026.03.03
|
||||||
|
|
||||||
#### Extractor changes
|
#### Extractor changes
|
||||||
|
|||||||
6
Makefile
6
Makefile
@ -202,9 +202,9 @@ CONTRIBUTORS: Changelog.md
|
|||||||
|
|
||||||
# The following EJS_-prefixed variables are auto-generated by devscripts/update_ejs.py
|
# The following EJS_-prefixed variables are auto-generated by devscripts/update_ejs.py
|
||||||
# DO NOT EDIT!
|
# DO NOT EDIT!
|
||||||
EJS_VERSION = 0.5.0
|
EJS_VERSION = 0.7.0
|
||||||
EJS_WHEEL_NAME = yt_dlp_ejs-0.5.0-py3-none-any.whl
|
EJS_WHEEL_NAME = yt_dlp_ejs-0.7.0-py3-none-any.whl
|
||||||
EJS_WHEEL_HASH = sha256:674fc0efea741d3100cdf3f0f9e123150715ee41edf47ea7a62fbdeda204bdec
|
EJS_WHEEL_HASH = sha256:967e9cbe114ddfd046ff4668af18b1827b4597e2e47a83deea668a355828c798
|
||||||
EJS_PY_FOLDERS = yt_dlp_ejs yt_dlp_ejs/yt yt_dlp_ejs/yt/solver
|
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_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
|
EJS_JS_FOLDERS = yt_dlp_ejs/yt/solver
|
||||||
|
|||||||
@ -1862,11 +1862,11 @@ The following extractors use this feature:
|
|||||||
* `skip`: One or more of `hls`, `dash` or `translated_subs` to skip extraction of the m3u8 manifests, dash manifests and [auto-translated subtitles](https://github.com/yt-dlp/yt-dlp/issues/4090#issuecomment-1158102032) respectively
|
* `skip`: One or more of `hls`, `dash` or `translated_subs` to skip extraction of the m3u8 manifests, dash manifests and [auto-translated subtitles](https://github.com/yt-dlp/yt-dlp/issues/4090#issuecomment-1158102032) respectively
|
||||||
* `player_client`: Clients to extract video data from. The currently available clients are `web`, `web_safari`, `web_embedded`, `web_music`, `web_creator`, `mweb`, `ios`, `android`, `android_vr`, `tv`, `tv_downgraded`, and `tv_simply`. By default, `android_vr,web,web_safari` is used. If no JavaScript runtime/engine is available, then only `android_vr` is used. If logged-in cookies are passed to yt-dlp, then `tv_downgraded,web,web_safari` is used for free accounts and `tv_downgraded,web_creator,web` is used for premium accounts. The `web_music` client is added for `music.youtube.com` URLs when logged-in cookies are used. The `web_embedded` client is added for age-restricted videos but only successfully works around the age-restriction sometimes (e.g. if the video is embeddable), and may be added as a fallback if `android_vr` is unable to access a video. The `web_creator` client is added for age-restricted videos if account age-verification is required. Some clients, such as `web_creator` and `web_music`, require a `po_token` for their formats to be downloadable. Some clients, such as `web_creator`, will only work with authentication. Not all clients support authentication via cookies. You can use `default` for the default clients, or you can use `all` for all clients (not recommended). You can prefix a client with `-` to exclude it, e.g. `youtube:player_client=default,-web`
|
* `player_client`: Clients to extract video data from. The currently available clients are `web`, `web_safari`, `web_embedded`, `web_music`, `web_creator`, `mweb`, `ios`, `android`, `android_vr`, `tv`, `tv_downgraded`, and `tv_simply`. By default, `android_vr,web,web_safari` is used. If no JavaScript runtime/engine is available, then only `android_vr` is used. If logged-in cookies are passed to yt-dlp, then `tv_downgraded,web,web_safari` is used for free accounts and `tv_downgraded,web_creator,web` is used for premium accounts. The `web_music` client is added for `music.youtube.com` URLs when logged-in cookies are used. The `web_embedded` client is added for age-restricted videos but only successfully works around the age-restriction sometimes (e.g. if the video is embeddable), and may be added as a fallback if `android_vr` is unable to access a video. The `web_creator` client is added for age-restricted videos if account age-verification is required. Some clients, such as `web_creator` and `web_music`, require a `po_token` for their formats to be downloadable. Some clients, such as `web_creator`, will only work with authentication. Not all clients support authentication via cookies. You can use `default` for the default clients, or you can use `all` for all clients (not recommended). You can prefix a client with `-` to exclude it, e.g. `youtube:player_client=default,-web`
|
||||||
* `player_skip`: Skip some network requests that are generally needed for robust extraction. One or more of `configs` (skip client configs), `webpage` (skip initial webpage), `js` (skip js player), `initial_data` (skip initial data/next ep request). While these options can help reduce the number of requests needed or avoid some rate-limiting, they could cause issues such as missing formats or metadata. See [#860](https://github.com/yt-dlp/yt-dlp/pull/860) and [#12826](https://github.com/yt-dlp/yt-dlp/issues/12826) for more details
|
* `player_skip`: Skip some network requests that are generally needed for robust extraction. One or more of `configs` (skip client configs), `webpage` (skip initial webpage), `js` (skip js player), `initial_data` (skip initial data/next ep request). While these options can help reduce the number of requests needed or avoid some rate-limiting, they could cause issues such as missing formats or metadata. See [#860](https://github.com/yt-dlp/yt-dlp/pull/860) and [#12826](https://github.com/yt-dlp/yt-dlp/issues/12826) for more details
|
||||||
* `webpage_skip`: Skip extraction of embedded webpage data. One or both of `player_response`, `initial_data`. Using these will not skip any network requests, and in some cases will result in additional network requests. Currently, the default is `player_response`; however, typically these are for testing purposes only
|
* `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)
|
* `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_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 `tv`, 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`). Currently, the default is to force `20514@9f4cc5e4`. 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)
|
* `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`
|
* `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`
|
||||||
* A `max-depth` value of `1` will discard all replies, regardless of the `max-replies` or `max-replies-per-thread` values given
|
* A `max-depth` value of `1` will discard all replies, regardless of the `max-replies` or `max-replies-per-thread` values given
|
||||||
|
|||||||
@ -55,7 +55,7 @@ default = [
|
|||||||
"requests>=2.32.2,<3",
|
"requests>=2.32.2,<3",
|
||||||
"urllib3>=2.0.2,<3",
|
"urllib3>=2.0.2,<3",
|
||||||
"websockets>=13.0",
|
"websockets>=13.0",
|
||||||
"yt-dlp-ejs==0.5.0",
|
"yt-dlp-ejs==0.7.0",
|
||||||
]
|
]
|
||||||
curl-cffi = [
|
curl-cffi = [
|
||||||
"curl-cffi>=0.5.10,!=0.6.*,!=0.7.*,!=0.8.*,!=0.9.*,<0.15; implementation_name=='cpython'",
|
"curl-cffi>=0.5.10,!=0.6.*,!=0.7.*,!=0.8.*,!=0.9.*,<0.15; implementation_name=='cpython'",
|
||||||
|
|||||||
@ -53,117 +53,49 @@ class Challenge:
|
|||||||
|
|
||||||
|
|
||||||
CHALLENGES: list[Challenge] = [
|
CHALLENGES: list[Challenge] = [
|
||||||
Challenge('3d3ba064', Variant.tce, JsChallengeType.N, {
|
# 20518
|
||||||
'ZdZIqFPQK-Ty8wId': 'qmtUsIz04xxiNW',
|
Challenge('edc3ba07', Variant.tv, JsChallengeType.N, {
|
||||||
'4GMrWHyKI5cEvhDO': 'N9gmEX7YhKTSmw',
|
'BQoJvGBkC2nj1ZZLK-': '-m-se9fQVnvEofLx',
|
||||||
}),
|
}),
|
||||||
Challenge('3d3ba064', Variant.tce, JsChallengeType.SIG, {
|
Challenge('edc3ba07', Variant.tv, JsChallengeType.SIG, {
|
||||||
'gN7a-hudCuAuPH6fByOk1_GNXN0yNMHShjZXS2VOgsEItAJz0tipeavEOmNdYN-wUtcEqD3bCXjc0iyKfAyZxCBGgIARwsSdQfJ2CJtt':
|
|
||||||
'ttJC2JfQdSswRAIgGBCxZyAfKyi0cjXCb3gqEctUw-NYdNmOEvaepit0zJAtIEsgOV2SXZjhSHMNy0NXNG_1kNyBf6HPuAuCduh-a7O',
|
|
||||||
}),
|
|
||||||
Challenge('5ec65609', Variant.tce, JsChallengeType.N, {
|
|
||||||
'0eRGgQWJGfT5rFHFj': '4SvMpDQH-vBJCw',
|
|
||||||
}),
|
|
||||||
Challenge('5ec65609', Variant.tce, JsChallengeType.SIG, {
|
|
||||||
'AAJAJfQdSswRQIhAMG5SN7-cAFChdrE7tLA6grH0rTMICA1mmDc0HoXgW3CAiAQQ4=CspfaF_vt82XH5yewvqcuEkvzeTsbRuHssRMyJQ=I':
|
|
||||||
'AJfQdSswRQIhAMG5SN7-cAFChdrE7tLA6grI0rTMICA1mmDc0HoXgW3CAiAQQ4HCspfaF_vt82XH5yewvqcuEkvzeTsbRuHssRMyJQ==',
|
|
||||||
}),
|
|
||||||
Challenge('6742b2b9', Variant.tce, JsChallengeType.N, {
|
|
||||||
'_HPB-7GFg1VTkn9u': 'qUAsPryAO_ByYg',
|
|
||||||
'K1t_fcB6phzuq2SF': 'Y7PcOt3VE62mog',
|
|
||||||
}),
|
|
||||||
Challenge('6742b2b9', Variant.tce, JsChallengeType.SIG, {
|
|
||||||
'MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA':
|
|
||||||
'AJfQdSswRAIgMVVvrovTbw6UNh99kPa4D_XQjGT4qYu7S6SHM8EjoCACIEQnz-nKN5RgG6iUTnNJC58csYPSrnS_SzricuUMJZGM',
|
|
||||||
}),
|
|
||||||
Challenge('2b83d2e0', Variant.main, JsChallengeType.N, {
|
|
||||||
'0eRGgQWJGfT5rFHFj': 'euHbygrCMLksxd',
|
|
||||||
}),
|
|
||||||
Challenge('2b83d2e0', Variant.main, JsChallengeType.SIG, {
|
|
||||||
'MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJA':
|
|
||||||
'-MGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKnMznQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJ',
|
|
||||||
}),
|
|
||||||
Challenge('638ec5c6', Variant.main, JsChallengeType.N, {
|
|
||||||
'ZdZIqFPQK-Ty8wId': '1qov8-KM-yH',
|
|
||||||
}),
|
|
||||||
Challenge('638ec5c6', Variant.main, JsChallengeType.SIG, {
|
|
||||||
'gN7a-hudCuAuPH6fByOk1_GNXN0yNMHShjZXS2VOgsEItAJz0tipeavEOmNdYN-wUtcEqD3bCXjc0iyKfAyZxCBGgIARwsSdQfJ2CJtt':
|
|
||||||
'MhudCuAuP-6fByOk1_GNXN7gNHHShjyXS2VOgsEItAJz0tipeav0OmNdYN-wUtcEqD3bCXjc0iyKfAyZxCBGgIARwsSdQfJ2CJtt',
|
|
||||||
}),
|
|
||||||
# c1c87fb0: tce variant broke sig solving; n and main variant are added only for regression testing
|
|
||||||
Challenge('c1c87fb0', Variant.main, JsChallengeType.N, {
|
|
||||||
'ZdZIqFPQK-Ty8wId': 'jCHBK5GuAFNa2',
|
|
||||||
}),
|
|
||||||
Challenge('c1c87fb0', Variant.main, JsChallengeType.SIG, {
|
|
||||||
'gN7a-hudCuAuPH6fByOk1_GNXN0yNMHShjZXS2VOgsEItAJz0tipeavEOmNdYN-wUtcEqD3bCXjc0iyKfAyZxCBGgIARwsSdQfJ2CJtt':
|
|
||||||
'ttJC2JfQdSswRAIgGBCxZyAfKyi0cjXCb3DqEctUw-NYdNmOEvaepit0zJAtIEsgOV2SXZjhSHMNy0NXNGa1kOyBf6HPuAuCduh-_',
|
|
||||||
}),
|
|
||||||
Challenge('c1c87fb0', Variant.tce, JsChallengeType.N, {
|
|
||||||
'ZdZIqFPQK-Ty8wId': 'jCHBK5GuAFNa2',
|
|
||||||
}),
|
|
||||||
Challenge('c1c87fb0', Variant.tce, JsChallengeType.SIG, {
|
|
||||||
'gN7a-hudCuAuPH6fByOk1_GNXN0yNMHShjZXS2VOgsEItAJz0tipeavEOmNdYN-wUtcEqD3bCXjc0iyKfAyZxCBGgIARwsSdQfJ2CJtt':
|
|
||||||
'ttJC2JfQdSswRAIgGBCxZyAfKyi0cjXCb3DqEctUw-NYdNmOEvaepit0zJAtIEsgOV2SXZjhSHMNy0NXNGa1kOyBf6HPuAuCduh-_',
|
|
||||||
}),
|
|
||||||
# 4e51e895: main variant broke sig solving; n challenge is added only for regression testing
|
|
||||||
Challenge('4e51e895', Variant.main, JsChallengeType.N, {
|
|
||||||
'0eRGgQWJGfT5rFHFj': 't5kO23_msekBur',
|
|
||||||
}),
|
|
||||||
Challenge('4e51e895', Variant.main, JsChallengeType.SIG, {
|
|
||||||
'AL6p_8AwdY9yAhRzK8rYA_9n97Kizf7_9n97Kizf7_9n97Kizf7_9n97Kizf7_9n97Kizf7_9n97Kizf7':
|
|
||||||
'AwdY9yAhRzK8rYA_9n97Kizf7_9n97Kizf7_9n9pKizf7_9n97Kizf7_9n97Kizf7_9n97Kizf7',
|
|
||||||
}),
|
|
||||||
# 42c5570b: tce variant broke sig solving; n challenge is added only for regression testing
|
|
||||||
Challenge('42c5570b', Variant.tce, JsChallengeType.N, {
|
|
||||||
'ZdZIqFPQK-Ty8wId': 'CRoXjB-R-R',
|
|
||||||
}),
|
|
||||||
Challenge('42c5570b', Variant.tce, JsChallengeType.SIG, {
|
|
||||||
'gN7a-hudCuAuPH6fByOk1_GNXN0yNMHShjZXS2VOgsEItAJz0tipeavEOmNdYN-wUtcEqD3bCXjc0iyKfAyZxCBGgIARwsSdQfJ2CJtt':
|
|
||||||
'EN7a-hudCuAuPH6fByOk1_GNXN0yNMHShjZXS2VOgsEItAJz0tipeavcOmNdYN-wUtgEqD3bCXjc0iyKfAyZxCBGgIARwsSdQfJ2CJtt',
|
|
||||||
}),
|
|
||||||
# 54bd1de4: tce variant broke sig solving; n challenge is added only for regression testing
|
|
||||||
Challenge('54bd1de4', Variant.tce, JsChallengeType.N, {
|
|
||||||
'ZdZIqFPQK-Ty8wId': 'ka-slAQ31sijFN',
|
|
||||||
}),
|
|
||||||
Challenge('54bd1de4', Variant.tce, JsChallengeType.SIG, {
|
|
||||||
'gN7a-hudCuAuPH6fByOk1_GNXN0yNMHShjZXS2VOgsEItAJz0tipeavEOmNdYN-wUtcEqD3bCXjc0iyKfAyZxCBGgIARwsSdQfJ2CJtt':
|
|
||||||
'gN7a-hudCuAuPH6fByOk1_GNXN0yNMHShjZXS2VOgsEItAJz0titeavEOmNdYN-wUtcEqD3bCXjc0iyKfAyZxCBGgIARwsSdQfJ2CJtp',
|
|
||||||
}),
|
|
||||||
# 94667337: tce and es6 variants broke sig solving; n and main/tv variants are added only for regression testing
|
|
||||||
Challenge('94667337', Variant.main, JsChallengeType.N, {
|
|
||||||
'BQoJvGBkC2nj1ZZLK-': 'ib1ShEOGoFXIIw',
|
|
||||||
}),
|
|
||||||
Challenge('94667337', Variant.main, JsChallengeType.SIG, {
|
|
||||||
'NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz':
|
'NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz':
|
||||||
'AJEij0EwRgIhAI0KExTgjfPk-MPM9MNdzyyPRtzBM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=',
|
'zwg=wgwCHlydB9zg7PMegXoVzaoAXXB8woPSNZqRUC3Pe7vAEiApVSCMlh5mt5OX-8MB=tRPyyEdAM9MPM-kPfjgTxEK0IAhIgRwE0jiz',
|
||||||
}),
|
}),
|
||||||
Challenge('94667337', Variant.tv, JsChallengeType.N, {
|
# 20521
|
||||||
'BQoJvGBkC2nj1ZZLK-': 'ib1ShEOGoFXIIw',
|
Challenge('316b61b4', Variant.tv, JsChallengeType.N, {
|
||||||
|
'IlLiA21ny7gqA2m4p37': 'GchRcsUC_WmnhOUVGV',
|
||||||
}),
|
}),
|
||||||
Challenge('94667337', Variant.tv, JsChallengeType.SIG, {
|
Challenge('316b61b4', Variant.tv, JsChallengeType.SIG, {
|
||||||
'NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz':
|
'NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz':
|
||||||
'AJEij0EwRgIhAI0KExTgjfPk-MPM9MNdzyyPRtzBM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=',
|
'tJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRN=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwz',
|
||||||
}),
|
}),
|
||||||
Challenge('94667337', Variant.es6, JsChallengeType.N, {
|
# 20522
|
||||||
'BQoJvGBkC2nj1ZZLK-': 'ib1ShEOGoFXIIw',
|
Challenge('74edf1a3', Variant.tv, JsChallengeType.N, {
|
||||||
|
'IlLiA21ny7gqA2m4p37': '9nRTxrbM1f0yHg',
|
||||||
|
'eabGFpsUKuWHXGh6FR4': 'izmYqDEY6kl7Sg',
|
||||||
|
'eabGF/ps%UK=uWHXGh6FR4': 'LACmqlhaBpiPlgE-a',
|
||||||
}),
|
}),
|
||||||
Challenge('94667337', Variant.es6, JsChallengeType.SIG, {
|
Challenge('74edf1a3', Variant.tv, JsChallengeType.SIG, {
|
||||||
'NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz':
|
'NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz':
|
||||||
'AJEij0EwRgIhAI0KExTgjfPk-MPM9MNdzyyPRtzBM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=',
|
'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',
|
||||||
}),
|
}),
|
||||||
Challenge('94667337', Variant.tce, JsChallengeType.N, {
|
# 20523
|
||||||
'BQoJvGBkC2nj1ZZLK-': 'ib1ShEOGoFXIIw',
|
Challenge('901741ab', Variant.tv, JsChallengeType.N, {
|
||||||
|
'BQoJvGBkC2nj1ZZLK-': 'UMPovvBZRh-sjb',
|
||||||
}),
|
}),
|
||||||
Challenge('94667337', Variant.tce, JsChallengeType.SIG, {
|
Challenge('901741ab', Variant.tv, JsChallengeType.SIG, {
|
||||||
'NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz':
|
'NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz':
|
||||||
'AJEij0EwRgIhAI0KExTgjfPk-MPM9MNdzyyPRtzBM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=',
|
'wgwCHlydB9Hg7PMegXoVzaoAXXB8woPSNZqRUC3Pe7vAEiApVSCMlhwmt5ON-8MB=5RPyyzdAM9MPM-kPfjgTxEK0IAhIgRwE0jiEJA',
|
||||||
}),
|
}),
|
||||||
Challenge('94667337', Variant.es6_tce, JsChallengeType.N, {
|
# 20524
|
||||||
'BQoJvGBkC2nj1ZZLK-': 'ib1ShEOGoFXIIw',
|
Challenge('e7573094', Variant.tv, JsChallengeType.N, {
|
||||||
|
'IlLiA21ny7gqA2m4p37': '3KuQ3235dojTSjo4',
|
||||||
}),
|
}),
|
||||||
Challenge('94667337', Variant.es6_tce, JsChallengeType.SIG, {
|
Challenge('e7573094', Variant.tv, JsChallengeType.SIG, {
|
||||||
'NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz':
|
'NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz':
|
||||||
'AJEij0EwRgIhAI0KExTgjfPk-MPM9MNdzyyPRtzBM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=',
|
'yEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyNPRt=BM8-XO5tm5hlMCSVNAiEAvpeP3CURqZJSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=g',
|
||||||
}),
|
}),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -220,7 +220,7 @@ class TikTokBaseIE(InfoExtractor):
|
|||||||
raise ExtractorError('Unable to extract aweme detail info', video_id=aweme_id)
|
raise ExtractorError('Unable to extract aweme detail info', video_id=aweme_id)
|
||||||
return self._parse_aweme_video_app(aweme_detail)
|
return self._parse_aweme_video_app(aweme_detail)
|
||||||
|
|
||||||
def _solve_challenge_and_set_cookie(self, webpage):
|
def _solve_challenge_and_set_cookies(self, webpage):
|
||||||
challenge_data = traverse_obj(webpage, (
|
challenge_data = traverse_obj(webpage, (
|
||||||
{find_element(id='cs', html=True)}, {extract_attributes}, 'class',
|
{find_element(id='cs', html=True)}, {extract_attributes}, 'class',
|
||||||
filter, {lambda x: f'{x}==='}, {base64.b64decode}, {json.loads}))
|
filter, {lambda x: f'{x}==='}, {base64.b64decode}, {json.loads}))
|
||||||
@ -250,17 +250,27 @@ class TikTokBaseIE(InfoExtractor):
|
|||||||
else:
|
else:
|
||||||
raise ExtractorError('Unable to solve JS challenge')
|
raise ExtractorError('Unable to solve JS challenge')
|
||||||
|
|
||||||
cookie_value = base64.b64encode(
|
wci_cookie_value = base64.b64encode(
|
||||||
json.dumps(challenge_data, separators=(',', ':')).encode()).decode()
|
json.dumps(challenge_data, separators=(',', ':')).encode()).decode()
|
||||||
|
|
||||||
# At time of writing, the cookie name was _wafchallengeid
|
# At time of writing, the wci cookie name was `_wafchallengeid`
|
||||||
cookie_name = traverse_obj(webpage, (
|
wci_cookie_name = traverse_obj(webpage, (
|
||||||
{find_element(id='wci', html=True)}, {extract_attributes},
|
{find_element(id='wci', html=True)}, {extract_attributes},
|
||||||
'class', {require('challenge cookie name')}))
|
'class', {require('challenge cookie name')}))
|
||||||
|
|
||||||
# Actual JS sets Max-Age=1, but we need to adjust for --sleep-requests and Python slowness
|
# At time of writing, the **optional** rci cookie name was `waforiginalreid`
|
||||||
expire_time = int(time.time()) + (self.get_param('sleep_interval_requests') or 0) + 2
|
rci_cookie_name = traverse_obj(webpage, (
|
||||||
self._set_cookie('.tiktok.com', cookie_name, cookie_value, expire_time=expire_time)
|
{find_element(id='rci', html=True)}, {extract_attributes}, 'class'))
|
||||||
|
rci_cookie_value = traverse_obj(webpage, (
|
||||||
|
{find_element(id='rs', html=True)}, {extract_attributes}, 'class'))
|
||||||
|
|
||||||
|
# Actual JS sets Max-Age=1 for the cookies, but we'll manually clear them later instead
|
||||||
|
expire_time = int(time.time()) + (self.get_param('sleep_interval_requests') or 0) + 120
|
||||||
|
self._set_cookie('.tiktok.com', wci_cookie_name, wci_cookie_value, expire_time=expire_time)
|
||||||
|
if rci_cookie_name and rci_cookie_value:
|
||||||
|
self._set_cookie('.tiktok.com', rci_cookie_name, rci_cookie_value, expire_time=expire_time)
|
||||||
|
|
||||||
|
return wci_cookie_name, rci_cookie_name
|
||||||
|
|
||||||
def _extract_web_data_and_status(self, url, video_id, fatal=True):
|
def _extract_web_data_and_status(self, url, video_id, fatal=True):
|
||||||
video_data, status = {}, -1
|
video_data, status = {}, -1
|
||||||
@ -287,7 +297,7 @@ class TikTokBaseIE(InfoExtractor):
|
|||||||
universal_data = self._get_universal_data(webpage, video_id)
|
universal_data = self._get_universal_data(webpage, video_id)
|
||||||
if not universal_data:
|
if not universal_data:
|
||||||
try:
|
try:
|
||||||
self._solve_challenge_and_set_cookie(webpage)
|
cookie_names = self._solve_challenge_and_set_cookies(webpage)
|
||||||
except ExtractorError as e:
|
except ExtractorError as e:
|
||||||
if fatal:
|
if fatal:
|
||||||
raise
|
raise
|
||||||
@ -295,6 +305,9 @@ class TikTokBaseIE(InfoExtractor):
|
|||||||
return video_data, status
|
return video_data, status
|
||||||
|
|
||||||
webpage = get_webpage(note='Downloading webpage with challenge cookie')
|
webpage = get_webpage(note='Downloading webpage with challenge cookie')
|
||||||
|
# Manually clear challenge cookies that should expire immediately after webpage request
|
||||||
|
for cookie_name in filter(None, cookie_names):
|
||||||
|
self.cookiejar.clear(domain='.tiktok.com', path='/', name=cookie_name)
|
||||||
if webpage is False:
|
if webpage is False:
|
||||||
return video_data, status
|
return video_data, status
|
||||||
universal_data = self._get_universal_data(webpage, video_id)
|
universal_data = self._get_universal_data(webpage, video_id)
|
||||||
|
|||||||
@ -1875,12 +1875,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'params': {'skip_download': True},
|
'params': {'skip_download': True},
|
||||||
}]
|
}]
|
||||||
|
|
||||||
@property
|
_DEFAULT_PLAYER_JS_VERSION = 'actual'
|
||||||
def _skipped_webpage_data(self):
|
|
||||||
# XXX: player_response as a default is a TEMPORARY workaround for pinning _DEFAULT_PLAYER_JS_VERSION
|
|
||||||
return self._configuration_arg('webpage_skip', default=['player_response'])
|
|
||||||
|
|
||||||
_DEFAULT_PLAYER_JS_VERSION = '20514@9f4cc5e4'
|
|
||||||
_DEFAULT_PLAYER_JS_VARIANT = 'tv'
|
_DEFAULT_PLAYER_JS_VARIANT = 'tv'
|
||||||
_PLAYER_JS_VARIANT_MAP = {
|
_PLAYER_JS_VARIANT_MAP = {
|
||||||
'main': 'player_ias.vflset/en_US/base.js',
|
'main': 'player_ias.vflset/en_US/base.js',
|
||||||
@ -1897,6 +1892,18 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
}
|
}
|
||||||
_INVERSE_PLAYER_JS_VARIANT_MAP = {v: k for k, v in _PLAYER_JS_VARIANT_MAP.items()}
|
_INVERSE_PLAYER_JS_VARIANT_MAP = {v: k for k, v in _PLAYER_JS_VARIANT_MAP.items()}
|
||||||
|
|
||||||
|
@functools.cached_property
|
||||||
|
def _player_js_version(self):
|
||||||
|
return self._configuration_arg('player_js_version', [None])[0] or self._DEFAULT_PLAYER_JS_VERSION
|
||||||
|
|
||||||
|
@functools.cached_property
|
||||||
|
def _skipped_webpage_data(self):
|
||||||
|
skipped = set(self._configuration_arg('webpage_skip'))
|
||||||
|
# If forcing a player version, the webpage player response must be skipped
|
||||||
|
if self._player_js_version != 'actual':
|
||||||
|
skipped.add('player_response')
|
||||||
|
return skipped
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def suitable(cls, url):
|
def suitable(cls, url):
|
||||||
from yt_dlp.utils import parse_qs
|
from yt_dlp.utils import parse_qs
|
||||||
@ -2084,15 +2091,14 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
time.sleep(max(0, FETCH_SPAN + fetch_time - time.time()))
|
time.sleep(max(0, FETCH_SPAN + fetch_time - time.time()))
|
||||||
|
|
||||||
def _get_player_js_version(self):
|
def _get_player_js_version(self):
|
||||||
player_js_version = self._configuration_arg('player_js_version', [''])[0] or self._DEFAULT_PLAYER_JS_VERSION
|
if self._player_js_version == 'actual':
|
||||||
if player_js_version == 'actual':
|
|
||||||
return None, None
|
return None, None
|
||||||
if not re.fullmatch(r'[0-9]{5,}@[0-9a-f]{8,}', player_js_version):
|
if not re.fullmatch(r'[0-9]{5,}@[0-9a-f]{8,}', self._player_js_version):
|
||||||
self.report_warning(
|
self.report_warning(
|
||||||
f'Invalid player JS version "{player_js_version}" specified. '
|
f'Invalid player JS version "{self._player_js_version}" specified. '
|
||||||
f'It should be "actual" or in the format of STS@HASH', only_once=True)
|
f'It should be "actual" or in the format of STS@HASH', only_once=True)
|
||||||
return None, None
|
return None, None
|
||||||
return player_js_version.split('@')
|
return self._player_js_version.split('@')
|
||||||
|
|
||||||
def _construct_player_url(self, *, player_id=None, player_url=None):
|
def _construct_player_url(self, *, player_id=None, player_url=None):
|
||||||
assert player_id or player_url, '_construct_player_url must take one of player_id or player_url'
|
assert player_id or player_url, '_construct_player_url must take one of player_id or player_url'
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
# This file is generated by devscripts/update_ejs.py. DO NOT MODIFY!
|
# This file is generated by devscripts/update_ejs.py. DO NOT MODIFY!
|
||||||
|
|
||||||
VERSION = '0.5.0'
|
VERSION = '0.7.0'
|
||||||
HASHES = {
|
HASHES = {
|
||||||
'yt.solver.bun.lib.js': '6ff45e94de9f0ea936a183c48173cfa9ce526ee4b7544cd556428427c1dd53c8073ef0174e79b320252bf0e7c64b0032cc1cf9c4358f3fda59033b7caa01c241',
|
'yt.solver.bun.lib.js': '6ff45e94de9f0ea936a183c48173cfa9ce526ee4b7544cd556428427c1dd53c8073ef0174e79b320252bf0e7c64b0032cc1cf9c4358f3fda59033b7caa01c241',
|
||||||
'yt.solver.core.js': '9742868113d7b0c29e24a95c8eb2c2bec7cdf95513dc7f55f523ba053c0ecf2af7dcb0138b1d933578304f0dda633a6b3bfff64e912b4c547b99dad083428c4b',
|
'yt.solver.core.js': '84e91a8ae91684272d11f1ef0970c757e9fec9ab277fb415b976c156163dde6ae2a9857c19c1ee21c9dcd01e2f89071098a1de2dc3072cf3ceeded84537db5e4',
|
||||||
'yt.solver.core.min.js': 'aee8c3354cfd535809c871c2a517d03231f89cd184e903af82ee274bcc2e90991ef19cb3f65f2ccc858c4963856ea87f8692fe16d71209f4fc7f41c44b828e36',
|
'yt.solver.core.min.js': 'd965ec01dcf44a0a9dea43f5935141c788471de9e8def5bf70d0b88ca656b79ca983d3e595f84b788d921dc98b900b7bf7380e9775ccb3b70a87c865482c71e3',
|
||||||
'yt.solver.deno.lib.js': '9c8ee3ab6c23e443a5a951e3ac73c6b8c1c8fb34335e7058a07bf99d349be5573611de00536dcd03ecd3cf34014c4e9b536081de37af3637c5390c6a6fd6a0f0',
|
'yt.solver.deno.lib.js': '9c8ee3ab6c23e443a5a951e3ac73c6b8c1c8fb34335e7058a07bf99d349be5573611de00536dcd03ecd3cf34014c4e9b536081de37af3637c5390c6a6fd6a0f0',
|
||||||
'yt.solver.lib.js': '1ee3753a8222fc855f5c39db30a9ccbb7967dbe1fb810e86dc9a89aa073a0907f294c720e9b65427d560a35aa1ce6af19ef854d9126a05ca00afe03f72047733',
|
'yt.solver.lib.js': '1ee3753a8222fc855f5c39db30a9ccbb7967dbe1fb810e86dc9a89aa073a0907f294c720e9b65427d560a35aa1ce6af19ef854d9126a05ca00afe03f72047733',
|
||||||
'yt.solver.lib.min.js': '8420c259ad16e99ce004e4651ac1bcabb53b4457bf5668a97a9359be9a998a789fee8ab124ee17f91a2ea8fd84e0f2b2fc8eabcaf0b16a186ba734cf422ad053',
|
'yt.solver.lib.min.js': '8420c259ad16e99ce004e4651ac1bcabb53b4457bf5668a97a9359be9a998a789fee8ab124ee17f91a2ea8fd84e0f2b2fc8eabcaf0b16a186ba734cf422ad053',
|
||||||
|
|||||||
@ -39,284 +39,8 @@ var jsc = (function (meriyah, astring) {
|
|||||||
function isOneOf(value, ...of) {
|
function isOneOf(value, ...of) {
|
||||||
return of.includes(value);
|
return of.includes(value);
|
||||||
}
|
}
|
||||||
function _optionalChain$2(ops) {
|
function generateArrowFunction(data) {
|
||||||
let lastAccessLHS = undefined;
|
return meriyah.parse(data).body[0].expression;
|
||||||
let value = ops[0];
|
|
||||||
let i = 1;
|
|
||||||
while (i < ops.length) {
|
|
||||||
const op = ops[i];
|
|
||||||
const fn = ops[i + 1];
|
|
||||||
i += 2;
|
|
||||||
if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (op === 'access' || op === 'optionalAccess') {
|
|
||||||
lastAccessLHS = value;
|
|
||||||
value = fn(value);
|
|
||||||
} else if (op === 'call' || op === 'optionalCall') {
|
|
||||||
value = fn((...args) => value.call(lastAccessLHS, ...args));
|
|
||||||
lastAccessLHS = undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
const nsig = {
|
|
||||||
type: 'CallExpression',
|
|
||||||
callee: { or: [{ type: 'Identifier' }, { type: 'SequenceExpression' }] },
|
|
||||||
arguments: [
|
|
||||||
{},
|
|
||||||
{
|
|
||||||
type: 'CallExpression',
|
|
||||||
callee: { type: 'Identifier', name: 'decodeURIComponent' },
|
|
||||||
arguments: [{}],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
const nsigAssignment = {
|
|
||||||
type: 'AssignmentExpression',
|
|
||||||
left: { type: 'Identifier' },
|
|
||||||
operator: '=',
|
|
||||||
right: nsig,
|
|
||||||
};
|
|
||||||
const nsigDeclarator = {
|
|
||||||
type: 'VariableDeclarator',
|
|
||||||
id: { type: 'Identifier' },
|
|
||||||
init: nsig,
|
|
||||||
};
|
|
||||||
const logicalExpression = {
|
|
||||||
type: 'ExpressionStatement',
|
|
||||||
expression: {
|
|
||||||
type: 'LogicalExpression',
|
|
||||||
left: { type: 'Identifier' },
|
|
||||||
right: {
|
|
||||||
type: 'SequenceExpression',
|
|
||||||
expressions: [
|
|
||||||
{
|
|
||||||
type: 'AssignmentExpression',
|
|
||||||
left: { type: 'Identifier' },
|
|
||||||
operator: '=',
|
|
||||||
right: {
|
|
||||||
type: 'CallExpression',
|
|
||||||
callee: { type: 'Identifier' },
|
|
||||||
arguments: {
|
|
||||||
or: [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
type: 'CallExpression',
|
|
||||||
callee: {
|
|
||||||
type: 'Identifier',
|
|
||||||
name: 'decodeURIComponent',
|
|
||||||
},
|
|
||||||
arguments: [{ type: 'Identifier' }],
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{ type: 'Literal' },
|
|
||||||
{
|
|
||||||
type: 'CallExpression',
|
|
||||||
callee: {
|
|
||||||
type: 'Identifier',
|
|
||||||
name: 'decodeURIComponent',
|
|
||||||
},
|
|
||||||
arguments: [{ type: 'Identifier' }],
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{ type: 'Literal' },
|
|
||||||
{ type: 'Literal' },
|
|
||||||
{
|
|
||||||
type: 'CallExpression',
|
|
||||||
callee: {
|
|
||||||
type: 'Identifier',
|
|
||||||
name: 'decodeURIComponent',
|
|
||||||
},
|
|
||||||
arguments: [{ type: 'Identifier' }],
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
],
|
|
||||||
},
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ type: 'CallExpression' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
operator: '&&',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const identifier$1 = {
|
|
||||||
or: [
|
|
||||||
{
|
|
||||||
type: 'ExpressionStatement',
|
|
||||||
expression: {
|
|
||||||
type: 'AssignmentExpression',
|
|
||||||
operator: '=',
|
|
||||||
left: { or: [{ type: 'Identifier' }, { type: 'MemberExpression' }] },
|
|
||||||
right: { type: 'FunctionExpression' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ type: 'FunctionDeclaration' },
|
|
||||||
{
|
|
||||||
type: 'VariableDeclaration',
|
|
||||||
declarations: {
|
|
||||||
anykey: [
|
|
||||||
{
|
|
||||||
type: 'VariableDeclarator',
|
|
||||||
init: { type: 'FunctionExpression' },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
function extract$1(node) {
|
|
||||||
const blocks = [];
|
|
||||||
if (matchesStructure(node, identifier$1)) {
|
|
||||||
if (
|
|
||||||
node.type === 'ExpressionStatement' &&
|
|
||||||
node.expression.type === 'AssignmentExpression' &&
|
|
||||||
node.expression.right.type === 'FunctionExpression' &&
|
|
||||||
node.expression.right.params.length >= 3
|
|
||||||
) {
|
|
||||||
blocks.push(node.expression.right.body);
|
|
||||||
} else if (node.type === 'VariableDeclaration') {
|
|
||||||
for (const decl of node.declarations) {
|
|
||||||
if (
|
|
||||||
_optionalChain$2([
|
|
||||||
decl,
|
|
||||||
'access',
|
|
||||||
(_) => _.init,
|
|
||||||
'optionalAccess',
|
|
||||||
(_2) => _2.type,
|
|
||||||
]) === 'FunctionExpression' &&
|
|
||||||
decl.init.params.length >= 3
|
|
||||||
) {
|
|
||||||
blocks.push(decl.init.body);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (
|
|
||||||
node.type === 'FunctionDeclaration' &&
|
|
||||||
node.params.length >= 3
|
|
||||||
) {
|
|
||||||
blocks.push(node.body);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} else if (
|
|
||||||
node.type === 'ExpressionStatement' &&
|
|
||||||
node.expression.type === 'SequenceExpression'
|
|
||||||
) {
|
|
||||||
for (const expr of node.expression.expressions) {
|
|
||||||
if (
|
|
||||||
expr.type === 'AssignmentExpression' &&
|
|
||||||
expr.right.type === 'FunctionExpression' &&
|
|
||||||
expr.right.params.length === 3
|
|
||||||
) {
|
|
||||||
blocks.push(expr.right.body);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
for (const block of blocks) {
|
|
||||||
let call = null;
|
|
||||||
for (const stmt of block.body) {
|
|
||||||
if (matchesStructure(stmt, logicalExpression)) {
|
|
||||||
if (
|
|
||||||
stmt.type === 'ExpressionStatement' &&
|
|
||||||
stmt.expression.type === 'LogicalExpression' &&
|
|
||||||
stmt.expression.right.type === 'SequenceExpression' &&
|
|
||||||
stmt.expression.right.expressions[0].type ===
|
|
||||||
'AssignmentExpression' &&
|
|
||||||
stmt.expression.right.expressions[0].right.type === 'CallExpression'
|
|
||||||
) {
|
|
||||||
call = stmt.expression.right.expressions[0].right;
|
|
||||||
}
|
|
||||||
} else if (stmt.type === 'IfStatement') {
|
|
||||||
let consequent = stmt.consequent;
|
|
||||||
while (consequent.type === 'LabeledStatement') {
|
|
||||||
consequent = consequent.body;
|
|
||||||
}
|
|
||||||
if (consequent.type !== 'BlockStatement') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (const n of consequent.body) {
|
|
||||||
if (n.type !== 'VariableDeclaration') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (const decl of n.declarations) {
|
|
||||||
if (
|
|
||||||
matchesStructure(decl, nsigDeclarator) &&
|
|
||||||
_optionalChain$2([
|
|
||||||
decl,
|
|
||||||
'access',
|
|
||||||
(_3) => _3.init,
|
|
||||||
'optionalAccess',
|
|
||||||
(_4) => _4.type,
|
|
||||||
]) === 'CallExpression'
|
|
||||||
) {
|
|
||||||
call = decl.init;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (call) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (stmt.type === 'ExpressionStatement') {
|
|
||||||
if (
|
|
||||||
stmt.expression.type !== 'LogicalExpression' ||
|
|
||||||
stmt.expression.operator !== '&&' ||
|
|
||||||
stmt.expression.right.type !== 'SequenceExpression'
|
|
||||||
) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (const expr of stmt.expression.right.expressions) {
|
|
||||||
if (matchesStructure(expr, nsigAssignment) && expr.type) {
|
|
||||||
if (
|
|
||||||
expr.type === 'AssignmentExpression' &&
|
|
||||||
expr.right.type === 'CallExpression'
|
|
||||||
) {
|
|
||||||
call = expr.right;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (call) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!call) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
type: 'ArrowFunctionExpression',
|
|
||||||
params: [{ type: 'Identifier', name: 'sig' }],
|
|
||||||
body: {
|
|
||||||
type: 'CallExpression',
|
|
||||||
callee: call.callee,
|
|
||||||
arguments: call.arguments.map((arg) => {
|
|
||||||
if (
|
|
||||||
arg.type === 'CallExpression' &&
|
|
||||||
arg.callee.type === 'Identifier' &&
|
|
||||||
arg.callee.name === 'decodeURIComponent'
|
|
||||||
) {
|
|
||||||
return { type: 'Identifier', name: 'sig' };
|
|
||||||
}
|
|
||||||
return arg;
|
|
||||||
}),
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
async: false,
|
|
||||||
expression: false,
|
|
||||||
generator: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
function _optionalChain$1(ops) {
|
function _optionalChain$1(ops) {
|
||||||
let lastAccessLHS = undefined;
|
let lastAccessLHS = undefined;
|
||||||
@ -341,153 +65,114 @@ var jsc = (function (meriyah, astring) {
|
|||||||
}
|
}
|
||||||
const identifier = {
|
const identifier = {
|
||||||
or: [
|
or: [
|
||||||
|
{
|
||||||
|
type: 'ExpressionStatement',
|
||||||
|
expression: {
|
||||||
|
type: 'AssignmentExpression',
|
||||||
|
operator: '=',
|
||||||
|
left: { or: [{ type: 'Identifier' }, { type: 'MemberExpression' }] },
|
||||||
|
right: { type: 'FunctionExpression', async: false },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ type: 'FunctionDeclaration', async: false, id: { type: 'Identifier' } },
|
||||||
{
|
{
|
||||||
type: 'VariableDeclaration',
|
type: 'VariableDeclaration',
|
||||||
kind: 'var',
|
|
||||||
declarations: {
|
declarations: {
|
||||||
anykey: [
|
anykey: [
|
||||||
{
|
{
|
||||||
type: 'VariableDeclarator',
|
type: 'VariableDeclarator',
|
||||||
id: { type: 'Identifier' },
|
init: { type: 'FunctionExpression', async: false },
|
||||||
init: {
|
|
||||||
type: 'ArrayExpression',
|
|
||||||
elements: [{ type: 'Identifier' }],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
type: 'ExpressionStatement',
|
|
||||||
expression: {
|
|
||||||
type: 'AssignmentExpression',
|
|
||||||
left: { type: 'Identifier' },
|
|
||||||
operator: '=',
|
|
||||||
right: {
|
|
||||||
type: 'ArrayExpression',
|
|
||||||
elements: [{ type: 'Identifier' }],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
const catchBlockBody = [
|
const asdasd = {
|
||||||
{
|
type: 'ExpressionStatement',
|
||||||
type: 'ReturnStatement',
|
expression: {
|
||||||
argument: {
|
type: 'CallExpression',
|
||||||
type: 'BinaryExpression',
|
callee: {
|
||||||
left: {
|
type: 'MemberExpression',
|
||||||
type: 'MemberExpression',
|
object: { type: 'Identifier' },
|
||||||
object: { type: 'Identifier' },
|
property: {},
|
||||||
computed: true,
|
optional: false,
|
||||||
property: { type: 'Literal' },
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
right: { type: 'Identifier' },
|
|
||||||
operator: '+',
|
|
||||||
},
|
},
|
||||||
|
arguments: [
|
||||||
|
{ type: 'Literal', value: 'alr' },
|
||||||
|
{ type: 'Literal', value: 'yes' },
|
||||||
|
],
|
||||||
|
optional: false,
|
||||||
},
|
},
|
||||||
];
|
};
|
||||||
function extract(node) {
|
function extract(node) {
|
||||||
if (!matchesStructure(node, identifier)) {
|
if (!matchesStructure(node, identifier)) {
|
||||||
let name = null;
|
|
||||||
let block = null;
|
|
||||||
switch (node.type) {
|
|
||||||
case 'ExpressionStatement': {
|
|
||||||
if (
|
|
||||||
node.expression.type === 'AssignmentExpression' &&
|
|
||||||
node.expression.left.type === 'Identifier' &&
|
|
||||||
node.expression.right.type === 'FunctionExpression' &&
|
|
||||||
node.expression.right.params.length === 1
|
|
||||||
) {
|
|
||||||
name = node.expression.left.name;
|
|
||||||
block = node.expression.right.body;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'FunctionDeclaration': {
|
|
||||||
if (node.params.length === 1) {
|
|
||||||
name = _optionalChain$1([
|
|
||||||
node,
|
|
||||||
'access',
|
|
||||||
(_) => _.id,
|
|
||||||
'optionalAccess',
|
|
||||||
(_2) => _2.name,
|
|
||||||
]);
|
|
||||||
block = node.body;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!block || !name) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const tryNode = block.body.at(-2);
|
|
||||||
if (
|
|
||||||
_optionalChain$1([tryNode, 'optionalAccess', (_3) => _3.type]) !==
|
|
||||||
'TryStatement' ||
|
|
||||||
_optionalChain$1([
|
|
||||||
tryNode,
|
|
||||||
'access',
|
|
||||||
(_4) => _4.handler,
|
|
||||||
'optionalAccess',
|
|
||||||
(_5) => _5.type,
|
|
||||||
]) !== 'CatchClause'
|
|
||||||
) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const catchBody = tryNode.handler.body.body;
|
|
||||||
if (matchesStructure(catchBody, catchBlockBody)) {
|
|
||||||
return makeSolverFuncFromName(name);
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (node.type === 'VariableDeclaration') {
|
const options = [];
|
||||||
for (const declaration of node.declarations) {
|
if (node.type === 'FunctionDeclaration') {
|
||||||
if (
|
if (
|
||||||
declaration.type !== 'VariableDeclarator' ||
|
node.id &&
|
||||||
!declaration.init ||
|
_optionalChain$1([
|
||||||
declaration.init.type !== 'ArrayExpression' ||
|
node,
|
||||||
declaration.init.elements.length !== 1
|
'access',
|
||||||
) {
|
(_) => _.body,
|
||||||
continue;
|
'optionalAccess',
|
||||||
}
|
(_2) => _2.body,
|
||||||
const [firstElement] = declaration.init.elements;
|
])
|
||||||
if (firstElement && firstElement.type === 'Identifier') {
|
) {
|
||||||
return makeSolverFuncFromName(firstElement.name);
|
options.push({
|
||||||
}
|
name: node.id,
|
||||||
|
statements: _optionalChain$1([
|
||||||
|
node,
|
||||||
|
'access',
|
||||||
|
(_3) => _3.body,
|
||||||
|
'optionalAccess',
|
||||||
|
(_4) => _4.body,
|
||||||
|
]),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else if (node.type === 'ExpressionStatement') {
|
} else if (node.type === 'ExpressionStatement') {
|
||||||
const expr = node.expression;
|
if (node.expression.type !== 'AssignmentExpression') {
|
||||||
if (
|
return null;
|
||||||
expr.type === 'AssignmentExpression' &&
|
}
|
||||||
expr.left.type === 'Identifier' &&
|
const name = node.expression.left;
|
||||||
expr.operator === '=' &&
|
const body = _optionalChain$1([
|
||||||
expr.right.type === 'ArrayExpression' &&
|
node.expression.right,
|
||||||
expr.right.elements.length === 1
|
'optionalAccess',
|
||||||
) {
|
(_5) => _5.body,
|
||||||
const [firstElement] = expr.right.elements;
|
'optionalAccess',
|
||||||
if (firstElement && firstElement.type === 'Identifier') {
|
(_6) => _6.body,
|
||||||
return makeSolverFuncFromName(firstElement.name);
|
]);
|
||||||
|
if (name && body) {
|
||||||
|
options.push({ name: name, statements: body });
|
||||||
|
}
|
||||||
|
} else if (node.type === 'VariableDeclaration') {
|
||||||
|
for (const declaration of node.declarations) {
|
||||||
|
const name = declaration.id;
|
||||||
|
const body = _optionalChain$1([
|
||||||
|
declaration.init,
|
||||||
|
'optionalAccess',
|
||||||
|
(_7) => _7.body,
|
||||||
|
'optionalAccess',
|
||||||
|
(_8) => _8.body,
|
||||||
|
]);
|
||||||
|
if (name && body) {
|
||||||
|
options.push({ name: name, statements: body });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (const { name: name, statements: statements } of options) {
|
||||||
|
if (matchesStructure(statements, { anykey: [asdasd] })) {
|
||||||
|
return createSolver(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
function makeSolverFuncFromName(name) {
|
function createSolver(expression) {
|
||||||
return {
|
return generateArrowFunction(
|
||||||
type: 'ArrowFunctionExpression',
|
`\n({sig, n}) => {\n const url = (${astring.generate(expression)})("https://youtube.com/watch?v=yt-dlp-wins", "s", sig ? encodeURIComponent(sig) : undefined);\n url.set("n", n);\n const proto = Object.getPrototypeOf(url);\n const keys = Object.keys(proto).concat(Object.getOwnPropertyNames(proto));\n for (const key of keys) {\n if (!["constructor", "set", "get", "clone"].includes(key)) {\n url[key]();\n break;\n }\n }\n const s = url.get("s");\n return {\n sig: s ? decodeURIComponent(s) : null,\n n: url.get("n") ?? null,\n };\n}\n`,
|
||||||
params: [{ type: 'Identifier', name: 'n' }],
|
);
|
||||||
body: {
|
|
||||||
type: 'CallExpression',
|
|
||||||
callee: { type: 'Identifier', name: name },
|
|
||||||
arguments: [{ type: 'Identifier', name: 'n' }],
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
async: false,
|
|
||||||
expression: false,
|
|
||||||
generator: false,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
const setupNodes = meriyah.parse(
|
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}\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`,
|
||||||
@ -585,235 +270,59 @@ var jsc = (function (meriyah, astring) {
|
|||||||
function getSolutions(statements) {
|
function getSolutions(statements) {
|
||||||
const found = { n: [], sig: [] };
|
const found = { n: [], sig: [] };
|
||||||
for (const statement of statements) {
|
for (const statement of statements) {
|
||||||
const n = extract(statement);
|
const result = extract(statement);
|
||||||
if (n) {
|
if (result) {
|
||||||
found.n.push(n);
|
found.n.push(makeSolver(result, { type: 'Identifier', name: 'n' }));
|
||||||
}
|
found.sig.push(makeSolver(result, { type: 'Identifier', name: 'sig' }));
|
||||||
const sig = extract$1(statement);
|
|
||||||
if (sig) {
|
|
||||||
found.sig.push(sig);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
function makeSolver(result, ident) {
|
||||||
|
return {
|
||||||
|
type: 'ArrowFunctionExpression',
|
||||||
|
params: [ident],
|
||||||
|
body: {
|
||||||
|
type: 'MemberExpression',
|
||||||
|
object: {
|
||||||
|
type: 'CallExpression',
|
||||||
|
callee: result,
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
type: 'ObjectExpression',
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
type: 'Property',
|
||||||
|
key: ident,
|
||||||
|
value: ident,
|
||||||
|
kind: 'init',
|
||||||
|
computed: false,
|
||||||
|
method: false,
|
||||||
|
shorthand: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
optional: false,
|
||||||
|
},
|
||||||
|
computed: false,
|
||||||
|
property: ident,
|
||||||
|
optional: false,
|
||||||
|
},
|
||||||
|
async: false,
|
||||||
|
expression: true,
|
||||||
|
generator: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
function getFromPrepared(code) {
|
function getFromPrepared(code) {
|
||||||
const resultObj = { n: null, sig: null };
|
const resultObj = { n: null, sig: null };
|
||||||
Function('_result', code)(resultObj);
|
Function('_result', code)(resultObj);
|
||||||
return resultObj;
|
return resultObj;
|
||||||
}
|
}
|
||||||
function multiTry(generators) {
|
function multiTry(generators) {
|
||||||
return {
|
return generateArrowFunction(
|
||||||
type: 'ArrowFunctionExpression',
|
`\n(_input) => {\n const _results = new Set();\n const errors = [];\n for (const _generator of ${astring.generate({ type: 'ArrayExpression', elements: generators })}) {\n try {\n _results.add(_generator(_input));\n } catch (e) {\n errors.push(e);\n }\n }\n if (!_results.size) {\n throw \`no solutions: \${errors.join(", ")}\`;\n }\n if (_results.size !== 1) {\n throw \`invalid solutions: \${[..._results].map(x => JSON.stringify(x)).join(", ")}\`;\n }\n return _results.values().next().value;\n}\n`,
|
||||||
params: [{ type: 'Identifier', name: '_input' }],
|
);
|
||||||
body: {
|
|
||||||
type: 'BlockStatement',
|
|
||||||
body: [
|
|
||||||
{
|
|
||||||
type: 'VariableDeclaration',
|
|
||||||
kind: 'const',
|
|
||||||
declarations: [
|
|
||||||
{
|
|
||||||
type: 'VariableDeclarator',
|
|
||||||
id: { type: 'Identifier', name: '_results' },
|
|
||||||
init: {
|
|
||||||
type: 'NewExpression',
|
|
||||||
callee: { type: 'Identifier', name: 'Set' },
|
|
||||||
arguments: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'ForOfStatement',
|
|
||||||
left: {
|
|
||||||
type: 'VariableDeclaration',
|
|
||||||
kind: 'const',
|
|
||||||
declarations: [
|
|
||||||
{
|
|
||||||
type: 'VariableDeclarator',
|
|
||||||
id: { type: 'Identifier', name: '_generator' },
|
|
||||||
init: null,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
right: { type: 'ArrayExpression', elements: generators },
|
|
||||||
body: {
|
|
||||||
type: 'BlockStatement',
|
|
||||||
body: [
|
|
||||||
{
|
|
||||||
type: 'TryStatement',
|
|
||||||
block: {
|
|
||||||
type: 'BlockStatement',
|
|
||||||
body: [
|
|
||||||
{
|
|
||||||
type: 'ExpressionStatement',
|
|
||||||
expression: {
|
|
||||||
type: 'CallExpression',
|
|
||||||
callee: {
|
|
||||||
type: 'MemberExpression',
|
|
||||||
object: { type: 'Identifier', name: '_results' },
|
|
||||||
computed: false,
|
|
||||||
property: { type: 'Identifier', name: 'add' },
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
arguments: [
|
|
||||||
{
|
|
||||||
type: 'CallExpression',
|
|
||||||
callee: {
|
|
||||||
type: 'Identifier',
|
|
||||||
name: '_generator',
|
|
||||||
},
|
|
||||||
arguments: [
|
|
||||||
{ type: 'Identifier', name: '_input' },
|
|
||||||
],
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
handler: {
|
|
||||||
type: 'CatchClause',
|
|
||||||
param: null,
|
|
||||||
body: { type: 'BlockStatement', body: [] },
|
|
||||||
},
|
|
||||||
finalizer: null,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
await: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'IfStatement',
|
|
||||||
test: {
|
|
||||||
type: 'UnaryExpression',
|
|
||||||
operator: '!',
|
|
||||||
argument: {
|
|
||||||
type: 'MemberExpression',
|
|
||||||
object: { type: 'Identifier', name: '_results' },
|
|
||||||
computed: false,
|
|
||||||
property: { type: 'Identifier', name: 'size' },
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
prefix: true,
|
|
||||||
},
|
|
||||||
consequent: {
|
|
||||||
type: 'BlockStatement',
|
|
||||||
body: [
|
|
||||||
{
|
|
||||||
type: 'ThrowStatement',
|
|
||||||
argument: {
|
|
||||||
type: 'TemplateLiteral',
|
|
||||||
expressions: [],
|
|
||||||
quasis: [
|
|
||||||
{
|
|
||||||
type: 'TemplateElement',
|
|
||||||
value: { cooked: 'no solutions', raw: 'no solutions' },
|
|
||||||
tail: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
alternate: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'IfStatement',
|
|
||||||
test: {
|
|
||||||
type: 'BinaryExpression',
|
|
||||||
left: {
|
|
||||||
type: 'MemberExpression',
|
|
||||||
object: { type: 'Identifier', name: '_results' },
|
|
||||||
computed: false,
|
|
||||||
property: { type: 'Identifier', name: 'size' },
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
right: { type: 'Literal', value: 1 },
|
|
||||||
operator: '!==',
|
|
||||||
},
|
|
||||||
consequent: {
|
|
||||||
type: 'BlockStatement',
|
|
||||||
body: [
|
|
||||||
{
|
|
||||||
type: 'ThrowStatement',
|
|
||||||
argument: {
|
|
||||||
type: 'TemplateLiteral',
|
|
||||||
expressions: [
|
|
||||||
{
|
|
||||||
type: 'CallExpression',
|
|
||||||
callee: {
|
|
||||||
type: 'MemberExpression',
|
|
||||||
object: { type: 'Identifier', name: '_results' },
|
|
||||||
computed: false,
|
|
||||||
property: { type: 'Identifier', name: 'join' },
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
arguments: [{ type: 'Literal', value: ', ' }],
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
quasis: [
|
|
||||||
{
|
|
||||||
type: 'TemplateElement',
|
|
||||||
value: {
|
|
||||||
cooked: 'invalid solutions: ',
|
|
||||||
raw: 'invalid solutions: ',
|
|
||||||
},
|
|
||||||
tail: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'TemplateElement',
|
|
||||||
value: { cooked: '', raw: '' },
|
|
||||||
tail: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
alternate: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'ReturnStatement',
|
|
||||||
argument: {
|
|
||||||
type: 'MemberExpression',
|
|
||||||
object: {
|
|
||||||
type: 'CallExpression',
|
|
||||||
callee: {
|
|
||||||
type: 'MemberExpression',
|
|
||||||
object: {
|
|
||||||
type: 'CallExpression',
|
|
||||||
callee: {
|
|
||||||
type: 'MemberExpression',
|
|
||||||
object: { type: 'Identifier', name: '_results' },
|
|
||||||
computed: false,
|
|
||||||
property: { type: 'Identifier', name: 'values' },
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
arguments: [],
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
computed: false,
|
|
||||||
property: { type: 'Identifier', name: 'next' },
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
arguments: [],
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
computed: false,
|
|
||||||
property: { type: 'Identifier', name: 'value' },
|
|
||||||
optional: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
async: false,
|
|
||||||
expression: false,
|
|
||||||
generator: false,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
function main(input) {
|
function main(input) {
|
||||||
const preprocessedPlayer =
|
const preprocessedPlayer =
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
# Autogenerated by devscripts/update-version.py
|
# Autogenerated by devscripts/update-version.py
|
||||||
|
|
||||||
__version__ = '2026.03.03'
|
__version__ = '2026.03.13'
|
||||||
|
|
||||||
RELEASE_GIT_HEAD = '2ecc4c3bc300701d85e2cbaeb2b28a921a68f0f0'
|
RELEASE_GIT_HEAD = '92f1d99dbe1e10d942ef0963f625dbc5bc0768aa'
|
||||||
|
|
||||||
VARIANT = None
|
VARIANT = None
|
||||||
|
|
||||||
@ -12,4 +12,4 @@ CHANNEL = 'stable'
|
|||||||
|
|
||||||
ORIGIN = 'yt-dlp/yt-dlp'
|
ORIGIN = 'yt-dlp/yt-dlp'
|
||||||
|
|
||||||
_pkg_version = '2026.03.03'
|
_pkg_version = '2026.03.13'
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user