Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package yt-dlp for openSUSE:Factory checked 
in at 2024-12-12 21:20:08
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/yt-dlp (Old)
 and      /work/SRC/openSUSE:Factory/.yt-dlp.new.29675 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "yt-dlp"

Thu Dec 12 21:20:08 2024 rev:52 rq:1230582 version:2024.12.06

Changes:
--------
--- /work/SRC/openSUSE:Factory/yt-dlp/yt-dlp.changes    2024-12-04 
15:27:06.313179943 +0100
+++ /work/SRC/openSUSE:Factory/.yt-dlp.new.29675/yt-dlp.changes 2024-12-12 
21:21:46.069658381 +0100
@@ -1,0 +2,6 @@
+Thu Dec 12 12:50:03 UTC 2024 - Jan Engelhardt <[email protected]>
+
+- Update to release 2024.12.06
+  * No changelog was provided
+
+-------------------------------------------------------------------

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ yt-dlp.spec ++++++
--- /var/tmp/diff_new_pack.mGAJ5H/_old  2024-12-12 21:21:46.613681048 +0100
+++ /var/tmp/diff_new_pack.mGAJ5H/_new  2024-12-12 21:21:46.613681048 +0100
@@ -21,7 +21,7 @@
 %define skip_python37 1
 %{?sle15_python_module_pythons}
 Name:           yt-dlp
-Version:        2024.12.03
+Version:        2024.12.06
 Release:        0
 Summary:        Enhanced fork of youtube-dl, a video site downloader for 
offline watching
 License:        CC-BY-SA-3.0 AND SUSE-Public-Domain

++++++ _scmsync.obsinfo ++++++
--- /var/tmp/diff_new_pack.mGAJ5H/_old  2024-12-12 21:21:46.641682215 +0100
+++ /var/tmp/diff_new_pack.mGAJ5H/_new  2024-12-12 21:21:46.641682215 +0100
@@ -1,5 +1,5 @@
-mtime: 1733259590
-commit: e67a7c9e7a6281dff155c28431ef9e13edd779ac81e96f287f20727aba1baac6
+mtime: 1734008116
+commit: 1775396c4acf4f889232cd2bf4f310801254679e6dc75883fc0cc73d47b1de46
 url: https://src.opensuse.org/jengelh/yt-dlp
 revision: master
 

