diff --git a/devscripts/make_supportedsites.py b/devscripts/make_supportedsites.py
index 0403c1ae6..5531fec4d 100644
--- a/devscripts/make_supportedsites.py
+++ b/devscripts/make_supportedsites.py
@@ -5,38 +5,19 @@
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
-import yt_dlp
+from yt_dlp.extractor import list_extractors
def main():
parser = optparse.OptionParser(usage='%prog OUTFILE.md')
- options, args = parser.parse_args()
+ _, args = parser.parse_args()
if len(args) != 1:
parser.error('Expected an output filename')
- outfile, = args
+ out = '\n'.join(ie.description() for ie in list_extractors(None) if ie.IE_DESC is not False)
- def gen_ies_md(ies):
- for ie in ies:
- ie_md = f'**{ie.IE_NAME}**'
- if ie.IE_DESC is False:
- continue
- if ie.IE_DESC is not None:
- ie_md += f': {ie.IE_DESC}'
- search_key = getattr(ie, 'SEARCH_KEY', None)
- if search_key is not None:
- ie_md += f'; "{ie.SEARCH_KEY}:" prefix'
- if not ie.working():
- ie_md += ' (Currently broken)'
- yield ie_md
-
- ies = sorted(yt_dlp.gen_extractors(), key=lambda i: i.IE_NAME.lower())
- out = '# Supported sites\n' + ''.join(
- ' - ' + md + '\n'
- for md in gen_ies_md(ies))
-
- with open(outfile, 'w', encoding='utf-8') as outf:
- outf.write(out)
+ with open(args[0], 'w', encoding='utf-8') as outf:
+ outf.write(f'# Supported sites\n{out}\n')
if __name__ == '__main__':
diff --git a/supportedsites.md b/supportedsites.md
index 746a93de6..31bd27768 100644
--- a/supportedsites.md
+++ b/supportedsites.md
@@ -24,12 +24,12 @@ # Supported sites
- **abcnews:video**
- **abcotvs**: ABC Owned Television Stations
- **abcotvs:clips**
- - **AbemaTV**
+ - **AbemaTV**: [abematv]
- **AbemaTVTitle**
- **AcademicEarth:Course**
- **acast**
- **acast:channel**
- - **ADN**: Anime Digital Network
+ - **ADN**: [animedigitalnetwork] Anime Digital Network
- **AdobeConnect**
- **adobetv**
- **adobetv:channel**
@@ -40,8 +40,8 @@ # Supported sites
- **aenetworks**: A+E Networks: A&E, Lifetime, History.com, FYI Network and History Vault
- **aenetworks:collection**
- **aenetworks:show**
- - **afreecatv**: afreecatv.com
- - **afreecatv:live**: afreecatv.com
+ - **afreecatv**: [afreecatv] afreecatv.com
+ - **afreecatv:live**: [afreecatv] afreecatv.com
- **afreecatv:user**
- **AirMozilla**
- **AliExpressLive**
@@ -50,8 +50,8 @@ # Supported sites
- **AlphaPorno**
- **Alsace20TV**
- **Alsace20TVEmbed**
- - **Alura**
- - **AluraCourse**
+ - **Alura**: [alura]
+ - **AluraCourse**: [aluracourse]
- **Amara**
- **AmazonStore**
- **AMCNetworks**
@@ -60,9 +60,9 @@ # Supported sites
- **AmHistoryChannel**
- **anderetijden**: npo.nl, ntr.nl, omroepwnl.nl, zapp.nl and npo3.nl
- **AnimalPlanet**
- - **AnimeLab**
- - **AnimeLabShows**
- - **AnimeOnDemand**
+ - **AnimeLab**: [animelab]
+ - **AnimeLabShows**: [animelab]
+ - **AnimeOnDemand**: [animeondemand]
- **ant1newsgr:article**: ant1news.gr articles
- **ant1newsgr:embed**: ant1news.gr embedded videos
- **ant1newsgr:watch**: ant1news.gr videos
@@ -88,7 +88,7 @@ # Supported sites
- **ArteTVPlaylist**
- **AsianCrush**
- **AsianCrushPlaylist**
- - **AtresPlayer**
+ - **AtresPlayer**: [atresplayer]
- **ATTTechChannel**
- **ATVAt**
- **AudiMedia**
@@ -114,13 +114,13 @@ # Supported sites
- **Bandcamp:weekly**
- **bangumi.bilibili.com**: BiliBili番剧
- **BannedVideo**
- - **bbc**: BBC
- - **bbc.co.uk**: BBC iPlayer
+ - **bbc**: [bbc] BBC
+ - **bbc.co.uk**: [bbc] BBC iPlayer
- **bbc.co.uk:article**: BBC articles
- **bbc.co.uk:iplayer:episodes**
- **bbc.co.uk:iplayer:group**
- **bbc.co.uk:playlist**
- - **BBVTV**
+ - **BBVTV**: [bbvtv]
- **Beatport**
- **Beeg**
- **BehindKink**
@@ -142,8 +142,9 @@ # Supported sites
- **BilibiliChannel**
- **BiliBiliPlayer**
- **BiliBiliSearch**: Bilibili video search; "bilisearch:" prefix
- - **BiliIntl**
- - **BiliIntlSeries**
+ - **BiliIntl**: [biliintl]
+ - **BiliIntlSeries**: [biliintl]
+ - **BiliLive**
- **BioBioChileTV**
- **Biography**
- **BIQLE**
@@ -252,10 +253,10 @@ # Supported sites
- **CrooksAndLiars**
- **CrowdBunker**
- **CrowdBunkerChannel**
- - **crunchyroll**
- - **crunchyroll:beta**
- - **crunchyroll:playlist**
- - **crunchyroll:playlist:beta**
+ - **crunchyroll**: [crunchyroll]
+ - **crunchyroll:beta**: [crunchyroll]
+ - **crunchyroll:playlist**: [crunchyroll]
+ - **crunchyroll:playlist:beta**: [crunchyroll]
- **CSpan**: C-SPAN
- **CSpanCongress**
- **CtsNews**: 華視新聞
@@ -263,18 +264,18 @@ # Supported sites
- **CTVNews**
- **cu.ntv.co.jp**: Nippon Television Network
- **CultureUnplugged**
- - **curiositystream**
- - **curiositystream:collections**
- - **curiositystream:series**
+ - **curiositystream**: [curiositystream]
+ - **curiositystream:collections**: [curiositystream]
+ - **curiositystream:series**: [curiositystream]
- **CWTV**
- - **Cybrary**
- - **CybraryCourse**
+ - **Cybrary**: [cybrary]
+ - **CybraryCourse**: [cybrary]
- **Daftsex**
- **DagelijkseKost**: dagelijksekost.een.be
- **DailyMail**
- - **dailymotion**
- - **dailymotion:playlist**
- - **dailymotion:user**
+ - **dailymotion**: [dailymotion]
+ - **dailymotion:playlist**: [dailymotion]
+ - **dailymotion:user**: [dailymotion]
- **damtomo:record**
- **damtomo:video**
- **daum.net**
@@ -291,7 +292,7 @@ # Supported sites
- **DestinationAmerica**
- **DHM**: Filmarchiv - Deutsches Historisches Museum
- **Digg**
- - **DigitalConcertHall**: DigitalConcertHall extractor
+ - **DigitalConcertHall**: [digitalconcerthall] DigitalConcertHall extractor
- **DigitallySpeaking**
- **Digiteka**
- **Discovery**
@@ -315,7 +316,7 @@ # Supported sites
- **DRBonanza**
- **Drooble**
- **Dropbox**
- - **Dropout**
+ - **Dropout**: [dropout]
- **DropoutSeason**
- **DrTuber**
- **drtv**
@@ -334,7 +335,7 @@ # Supported sites
- **egghead:lesson**: egghead.io lesson
- **ehftv**
- **eHow**
- - **EinsUndEinsTV**
+ - **EinsUndEinsTV**: [1und1tv]
- **Einthusan**
- **eitb.tv**
- **EllenTube**
@@ -348,7 +349,7 @@ # Supported sites
- **Epicon**
- **EpiconSeries**
- **Eporner**
- - **EroProfile**
+ - **EroProfile**: [eroprofile]
- **EroProfile:album**
- **ertflix**: ERTFLIX videos
- **ertflix:codename**: ERTFLIX videos by codename
@@ -361,17 +362,17 @@ # Supported sites
- **Europa**
- **EuropeanTour**
- **EUScreen**
- - **EWETV**
+ - **EWETV**: [ewetv]
- **ExpoTV**
- **Expressen**
- **ExtremeTube**
- **EyedoTV**
- - **facebook**
+ - **facebook**: [facebook]
- **FacebookPluginsVideo**
- - **fancode:live**
- - **fancode:vod**
+ - **fancode:live**: [fancode]
+ - **fancode:vod**: [fancode]
- **faz.net**
- - **fc2**
+ - **fc2**: [fc2]
- **fc2:embed**
- **fc2:live**
- **Fczenit**
@@ -401,19 +402,19 @@ # Supported sites
- **FranceTVSite**
- **Freesound**
- **freespeech.org**
- - **FrontendMasters**
- - **FrontendMastersCourse**
- - **FrontendMastersLesson**
+ - **FrontendMasters**: [frontendmasters]
+ - **FrontendMastersCourse**: [frontendmasters]
+ - **FrontendMastersLesson**: [frontendmasters]
- **FujiTVFODPlus7**
- - **Funimation**
- - **funimation:page**
- - **funimation:show**
+ - **Funimation**: [funimation]
+ - **funimation:page**: [funimation]
+ - **funimation:show**: [funimation]
- **Funk**
- **Fusion**
- **Fux**
- **Gab**
- **GabTV**
- - **Gaia**
+ - **Gaia**: [gaia]
- **GameInformer**
- **GameJolt**
- **GameJoltCommunity**
@@ -425,9 +426,9 @@ # Supported sites
- **GameStar**
- **Gaskrank**
- **Gazeta**
- - **GDCVault**
+ - **GDCVault**: [gdcvault]
- **GediDigital**
- - **gem.cbc.ca**
+ - **gem.cbc.ca**: [cbcgem]
- **gem.cbc.ca:live**
- **gem.cbc.ca:playlist**
- **generic**: Generic downloader that works on some sites
@@ -436,9 +437,9 @@ # Supported sites
- **Gfycat**
- **GiantBomb**
- **Giga**
- - **GlattvisionTV**
+ - **GlattvisionTV**: [glattvisiontv]
- **Glide**: Glide mobile video messages (glide.me)
- - **Globo**
+ - **Globo**: [globo]
- **GloboArticle**
- **glomex**: Glomex videos
- **glomex:embed**: Glomex embedded videos
@@ -466,7 +467,7 @@ # Supported sites
- **hgtv.com:show**
- **HGTVDe**
- **HGTVUsa**
- - **HiDive**
+ - **HiDive**: [hidive]
- **HistoricFilms**
- **history:player**
- **history:topic**: History.com Topic
@@ -481,8 +482,8 @@ # Supported sites
- **Howcast**
- **HowStuffWorks**
- **hrfernsehen**
- - **HRTi**
- - **HRTiPlaylist**
+ - **HRTi**: [hrti]
+ - **HRTiPlaylist**: [hrti]
- **HSEProduct**
- **HSEShow**
- **Huajiao**: 花椒直播
@@ -506,19 +507,19 @@ # Supported sites
- **Inc**
- **IndavideoEmbed**
- **InfoQ**
- - **Instagram**
- - **instagram:story**
- - **instagram:tag**: Instagram hashtag search URLs
- - **instagram:user**: Instagram user profile
+ - **Instagram**: [instagram]
+ - **instagram:story**: [instagram]
+ - **instagram:tag**: [instagram] Instagram hashtag search URLs
+ - **instagram:user**: [instagram] Instagram user profile
- **InstagramIOS**: IOS instagram:// URL
- **Internazionale**
- **InternetVideoArchive**
- **InvestigationDiscovery**
- - **IPrima**
+ - **IPrima**: [iprima]
- **IPrimaCNN**
- **iq.com**: International version of iQiyi
- **iq.com:album**
- - **iqiyi**: 爱奇艺
+ - **iqiyi**: [iqiyi] 爱奇艺
- **ITProTV**
- **ITProTVCourse**
- **ITTF**
@@ -576,9 +577,9 @@ # Supported sites
- **LcpPlay**
- **Le**: 乐视网
- **Lecture2Go**
- - **Lecturio**
- - **LecturioCourse**
- - **LecturioDeCourse**
+ - **Lecturio**: [lecturio]
+ - **LecturioCourse**: [lecturio]
+ - **LecturioDeCourse**: [lecturio]
- **LEGO**
- **Lemonde**
- **Lenta**
@@ -592,10 +593,10 @@ # Supported sites
- **limelight:channel_list**
- **LineLive**
- **LineLiveChannel**
- - **LinkedIn**
- - **linkedin:learning**
- - **linkedin:learning:course**
- - **LinuxAcademy**
+ - **LinkedIn**: [linkedin]
+ - **linkedin:learning**: [linkedin]
+ - **linkedin:learning:course**: [linkedin]
+ - **LinuxAcademy**: [linuxacademy]
- **LiTV**
- **LiveJournal**
- **livestream**
@@ -606,8 +607,8 @@ # Supported sites
- **LocalNews8**
- **LoveHomePorn**
- **lrt.lt**
- - **lynda**: lynda.com videos
- - **lynda:course**: lynda.com online courses
+ - **lynda**: [lynda] lynda.com videos
+ - **lynda:course**: [lynda] lynda.com online courses
- **m6**
- **MagentaMusik360**
- **mailru**: Видео@Mail.Ru
@@ -674,7 +675,7 @@ # Supported sites
- **MLBVideo**
- **MLSSoccer**
- **Mnet**
- - **MNetTV**
+ - **MNetTV**: [mnettv]
- **MoeVideo**: LetitBit video services: moevideo.net, playreplay.net and videochart.net
- **Mofosex**
- **MofosexEmbed**
@@ -746,8 +747,8 @@ # Supported sites
- **ndr:embed**
- **ndr:embed:base**
- **NDTV**
- - **Nebula**
- - **nebula:collection**
+ - **Nebula**: [watchnebula]
+ - **nebula:collection**: [watchnebula]
- **NerdCubedFeed**
- **netease:album**: 网易云音乐 - 专辑
- **netease:djradio**: 网易云音乐 - 电台
@@ -756,7 +757,7 @@ # Supported sites
- **netease:program**: 网易云音乐 - 电台节目
- **netease:singer**: 网易云音乐 - 歌手
- **netease:song**: 网易云音乐
- - **NetPlus**
+ - **NetPlus**: [netplus]
- **Netzkino**
- **Newgrounds**
- **Newgrounds:playlist**
@@ -770,8 +771,8 @@ # Supported sites
- **NexxEmbed**
- **NFB**
- **NFHSNetwork**
- - **nfl.com** (Currently broken)
- - **nfl.com:article** (Currently broken)
+ - **nfl.com**: (**Currently broken**)
+ - **nfl.com:article**: (**Currently broken**)
- **NhkForSchoolBangumi**
- **NhkForSchoolProgramList**
- **NhkForSchoolSubject**: Portal page for each school subjects, like Japanese (kokugo, 国語) or math (sansuu/suugaku or 算数・数学)
@@ -783,7 +784,7 @@ # Supported sites
- **nickelodeon:br**
- **nickelodeonru**
- **nicknight**
- - **niconico**: ニコニコ動画
+ - **niconico**: [niconico] ニコニコ動画
- **niconico:history**: NicoNico user history. Requires cookies.
- **niconico:playlist**
- **niconico:series**
@@ -796,7 +797,7 @@ # Supported sites
- **Nitter**
- **njoy**: N-JOY
- **njoy:embed**
- - **NJPWWorld**: 新日本プロレスワールド
+ - **NJPWWorld**: [njpwworld] 新日本プロレスワールド
- **NobelPrize**
- **NonkTube**
- **NoodleMagazine**
@@ -869,9 +870,9 @@ # Supported sites
- **orf:tvthek**: ORF TVthek
- **orf:vorarlberg**: Radio Vorarlberg
- **orf:wien**: Radio Wien
- - **OsnatelTV**
+ - **OsnatelTV**: [osnateltv]
- **OutsideTV**
- - **PacktPub**
+ - **PacktPub**: [packtpub]
- **PacktPubCourse**
- **PalcoMP3:artist**
- **PalcoMP3:song**
@@ -893,7 +894,7 @@ # Supported sites
- **peer.tv**
- **PeerTube**
- **PeerTube:Playlist**
- - **peloton**
+ - **peloton**: [peloton]
- **peloton:live**: Peloton Live
- **People**
- **PerformGroup**
@@ -902,7 +903,7 @@ # Supported sites
- **PhilharmonieDeParis**: Philharmonie de Paris
- **phoenix.de**
- **Photobucket**
- - **Piapro**
+ - **Piapro**: [piapro]
- **Picarto**
- **PicartoVod**
- **Piksel**
@@ -913,26 +914,26 @@ # Supported sites
- **pixiv:sketch:user**
- **Pladform**
- **PlanetMarathi**
- - **Platzi**
- - **PlatziCourse**
+ - **Platzi**: [platzi]
+ - **PlatziCourse**: [platzi]
- **play.fm**
- **player.sky.it**
- - **PlayPlusTV**
+ - **PlayPlusTV**: [playplustv]
- **PlayStuff**
- **PlaysTV**
- **Playtvak**: Playtvak.cz, iDNES.cz and Lidovky.cz
- **Playvid**
- **PlayVids**
- **Playwire**
- - **pluralsight**
+ - **pluralsight**: [pluralsight]
- **pluralsight:course**
- **PlutoTV**
- **podomatic**
- **Pokemon**
- **PokemonSoundLibrary**
- **PokemonWatch**
- - **PokerGo**
- - **PokerGoCollection**
+ - **PokerGo**: [pokergo]
+ - **PokerGoCollection**: [pokergo]
- **PolsatGo**
- **PolskieRadio**
- **polskieradio:kierowcow**
@@ -947,11 +948,11 @@ # Supported sites
- **Pornez**
- **PornFlip**
- **PornHd**
- - **PornHub**: PornHub and Thumbzilla
- - **PornHubPagedVideoList**
- - **PornHubPlaylist**
- - **PornHubUser**
- - **PornHubUserVideosUpload**
+ - **PornHub**: [pornhub] PornHub and Thumbzilla
+ - **PornHubPagedVideoList**: [pornhub]
+ - **PornHubPlaylist**: [pornhub]
+ - **PornHubUser**: [pornhub]
+ - **PornHubUserVideosUpload**: [pornhub]
- **Pornotube**
- **PornoVoisines**
- **PornoXO**
@@ -973,7 +974,7 @@ # Supported sites
- **qqmusic:playlist**: QQ音乐 - 歌单
- **qqmusic:singer**: QQ音乐 - 歌手
- **qqmusic:toplist**: QQ音乐 - 排行榜
- - **QuantumTV**
+ - **QuantumTV**: [quantumtv]
- **Qub**
- **R7**
- **R7Article**
@@ -1029,8 +1030,8 @@ # Supported sites
- **Rokfin**
- **rokfin:channel**
- **rokfin:stack**
- - **RoosterTeeth**
- - **RoosterTeethSeries**
+ - **RoosterTeeth**: [roosterteeth]
+ - **RoosterTeethSeries**: [roosterteeth]
- **RottenTomatoes**
- **Rozhlas**
- **RTBF**
@@ -1069,12 +1070,12 @@ # Supported sites
- **Ruutu**
- **Ruv**
- **ruv.is:spila**
- - **safari**: safaribooksonline.com online video
- - **safari:api**
- - **safari:course**: safaribooksonline.com online courses
+ - **safari**: [safari] safaribooksonline.com online video
+ - **safari:api**: [safari]
+ - **safari:course**: [safari] safaribooksonline.com online courses
- **Saitosan**
- - **SAKTV**
- - **SaltTV**
+ - **SAKTV**: [saktv]
+ - **SaltTV**: [salttv]
- **SampleFocus**
- **Sapo**: SAPO Vídeos
- **savefrom.net**
@@ -1086,8 +1087,8 @@ # Supported sites
- **ScreencastOMatic**
- **ScrippsNetworks**
- **scrippsnetworks:watch**
- - **SCTE**
- - **SCTECourse**
+ - **SCTE**: [scte]
+ - **SCTECourse**: [scte]
- **Seeker**
- **SenateGov**
- **SenateISVP**
@@ -1096,7 +1097,7 @@ # Supported sites
- **Sexu**
- **SeznamZpravy**
- **SeznamZpravyArticle**
- - **Shahid**
+ - **Shahid**: [shahid]
- **ShahidShow**
- **Shared**: shared.sx
- **ShemarooMe**
@@ -1121,15 +1122,15 @@ # Supported sites
- **Slutload**
- **Snotr**
- **Sohu**
- - **SonyLIV**
+ - **SonyLIV**: [sonyliv]
- **SonyLIVSeries**
- - **soundcloud**
- - **soundcloud:playlist**
- - **soundcloud:related**
- - **soundcloud:search**: Soundcloud search; "scsearch:" prefix
- - **soundcloud:set**
- - **soundcloud:trackstation**
- - **soundcloud:user**
+ - **soundcloud**: [soundcloud]
+ - **soundcloud:playlist**: [soundcloud]
+ - **soundcloud:related**: [soundcloud]
+ - **soundcloud:search**: [soundcloud] Soundcloud search; "scsearch:" prefix
+ - **soundcloud:set**: [soundcloud]
+ - **soundcloud:trackstation**: [soundcloud]
+ - **soundcloud:user**: [soundcloud]
- **SoundcloudEmbed**
- **soundgasm**
- **soundgasm:profile**
@@ -1190,13 +1191,13 @@ # Supported sites
- **Tass**
- **TBS**
- **TDSLifeway**
- - **Teachable**
- - **TeachableCourse**
+ - **Teachable**: [teachable]
+ - **TeachableCourse**: [teachable]
- **teachertube**: teachertube.com videos
- **teachertube:user:collection**: teachertube.com user and collection videos
- **TeachingChannel**
- **Teamcoco**
- - **TeamTreeHouse**
+ - **TeamTreeHouse**: [teamtreehouse]
- **TechTalks**
- **techtv.mit.edu**
- **TedEmbed**
@@ -1218,8 +1219,8 @@ # Supported sites
- **TeleQuebecVideo**
- **TeleTask**
- **Telewebion**
- - **TennisTV**
- - **TenPlay**
+ - **TennisTV**: [tennistv]
+ - **TenPlay**: [10play]
- **TF1**
- **TFO**
- **TheIntercept**
@@ -1250,10 +1251,10 @@ # Supported sites
- **Tokentube**
- **Tokentube:channel**
- **ToonGoggles**
- - **tou.tv**
+ - **tou.tv**: [toutv]
- **Toypics**: Toypics video
- **ToypicsUser**: Toypics user profile
- - **TrailerAddict** (Currently broken)
+ - **TrailerAddict**: (**Currently broken**)
- **TravelChannel**
- **Trilulilu**
- **Trovo**
@@ -1264,9 +1265,9 @@ # Supported sites
- **TruNews**
- **TruTV**
- **Tube8**
- - **TubiTv**
+ - **TubiTv**: [tubitv]
- **TubiTvShow**
- - **Tumblr**
+ - **Tumblr**: [tumblr]
- **tunein:clip**
- **tunein:program**
- **tunein:station**
@@ -1314,23 +1315,23 @@ # Supported sites
- **TwitCasting**
- **TwitCastingLive**
- **TwitCastingUser**
- - **twitch:clips**
- - **twitch:stream**
- - **twitch:vod**
- - **TwitchCollection**
- - **TwitchVideos**
- - **TwitchVideosClips**
- - **TwitchVideosCollections**
+ - **twitch:clips**: [twitch]
+ - **twitch:stream**: [twitch]
+ - **twitch:vod**: [twitch]
+ - **TwitchCollection**: [twitch]
+ - **TwitchVideos**: [twitch]
+ - **TwitchVideosClips**: [twitch]
+ - **TwitchVideosCollections**: [twitch]
- **twitter**
- **twitter:amplify**
- **twitter:broadcast**
- **twitter:card**
- **twitter:shortener**
- - **udemy**
- - **udemy:course**
+ - **udemy**: [udemy]
+ - **udemy:course**: [udemy]
- **UDNEmbed**: 聯合影音
- - **UFCArabia**
- - **UFCTV**
+ - **UFCArabia**: [ufcarabia]
+ - **UFCTV**: [ufctv]
- **ukcolumn**
- **UKTVPlay**
- **umg:de**: Universal Music Deutschland
@@ -1358,7 +1359,7 @@ # Supported sites
- **VevoPlaylist**
- **VGTV**: VGTV, BTTV, FTV, Aftenposten and Aftonbladet
- **vh1.com**
- - **vhx:embed**
+ - **vhx:embed**: [vimeo]
- **Viafree**
- **vice**
- **vice:article**
@@ -1378,26 +1379,26 @@ # Supported sites
- **videomore:season**
- **videomore:video**
- **VideoPress**
- - **Vidio**
- - **VidioLive**
- - **VidioPremier**
+ - **Vidio**: [vidio]
+ - **VidioLive**: [vidio]
+ - **VidioPremier**: [vidio]
- **VidLii**
- - **vier**: vier.be and vijf.be
+ - **vier**: [vier] vier.be and vijf.be
- **vier:videos**
- **viewlift**
- **viewlift:embed**
- **Viidea**
- - **viki**
- - **viki:channel**
- - **vimeo**
- - **vimeo:album**
- - **vimeo:channel**
- - **vimeo:group**
- - **vimeo:likes**: Vimeo user likes
- - **vimeo:ondemand**
- - **vimeo:review**: Review pages on vimeo
- - **vimeo:user**
- - **vimeo:watchlater**: Vimeo watch later list, "vimeowatchlater" keyword (requires authentication)
+ - **viki**: [viki]
+ - **viki:channel**: [viki]
+ - **vimeo**: [vimeo]
+ - **vimeo:album**: [vimeo]
+ - **vimeo:channel**: [vimeo]
+ - **vimeo:group**: [vimeo]
+ - **vimeo:likes**: [vimeo] Vimeo user likes
+ - **vimeo:ondemand**: [vimeo]
+ - **vimeo:review**: [vimeo] Review pages on vimeo
+ - **vimeo:user**: [vimeo]
+ - **vimeo:watchlater**: [vimeo] Vimeo watch later list, ":vimeowatchlater" keyword (requires authentication)
- **Vimm:recording**
- **Vimm:stream**
- **Vimple**: Vimple - one-click video hosting
@@ -1405,15 +1406,15 @@ # Supported sites
- **vine:user**
- **Viqeo**
- **Viu**
- - **viu:ott**
+ - **viu:ott**: [viu]
- **viu:playlist**
- **Vivo**: vivo.sx
- - **vk**: VK
- - **vk:uservideos**: VK - User's Videos
- - **vk:wallpost**
- - **vlive**
- - **vlive:channel**
- - **vlive:post**
+ - **vk**: [vk] VK
+ - **vk:uservideos**: [vk] VK - User's Videos
+ - **vk:wallpost**: [vk]
+ - **vlive**: [vlive]
+ - **vlive:channel**: [vlive]
+ - **vlive:post**: [vlive]
- **vm.tiktok**
- **Vodlocker**
- **VODPl**
@@ -1428,12 +1429,12 @@ # Supported sites
- **vpro**: npo.nl, ntr.nl, omroepwnl.nl, zapp.nl and npo3.nl
- **Vrak**
- **VRT**: VRT NWS, Flanders News, Flandern Info and Sporza
- - **VrtNU**: VrtNU.be
- - **vrv**
+ - **VrtNU**: [vrtnu] VrtNU.be
+ - **vrv**: [vrv]
- **vrv:series**
- **VShare**
- **VTM**
- - **VTXTV**
+ - **VTXTV**: [vtxtv]
- **VuClip**
- **Vupload**
- **VVVVID**
@@ -1442,7 +1443,7 @@ # Supported sites
- **Vzaar**
- **Wakanim**
- **Walla**
- - **WalyTV**
+ - **WalyTV**: [walytv]
- **wasdtv:clip**
- **wasdtv:record**
- **wasdtv:stream**
@@ -1452,7 +1453,7 @@ # Supported sites
- **WatchBox**
- **WatchIndianPorn**: Watch Indian Porn
- **WDR**
- - **wdr:mobile** (Currently broken)
+ - **wdr:mobile**: (**Currently broken**)
- **WDRElefant**
- **WDRPage**
- **web.archive:youtube**: web.archive.org saved youtube videos, "ytarchive:" prefix
@@ -1537,13 +1538,13 @@ # Supported sites
- **YoutubeLivestreamEmbed**: YouTube livestream embeds
- **YoutubeYtBe**: youtu.be
- **Zapiks**
- - **Zattoo**
- - **ZattooLive**
- - **ZattooMovies**
- - **ZattooRecordings**
+ - **Zattoo**: [zattoo]
+ - **ZattooLive**: [zattoo]
+ - **ZattooMovies**: [zattoo]
+ - **ZattooRecordings**: [zattoo]
- **ZDF**
- **ZDFChannel**
- - **Zee5**
+ - **Zee5**: [zee5]
- **zee5:series**
- **ZenYandex**
- **ZenYandexChannel**
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 @@
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 @@ def initialize(self):
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 @@ def ie_key(cls):
@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 @@ def raise_login_required(
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 @@ def is_suitable(self, age_limit):
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' [{self._NETRC_MACHINE}]'
+ 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 @@ def _real_extract(self, url):
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 @@ def _real_extract(self, url):
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