mirror of
				https://github.com/yt-dlp/yt-dlp.git
				synced 2025-10-31 06:35:12 +00:00 
			
		
		
		
	| @@ -15,7 +15,7 @@ | |||||||
| 
 | 
 | ||||||
| * Use certificates from `certifi` if installed by [coletdjnz](https://github.com/coletdjnz) | * Use certificates from `certifi` if installed by [coletdjnz](https://github.com/coletdjnz) | ||||||
| * Treat multiple `--match-filters` as OR | * Treat multiple `--match-filters` as OR | ||||||
| * File locking improvevemnts: | * File locking improvements: | ||||||
|     * Do not lock downloading file on Windows |     * Do not lock downloading file on Windows | ||||||
|     * Do not prevent download if locking is unsupported |     * Do not prevent download if locking is unsupported | ||||||
|     * Do not truncate files before locking by [jakeogh](https://github.com/jakeogh), [pukkandan](https://github.com/pukkandan) |     * Do not truncate files before locking by [jakeogh](https://github.com/jakeogh), [pukkandan](https://github.com/pukkandan) | ||||||
|   | |||||||
| @@ -1748,7 +1748,7 @@ with YoutubeDL(ydl_opts) as ydl: | |||||||
|     ydl.download(['https://www.youtube.com/watch?v=BaW_jenozKc']) |     ydl.download(['https://www.youtube.com/watch?v=BaW_jenozKc']) | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| Most likely, you'll want to use various options. For a list of options available, have a look at [`yt_dlp/YoutubeDL.py`](yt_dlp/YoutubeDL.py#L197). | Most likely, you'll want to use various options. For a list of options available, have a look at [`yt_dlp/YoutubeDL.py`](yt_dlp/YoutubeDL.py#L181). | ||||||
| 
 | 
 | ||||||
| Here's a more complete example demonstrating various functionality: | Here's a more complete example demonstrating various functionality: | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -1,9 +1,9 @@ | |||||||
| #!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||||
| import os | import os | ||||||
| import sys | import sys | ||||||
| from os.path import dirname as dirn |  | ||||||
| 
 | 
 | ||||||
| sys.path.insert(0, dirn(dirn(os.path.abspath(__file__)))) | sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | ||||||
|  | 
 | ||||||
| import yt_dlp | import yt_dlp | ||||||
| 
 | 
 | ||||||
| BASH_COMPLETION_FILE = "completions/bash/yt-dlp" | BASH_COMPLETION_FILE = "completions/bash/yt-dlp" | ||||||
|   | |||||||
| @@ -2,9 +2,9 @@ | |||||||
| import optparse | import optparse | ||||||
| import os | import os | ||||||
| import sys | import sys | ||||||
| from os.path import dirname as dirn |  | ||||||
| 
 | 
 | ||||||
| sys.path.insert(0, dirn(dirn(os.path.abspath(__file__)))) | sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | ||||||
|  | 
 | ||||||
| import yt_dlp | import yt_dlp | ||||||
| from yt_dlp.utils import shell_quote | from yt_dlp.utils import shell_quote | ||||||
| 
 | 
 | ||||||
|   | |||||||
| @@ -2,9 +2,8 @@ | |||||||
| import os | import os | ||||||
| import sys | import sys | ||||||
| from inspect import getsource | from inspect import getsource | ||||||
| from os.path import dirname as dirn |  | ||||||
| 
 | 
 | ||||||
| sys.path.insert(0, dirn(dirn(os.path.abspath(__file__)))) | sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | ||||||
| 
 | 
 | ||||||
| lazy_extractors_filename = sys.argv[1] if len(sys.argv) > 1 else 'yt_dlp/extractor/lazy_extractors.py' | lazy_extractors_filename = sys.argv[1] if len(sys.argv) > 1 else 'yt_dlp/extractor/lazy_extractors.py' | ||||||
| if os.path.exists(lazy_extractors_filename): | if os.path.exists(lazy_extractors_filename): | ||||||
|   | |||||||
| @@ -1,9 +1,9 @@ | |||||||
| #!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||||
| import os | import os | ||||||
| import sys | import sys | ||||||
| from os.path import dirname as dirn |  | ||||||
| 
 | 
 | ||||||
| sys.path.insert(0, dirn(dirn(os.path.abspath(__file__)))) | sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | ||||||
|  | 
 | ||||||
| import yt_dlp | import yt_dlp | ||||||
| 
 | 
 | ||||||
| ZSH_COMPLETION_FILE = "completions/zsh/_yt-dlp" | ZSH_COMPLETION_FILE = "completions/zsh/_yt-dlp" | ||||||
|   | |||||||
| @@ -3,14 +3,13 @@ import os | |||||||
| import subprocess | import subprocess | ||||||
| import sys | import sys | ||||||
| import unittest | import unittest | ||||||
| from os.path import join |  | ||||||
| 
 | 
 | ||||||
| sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | ||||||
| 
 | 
 | ||||||
| from test.helper import is_download_test, try_rm | from test.helper import is_download_test, try_rm | ||||||
| 
 | 
 | ||||||
| root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | ||||||
| download_file = join(root_dir, 'test.webm') | download_file = os.path.join(root_dir, 'test.webm') | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @is_download_test | @is_download_test | ||||||
| @@ -44,7 +43,7 @@ class TestOverwrites(unittest.TestCase): | |||||||
|         self.assertTrue(os.path.getsize(download_file) > 1) |         self.assertTrue(os.path.getsize(download_file) > 1) | ||||||
| 
 | 
 | ||||||
|     def tearDown(self): |     def tearDown(self): | ||||||
|         try_rm(join(root_dir, 'test.webm')) |         try_rm(os.path.join(root_dir, 'test.webm')) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|   | |||||||
| @@ -888,6 +888,7 @@ class YoutubeDL: | |||||||
|         SUPPRESS = 'light black' |         SUPPRESS = 'light black' | ||||||
| 
 | 
 | ||||||
|     def _format_text(self, handle, allow_colors, text, f, fallback=None, *, test_encoding=False): |     def _format_text(self, handle, allow_colors, text, f, fallback=None, *, test_encoding=False): | ||||||
|  |         text = str(text) | ||||||
|         if test_encoding: |         if test_encoding: | ||||||
|             original_text = text |             original_text = text | ||||||
|             # handle.encoding can be None. See https://github.com/yt-dlp/yt-dlp/issues/2711 |             # handle.encoding can be None. See https://github.com/yt-dlp/yt-dlp/issues/2711 | ||||||
| @@ -895,7 +896,7 @@ class YoutubeDL: | |||||||
|             text = text.encode(encoding, 'ignore').decode(encoding) |             text = text.encode(encoding, 'ignore').decode(encoding) | ||||||
|             if fallback is not None and text != original_text: |             if fallback is not None and text != original_text: | ||||||
|                 text = fallback |                 text = fallback | ||||||
|         if isinstance(f, self.Styles): |         if isinstance(f, Enum): | ||||||
|             f = f.value |             f = f.value | ||||||
|         return format_text(text, f) if allow_colors else text if fallback is None else fallback |         return format_text(text, f) if allow_colors else text if fallback is None else fallback | ||||||
| 
 | 
 | ||||||
| @@ -1708,6 +1709,7 @@ class YoutubeDL: | |||||||
|             entries.append(entry) |             entries.append(entry) | ||||||
|             try: |             try: | ||||||
|                 if entry is not None: |                 if entry is not None: | ||||||
|  |                     # TODO: Add auto-generated fields | ||||||
|                     self._match_entry(entry, incomplete=True, silent=True) |                     self._match_entry(entry, incomplete=True, silent=True) | ||||||
|             except (ExistingVideoReached, RejectedVideoReached): |             except (ExistingVideoReached, RejectedVideoReached): | ||||||
|                 broken = True |                 broken = True | ||||||
|   | |||||||
| @@ -196,7 +196,7 @@ compat_urllib_request = urllib.request | |||||||
| compat_urlparse = compat_urllib_parse = urllib.parse | compat_urlparse = compat_urllib_parse = urllib.parse | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # To be removed | # To be removed - Do not use | ||||||
| 
 | 
 | ||||||
| compat_basestring = str | compat_basestring = str | ||||||
| compat_collections_abc = collections.abc | compat_collections_abc = collections.abc | ||||||
|   | |||||||
| @@ -28,6 +28,7 @@ from ..utils import ( | |||||||
| 
 | 
 | ||||||
| # NOTE: network handler related code is temporary thing until network stack overhaul PRs are merged (#2861/#2862) | # NOTE: network handler related code is temporary thing until network stack overhaul PRs are merged (#2861/#2862) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| def add_opener(ydl, handler): | def add_opener(ydl, handler): | ||||||
|     ''' Add a handler for opening URLs, like _download_webpage ''' |     ''' Add a handler for opening URLs, like _download_webpage ''' | ||||||
|     # https://github.com/python/cpython/blob/main/Lib/urllib/request.py#L426 |     # https://github.com/python/cpython/blob/main/Lib/urllib/request.py#L426 | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| import datetime | import datetime | ||||||
|  | import json | ||||||
| import math | import math | ||||||
| import random | import random | ||||||
| import time | import time | ||||||
| @@ -82,21 +83,32 @@ class SonyLIVIE(InfoExtractor): | |||||||
|             raise ExtractorError(f'Invalid username/password; {self._LOGIN_HINT}') |             raise ExtractorError(f'Invalid username/password; {self._LOGIN_HINT}') | ||||||
| 
 | 
 | ||||||
|         self.report_login() |         self.report_login() | ||||||
|         data = '''{"mobileNumber":"%s","channelPartnerID":"MSMIND","country":"IN","timestamp":"%s", |  | ||||||
|         "otpSize":6,"loginType":"REGISTERORSIGNIN","isMobileMandatory":true} |  | ||||||
|          ''' % (username, datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%MZ")) |  | ||||||
|         otp_request_json = self._download_json( |         otp_request_json = self._download_json( | ||||||
|             'https://apiv2.sonyliv.com/AGL/1.6/A/ENG/WEB/IN/HR/CREATEOTP-V2', |             'https://apiv2.sonyliv.com/AGL/1.6/A/ENG/WEB/IN/HR/CREATEOTP-V2', | ||||||
|             None, note='Sending OTP', data=data.encode(), headers=self._HEADERS) |             None, note='Sending OTP', headers=self._HEADERS, data=json.dumps({ | ||||||
|  |                 'mobileNumber': username, | ||||||
|  |                 'channelPartnerID': 'MSMIND', | ||||||
|  |                 'country': 'IN', | ||||||
|  |                 'timestamp': datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%MZ'), | ||||||
|  |                 'otpSize': 6, | ||||||
|  |                 'loginType': 'REGISTERORSIGNIN', | ||||||
|  |                 'isMobileMandatory': True, | ||||||
|  |             }).encode()) | ||||||
|         if otp_request_json['resultCode'] == 'KO': |         if otp_request_json['resultCode'] == 'KO': | ||||||
|             raise ExtractorError(otp_request_json['message'], expected=True) |             raise ExtractorError(otp_request_json['message'], expected=True) | ||||||
|         otp_code = self._get_tfa_info('OTP') | 
 | ||||||
|         data = '''{"channelPartnerID":"MSMIND","mobileNumber":"%s","country":"IN","otp":"%s", |  | ||||||
|         "dmaId":"IN","ageConfirmation":true,"timestamp":"%s","isMobileMandatory":true} |  | ||||||
|          ''' % (username, otp_code, datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%MZ")) |  | ||||||
|         otp_verify_json = self._download_json( |         otp_verify_json = self._download_json( | ||||||
|             'https://apiv2.sonyliv.com/AGL/2.0/A/ENG/WEB/IN/HR/CONFIRMOTP-V2', |             'https://apiv2.sonyliv.com/AGL/2.0/A/ENG/WEB/IN/HR/CONFIRMOTP-V2', | ||||||
|             None, note='Verifying OTP', data=data.encode(), headers=self._HEADERS) |             None, note='Verifying OTP', headers=self._HEADERS, data=json.dumps({ | ||||||
|  |                 'channelPartnerID': 'MSMIND', | ||||||
|  |                 'mobileNumber': username, | ||||||
|  |                 'country': 'IN', | ||||||
|  |                 'otp': self._get_tfa_info('OTP'), | ||||||
|  |                 'dmaId': 'IN', | ||||||
|  |                 'ageConfirmation': True, | ||||||
|  |                 'timestamp': datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%MZ'), | ||||||
|  |                 'isMobileMandatory': True, | ||||||
|  |             }).encode()) | ||||||
|         if otp_verify_json['resultCode'] == 'KO': |         if otp_verify_json['resultCode'] == 'KO': | ||||||
|             raise ExtractorError(otp_request_json['message'], expected=True) |             raise ExtractorError(otp_request_json['message'], expected=True) | ||||||
|         self._HEADERS['authorization'] = otp_verify_json['resultObj']['accessToken'] |         self._HEADERS['authorization'] = otp_verify_json['resultObj']['accessToken'] | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
|  | import hashlib | ||||||
| import json | import json | ||||||
| import re | import re | ||||||
| from hashlib import sha256 |  | ||||||
| 
 | 
 | ||||||
| from .ffmpeg import FFmpegPostProcessor | from .ffmpeg import FFmpegPostProcessor | ||||||
| from ..compat import compat_urllib_parse_urlencode | from ..compat import compat_urllib_parse_urlencode | ||||||
| @@ -84,7 +84,7 @@ class SponsorBlockPP(FFmpegPostProcessor): | |||||||
|         return sponsor_chapters |         return sponsor_chapters | ||||||
| 
 | 
 | ||||||
|     def _get_sponsor_segments(self, video_id, service): |     def _get_sponsor_segments(self, video_id, service): | ||||||
|         hash = sha256(video_id.encode('ascii')).hexdigest() |         hash = hashlib.sha256(video_id.encode('ascii')).hexdigest() | ||||||
|         # SponsorBlock API recommends using first 4 hash characters. |         # SponsorBlock API recommends using first 4 hash characters. | ||||||
|         url = f'{self._API_URL}/api/skipSegments/{hash[:4]}?' + compat_urllib_parse_urlencode({ |         url = f'{self._API_URL}/api/skipSegments/{hash[:4]}?' + compat_urllib_parse_urlencode({ | ||||||
|             'service': service, |             'service': service, | ||||||
|   | |||||||
| @@ -4793,12 +4793,12 @@ def random_birthday(year_field, month_field, day_field): | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # Templates for internet shortcut files, which are plain text files. | # Templates for internet shortcut files, which are plain text files. | ||||||
| DOT_URL_LINK_TEMPLATE = ''' | DOT_URL_LINK_TEMPLATE = '''\ | ||||||
| [InternetShortcut] | [InternetShortcut] | ||||||
| URL=%(url)s | URL=%(url)s | ||||||
| '''.lstrip() | ''' | ||||||
| 
 | 
 | ||||||
| DOT_WEBLOC_LINK_TEMPLATE = ''' | DOT_WEBLOC_LINK_TEMPLATE = '''\ | ||||||
| <?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||||||
| <plist version="1.0"> | <plist version="1.0"> | ||||||
| @@ -4807,16 +4807,16 @@ DOT_WEBLOC_LINK_TEMPLATE = ''' | |||||||
| \t<string>%(url)s</string> | \t<string>%(url)s</string> | ||||||
| </dict> | </dict> | ||||||
| </plist> | </plist> | ||||||
| '''.lstrip() | ''' | ||||||
| 
 | 
 | ||||||
| DOT_DESKTOP_LINK_TEMPLATE = ''' | DOT_DESKTOP_LINK_TEMPLATE = '''\ | ||||||
| [Desktop Entry] | [Desktop Entry] | ||||||
| Encoding=UTF-8 | Encoding=UTF-8 | ||||||
| Name=%(filename)s | Name=%(filename)s | ||||||
| Type=Link | Type=Link | ||||||
| URL=%(url)s | URL=%(url)s | ||||||
| Icon=text-html | Icon=text-html | ||||||
| '''.lstrip() | ''' | ||||||
| 
 | 
 | ||||||
| LINK_TEMPLATES = { | LINK_TEMPLATES = { | ||||||
|     'url': DOT_URL_LINK_TEMPLATE, |     'url': DOT_URL_LINK_TEMPLATE, | ||||||
| @@ -4872,7 +4872,7 @@ def iri_to_uri(iri): | |||||||
| def to_high_limit_path(path): | def to_high_limit_path(path): | ||||||
|     if sys.platform in ['win32', 'cygwin']: |     if sys.platform in ['win32', 'cygwin']: | ||||||
|         # Work around MAX_PATH limitation on Windows. The maximum allowed length for the individual path segments may still be quite limited. |         # Work around MAX_PATH limitation on Windows. The maximum allowed length for the individual path segments may still be quite limited. | ||||||
|         return r'\\?\ '.rstrip() + os.path.abspath(path) |         return '\\\\?\\' + os.path.abspath(path) | ||||||
| 
 | 
 | ||||||
|     return path |     return path | ||||||
| 
 | 
 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 pukkandan
					pukkandan