++++++ build.specials.obscpio ++++++
diff: old/*: No such file or directory
diff: new/*: No such file or directory

++++++ yt-dlp.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/AUTHORS new/yt-dlp/AUTHORS
--- old/yt-dlp/AUTHORS  2024-12-03 21:31:23.000000000 +0100
+++ new/yt-dlp/AUTHORS  2024-12-06 17:07:46.000000000 +0100
@@ -1524,6 +1524,7 @@
 vtexier
 vvto33
 wankerer
+wesson09
 willbeaufoy
 winterbird-code
 winwon
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/CONTRIBUTORS new/yt-dlp/CONTRIBUTORS
--- old/yt-dlp/CONTRIBUTORS     2024-12-03 21:31:22.000000000 +0100
+++ new/yt-dlp/CONTRIBUTORS     2024-12-06 17:07:45.000000000 +0100
@@ -710,3 +710,4 @@
 gitninja1234
 jkruse
 xiaomac
+wesson09
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/Changelog.md new/yt-dlp/Changelog.md
--- old/yt-dlp/Changelog.md     2024-12-03 21:31:18.000000000 +0100
+++ new/yt-dlp/Changelog.md     2024-12-06 17:07:42.000000000 +0100
@@ -4,6 +4,19 @@
 # To create a release, dispatch the 
https://github.com/yt-dlp/yt-dlp/actions/workflows/release.yml workflow on 
master
 -->
 
+### 2024.12.06
+
+#### Core changes
+- **cookies**: [Add `--cookies-from-browser` support for MS Store 
Firefox](https://github.com/yt-dlp/yt-dlp/commit/354cb4026cf2191e1a130ec2a627b95cabfbc60a)
 ([#11731](https://github.com/yt-dlp/yt-dlp/issues/11731)) by 
[wesson09](https://github.com/wesson09)
+
+#### Extractor changes
+- **bilibili**: [Fix HD formats 
extraction](https://github.com/yt-dlp/yt-dlp/commit/fca3eb5f8be08d5fab2e18b45b7281a12e566725)
 ([#11734](https://github.com/yt-dlp/yt-dlp/issues/11734)) by 
[grqz](https://github.com/grqz)
+- **soundcloud**: [Fix formats 
extraction](https://github.com/yt-dlp/yt-dlp/commit/2feb28028ee48f2185d2d95076e62accb09b9e2e)
 ([#11742](https://github.com/yt-dlp/yt-dlp/issues/11742)) by 
[bashonly](https://github.com/bashonly)
+- **youtube**
+    - [Fix `n` sig extraction for player 
`3bb1f723`](https://github.com/yt-dlp/yt-dlp/commit/a95ee6d8803fca9157adecf63732ab58bf87fd88)
 ([#11750](https://github.com/yt-dlp/yt-dlp/issues/11750)) by 
[bashonly](https://github.com/bashonly) (With fixes in 
[4bd2655](https://github.com/yt-dlp/yt-dlp/commit/4bd2655398aed450456197a6767639114a24eac2))
+    - [Fix signature function 
extraction](https://github.com/yt-dlp/yt-dlp/commit/4c85ccd1366c88cf93982f8350f58eed17355981)
 ([#11751](https://github.com/yt-dlp/yt-dlp/issues/11751)) by 
[bashonly](https://github.com/bashonly)
+    - [Player client 
maintenance](https://github.com/yt-dlp/yt-dlp/commit/2e49c789d3eebc39af8910705d65a98bca0e4c4f)
 ([#11724](https://github.com/yt-dlp/yt-dlp/issues/11724)) by 
[bashonly](https://github.com/bashonly)
+
 ### 2024.12.03
 
 #### Core changes
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/README.md new/yt-dlp/README.md
--- old/yt-dlp/README.md        2024-12-03 21:31:22.000000000 +0100
+++ new/yt-dlp/README.md        2024-12-06 17:07:45.000000000 +0100
@@ -1860,7 +1860,7 @@
 * `cdn`: One or more CDN IDs to use with the API call for stream URLs, e.g. 
`gcp_cdn`, `gs_cdn_pc_app`, `gs_cdn_mobile_web`, `gs_cdn_pc_web`
 
 #### soundcloud
-* `formats`: Formats to request from the API. Requested values should be in 
the format of `{protocol}_{extension}` (omitting the bitrate), e.g. 
`hls_opus,http_aac`. The `*` character functions as a wildcard, e.g. `*_mp3`, 
and can be passed by itself to request all formats. Known protocols include 
`http`, `hls` and `hls-aes`; known extensions include `aac`, `opus` and `mp3`. 
Original `download` formats are always extracted. Default is 
`http_aac,hls_aac,http_opus,hls_opus,http_mp3,hls_mp3`
+* `formats`: Formats to request from the API. Requested values should be in 
the format of `{protocol}_{codec}`, e.g. `hls_opus,http_aac`. The `*` character 
functions as a wildcard, e.g. `*_mp3`, and can be passed by itself to request 
all formats. Known protocols include `http`, `hls` and `hls-aes`; known codecs 
include `aac`, `opus` and `mp3`. Original `download` formats are always 
extracted. Default is `http_aac,hls_aac,http_opus,hls_opus,http_mp3,hls_mp3`
 
 #### orfon (orf:on)
 * `prefer_segments_playlist`: Prefer a playlist of program segments instead of 
a single complete video when available. If individual segments are desired, use 
`--concat-playlist never --extractor-args "orfon:prefer_segments_playlist"`
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/README.txt new/yt-dlp/README.txt
--- old/yt-dlp/README.txt       2024-12-03 21:31:23.000000000 +0100
+++ new/yt-dlp/README.txt       2024-12-06 17:07:46.000000000 +0100
@@ -2350,12 +2350,12 @@
 soundcloud
 
 -   formats: Formats to request from the API. Requested values should be
-    in the format of {protocol}_{extension} (omitting the bitrate), e.g.
-    hls_opus,http_aac. The * character functions as a wildcard, e.g.
-    *_mp3, and can be passed by itself to request all formats. Known
-    protocols include http, hls and hls-aes; known extensions include
-    aac, opus and mp3. Original download formats are always extracted.
-    Default is http_aac,hls_aac,http_opus,hls_opus,http_mp3,hls_mp3
+    in the format of {protocol}_{codec}, e.g. hls_opus,http_aac. The *
+    character functions as a wildcard, e.g. *_mp3, and can be passed by
+    itself to request all formats. Known protocols include http, hls and
+    hls-aes; known codecs include aac, opus and mp3. Original download
+    formats are always extracted. Default is
+    http_aac,hls_aac,http_opus,hls_opus,http_mp3,hls_mp3
 
 orfon (orf:on)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/test/test_youtube_signature.py 
new/yt-dlp/test/test_youtube_signature.py
--- old/yt-dlp/test/test_youtube_signature.py   2024-12-03 21:30:58.000000000 
+0100
+++ new/yt-dlp/test/test_youtube_signature.py   2024-12-06 17:07:34.000000000 
+0100
@@ -68,6 +68,11 @@
         
'2aq0aqSyOoJXtK73m-uME_jv7-pT15gOFC02RFkGMqWpzEICs69VdbwQ0LDp1v7j8xx92efCJlYFYb1sUkkBSPOlPmXgIARw8JQ0qOAOAA',
         
'AOq0QJ8wRAIgXmPlOPSBkkUs1bYFYlJCfe29xx8j7v1pDL2QwbdV96sCIEzpWqMGkFR20CFOg51Tp-7vj_EMu-m37KtXJoOySqa0',
     ),
+    (
+        
'https://www.youtube.com/s/player/3bb1f723/player_ias.vflset/en_US/base.js',
+        
'2aq0aqSyOoJXtK73m-uME_jv7-pT15gOFC02RFkGMqWpzEICs69VdbwQ0LDp1v7j8xx92efCJlYFYb1sUkkBSPOlPmXgIARw8JQ0qOAOAA',
+        
'MyOSJXtKI3m-uME_jv7-pT12gOFC02RFkGoqWpzE0Cs69VdbwQ0LDp1v7j8xx92efCJlYFYb1sUkkBSPOlPmXgIARw8JQ0qOAOAA',
+    ),
 ]
 
 _NSIG_TESTS = [
@@ -183,6 +188,10 @@
         
'https://www.youtube.com/s/player/b12cc44b/player_ias.vflset/en_US/base.js',
         'keLa5R2U00sR9SQK', 'N1OGyujjEwMnLw',
     ),
+    (
+        
'https://www.youtube.com/s/player/3bb1f723/player_ias.vflset/en_US/base.js',
+        'gK15nzVyaXE9RsMP3z', 'ZFFWFLPWx9DEgQ',
+    ),
 ]
 
 
@@ -254,8 +263,11 @@
 
 
 def n_sig(jscode, sig_input):
-    funcname = YoutubeIE(FakeYDL())._extract_n_function_name(jscode)
-    return JSInterpreter(jscode).call_function(funcname, sig_input)
+    ie = YoutubeIE(FakeYDL())
+    funcname = ie._extract_n_function_name(jscode)
+    jsi = JSInterpreter(jscode)
+    func = 
jsi.extract_function_from_code(*ie._fixup_n_function_code(*jsi.extract_function_code(funcname)))
+    return func([sig_input])
 
 
 make_sig_test = t_factory(
Binary files old/yt-dlp/yt-dlp and new/yt-dlp/yt-dlp differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/yt-dlp.1 new/yt-dlp/yt-dlp.1
--- old/yt-dlp/yt-dlp.1 2024-12-03 21:31:24.000000000 +0100
+++ new/yt-dlp/yt-dlp.1 2024-12-06 17:07:47.000000000 +0100
@@ -2883,13 +2883,13 @@
 .IP \[bu] 2
 \f[C]formats\f[R]: Formats to request from the API.
 Requested values should be in the format of
-\f[C]{protocol}_{extension}\f[R] (omitting the bitrate), e.g.
+\f[C]{protocol}_{codec}\f[R], e.g.
 \f[C]hls_opus,http_aac\f[R].
 The \f[C]*\f[R] character functions as a wildcard, e.g.
 \f[C]*_mp3\f[R], and can be passed by itself to request all formats.
 Known protocols include \f[C]http\f[R], \f[C]hls\f[R] and
-\f[C]hls-aes\f[R]; known extensions include \f[C]aac\f[R],
-\f[C]opus\f[R] and \f[C]mp3\f[R].
+\f[C]hls-aes\f[R]; known codecs include \f[C]aac\f[R], \f[C]opus\f[R]
+and \f[C]mp3\f[R].
 Original \f[C]download\f[R] formats are always extracted.
 Default is
 \f[C]http_aac,hls_aac,http_opus,hls_opus,http_mp3,hls_mp3\f[R]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/yt_dlp/cookies.py new/yt-dlp/yt_dlp/cookies.py
--- old/yt-dlp/yt_dlp/cookies.py        2024-12-03 21:30:58.000000000 +0100
+++ new/yt-dlp/yt_dlp/cookies.py        2024-12-06 17:07:34.000000000 +0100
@@ -195,7 +195,10 @@
 
 def _firefox_browser_dirs():
     if sys.platform in ('cygwin', 'win32'):
-        yield os.path.expandvars(R'%APPDATA%\Mozilla\Firefox\Profiles')
+        yield from map(os.path.expandvars, (
+            R'%APPDATA%\Mozilla\Firefox\Profiles',
+            
R'%LOCALAPPDATA%\Packages\Mozilla.Firefox_n80bbvh6b1yt2\LocalCache\Roaming\Mozilla\Firefox\Profiles',
+        ))
 
     elif sys.platform == 'darwin':
         yield os.path.expanduser('~/Library/Application 
Support/Firefox/Profiles')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/yt_dlp/extractor/bilibili.py 
new/yt-dlp/yt_dlp/extractor/bilibili.py
--- old/yt-dlp/yt_dlp/extractor/bilibili.py     2024-12-03 21:30:58.000000000 
+0100
+++ new/yt-dlp/yt_dlp/extractor/bilibili.py     2024-12-06 17:07:34.000000000 
+0100
@@ -681,12 +681,6 @@
         old_video_id = format_field(aid, None, f'%s_part{part_id or 1}')
         cid = traverse_obj(video_data, ('pages', part_id - 1, 'cid')) if 
part_id else video_data.get('cid')
 
-        play_info = (
-            traverse_obj(
-                self._search_json(r'window\.__playinfo__\s*=', webpage, 'play 
info', video_id, default=None),
-                ('data', {dict}))
-            or self._download_playinfo(video_id, cid, headers=headers, 
query={'try_look': 1}))
-
         festival_info = {}
         if is_festival:
             festival_info = traverse_obj(initial_state, {
@@ -724,6 +718,13 @@
                 duration=traverse_obj(initial_state, ('videoData', 'duration', 
{int_or_none})),
                 __post_extractor=self.extract_comments(aid))
 
+        play_info = None
+        if self.is_logged_in:
+            play_info = traverse_obj(
+                self._search_json(r'window\.__playinfo__\s*=', webpage, 'play 
info', video_id, default=None),
+                ('data', {dict}))
+        if not play_info:
+            play_info = self._download_playinfo(video_id, cid, 
headers=headers, query={'try_look': 1})
         formats = self.extract_formats(play_info)
 
         if video_data.get('is_upower_exclusive'):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/yt_dlp/extractor/soundcloud.py 
new/yt-dlp/yt_dlp/extractor/soundcloud.py
--- old/yt-dlp/yt_dlp/extractor/soundcloud.py   2024-12-03 21:30:58.000000000 
+0100
+++ new/yt-dlp/yt_dlp/extractor/soundcloud.py   2024-12-06 17:07:34.000000000 
+0100
@@ -7,7 +7,6 @@
 from ..networking import HEADRequest
 from ..networking.exceptions import HTTPError
 from ..utils import (
-    KNOWN_EXTENSIONS,
     ExtractorError,
     float_or_none,
     int_or_none,
@@ -251,50 +250,15 @@
         def invalid_url(url):
             return not url or url in format_urls
 
-        def add_format(f, protocol, is_preview=False):
-            mobj = 
re.search(r'\.(?P<abr>\d+)\.(?P<ext>[0-9a-z]{3,4})(?=[/?])', stream_url)
-            if mobj:
-                for k, v in mobj.groupdict().items():
-                    if not f.get(k):
-                        f[k] = v
-            format_id_list = []
-            if protocol:
-                format_id_list.append(protocol)
-            ext = f.get('ext')
-            if ext == 'aac':
-                f.update({
-                    'abr': 256,
-                    'quality': 5,
-                    'format_note': 'Premium',
-                })
-            for k in ('ext', 'abr'):
-                v = str_or_none(f.get(k))
-                if v:
-                    format_id_list.append(v)
-            preview = is_preview or re.search(r'/(?:preview|playlist)/0/30/', 
f['url'])
-            if preview:
-                format_id_list.append('preview')
-            abr = f.get('abr')
-            if abr:
-                f['abr'] = int(abr)
-            if protocol in ('hls', 'hls-aes'):
-                protocol = 'm3u8' if ext == 'aac' else 'm3u8_native'
-            else:
-                protocol = 'http'
-            f.update({
-                'format_id': '_'.join(format_id_list),
-                'protocol': protocol,
-                'preference': -10 if preview else None,
-            })
-            formats.append(f)
-
         # New API
-        for t in traverse_obj(info, ('media', 'transcodings', lambda _, v: 
url_or_none(v['url']))):
+        for t in traverse_obj(info, ('media', 'transcodings', lambda _, v: 
url_or_none(v['url']) and v['preset'])):
             if extract_flat:
                 break
             format_url = t['url']
+            preset = t['preset']
+            preset_base = preset.partition('_')[0]
 
-            protocol = traverse_obj(t, ('format', 'protocol', {str}))
+            protocol = traverse_obj(t, ('format', 'protocol', {str})) or 'http'
             if protocol == 'progressive':
                 protocol = 'http'
             if protocol != 'hls' and '/hls' in format_url:
@@ -302,32 +266,54 @@
             if protocol == 'encrypted-hls' or '/encrypted-hls' in format_url:
                 protocol = 'hls-aes'
 
-            ext = None
-            if preset := traverse_obj(t, ('preset', {str_or_none})):
-                ext = preset.split('_')[0]
-            if ext not in KNOWN_EXTENSIONS:
-                ext = mimetype2ext(traverse_obj(t, ('format', 'mime_type', 
{str})))
-
-            identifier = join_nonempty(protocol, ext, delim='_')
-            if not self._is_requested(identifier):
-                self.write_debug(f'"{identifier}" is not a requested format, 
skipping')
+            short_identifier = f'{protocol}_{preset_base}'
+            if preset_base == 'abr':
+                self.write_debug(f'Skipping broken "{short_identifier}" 
format')
+                continue
+            if not self._is_requested(short_identifier):
+                self.write_debug(f'"{short_identifier}" is not a requested 
format, skipping')
                 continue
 
             # XXX: if not extract_flat, 429 error must be caught where 
_extract_info_dict is called
             stream_url = traverse_obj(self._call_api(
-                format_url, track_id, f'Downloading {identifier} format info 
JSON',
+                format_url, track_id, f'Downloading {short_identifier} format 
info JSON',
                 query=query, headers=self._HEADERS), ('url', {url_or_none}))
-
             if invalid_url(stream_url):
                 continue
             format_urls.add(stream_url)
-            add_format({
+
+            mime_type = traverse_obj(t, ('format', 'mime_type', {str}))
+            codec = self._search_regex(r'codecs="([^"]+)"', mime_type, 
'codec', default=None)
+            ext = {
+                'mp4a': 'm4a',
+                'opus': 'opus',
+            }.get(codec[:4] if codec else None) or mimetype2ext(mime_type, 
default=None)
+            if not ext or ext == 'm3u8':
+                ext = preset_base
+
+            is_premium = t.get('quality') == 'hq'
+            abr = int_or_none(
+                self._search_regex(r'(\d+)k$', preset, 'abr', default=None)
+                or self._search_regex(r'\.(\d+)\.(?:opus|mp3)[/?]', 
stream_url, 'abr', default=None)
+                or (256 if (is_premium and 'aac' in preset) else None))
+
+            is_preview = (t.get('snipped')
+                          or '/preview/' in format_url
+                          or re.search(r'/(?:preview|playlist)/0/30/', 
stream_url))
+
+            formats.append({
+                'format_id': join_nonempty(protocol, preset, is_preview and 
'preview', delim='_'),
                 'url': stream_url,
                 'ext': ext,
-            }, protocol, t.get('snipped') or '/preview/' in format_url)
-
-        for f in formats:
-            f['vcodec'] = 'none'
+                'acodec': codec,
+                'vcodec': 'none',
+                'abr': abr,
+                'protocol': 'm3u8_native' if protocol in ('hls', 'hls-aes') 
else 'http',
+                'container': 'm4a_dash' if ext == 'm4a' else None,
+                'quality': 5 if is_premium else 0 if (abr and abr >= 160) else 
-1,
+                'format_note': 'Premium' if is_premium else None,
+                'preference': -10 if is_preview else None,
+            })
 
         if not formats and info.get('policy') == 'BLOCK':
             self.raise_geo_restricted(metadata_available=True)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/yt_dlp/extractor/youtube.py 
new/yt-dlp/yt_dlp/extractor/youtube.py
--- old/yt-dlp/yt_dlp/extractor/youtube.py      2024-12-03 21:30:58.000000000 
+0100
+++ new/yt-dlp/yt_dlp/extractor/youtube.py      2024-12-06 17:07:34.000000000 
+0100
@@ -78,7 +78,7 @@
         'INNERTUBE_CONTEXT': {
             'client': {
                 'clientName': 'WEB',
-                'clientVersion': '2.20240726.00.00',
+                'clientVersion': '2.20241126.01.00',
             },
         },
         'INNERTUBE_CONTEXT_CLIENT_NAME': 1,
@@ -90,7 +90,7 @@
         'INNERTUBE_CONTEXT': {
             'client': {
                 'clientName': 'WEB',
-                'clientVersion': '2.20240726.00.00',
+                'clientVersion': '2.20241126.01.00',
                 'userAgent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) 
AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.5 
Safari/605.1.15,gzip(gfe)',
             },
         },
@@ -102,7 +102,7 @@
         'INNERTUBE_CONTEXT': {
             'client': {
                 'clientName': 'WEB_EMBEDDED_PLAYER',
-                'clientVersion': '1.20240723.01.00',
+                'clientVersion': '1.20241201.00.00',
             },
         },
         'INNERTUBE_CONTEXT_CLIENT_NAME': 56,
@@ -113,7 +113,7 @@
         'INNERTUBE_CONTEXT': {
             'client': {
                 'clientName': 'WEB_REMIX',
-                'clientVersion': '1.20240724.00.00',
+                'clientVersion': '1.20241127.01.00',
             },
         },
         'INNERTUBE_CONTEXT_CLIENT_NAME': 67,
@@ -124,7 +124,7 @@
         'INNERTUBE_CONTEXT': {
             'client': {
                 'clientName': 'WEB_CREATOR',
-                'clientVersion': '1.20240723.03.00',
+                'clientVersion': '1.20241203.01.00',
             },
         },
         'INNERTUBE_CONTEXT_CLIENT_NAME': 62,
@@ -257,7 +257,8 @@
         'INNERTUBE_CONTEXT': {
             'client': {
                 'clientName': 'MWEB',
-                'clientVersion': '2.20240726.01.00',
+                'clientVersion': '2.20241202.07.00',
+                'userAgent': 'Mozilla/5.0 (iPad; CPU OS 16_7_10 like Mac OS X) 
AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 
Safari/604.1,gzip(gfe)',
             },
         },
         'INNERTUBE_CONTEXT_CLIENT_NAME': 2,
@@ -267,7 +268,7 @@
         'INNERTUBE_CONTEXT': {
             'client': {
                 'clientName': 'TVHTML5',
-                'clientVersion': '7.20240724.13.00',
+                'clientVersion': '7.20241201.18.00',
             },
         },
         'INNERTUBE_CONTEXT_CLIENT_NAME': 7,
@@ -3118,19 +3119,26 @@
         self.to_screen('Extracted signature function:\n' + code)
 
     def _parse_sig_js(self, jscode):
+        # Examples where `sig` is funcname:
+        # sig=function(a){a=a.split(""); ... ;return a.join("")};
+        # 
;c&&(c=sig(decodeURIComponent(c)),a.set(b,encodeURIComponent(c)));return a};
+        # {var 
l=f,m=h.sp,n=sig(decodeURIComponent(h.s));l.set(m,encodeURIComponent(n))}
+        # sig=function(J){J=J.split(""); ... ;return J.join("")};
+        # 
;N&&(N=sig(decodeURIComponent(N)),J.set(R,encodeURIComponent(N)));return J};
+        # {var 
H=u,k=f.sp,v=sig(decodeURIComponent(f.s));H.set(k,encodeURIComponent(v))}
         funcname = self._search_regex(
-            
(r'\b[cs]\s*&&\s*[adf]\.set\([^,]+\s*,\s*encodeURIComponent\s*\(\s*(?P<sig>[a-zA-Z0-9$]+)\(',
+            
(r'\b(?P<var>[a-zA-Z0-9$]+)&&\((?P=var)=(?P<sig>[a-zA-Z0-9$]{2,})\(decodeURIComponent\((?P=var)\)\)',
+             
r'(?P<sig>[a-zA-Z0-9$]+)\s*=\s*function\(\s*(?P<arg>[a-zA-Z0-9$]+)\s*\)\s*{\s*(?P=arg)\s*=\s*(?P=arg)\.split\(\s*""\s*\)\s*;\s*[^}]+;\s*return\s+(?P=arg)\.join\(\s*""\s*\)',
+             
r'(?:\b|[^a-zA-Z0-9$])(?P<sig>[a-zA-Z0-9$]{2,})\s*=\s*function\(\s*a\s*\)\s*{\s*a\s*=\s*a\.split\(\s*""\s*\)(?:;[a-zA-Z0-9$]{2}\.[a-zA-Z0-9$]{2}\(a,\d+\))?',
+             # Old patterns
+             
r'\b[cs]\s*&&\s*[adf]\.set\([^,]+\s*,\s*encodeURIComponent\s*\(\s*(?P<sig>[a-zA-Z0-9$]+)\(',
              
r'\b[a-zA-Z0-9]+\s*&&\s*[a-zA-Z0-9]+\.set\([^,]+\s*,\s*encodeURIComponent\s*\(\s*(?P<sig>[a-zA-Z0-9$]+)\(',
              r'\bm=(?P<sig>[a-zA-Z0-9$]{2,})\(decodeURIComponent\(h\.s\)\)',
-             r'\bc&&\(c=(?P<sig>[a-zA-Z0-9$]{2,})\(decodeURIComponent\(c\)\)',
-             
r'(?:\b|[^a-zA-Z0-9$])(?P<sig>[a-zA-Z0-9$]{2,})\s*=\s*function\(\s*a\s*\)\s*{\s*a\s*=\s*a\.split\(\s*""\s*\)(?:;[a-zA-Z0-9$]{2}\.[a-zA-Z0-9$]{2}\(a,\d+\))?',
-             
r'(?P<sig>[a-zA-Z0-9$]+)\s*=\s*function\(\s*a\s*\)\s*{\s*a\s*=\s*a\.split\(\s*""\s*\)',
              # Obsolete patterns
              r'("|\')signature\1\s*,\s*(?P<sig>[a-zA-Z0-9$]+)\(',
              r'\.sig\|\|(?P<sig>[a-zA-Z0-9$]+)\(',
              
r'yt\.akamaized\.net/\)\s*\|\|\s*.*?\s*[cs]\s*&&\s*[adf]\.set\([^,]+\s*,\s*(?:encodeURIComponent\s*\()?\s*(?P<sig>[a-zA-Z0-9$]+)\(',
              r'\b[cs]\s*&&\s*[adf]\.set\([^,]+\s*,\s*(?P<sig>[a-zA-Z0-9$]+)\(',
-             
r'\b[a-zA-Z0-9]+\s*&&\s*[a-zA-Z0-9]+\.set\([^,]+\s*,\s*(?P<sig>[a-zA-Z0-9$]+)\(',
              
r'\bc\s*&&\s*[a-zA-Z0-9]+\.set\([^,]+\s*,\s*\([^)]*\)\s*\(\s*(?P<sig>[a-zA-Z0-9$]+)\('),
             jscode, 'Initial JS player signature function name', group='sig')
 
@@ -3204,6 +3212,7 @@
         # *  
a.D&&(b="nn"[+a.D],c=a.get(b))&&(c=narray[idx](c),a.set(b,c),narray.length||nfunc("")
         # *  
a.D&&(PL(a),b=a.j.n||null)&&(b=narray[0](b),a.set("n",b),narray.length||nfunc("")
         # *  
a.D&&(b="nn"[+a.D],vL(a),c=a.j[b]||null)&&(c=narray[idx](c),a.set(b,c),narray.length||nfunc("")
+        # *  
J.J="";J.url="";J.Z&&(R="nn"[+J.Z],mW(J),N=J.K[R]||null)&&(N=narray[idx](N),J.set(R,N))}};
         funcname, idx = self._search_regex(
             r'''(?x)
             (?:
@@ -3220,7 +3229,7 @@
                     )\)&&\(c=|
                 \b(?P<var>[a-zA-Z0-9_$]+)=
             )(?P<nfunc>[a-zA-Z0-9_$]+)(?:\[(?P<idx>\d+)\])?\([a-zA-Z]\)
-            
(?(var),[a-zA-Z0-9_$]+\.set\("n"\,(?P=var)\),(?P=nfunc)\.length)''',
+            
(?(var),[a-zA-Z0-9_$]+\.set\((?:"n+"|[a-zA-Z0-9_$]+)\,(?P=var)\))''',
             jscode, 'n function name', group=('nfunc', 'idx'), default=(None, 
None))
         if not funcname:
             self.report_warning(join_nonempty(
@@ -3229,7 +3238,7 @@
             return self._search_regex(
                 r'''(?xs)
                 ;\s*(?P<name>[a-zA-Z0-9_$]+)\s*=\s*function\([a-zA-Z0-9_$]+\)
-                \s*\{(?:(?!};).)+?["']enhanced_except_''',
+                
\s*\{(?:(?!};).)+?return\s*(?P<q>["'])[\w-]+_w8_(?P=q)\s*\+\s*[a-zA-Z0-9_$]+''',
                 jscode, 'Initial JS player n function name', group='name')
         elif not idx:
             return funcname
@@ -3238,6 +3247,11 @@
             rf'var {re.escape(funcname)}\s*=\s*(\[.+?\])\s*[,;]', jscode,
             f'Initial JS player n function list 
({funcname}.{idx})')))[int(idx)]
 
+    def _fixup_n_function_code(self, argnames, code):
+        return argnames, re.sub(
+            
rf';\s*if\s*\(\s*typeof\s+[a-zA-Z0-9_$]+\s*===?\s*(["\'])undefined\1\s*\)\s*return\s+{argnames[0]};',
+            ';', code)
+
     def _extract_n_function_code(self, video_id, player_url):
         player_id = self._extract_player_info(player_url)
         func_code = self.cache.load('youtube-nsig', player_id, 
min_ver='2024.07.09')
@@ -3249,7 +3263,8 @@
 
         func_name = self._extract_n_function_name(jscode, 
player_url=player_url)
 
-        func_code = jsi.extract_function_code(func_name)
+        # XXX: Workaround for the `typeof` gotcha
+        func_code = 
self._fixup_n_function_code(*jsi.extract_function_code(func_name))
 
         self.cache.store('youtube-nsig', player_id, func_code)
         return jsi, player_id, func_code
@@ -3265,7 +3280,7 @@
             except Exception as e:
                 raise JSInterpreter.Exception(traceback.format_exc(), cause=e)
 
-            if ret.startswith('enhanced_except_'):
+            if ret.startswith('enhanced_except_') or ret.endswith(s):
                 raise JSInterpreter.Exception('Signature function returned an 
exception')
             return ret
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/yt_dlp/version.py new/yt-dlp/yt_dlp/version.py
--- old/yt-dlp/yt_dlp/version.py        2024-12-03 21:31:18.000000000 +0100
+++ new/yt-dlp/yt_dlp/version.py        2024-12-06 17:07:41.000000000 +0100
@@ -1,8 +1,8 @@
 # Autogenerated by devscripts/update-version.py
 
-__version__ = '2024.12.03'
+__version__ = '2024.12.06'
 
-RELEASE_GIT_HEAD = '2b67ac300ac8b44368fb121637d1743cea8c5b6b'
+RELEASE_GIT_HEAD = '4bd2655398aed450456197a6767639114a24eac2'
 
 VARIANT = None
 
@@ -12,4 +12,4 @@
 
 ORIGIN = 'yt-dlp/yt-dlp'
 
-_pkg_version = '2024.12.03'
+_pkg_version = '2024.12.06'

Reply via email to