diff --git a/.gitignore b/.gitignore index 92f9029e3e..2e84762bcd 100644 --- a/.gitignore +++ b/.gitignore @@ -27,11 +27,13 @@ cookies *.ass *.avi *.desktop +*.f4v *.flac *.flv *.jpeg *.jpg *.m4a +*.mpga *.m4v *.mhtml *.mkv diff --git a/Makefile b/Makefile index f8b6e556f5..d6a00d332b 100644 --- a/Makefile +++ b/Makefile @@ -17,8 +17,8 @@ pypi-files: AUTHORS Changelog.md LICENSE README.md README.txt supportedsites \ clean-test: rm -rf test/testdata/sigs/player-*.js tmp/ *.annotations.xml *.aria2 *.description *.dump *.frag \ *.frag.aria2 *.frag.urls *.info.json *.live_chat.json *.meta *.part* *.tmp *.temp *.unknown_video *.ytdl \ - *.3gp *.ape *.ass *.avi *.desktop *.flac *.flv *.jpeg *.jpg *.m4a *.m4v *.mhtml *.mkv *.mov *.mp3 \ - *.mp4 *.ogg *.opus *.png *.sbv *.srt *.swf *.swp *.ttml *.url *.vtt *.wav *.webloc *.webm *.webp + *.3gp *.ape *.ass *.avi *.desktop *.f4v *.flac *.flv *.jpeg *.jpg *.m4a *.mpga *.m4v *.mhtml *.mkv *.mov \ + *.mp3 *.mp4 *.ogg *.opus *.png *.sbv *.srt *.swf *.swp *.ttml *.url *.vtt *.wav *.webloc *.webm *.webp clean-dist: rm -rf yt-dlp.1.temp.md yt-dlp.1 README.txt MANIFEST build/ dist/ .coverage cover/ yt-dlp.tar.gz completions/ \ yt_dlp/extractor/lazy_extractors.py *.spec CONTRIBUTING.md.tmp yt-dlp yt-dlp.exe yt_dlp.egg-info/ AUTHORS .mailmap diff --git a/yt_dlp/YoutubeDL.py b/yt_dlp/YoutubeDL.py index d6dac7a901..31fbbdb546 100644 --- a/yt_dlp/YoutubeDL.py +++ b/yt_dlp/YoutubeDL.py @@ -306,7 +306,7 @@ class YoutubeDL: client_certificate_password: Password for client certificate private key, if encrypted. If not provided and the key is encrypted, yt-dlp will ask interactively prefer_insecure: Use HTTP instead of HTTPS to retrieve information. - At the moment, this is only supported by YouTube. + (Only supported by some extractors) http_headers: A dictionary of custom headers to be used for all requests proxy: URL of the proxy server to use geo_verification_proxy: URL of the proxy to use for IP address verification @@ -589,7 +589,7 @@ class YoutubeDL: if current_version < MIN_RECOMMENDED: msg = ('Support for Python version %d.%d has been deprecated. ' 'See https://github.com/yt-dlp/yt-dlp/issues/3764 for more details.' - '\n You will no longer recieve updates on this version') + '\n You will no longer receive updates on this version') if current_version < MIN_SUPPORTED: msg = 'Python version %d.%d is no longer supported' self.deprecation_warning( @@ -1693,7 +1693,7 @@ class YoutubeDL: assert ie_result['_type'] in ('playlist', 'multi_video') title = ie_result.get('title') or ie_result.get('id') or '' - self.to_screen(f'[download] Downloading playlist: {title}') + self.to_screen(f'[download] Downloading {ie_result["_type"]}: {title}') all_entries = PlaylistEntries(self, ie_result) entries = orderedSet(all_entries.get_requested_items(), lazy=True) diff --git a/yt_dlp/aes.py b/yt_dlp/aes.py index f9920c5b88..b428c682bf 100644 --- a/yt_dlp/aes.py +++ b/yt_dlp/aes.py @@ -24,6 +24,10 @@ else: return intlist_to_bytes(aes_gcm_decrypt_and_verify(*map(bytes_to_intlist, (data, key, tag, nonce)))) +def aes_cbc_encrypt_bytes(data, key, iv, **kwargs): + return intlist_to_bytes(aes_cbc_encrypt(*map(bytes_to_intlist, (data, key, iv)), **kwargs)) + + def unpad_pkcs7(data): return data[:-compat_ord(data[-1])] @@ -164,7 +168,7 @@ def aes_cbc_decrypt(data, key, iv): return decrypted_data -def aes_cbc_encrypt(data, key, iv, padding_mode='pkcs7'): +def aes_cbc_encrypt(data, key, iv, *, padding_mode='pkcs7'): """ Encrypt with aes in CBC mode @@ -530,13 +534,21 @@ def ghash(subkey, data): __all__ = [ - 'aes_ctr_decrypt', 'aes_cbc_decrypt', 'aes_cbc_decrypt_bytes', + 'aes_ctr_decrypt', 'aes_decrypt_text', - 'aes_encrypt', + 'aes_decrypt', + 'aes_ecb_decrypt', 'aes_gcm_decrypt_and_verify', 'aes_gcm_decrypt_and_verify_bytes', + + 'aes_cbc_encrypt', + 'aes_cbc_encrypt_bytes', + 'aes_ctr_encrypt', + 'aes_ecb_encrypt', + 'aes_encrypt', + 'key_expansion', 'pad_block', 'unpad_pkcs7', diff --git a/yt_dlp/extractor/_extractors.py b/yt_dlp/extractor/_extractors.py index 3c233d937e..9a8059c935 100644 --- a/yt_dlp/extractor/_extractors.py +++ b/yt_dlp/extractor/_extractors.py @@ -1446,7 +1446,7 @@ from .rtbf import RTBFIE from .rte import RteIE, RteRadioIE from .rtlnl import ( RtlNlIE, - RTLLuTeleVODIE, + RTLLuTeleVODIE, RTLLuArticleIE, RTLLuLiveIE, RTLLuRadioIE, diff --git a/yt_dlp/extractor/common.py b/yt_dlp/extractor/common.py index 47c8298579..f0eddcf26e 100644 --- a/yt_dlp/extractor/common.py +++ b/yt_dlp/extractor/common.py @@ -931,9 +931,9 @@ class InfoExtractor: def __print_error(self, errnote, fatal, video_id, err): if fatal: - raise ExtractorError(f'{video_id}: {errnote} ', cause=err) + raise ExtractorError(f'{video_id}: {errnote}', cause=err) elif errnote: - self.report_warning(f'{video_id}: {errnote} {err}') + self.report_warning(f'{video_id}: {errnote}: {err}') def _parse_xml(self, xml_string, video_id, transform_source=None, fatal=True, errnote=None): if transform_source: diff --git a/yt_dlp/extractor/mgtv.py b/yt_dlp/extractor/mgtv.py index 6d1843a186..37594d12d9 100644 --- a/yt_dlp/extractor/mgtv.py +++ b/yt_dlp/extractor/mgtv.py @@ -67,7 +67,7 @@ class MGTVIE(InfoExtractor): def _real_extract(self, url): video_id = self._match_id(url) tk2 = base64.urlsafe_b64encode( - f'did={compat_str(uuid.uuid4()).encode()}|pno=1030|ver=0.3.0301|clit={int(time.time())}'.encode())[::-1] + f'did={str(uuid.uuid4())}|pno=1030|ver=0.3.0301|clit={int(time.time())}'.encode())[::-1] try: api_data = self._download_json( 'https://pcweb.api.mgtv.com/player/video', video_id, query={ diff --git a/yt_dlp/extractor/openload.py b/yt_dlp/extractor/openload.py index 79dad09e35..f844ee6fbf 100644 --- a/yt_dlp/extractor/openload.py +++ b/yt_dlp/extractor/openload.py @@ -104,9 +104,8 @@ class PhantomJSwrapper: self.exe = check_executable('phantomjs', ['-v']) if not self.exe: - raise ExtractorError('PhantomJS executable not found in PATH, ' - 'download it from http://phantomjs.org', - expected=True) + raise ExtractorError( + 'PhantomJS not found, Please download it from https://phantomjs.org/download.html', expected=True) self.extractor = extractor diff --git a/yt_dlp/extractor/rtvslo.py b/yt_dlp/extractor/rtvslo.py index e402a75ded..b63ccb96f8 100644 --- a/yt_dlp/extractor/rtvslo.py +++ b/yt_dlp/extractor/rtvslo.py @@ -1,7 +1,10 @@ from .common import InfoExtractor from ..utils import ( - ExtractorError, traverse_obj, parse_duration, unified_timestamp, - url_or_none + ExtractorError, + parse_duration, + traverse_obj, + unified_timestamp, + url_or_none, ) diff --git a/yt_dlp/extractor/wetv.py b/yt_dlp/extractor/wetv.py index d10783891e..ea2d0517ed 100644 --- a/yt_dlp/extractor/wetv.py +++ b/yt_dlp/extractor/wetv.py @@ -3,8 +3,8 @@ import re import time from .common import InfoExtractor -from ..aes import aes_cbc_encrypt -from ..utils import bytes_to_intlist, determine_ext, intlist_to_bytes, int_or_none, traverse_obj, urljoin +from ..aes import aes_cbc_encrypt_bytes +from ..utils import determine_ext, int_or_none, traverse_obj, urljoin class WeTvBaseIE(InfoExtractor): @@ -16,13 +16,11 @@ class WeTvBaseIE(InfoExtractor): payload = (f'{video_id}|{int(time.time())}|mg3c3b04ba|{app_version}|0000000000000000|' f'{platform}|{url[:48]}|{ua.lower()[:48]}||Mozilla|Netscape|Win32|00|') - ciphertext_int_bytes = aes_cbc_encrypt( - bytes_to_intlist(bytes(f'|{sum(map(ord, payload))}|{payload}', 'utf-8')), - bytes_to_intlist(b'Ok\xda\xa3\x9e/\x8c\xb0\x7f^r-\x9e\xde\xf3\x14'), - bytes_to_intlist(b'\x01PJ\xf3V\xe6\x19\xcf.B\xbb\xa6\x8c?p\xf9'), - 'whitespace') - - return intlist_to_bytes(ciphertext_int_bytes).hex() + return aes_cbc_encrypt_bytes( + bytes(f'|{sum(map(ord, payload))}|{payload}', 'utf-8'), + b'Ok\xda\xa3\x9e/\x8c\xb0\x7f^r-\x9e\xde\xf3\x14', + b'\x01PJ\xf3V\xe6\x19\xcf.B\xbb\xa6\x8c?p\xf9', + padding_mode='whitespace').hex() def _get_video_api_response(self, video_url, video_id, series_id, subtitle_format, video_format, video_quality): app_version = '3.5.57'