Compare commits

..

No commits in common. "600d7992b0c003a7182e0d59af10fac3fc6070f5" and "7dcf23c03adb3f09e51f071056725c1b812e35e8" have entirely different histories.

8 changed files with 43 additions and 29 deletions

View File

@ -243,10 +243,12 @@ jobs:
python3 -m pip install -U --user pip setuptools wheel delocate
# curl_cffi must be removed from reqs
gsed -i -E '/^curl_cffi.*/d' requirements.txt
python3 -m pip install -U --user --no-binary :all: Pyinstaller>=6.3 -r requirements.txt
# We need to ignore wheels otherwise we break universal2 builds
# PyInstaller v6 currently does not work with this
python3 -m pip install -U --user --no-binary :all: Pyinstaller==5.13.2 -r requirements.txt
mkdir curl_cffi_whls curl_cffi_universal2
python3 -m pip download --only-binary=:all: --platform macosx_11_0_arm64 curl_cffi>=0.5.9,<0.6.0 --pre -d curl_cffi_whls
python3 -m pip download --only-binary=:all: --platform macosx_11_0_x86_64 curl_cffi>=0.5.9,<0.6.0 --pre -d curl_cffi_whls
python3 -m pip download --only-binary=:all: --platform macosx_11_0_arm64 curl_cffi --pre -d curl_cffi_whls
python3 -m pip download --only-binary=:all: --platform macosx_11_0_x86_64 curl_cffi --pre -d curl_cffi_whls
python3 -m delocate.cmd.delocate_fuse curl_cffi_whls/curl_cffi* -w curl_cffi_universal2
python3 -m delocate.cmd.delocate_fuse curl_cffi_whls/cffi-* -w curl_cffi_universal2
cd curl_cffi_universal2

View File

@ -476,11 +476,10 @@ If you fork the project on GitHub, you can run your fork's [build workflow](.git
--socket-timeout SECONDS Time to wait before giving up, in seconds
--source-address IP Client-side IP address to bind to
--impersonate [CLIENT[:[VERSION][:[OS][:OS_VERSION]]]]
Client to impersonate for requests. E.g.
chrome, chrome:110, chrome::android. Pass in
Client to impersonate for requests. Pass in
an empty string (--impersonate "") to
impersonate any client.
--list-impersonate-targets List available clients to impersonate.
impersonate any client
--list-impersonate-targets List available clients to impersonate
-4, --force-ipv4 Make all connections via IPv4
-6, --force-ipv6 Make all connections via IPv6
--enable-file-urls Enable file:// URLs. This is disabled by

View File

@ -24,6 +24,7 @@ import traceback
import unicodedata
from .cache import Cache
from .compat import functools, urllib # isort: split
from .compat import compat_os_name, compat_shlex_quote, urllib_req_to_req
from .cookies import LenientSimpleCookie, load_cookies
@ -61,7 +62,13 @@ from .postprocessor import (
get_postprocessor,
)
from .postprocessor.ffmpeg import resolve_mapping as resolve_recode_mapping
from .update import REPOSITORY, _get_system_deprecation, _make_label, current_git_head, detect_variant
from .update import (
REPOSITORY,
_get_system_deprecation,
_make_label,
current_git_head,
detect_variant,
)
from .utils import (
DEFAULT_OUTTMPL,
IDENTITY,
@ -707,6 +714,7 @@ class YoutubeDL:
impersonate_target = self.params.get('impersonate')
if impersonate_target is not None:
# This assumes that all handlers that support impersonation subclass ImpersonateRequestHandler
if not self.impersonate_target_available(impersonate_target):
raise ValueError(
f'Impersonate target "{self.params.get("impersonate")}" is not available. '
@ -3901,10 +3909,9 @@ class YoutubeDL:
# These imports can be slow. So import them only as needed
from .extractor.extractors import _LAZY_LOADER
from .extractor.extractors import (
_PLUGIN_CLASSES as plugin_ies,
from .extractor.extractors import _PLUGIN_CLASSES as plugin_ies
from .extractor.extractors import \
_PLUGIN_OVERRIDES as plugin_ie_overrides
)
def get_encoding(stream):
ret = str(getattr(stream, 'encoding', 'missing (%s)' % type(stream).__name__))
@ -4049,7 +4056,6 @@ class YoutubeDL:
if isinstance(rh, ImpersonateRequestHandler)]), key=lambda x: x[0])
def impersonate_target_available(self, target):
# This assumes that all handlers that support impersonation subclass ImpersonateRequestHandler
return any(
rh.is_supported_target(target)
for rh in self._request_director.handlers.values()
@ -4089,10 +4095,9 @@ class YoutubeDL:
if (
'unsupported proxy type: "https"' in ue.msg.lower()
and 'requests' not in self._request_director.handlers
and 'curl_cffi' not in self._request_director.handlers
):
raise RequestError(
'To use an HTTPS proxy for this request, one of the following dependencies needs to be installed: requests, curl_cffi')
'To use an HTTPS proxy for this request, one of the following dependencies needs to be installed: requests')
elif (
re.match(r'unsupported url scheme: "wss?"', ue.msg.lower())

View File

@ -389,7 +389,7 @@ def validate_options(opts):
opts.cookiesfrombrowser = (browser_name, profile, keyring, container)
if opts.impersonate is not None:
opts.impersonate = ImpersonateTarget.from_str(opts.impersonate.lower())
opts.impersonate = ImpersonateTarget.from_str(opts.impersonate)
# MetadataParser
def metadataparser_actions(f):
@ -987,18 +987,19 @@ def _real_main(argv=None):
if opts.list_impersonate_targets:
available_targets = ydl.get_available_impersonate_targets()
rows = [
[target.client, target.version, target.os, target.os_vers, handler]
[target.client, target.version, target.os, target.os_vers, handler, str(target)]
for target, handler in available_targets
]
ydl.to_screen('[info] Available impersonate targets')
ydl.to_stdout(
render_table(['Client', 'Version', 'OS', 'OS Version', 'Source'], rows)
render_table(['Client', 'Version', 'OS', 'OS Version', 'Handler', 'Example'], rows)
)
if not available_targets:
ydl.to_stdout('You are missing dependencies for impersonation. See the README for more info.')
ydl.to_stdout(
'If the above table is missing targets, you may be missing dependencies for impersonation.')
'If the above table is missing targets, you may be missing dependencies for impersonation. '
'See the documentation for more information.')
return
if not actual_use:

