Hello community,

here is the log from the commit of package youtube-dl for openSUSE:Factory 
checked in at 2020-11-03 15:16:35
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/youtube-dl (Old)
 and      /work/SRC/openSUSE:Factory/.youtube-dl.new.3463 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "youtube-dl"

Tue Nov  3 15:16:35 2020 rev:140 rq:845526 version:2020.11.01.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/youtube-dl/python-youtube-dl.changes     
2020-09-21 17:47:26.861140570 +0200
+++ /work/SRC/openSUSE:Factory/.youtube-dl.new.3463/python-youtube-dl.changes   
2020-11-03 15:17:00.796065886 +0100
@@ -1,0 +2,9 @@
+Mon Nov  2 12:59:41 UTC 2020 - Jan Engelhardt <jeng...@inai.de>
+
+- Update to release 2020.11.01.1
+  * youtube: Fix JS player URL extraction
+  * ytsearch: Fix extraction
+  * ustream: Add support for video.ibm.com
+  * expressen: Add support for di.se
+
+-------------------------------------------------------------------
youtube-dl.changes: same change

Old:
----
  youtube-dl-2020.09.20.tar.gz
  youtube-dl-2020.09.20.tar.gz.sig

New:
----
  youtube-dl-2020.11.01.1.tar.gz
  youtube-dl-2020.11.01.1.tar.gz.sig

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

Other differences:
------------------
++++++ python-youtube-dl.spec ++++++
--- /var/tmp/diff_new_pack.oG0WeY/_old  2020-11-03 15:17:05.640070548 +0100
+++ /var/tmp/diff_new_pack.oG0WeY/_new  2020-11-03 15:17:05.644070552 +0100
@@ -19,7 +19,7 @@
 %define modname youtube-dl
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-youtube-dl
-Version:        2020.09.20
+Version:        2020.11.01.1
 Release:        0
 Summary:        A Python module for downloading from video sites for offline 
watching
 License:        SUSE-Public-Domain AND CC-BY-SA-3.0

++++++ youtube-dl.spec ++++++
--- /var/tmp/diff_new_pack.oG0WeY/_old  2020-11-03 15:17:05.664070572 +0100
+++ /var/tmp/diff_new_pack.oG0WeY/_new  2020-11-03 15:17:05.668070575 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           youtube-dl
-Version:        2020.09.20
+Version:        2020.11.01.1
 Release:        0
 Summary:        A tool for downloading from video sites for offline watching
 License:        SUSE-Public-Domain AND CC-BY-SA-3.0

