aboutsummaryrefslogtreecommitdiffstats
path: root/yt_dlp
diff options
context:
space:
mode:
authorpukkandan <pukkandan.ytdlp@gmail.com>2022-05-09 10:02:17 +0530
committerpukkandan <pukkandan.ytdlp@gmail.com>2022-05-11 22:10:15 +0530
commit8dcce6a89ca0dcb875fa1ba5f8a83cc244ceabcb (patch)
treedee8c422585730446ca4b502325ea9eed6c2f722 /yt_dlp
parent494f52308b313110b481711d3d1cb8f3630a5bbe (diff)
downloadhypervideo-pre-8dcce6a89ca0dcb875fa1ba5f8a83cc244ceabcb.tar.lz
hypervideo-pre-8dcce6a89ca0dcb875fa1ba5f8a83cc244ceabcb.tar.xz
hypervideo-pre-8dcce6a89ca0dcb875fa1ba5f8a83cc244ceabcb.zip
[extractor] Document netrc machines
Closes #3169
Diffstat (limited to 'yt_dlp')
-rw-r--r--yt_dlp/__init__.py32
-rw-r--r--yt_dlp/extractor/__init__.py12
-rw-r--r--yt_dlp/extractor/common.py51
-rw-r--r--yt_dlp/extractor/fujitv.py2
-rw-r--r--yt_dlp/extractor/vimeo.py2
5 files changed, 56 insertions, 43 deletions
diff --git a/yt_dlp/__init__.py b/yt_dlp/__init__.py
index 2e9da4c98..924604631 100644
--- a/yt_dlp/__init__.py
+++ b/yt_dlp/__init__.py
@@ -5,14 +5,13 @@ __license__ = 'Public Domain'
import itertools
import os
-import random
import re
import sys
from .compat import compat_getpass, compat_os_name, compat_shlex_quote
from .cookies import SUPPORTED_BROWSERS, SUPPORTED_KEYRINGS
from .downloader import FileDownloader
-from .extractor import gen_extractors, list_extractors
+from .extractor import list_extractors
from .extractor.adobepass import MSO_INFO
from .extractor.common import InfoExtractor
from .options import parseOpts
@@ -75,29 +74,23 @@ def get_urls(urls, batchfile, verbose):
def print_extractor_information(opts, urls):
+ out = ''
if opts.list_extractors:
for ie in list_extractors(opts.age_limit):
- write_string(ie.IE_NAME + (' (CURRENTLY BROKEN)' if not ie.working() else '') + '\n', out=sys.stdout)
- matchedUrls = [url for url in urls if ie.suitable(url)]
- for mu in matchedUrls:
- write_string(' ' + mu + '\n', out=sys.stdout)
+ out += ie.IE_NAME + (' (CURRENTLY BROKEN)' if not ie.working() else '') + '\n'
+ out += ''.join(f' {url}\n' for url in filter(ie.suitable, urls))
elif opts.list_extractor_descriptions:
- for ie in list_extractors(opts.age_limit):
- if not ie.working():
- continue
- if ie.IE_DESC is False:
- continue
- desc = ie.IE_DESC or ie.IE_NAME
- if getattr(ie, 'SEARCH_KEY', None) is not None:
- _SEARCHES = ('cute kittens', 'slithering pythons', 'falling cat', 'angry poodle', 'purple fish', 'running tortoise', 'sleeping bunny', 'burping cow')
- _COUNTS = ('', '5', '10', 'all')
- desc += f'; "{ie.SEARCH_KEY}:" prefix (Example: "{ie.SEARCH_KEY}{random.choice(_COUNTS)}:{random.choice(_SEARCHES)}")'
- write_string(desc + '\n', out=sys.stdout)
+ _SEARCHES = ('cute kittens', 'slithering pythons', 'falling cat', 'angry poodle', 'purple fish', 'running tortoise', 'sleeping bunny', 'burping cow')
+ out = '\n'.join(
+ ie.description(markdown=False, search_examples=_SEARCHES)
+ for ie in list_extractors(opts.age_limit) if ie.working() and ie.IE_DESC is not False) + '\n'
elif opts.ap_list_mso:
- table = [[mso_id, mso_info['name']] for mso_id, mso_info in MSO_INFO.items()]
- write_string('Supported TV Providers:\n' + render_table(['mso', 'mso name'], table) + '\n', out=sys.stdout)
+ out = 'Supported TV Providers:\n%s\n' % render_table(
+ ['mso', 'mso name'],
+ [[mso_id, mso_info['name']] for mso_id, mso_info in MSO_INFO.items()])
else:
return False
+ write_string(out, out=sys.stdout)
return True
@@ -869,6 +862,7 @@ def main(argv=None):
sys.exit(f'\nERROR: {e}')
+from .extractor import gen_extractors
__all__ = [
'main',
'YoutubeDL',
diff --git a/yt_dlp/extractor/__init__.py b/yt_dlp/extractor/__init__.py
index 6288c5c6b..506ffe87c 100644
--- a/yt_dlp/extractor/__init__.py
+++ b/yt_dlp/extractor/__init__.py
@@ -38,14 +38,10 @@ def gen_extractors():
def list_extractors(age_limit):
- """
- Return a list of extractors that are suitable for the given age,
- sorted by extractor ID.
- """
-
- return sorted(
- filter(lambda ie: ie.is_suitable(age_limit), gen_extractors()),
- key=lambda ie: ie.IE_NAME.lower())
+ """Return a list of extractors that are suitable for the given age, sorted by extractor name"""
+ return sorted(filter(
+ lambda ie: ie.is_suitable(age_limit),
+ gen_extractors()), key=lambda ie: ie.IE_NAME.lower())
def get_info_extractor(ie_name):
diff --git a/yt_dlp/extractor/common.py b/yt_dlp/extractor/common.py
index e5a44e296..23d57ddaf 100644
--- a/yt_dlp/extractor/common.py
+++ b/yt_dlp/extractor/common.py
@@ -469,14 +469,18 @@ class InfoExtractor:
_WORKING = True
_NETRC_MACHINE = None
IE_DESC = None
+ SEARCH_KEY = None
- _LOGIN_HINTS = {
- 'any': 'Use --cookies, --cookies-from-browser, --username and --password, or --netrc to provide account credentials',
- 'cookies': (
- 'Use --cookies-from-browser or --cookies for the authentication. '
- 'See https://github.com/ytdl-org/youtube-dl#how-do-i-pass-cookies-to-youtube-dl for how to manually pass cookies'),
- 'password': 'Use --username and --password, or --netrc to provide account credentials',
- }
+ def _login_hint(self, method=NO_DEFAULT, netrc=None):
+ password_hint = f'--username and --password, or --netrc ({netrc or self._NETRC_MACHINE}) to provide account credentials'
+ return {
+ None: '',
+ 'any': f'Use --cookies, --cookies-from-browser, {password_hint}',
+ 'password': f'Use {password_hint}',
+ 'cookies': (
+ 'Use --cookies-from-browser or --cookies for the authentication. '
+ 'See https://github.com/ytdl-org/youtube-dl#how-do-i-pass-cookies-to-youtube-dl for how to manually pass cookies'),
+ }[method if method is not NO_DEFAULT else 'any' if self.supports_login() else 'cookies']
def __init__(self, downloader=None):
"""Constructor. Receives an optional downloader (a YoutubeDL instance).
@@ -539,7 +543,7 @@ class InfoExtractor:
if username:
self._perform_login(username, password)
elif self.get_param('username') and False not in (self.IE_DESC, self._NETRC_MACHINE):
- self.report_warning(f'Login with password is not supported for this website. {self._LOGIN_HINTS["cookies"]}')
+ self.report_warning(f'Login with password is not supported for this website. {self._login_hint("cookies")}')
self._real_initialize()
self._ready = True
@@ -708,7 +712,7 @@ class InfoExtractor:
@property
def IE_NAME(self):
- return compat_str(type(self).__name__[:-2])
+ return type(self).__name__[:-2]
@staticmethod
def __can_accept_status_code(err, expected_status):
@@ -1131,11 +1135,7 @@ class InfoExtractor:
self.get_param('ignore_no_formats_error') or self.get_param('wait_for_video')):
self.report_warning(msg)
return
- if method is NO_DEFAULT:
- method = 'any' if self.supports_login() else 'cookies'
- if method is not None:
- assert method in self._LOGIN_HINTS, 'Invalid login method'
- msg = f'{msg}. {self._LOGIN_HINTS[method]}'
+ msg += format_field(self._login_hint(method), template='. %s')
raise ExtractorError(msg, expected=True)
def raise_geo_restricted(
@@ -3653,6 +3653,29 @@ class InfoExtractor:
any_restricted = any_restricted or is_restricted
return not any_restricted
+ def description(self, *, markdown=True, search_examples=None):
+ """Description of the extractor"""
+ desc = ''
+ if self._NETRC_MACHINE:
+ if markdown:
+ desc += f' [<abbr title="netrc machine"><em>{self._NETRC_MACHINE}</em></abbr>]'
+ else:
+ desc += f' [{self._NETRC_MACHINE}]'
+ if self.IE_DESC is False:
+ desc += ' [HIDDEN]'
+ elif self.IE_DESC:
+ desc += f' {self.IE_DESC}'
+ if self.SEARCH_KEY:
+ desc += f'; "{self.SEARCH_KEY}:" prefix'
+ if search_examples:
+ _COUNTS = ('', '5', '10', 'all')
+ desc += f' (Example: "{self.SEARCH_KEY}{random.choice(_COUNTS)}:{random.choice(search_examples)}")'
+ if not self.working():
+ desc += ' (**Currently broken**)' if markdown else ' (Currently broken)'
+
+ name = f' - **{self.IE_NAME}**' if markdown else self.IE_NAME
+ return f'{name}:{desc}' if desc else name
+
def extract_subtitles(self, *args, **kwargs):
if (self.get_param('writesubtitles', False)
or self.get_param('listsubtitles')):
diff --git a/yt_dlp/extractor/fujitv.py b/yt_dlp/extractor/fujitv.py
index f66149d2c..d7f49accd 100644
--- a/yt_dlp/extractor/fujitv.py
+++ b/yt_dlp/extractor/fujitv.py
@@ -45,7 +45,7 @@ class FujiTVFODPlus7IE(InfoExtractor):
if token:
json_info = self._download_json('https://fod-sp.fujitv.co.jp/apps/api/episode/detail/?ep_id=%s&is_premium=false' % video_id, video_id, headers={'x-authorization': f'Bearer {token.value}'}, fatal=False)
else:
- self.report_warning(f'The token cookie is needed to extract video metadata. {self._LOGIN_HINTS["cookies"]}')
+ self.report_warning(f'The token cookie is needed to extract video metadata. {self._login_hint("cookies")}')
formats, subtitles = [], {}
src_json = self._download_json(f'{self._BASE_URL}abrjson_v2/tv_android/{video_id}', video_id)
for src in src_json['video_selector']:
diff --git a/yt_dlp/extractor/vimeo.py b/yt_dlp/extractor/vimeo.py
index b2c929373..de4fc61cc 100644
--- a/yt_dlp/extractor/vimeo.py
+++ b/yt_dlp/extractor/vimeo.py
@@ -1333,7 +1333,7 @@ class VimeoReviewIE(VimeoBaseInfoExtractor):
class VimeoWatchLaterIE(VimeoChannelIE):
IE_NAME = 'vimeo:watchlater'
- IE_DESC = 'Vimeo watch later list, "vimeowatchlater" keyword (requires authentication)'
+ IE_DESC = 'Vimeo watch later list, ":vimeowatchlater" keyword (requires authentication)'
_VALID_URL = r'https://vimeo\.com/(?:home/)?watchlater|:vimeowatchlater'
_TITLE = 'Watch Later'
_LOGIN_REQUIRED = True