View File

@ -5,20 +5,26 @@ import logging
import ssl
import sys
from ._helper import create_connection, select_proxy, make_socks_proxy_opts, create_socks_proxy_socket
from .common import Response, register_rh, Features
from ._helper import (
create_connection,
create_socks_proxy_socket,
make_socks_proxy_opts,
select_proxy,
)
from .common import Features, Response, register_rh
from .exceptions import (
CertificateVerifyError,
HTTPError,
ProxyError,
RequestError,
SSLError,
TransportError, ProxyError,
TransportError,
)
from .websocket import WebSocketRequestHandler, WebSocketResponse
from ..compat import functools
from ..dependencies import websockets
from ..utils import int_or_none
from ..socks import ProxyError as SocksProxyError
from ..utils import int_or_none
if not websockets:
raise ImportError('websockets is not installed')
@ -98,10 +104,10 @@ class WebsocketsRH(WebSocketRequestHandler):
extensions.pop('cookiejar', None)
def _send(self, request):
timeout = float(request.extensions.get('timeout') or self.timeout)
timeout = self._calculate_timeout(request)
headers = self._merge_headers(request.headers)
if 'cookie' not in headers:
cookiejar = request.extensions.get('cookiejar') or self.cookiejar
cookiejar = self._get_cookiejar(request)
cookie_header = cookiejar.get_cookie_header(request.url)
if cookie_header:
headers['cookie'] = cookie_header
@ -111,7 +117,7 @@ class WebsocketsRH(WebSocketRequestHandler):
'source_address': (self.source_address, 0) if self.source_address else None,
'timeout': timeout
}
proxy = select_proxy(request.url, request.proxies or self.proxies or {})
proxy = select_proxy(request.url, self._get_proxies(request))
try:
if proxy:
socks_proxy_options = make_socks_proxy_opts(proxy)

View File

@ -49,7 +49,8 @@ class ImpersonateTarget:
@classmethod
def from_str(cls, target: str):
return ImpersonateTarget(*[
None if (v or '').strip() == '' else v for v in target.split(':')
None if (v or '').strip() == '' else v
for v in (target.split(':') + [None, None, None, None])[:4]
])
def __hash__(self):

View File

@ -514,13 +514,12 @@ def create_parser():
network.add_option(
'--impersonate',
metavar='[CLIENT[:[VERSION][:[OS][:OS_VERSION]]]]', dest='impersonate', default=None,
help='Client to impersonate for requests. E.g. chrome, chrome:110, chrome::android.'
' Pass in an empty string (--impersonate "") to impersonate any client.',
help='Client to impersonate for requests. Pass in an empty string (--impersonate "") to impersonate any client',
)
network.add_option(
'--list-impersonate-targets',
dest='list_impersonate_targets', default=False, action='store_true',
help='List available clients to impersonate.',
help='List available clients to impersonate',
)
network.add_option(
'-4', '--force-ipv4',

View File

@ -4,6 +4,7 @@ import collections
import random
import urllib.parse
import urllib.request
from typing import Optional, Tuple
from ._utils import remove_start