1
0
mirror of https://github.com/yt-dlp/yt-dlp.git synced 2025-07-05 04:48:31 +00:00
This commit is contained in:
c-basalt 2024-08-02 19:35:28 -04:00
parent 532c6b2eb5
commit e13c4573d9
3 changed files with 39 additions and 25 deletions

View File

@ -4,7 +4,7 @@
import uuid import uuid
from .common import InfoExtractor from .common import InfoExtractor
from .openload import PhantomJSwrapper from .openload import DenoWrapper, PhantomJSwrapper
from ..utils import ( from ..utils import (
ExtractorError, ExtractorError,
UserNotLive, UserNotLive,
@ -43,9 +43,14 @@ def _calc_sign(self, sign_func, video_id, a):
b = uuid.uuid4().hex b = uuid.uuid4().hex
c = round(time.time()) c = round(time.time())
js_script = f'{self._get_cryptojs_md5(video_id)};{sign_func};console.log(ub98484234("{a}","{b}","{c}"))' js_script = f'{self._get_cryptojs_md5(video_id)};{sign_func};console.log(ub98484234("{a}","{b}","{c}"))'
phantom = PhantomJSwrapper(self) if DenoWrapper.is_available:
result = phantom.execute(js_script, video_id, jsi = DenoWrapper(self)
note='Executing JS signing script').strip() elif PhantomJSwrapper.is_available:
jsi = PhantomJSwrapper(self)
else:
raise ExtractorError('You need to install either Deno or PhantomJS. '
f'{DenoWrapper.INSTALL_HINT}. {PhantomJSwrapper.INSTALL_HINT}', expected=True)
result = jsi.execute(js_script, video_id, note='Executing JS signing script').strip()
return {i: v[0] for i, v in urllib.parse.parse_qs(result).items()} return {i: v[0] for i, v in urllib.parse.parse_qs(result).items()}
def _search_js_sign_func(self, webpage, fatal=True): def _search_js_sign_func(self, webpage, fatal=True):

View File

@ -10,7 +10,7 @@
from ..utils import ( from ..utils import (
ExtractorError, ExtractorError,
Popen, Popen,
check_executable, classproperty,
format_field, format_field,
get_exe_version, get_exe_version,
is_outdated_version, is_outdated_version,
@ -47,22 +47,32 @@ def cookie_jar_to_list(cookie_jar):
return [cookie_to_dict(cookie) for cookie in cookie_jar] return [cookie_to_dict(cookie) for cookie in cookie_jar]
class DenoWrapper: class ExternalJSI:
INSTALL_HINT = 'Please install deno following https://docs.deno.com/runtime/manual/getting_started/installation/ or download its binary from https://github.com/denoland/deno/releases' @classproperty(cache=True)
def version(cls):
return get_exe_version(cls.EXE_NAME, args=getattr(cls, 'V_ARGS', ['--version']), version_re=r'([0-9.]+)')
@staticmethod @classproperty
def _version(): def exe(cls):
return get_exe_version('deno', version_re=r'([0-9.]+)') return cls.EXE_NAME if cls.version else None
@classproperty
def is_available(cls):
return bool(cls.exe)
class DenoWrapper(ExternalJSI):
EXE_NAME = 'deno'
INSTALL_HINT = 'Please install deno following https://docs.deno.com/runtime/manual/getting_started/installation/ or download its binary from https://github.com/denoland/deno/releases'
def __init__(self, extractor: InfoExtractor, required_version=None, timeout=10000): def __init__(self, extractor: InfoExtractor, required_version=None, timeout=10000):
self.extractor = extractor self.extractor = extractor
self.timeout = timeout self.timeout = timeout
self.exe = check_executable('deno', ['-V'])
if not self.exe: if not self.exe:
raise ExtractorError(f'Deno not found, {self.INSTALL_HINT}', expected=True) raise ExtractorError(f'Deno not found, {self.INSTALL_HINT}', expected=True)
if required_version: if required_version:
if is_outdated_version(self._version(), required_version): if is_outdated_version(self.version, required_version):
self.extractor.report_warning( self.extractor.report_warning(
f'Deno is outdated, update it to version {required_version} or newer if you encounter any errors.') f'Deno is outdated, update it to version {required_version} or newer if you encounter any errors.')
@ -77,10 +87,11 @@ def _create_temp_js(self, jscode):
with contextlib.suppress(OSError): with contextlib.suppress(OSError):
os.remove(js_file.name) os.remove(js_file.name)
def deno_execute(self, jscode, video_id=None, *, note='Executing JS in Deno', allow_net=None, jit_less=True): def execute(self, jscode, video_id=None, *, note='Executing JS in Deno',
"""Execute JS directly in Deno environment and return stdout""" allow_net=None, jit_less=True, base_js=None):
"""Execute JS directly in Deno runtime and return stdout"""
base_js = 'delete window.Deno; global = window;' base_js = base_js if base_js is not None else 'delete window.Deno; global = window;'
with self._create_temp_js(base_js + jscode) as js_file: with self._create_temp_js(base_js + jscode) as js_file:
self.extractor.to_screen(f'{format_field(video_id, None, "%s: ")}{note}') self.extractor.to_screen(f'{format_field(video_id, None, "%s: ")}{note}')
@ -105,13 +116,13 @@ def deno_execute(self, jscode, video_id=None, *, note='Executing JS in Deno', al
return stdout.strip() return stdout.strip()
class PhantomJSwrapper: class PhantomJSwrapper(ExternalJSI):
"""PhantomJS wrapper class """PhantomJS wrapper class
This class is experimental. This class is experimental.
""" """
EXE_NAME = 'phantomjs'
INSTALL_HINT = 'Please download it from https://phantomjs.org/download.html' INSTALL_HINT = 'Please download PhantomJS from https://phantomjs.org/download.html'
_BASE_JS = R''' _BASE_JS = R'''
phantom.onError = function(msg, trace) {{ phantom.onError = function(msg, trace) {{
@ -162,22 +173,20 @@ class PhantomJSwrapper:
_TMP_FILE_NAMES = ['script', 'html', 'cookies'] _TMP_FILE_NAMES = ['script', 'html', 'cookies']
@staticmethod @classmethod
def _version(): def _version(cls):
return get_exe_version('phantomjs', version_re=r'([0-9.]+)') return cls.version
def __init__(self, extractor, required_version=None, timeout=10000): def __init__(self, extractor, required_version=None, timeout=10000):
self._TMP_FILES = {} self._TMP_FILES = {}
self.exe = check_executable('phantomjs', ['-v'])
if not self.exe: if not self.exe:
raise ExtractorError(f'PhantomJS not found, {self.INSTALL_HINT}', expected=True) raise ExtractorError(f'PhantomJS not found, {self.INSTALL_HINT}', expected=True)
self.extractor = extractor self.extractor = extractor
if required_version: if required_version:
version = self._version() if is_outdated_version(self.version, required_version):
if is_outdated_version(version, required_version):
self.extractor._downloader.report_warning( self.extractor._downloader.report_warning(
'Your copy of PhantomJS is outdated, update it to version ' 'Your copy of PhantomJS is outdated, update it to version '
f'{required_version} or newer if you encounter any errors.') f'{required_version} or newer if you encounter any errors.')

View File

@ -121,7 +121,7 @@ def _calc_butter_token(self):
butter_js += '__new_init().then(() => console.log((new ButterFactory()).generate_butter()));' butter_js += '__new_init().then(() => console.log((new ButterFactory()).generate_butter()));'
jsi = DenoWrapper(self) jsi = DenoWrapper(self)
return jsi.deno_execute(butter_js) return jsi.execute(butter_js)
def get_butter_token(self): def get_butter_token(self):
cache = self.cache.load('rplay', 'butter-token') or {} cache = self.cache.load('rplay', 'butter-token') or {}