++++++ youtube-dl-2020.09.20.tar.gz -> youtube-dl-2020.11.01.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/youtube-dl/ChangeLog new/youtube-dl/ChangeLog
--- old/youtube-dl/ChangeLog    2020-09-20 07:30:42.000000000 +0200
+++ new/youtube-dl/ChangeLog    2020-11-01 02:58:37.000000000 +0100
@@ -1,3 +1,21 @@
+version 2020.11.01
+
+Core
+* [utils] Don't attempt to coerce JS strings to numbers in js_to_json (#26851)
+* [downloader/http] Properly handle missing message in SSLError (#26646)
+* [downloader/http] Fix access to not yet opened stream in retry
+
+Extractors
+* [youtube] Fix JS player URL extraction
+* [ytsearch] Fix extraction (#26920)
+* [afreecatv] Fix typo (#26970)
+* [23video] Relax URL regular expression (#26870)
++ [ustream] Add support for video.ibm.com (#26894)
+* [iqiyi] Fix typo (#26884)
++ [expressen] Add support for di.se (#26670)
+* [iprima] Improve video id extraction (#26507, #26494)
+
+
 version 2020.09.20
 
 Core
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/youtube-dl/README.md new/youtube-dl/README.md
--- old/youtube-dl/README.md    2020-09-20 07:30:44.000000000 +0200
+++ new/youtube-dl/README.md    2020-11-01 02:58:39.000000000 +0100
@@ -545,7 +545,7 @@
  - `extractor` (string): Name of the extractor
  - `extractor_key` (string): Key name of the extractor
  - `epoch` (numeric): Unix epoch when creating the file
- - `autonumber` (numeric): Five-digit number that will be increased with each 
download, starting at zero
+ - `autonumber` (numeric): Number that will be increased with each download, 
starting at `--autonumber-start`
  - `playlist` (string): Name or id of the playlist that contains the video
  - `playlist_index` (numeric): Index of the video in the playlist padded with 
leading zeros according to the total length of the playlist
  - `playlist_id` (string): Playlist identifier
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/youtube-dl/README.txt new/youtube-dl/README.txt
--- old/youtube-dl/README.txt   2020-09-20 07:31:22.000000000 +0200
+++ new/youtube-dl/README.txt   2020-11-01 02:58:52.000000000 +0100
@@ -634,8 +634,8 @@
 -   extractor (string): Name of the extractor
 -   extractor_key (string): Key name of the extractor
 -   epoch (numeric): Unix epoch when creating the file
--   autonumber (numeric): Five-digit number that will be increased with
-    each download, starting at zero
+-   autonumber (numeric): Number that will be increased with each
+    download, starting at --autonumber-start
 -   playlist (string): Name or id of the playlist that contains the
     video
 -   playlist_index (numeric): Index of the video in the playlist padded
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/youtube-dl/devscripts/release_gitlab.sh 
new/youtube-dl/devscripts/release_gitlab.sh
--- old/youtube-dl/devscripts/release_gitlab.sh 1970-01-01 01:00:00.000000000 
+0100
+++ new/youtube-dl/devscripts/release_gitlab.sh 2020-11-01 02:58:20.000000000 
+0100
@@ -0,0 +1,141 @@
+#!/bin/bash
+
+# IMPORTANT: the following assumptions are made
+# * the GH repo is on the origin remote
+# * the gh-pages branch is named so locally
+# * the git config user.signingkey is properly set
+
+# You will need
+# pip install coverage nose rsa wheel
+
+# TODO
+# release notes
+# make hash on local files
+
+set -e
+
+skip_tests=true
+gpg_sign_commits=""
+buildserver='localhost:8142'
+
+while true
+do
+case "$1" in
+    --run-tests)
+        skip_tests=false
+        shift
+    ;;
+    --gpg-sign-commits|-S)
+        gpg_sign_commits="-S"
+        shift
+    ;;
+    --buildserver)
+        buildserver="$2"
+        shift 2
+    ;;
+    --*)
+        echo "ERROR: unknown option $1"
+        exit 1
+    ;;
+    *)
+        break
+    ;;
+esac
+done
+
+if [ -z "$1" ]; then echo "ERROR: specify version number like this: $0 
1994.09.06"; exit 1; fi
+version="$1"
+major_version=$(echo "$version" | sed -n 
's#^\([0-9]*\.[0-9]*\.[0-9]*\).*#\1#p')
+if test "$major_version" '!=' "$(date '+%Y.%m.%d')"; then
+    echo "$version does not start with today's date!"
+    exit 1
+fi
+
+if [ ! -z "`git tag | grep "$version"`" ]; then echo 'ERROR: version already 
present'; exit 1; fi
+#if [ ! -z "`git status --porcelain | grep -v CHANGELOG`" ]; then echo 'ERROR: 
the working directory is not clean; commit or stash changes'; exit 1; fi
+useless_files=$(find youtube_dl -type f -not -name '*.py')
+if [ ! -z "$useless_files" ]; then echo "ERROR: Non-.py files in youtube_dl: 
$useless_files"; exit 1; fi
+if [ ! -f "updates_key.pem" ]; then echo 'ERROR: updates_key.pem missing'; 
exit 1; fi
+if ! type pandoc >/dev/null 2>/dev/null; then echo 'ERROR: pandoc is missing'; 
exit 1; fi
+if ! python3 -c 'import rsa' 2>/dev/null; then echo 'ERROR: python3-rsa is 
missing'; exit 1; fi
+if ! python3 -c 'import wheel' 2>/dev/null; then echo 'ERROR: wheel is 
missing'; exit 1; fi
+
+read -p "Is ChangeLog up to date? (y/n) " -n 1
+if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 1; fi
+
+/bin/echo -e "\n### First of all, testing..."
+make clean
+if $skip_tests ; then
+    echo 'SKIPPING TESTS'
+else
+    nosetests --verbose --with-coverage --cover-package=youtube_dl 
--cover-html test --stop || exit 1
+fi
+
+/bin/echo -e "\n### Changing version in version.py..."
+sed -i "s/__version__ = '.*'/__version__ = '$version'/" youtube_dl/version.py
+
+/bin/echo -e "\n### Changing version in ChangeLog..."
+sed -i "s/<unreleased>/$version/" ChangeLog
+
+/bin/echo -e "\n### Committing documentation, templates and 
youtube_dl/version.py..."
+make README.md CONTRIBUTING.md issuetemplates supportedsites
+git add README.md CONTRIBUTING.md .github/ISSUE_TEMPLATE/1_broken_site.md 
.github/ISSUE_TEMPLATE/2_site_support_request.md 
.github/ISSUE_TEMPLATE/3_site_feature_request.md 
.github/ISSUE_TEMPLATE/4_bug_report.md 
.github/ISSUE_TEMPLATE/5_feature_request.md 
.github/ISSUE_TEMPLATE/6_question.md docs/supportedsites.md 
youtube_dl/version.py ChangeLog
+git commit $gpg_sign_commits -m "release $version"
+
+/bin/echo -e "\n### Now tagging, signing and pushing..."
+git tag -s -m "Release $version" "$version"
+git show "$version"
+read -p "Is it good, can I push? (y/n) " -n 1
+if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 1; fi
+echo
+MASTER=$(git rev-parse --abbrev-ref HEAD)
+git push dstftw-gitlab $MASTER:master
+git push dstftw-gitlab "$version"
+
+/bin/echo -e "\n### OK, now it is time to build the binaries..."
+REV=$(git rev-parse HEAD)
+make youtube-dl youtube-dl.tar.gz
+read -p "VM running? (y/n) " -n 1
+wget "http://$buildserver/build/ytdl-org/youtube-dl/youtube-dl.exe?rev=$REV"; 
-O youtube-dl.exe
+mkdir -p "build/$version"
+mv youtube-dl youtube-dl.exe "build/$version"
+mv youtube-dl.tar.gz "build/$version/youtube-dl-$version.tar.gz"
+RELEASE_FILES="youtube-dl youtube-dl.exe youtube-dl-$version.tar.gz"
+(cd build/$version/ && md5sum $RELEASE_FILES > MD5SUMS)
+(cd build/$version/ && sha1sum $RELEASE_FILES > SHA1SUMS)
+(cd build/$version/ && sha256sum $RELEASE_FILES > SHA2-256SUMS)
+(cd build/$version/ && sha512sum $RELEASE_FILES > SHA2-512SUMS)
+
+/bin/echo -e "\n### Signing and uploading the new binaries to GitHub..."
+for f in $RELEASE_FILES; do gpg --passphrase-repeat 5 --detach-sig 
"build/$version/$f"; done
+
+ROOT=$(pwd)
+#python devscripts/create-github-release.py ChangeLog $version 
"$ROOT/build/$version"
+
+#ssh y...@yt-dl.org "sh html/update_latest.sh $version"
+
+/bin/echo -e "\n### Now switching to gh-pages..."
+git clone --branch gh-pages --single-branch . build/gh-pages
+(
+    set -e
+    ORIGIN_URL=$(git config --get remote.dstftw-gitlab.url)
+    cd build/gh-pages
+    "$ROOT/devscripts/gh-pages/add-version.py" $version
+    "$ROOT/devscripts/gh-pages/update-feed.py"
+    "$ROOT/devscripts/gh-pages/sign-versions.py" < "$ROOT/updates_key.pem"
+    "$ROOT/devscripts/gh-pages/generate-download.py"
+    "$ROOT/devscripts/gh-pages/update-copyright.py"
+    "$ROOT/devscripts/gh-pages/update-sites.py"
+    git add *.html *.html.in update
+    git commit $gpg_sign_commits -m "release $version"
+    git push "$ROOT" gh-pages
+    git push "$ORIGIN_URL" gh-pages
+)
+#rm -rf build
+
+make pypi-files
+echo "Uploading to PyPi ..."
+python setup.py sdist bdist_wheel upload
+#make clean
+
+/bin/echo -e "\n### DONE!"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/youtube-dl/test/test_utils.py 
new/youtube-dl/test/test_utils.py
--- old/youtube-dl/test/test_utils.py   2020-09-20 07:29:46.000000000 +0200
+++ new/youtube-dl/test/test_utils.py   2020-11-01 02:52:19.000000000 +0100
@@ -994,6 +994,12 @@
         on = js_to_json('{42:4.2e1}')
         self.assertEqual(json.loads(on), {'42': 42.0})
 
+        on = js_to_json('{ "0x40": "0x40" }')
+        self.assertEqual(json.loads(on), {'0x40': '0x40'})
+
+        on = js_to_json('{ "040": "040" }')
+        self.assertEqual(json.loads(on), {'040': '040'})
+
     def test_js_to_json_malformed(self):
         self.assertEqual(js_to_json('42a1'), '42"a1"')
         self.assertEqual(js_to_json('42a-1'), '42"a"-1')
Binary files old/youtube-dl/youtube-dl and new/youtube-dl/youtube-dl differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/youtube-dl/youtube-dl.1 new/youtube-dl/youtube-dl.1
--- old/youtube-dl/youtube-dl.1 2020-09-20 07:31:23.000000000 +0200
+++ new/youtube-dl/youtube-dl.1 2020-11-01 02:58:53.000000000 +0100
@@ -1141,8 +1141,8 @@
 .IP \[bu] 2
 \f[C]epoch\f[] (numeric): Unix epoch when creating the file
 .IP \[bu] 2
-\f[C]autonumber\f[] (numeric): Five\-digit number that will be increased
-with each download, starting at zero
+\f[C]autonumber\f[] (numeric): Number that will be increased with each
+download, starting at \f[C]\-\-autonumber\-start\f[]
 .IP \[bu] 2
 \f[C]playlist\f[] (string): Name or id of the playlist that contains the
 video
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/youtube-dl/youtube_dl/downloader/http.py 
new/youtube-dl/youtube_dl/downloader/http.py
--- old/youtube-dl/youtube_dl/downloader/http.py        2020-09-20 
07:29:51.000000000 +0200
+++ new/youtube-dl/youtube_dl/downloader/http.py        2020-11-01 
02:52:19.000000000 +0100
@@ -223,9 +223,10 @@
 
             def retry(e):
                 to_stdout = ctx.tmpfilename == '-'
-                if not to_stdout:
-                    ctx.stream.close()
-                ctx.stream = None
+                if ctx.stream is not None:
+                    if not to_stdout:
+                        ctx.stream.close()
+                    ctx.stream = None
                 ctx.resume_len = byte_counter if to_stdout else 
os.path.getsize(encodeFilename(ctx.tmpfilename))
                 raise RetryDownload(e)
 
@@ -240,7 +241,7 @@
                 except socket.error as e:
                     # SSLError on python 2 (inherits socket.error) may have
                     # no errno set but this error message
-                    if e.errno in (errno.ECONNRESET, errno.ETIMEDOUT) or 
getattr(e, 'message') == 'The read operation timed out':
+                    if e.errno in (errno.ECONNRESET, errno.ETIMEDOUT) or 
getattr(e, 'message', None) == 'The read operation timed out':
                         retry(e)
                     raise
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/youtube-dl/youtube_dl/extractor/afreecatv.py 
new/youtube-dl/youtube_dl/extractor/afreecatv.py
--- old/youtube-dl/youtube_dl/extractor/afreecatv.py    2020-09-20 
07:29:46.000000000 +0200
+++ new/youtube-dl/youtube_dl/extractor/afreecatv.py    2020-11-01 
02:52:19.000000000 +0100
@@ -275,7 +275,7 @@
         video_element = video_xml.findall(compat_xpath('./track/video'))[-1]
         if video_element is None or video_element.text is None:
             raise ExtractorError(
-                'Video %s video does not exist' % video_id, expected=True)
+                'Video %s does not exist' % video_id, expected=True)
 
         video_url = video_element.text.strip()
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/youtube-dl/youtube_dl/extractor/expressen.py 
new/youtube-dl/youtube_dl/extractor/expressen.py
--- old/youtube-dl/youtube_dl/extractor/expressen.py    2020-09-20 
07:29:46.000000000 +0200
+++ new/youtube-dl/youtube_dl/extractor/expressen.py    2020-11-01 
02:52:19.000000000 +0100
@@ -15,7 +15,7 @@
 class ExpressenIE(InfoExtractor):
     _VALID_URL = r'''(?x)
                     https?://
-                        (?:www\.)?expressen\.se/
+                        (?:www\.)?(?:expressen|di)\.se/
                         (?:(?:tvspelare/video|videoplayer/embed)/)?
                         tv/(?:[^/]+/)*
                         (?P<id>[^/?#&]+)
@@ -42,13 +42,16 @@
     }, {
         'url': 
'https://www.expressen.se/videoplayer/embed/tv/ditv/ekonomistudion/experterna-har-ar-fragorna-som-avgor-valet/?embed=true&external=true&autoplay=true&startVolume=0&partnerId=di',
         'only_matching': True,
+    }, {
+        'url': 
'https://www.di.se/videoplayer/embed/tv/ditv/borsmorgon/implantica-rusar-70--under-borspremiaren-hor-styrelsemedlemmen/?embed=true&external=true&autoplay=true&startVolume=0&partnerId=di',
+        'only_matching': True,
     }]
 
     @staticmethod
     def _extract_urls(webpage):
         return [
             mobj.group('url') for mobj in re.finditer(
-                
r'<iframe[^>]+\bsrc=(["\'])(?P<url>(?:https?:)?//(?:www\.)?expressen\.se/(?:tvspelare/video|videoplayer/embed)/tv/.+?)\1',
+                
r'<iframe[^>]+\bsrc=(["\'])(?P<url>(?:https?:)?//(?:www\.)?(?:expressen|di)\.se/(?:tvspelare/video|videoplayer/embed)/tv/.+?)\1',
                 webpage)]
 
     def _real_extract(self, url):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/youtube-dl/youtube_dl/extractor/iprima.py 
new/youtube-dl/youtube_dl/extractor/iprima.py
--- old/youtube-dl/youtube_dl/extractor/iprima.py       2020-09-20 
07:29:46.000000000 +0200
+++ new/youtube-dl/youtube_dl/extractor/iprima.py       2020-11-01 
02:52:19.000000000 +0100
@@ -86,7 +86,8 @@
             
(r'<iframe[^>]+\bsrc=["\'](?:https?:)?//(?:api\.play-backend\.iprima\.cz/prehravac/embedded|prima\.iprima\.cz/[^/]+/[^/]+)\?.*?\bid=(p\d+)',
              r'data-product="([^"]+)">',
              r'id=["\']player-(p\d+)"',
-             r'playerId\s*:\s*["\']player-(p\d+)'),
+             r'playerId\s*:\s*["\']player-(p\d+)',
+             r'\bvideos\s*=\s*["\'](p\d+)'),
             webpage, 'real id')
 
         playerpage = self._download_webpage(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/youtube-dl/youtube_dl/extractor/iqiyi.py 
new/youtube-dl/youtube_dl/extractor/iqiyi.py
--- old/youtube-dl/youtube_dl/extractor/iqiyi.py        2020-09-20 
07:29:46.000000000 +0200
+++ new/youtube-dl/youtube_dl/extractor/iqiyi.py        2020-11-01 
02:52:19.000000000 +0100
@@ -150,7 +150,7 @@
             elif function in other_functions:
                 other_functions[function]()
             else:
-                raise ExtractorError('Unknown funcion %s' % function)
+                raise ExtractorError('Unknown function %s' % function)
 
         return sdk.target
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/youtube-dl/youtube_dl/extractor/twentythreevideo.py 
new/youtube-dl/youtube_dl/extractor/twentythreevideo.py
--- old/youtube-dl/youtube_dl/extractor/twentythreevideo.py     2020-09-20 
07:29:46.000000000 +0200
+++ new/youtube-dl/youtube_dl/extractor/twentythreevideo.py     2020-11-01 
02:52:19.000000000 +0100
@@ -8,8 +8,8 @@
 
 class TwentyThreeVideoIE(InfoExtractor):
     IE_NAME = '23video'
-    _VALID_URL = 
r'https?://video\.(?P<domain>twentythree\.net|23video\.com|filmweb\.no)/v\.ihtml/player\.html\?(?P<query>.*?\bphoto(?:_|%5f)id=(?P<id>\d+).*)'
-    _TEST = {
+    _VALID_URL = 
r'https?://(?P<domain>[^.]+\.(?:twentythree\.net|23video\.com|filmweb\.no))/v\.ihtml/player\.html\?(?P<query>.*?\bphoto(?:_|%5f)id=(?P<id>\d+).*)'
+    _TESTS = [{
         'url': 
'https://video.twentythree.net/v.ihtml/player.html?showDescriptions=0&source=site&photo%5fid=20448876&autoPlay=1',
         'md5': '75fcf216303eb1dae9920d651f85ced4',
         'info_dict': {
@@ -21,11 +21,14 @@
             'uploader_id': '12258964',
             'uploader': 'Rasmus Bysted',
         }
-    }
+    }, {
+        'url': 
'https://bonnier-publications-danmark.23video.com/v.ihtml/player.html?token=f0dc46476e06e13afd5a1f84a29e31e8&source=embed&photo%5fid=36137620',
+        'only_matching': True,
+    }]
 
     def _real_extract(self, url):
         domain, query, photo_id = re.match(self._VALID_URL, url).groups()
-        base_url = 'https://video.%s' % domain
+        base_url = 'https://%s' % domain
         photo_data = self._download_json(
             base_url + '/api/photo/list?' + query, photo_id, query={
                 'format': 'json',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/youtube-dl/youtube_dl/extractor/ustream.py 
new/youtube-dl/youtube_dl/extractor/ustream.py
--- old/youtube-dl/youtube_dl/extractor/ustream.py      2020-09-20 
07:29:46.000000000 +0200
+++ new/youtube-dl/youtube_dl/extractor/ustream.py      2020-11-01 
02:52:19.000000000 +0100
@@ -19,7 +19,7 @@
 
 
 class UstreamIE(InfoExtractor):
-    _VALID_URL = 
r'https?://(?:www\.)?ustream\.tv/(?P<type>recorded|embed|embed/recorded)/(?P<id>\d+)'
+    _VALID_URL = 
r'https?://(?:www\.)?(?:ustream\.tv|video\.ibm\.com)/(?P<type>recorded|embed|embed/recorded)/(?P<id>\d+)'
     IE_NAME = 'ustream'
     _TESTS = [{
         'url': 'http://www.ustream.tv/recorded/20274954',
@@ -67,12 +67,15 @@
         'params': {
             'skip_download': True,  # m3u8 download
         },
+    }, {
+        'url': 
'https://video.ibm.com/embed/recorded/128240221?&autoplay=true&controls=true&volume=100',
+        'only_matching': True,
     }]
 
     @staticmethod
     def _extract_url(webpage):
         mobj = re.search(
-            
r'<iframe[^>]+?src=(["\'])(?P<url>http://www\.ustream\.tv/embed/.+?)\1', 
webpage)
+            
r'<iframe[^>]+?src=(["\'])(?P<url>http://(?:www\.)?(?:ustream\.tv|video\.ibm\.com)/embed/.+?)\1',
 webpage)
         if mobj is not None:
             return mobj.group('url')
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/youtube-dl/youtube_dl/extractor/youtube.py 
new/youtube-dl/youtube_dl/extractor/youtube.py
--- old/youtube-dl/youtube_dl/extractor/youtube.py      2020-09-20 
07:29:46.000000000 +0200
+++ new/youtube-dl/youtube_dl/extractor/youtube.py      2020-11-01 
02:52:19.000000000 +0100
@@ -2086,7 +2086,10 @@
 
                 if cipher:
                     if 's' in url_data or 
self._downloader.params.get('youtube_include_dash_manifest', True):
-                        ASSETS_RE = r'"assets":.+?"js":\s*("[^"]+")'
+                        ASSETS_RE = (
+                            
r'<script[^>]+\bsrc=("[^"]+")[^>]+\bname=["\']player_ias/base',
+                            r'"jsUrl"\s*:\s*("[^"]+")',
+                            r'"assets":.+?"js":\s*("[^"]+")')
                         jsplayer_url_json = self._search_regex(
                             ASSETS_RE,
                             embed_webpage if age_gate else video_webpage,
@@ -3181,54 +3184,94 @@
     _MAX_RESULTS = float('inf')
     IE_NAME = 'youtube:search'
     _SEARCH_KEY = 'ytsearch'
-    _EXTRA_QUERY_ARGS = {}
+    _SEARCH_PARAMS = None
     _TESTS = []
 
-    def _get_n_results(self, query, n):
-        """Get a specified number of results for a query"""
-
-        videos = []
-        limit = n
-
-        url_query = {
-            'search_query': query.encode('utf-8'),
+    def _entries(self, query, n):
+        data = {
+            'context': {
+                'client': {
+                    'clientName': 'WEB',
+                    'clientVersion': '2.20201021.03.00',
+                }
+            },
+            'query': query,
         }
-        url_query.update(self._EXTRA_QUERY_ARGS)
-        result_url = 'https://www.youtube.com/results?' + 
compat_urllib_parse_urlencode(url_query)
-
-        for pagenum in itertools.count(1):
-            data = self._download_json(
-                result_url, video_id='query "%s"' % query,
-                note='Downloading page %s' % pagenum,
-                errnote='Unable to download API page',
-                query={'spf': 'navigate'})
-            html_content = data[1]['body']['content']
-
-            if 'class="search-message' in html_content:
-                raise ExtractorError(
-                    '[youtube] No video results', expected=True)
-
-            new_videos = list(self._process_page(html_content))
-            videos += new_videos
-            if not new_videos or len(videos) > limit:
+        if self._SEARCH_PARAMS:
+            data['params'] = self._SEARCH_PARAMS
+        total = 0
+        for page_num in itertools.count(1):
+            search = self._download_json(
+                
'https://www.youtube.com/youtubei/v1/search?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8',
+                video_id='query "%s"' % query,
+                note='Downloading page %s' % page_num,
+                errnote='Unable to download API page', fatal=False,
+                data=json.dumps(data).encode('utf8'),
+                headers={'content-type': 'application/json'})
+            if not search:
                 break
-            next_link = self._html_search_regex(
-                
r'href="(/results\?[^"]*\bsp=[^"]+)"[^>]*>\s*<span[^>]+class="[^"]*\byt-uix-button-content\b[^"]*"[^>]*>Next',
-                html_content, 'next link', default=None)
-            if next_link is None:
+            slr_contents = try_get(
+                search,
+                (lambda x: 
x['contents']['twoColumnSearchResultsRenderer']['primaryContents']['sectionListRenderer']['contents'],
+                 lambda x: 
x['onResponseReceivedCommands'][0]['appendContinuationItemsAction']['continuationItems']),
+                list)
+            if not slr_contents:
                 break
-            result_url = compat_urlparse.urljoin('https://www.youtube.com/', 
next_link)
+            isr_contents = try_get(
+                slr_contents,
+                lambda x: x[0]['itemSectionRenderer']['contents'],
+                list)
+            if not isr_contents:
+                break
+            for content in isr_contents:
+                if not isinstance(content, dict):
+                    continue
+                video = content.get('videoRenderer')
+                if not isinstance(video, dict):
+                    continue
+                video_id = video.get('videoId')
+                if not video_id:
+                    continue
+                title = try_get(video, lambda x: 
x['title']['runs'][0]['text'], compat_str)
+                description = try_get(video, lambda x: 
x['descriptionSnippet']['runs'][0]['text'], compat_str)
+                duration = parse_duration(try_get(video, lambda x: 
x['lengthText']['simpleText'], compat_str))
+                view_count_text = try_get(video, lambda x: 
x['viewCountText']['simpleText'], compat_str) or ''
+                view_count = int_or_none(self._search_regex(
+                    r'^(\d+)', re.sub(r'\s', '', view_count_text),
+                    'view count', default=None))
+                uploader = try_get(video, lambda x: 
x['ownerText']['runs'][0]['text'], compat_str)
+                total += 1
+                yield {
+                    '_type': 'url_transparent',
+                    'ie_key': YoutubeIE.ie_key(),
+                    'id': video_id,
+                    'url': video_id,
+                    'title': title,
+                    'description': description,
+                    'duration': duration,
+                    'view_count': view_count,
+                    'uploader': uploader,
+                }
+                if total == n:
+                    return
+            token = try_get(
+                slr_contents,
+                lambda x: 
x[1]['continuationItemRenderer']['continuationEndpoint']['continuationCommand']['token'],
+                compat_str)
+            if not token:
+                break
+            data['continuation'] = token
 
-        if len(videos) > n:
-            videos = videos[:n]
-        return self.playlist_result(videos, query)
+    def _get_n_results(self, query, n):
+        """Get a specified number of results for a query"""
+        return self.playlist_result(self._entries(query, n), query)
 
 
 class YoutubeSearchDateIE(YoutubeSearchIE):
     IE_NAME = YoutubeSearchIE.IE_NAME + ':date'
     _SEARCH_KEY = 'ytsearchdate'
     IE_DESC = 'YouTube.com searches, newest videos first'
-    _EXTRA_QUERY_ARGS = {'search_sort': 'video_date_uploaded'}
+    _SEARCH_PARAMS = 'CAI%3D'
 
 
 class YoutubeSearchURLIE(YoutubeSearchBaseInfoExtractor):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/youtube-dl/youtube_dl/utils.py 
new/youtube-dl/youtube_dl/utils.py
--- old/youtube-dl/youtube_dl/utils.py  2020-09-20 07:29:46.000000000 +0200
+++ new/youtube-dl/youtube_dl/utils.py  2020-11-01 02:52:19.000000000 +0100
@@ -4088,12 +4088,12 @@
                 '\\\n': '',
                 '\\x': '\\u00',
             }.get(m.group(0), m.group(0)), v[1:-1])
-
-        for regex, base in INTEGER_TABLE:
-            im = re.match(regex, v)
-            if im:
-                i = int(im.group(1), base)
-                return '"%d":' % i if v.endswith(':') else '%d' % i
+        else:
+            for regex, base in INTEGER_TABLE:
+                im = re.match(regex, v)
+                if im:
+                    i = int(im.group(1), base)
+                    return '"%d":' % i if v.endswith(':') else '%d' % i
 
         return '"%s"' % v
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/youtube-dl/youtube_dl/version.py 
new/youtube-dl/youtube_dl/version.py
--- old/youtube-dl/youtube_dl/version.py        2020-09-20 07:30:42.000000000 
+0200
+++ new/youtube-dl/youtube_dl/version.py        2020-11-01 02:58:37.000000000 
+0100
@@ -1,3 +1,3 @@
 from __future__ import unicode_literals
 
-__version__ = '2020.09.20'
+__version__ = '2020.11.01.1'


Reply via email to