From b705de2186225a0861b4b8280b0e63ad16352e57 Mon Sep 17 00:00:00 2001 From: e1ven <401330+e1ven@users.noreply.github.com> Date: Wed, 5 Nov 2025 13:33:39 -0400 Subject: [PATCH] Support for multi-season dropout shows --- yt_dlp/extractor/_extractors.py | 1 + yt_dlp/extractor/dropout.py | 73 ++++++++++++++++++++++++--------- 2 files changed, 55 insertions(+), 19 deletions(-) diff --git a/yt_dlp/extractor/_extractors.py b/yt_dlp/extractor/_extractors.py index 8c247908de..070332d738 100644 --- a/yt_dlp/extractor/_extractors.py +++ b/yt_dlp/extractor/_extractors.py @@ -537,6 +537,7 @@ from .dropbox import DropboxIE from .dropout import ( DropoutIE, DropoutSeasonIE, + DropoutShowIE, ) from .drtalks import DrTalksIE from .drtuber import DrTuberIE diff --git a/yt_dlp/extractor/dropout.py b/yt_dlp/extractor/dropout.py index 2cfb0800fb..a2584e0ff9 100644 --- a/yt_dlp/extractor/dropout.py +++ b/yt_dlp/extractor/dropout.py @@ -1,4 +1,5 @@ import functools +import re from .common import InfoExtractor from .vimeo import VHXEmbedIE @@ -167,7 +168,7 @@ class DropoutIE(InfoExtractor): class DropoutSeasonIE(InfoExtractor): _PAGE_SIZE = 24 - _VALID_URL = r'https?://(?:watch\.)?dropout\.tv/(?P[^\/$&?#]+)(?:/?$|/season:(?P[0-9]+)/?$)' + _VALID_URL = r'https?://(?:watch\.)?dropout\.tv/(?P[^\/$&?#]+)(?:/season:(?P[0-9]+))/?$' _TESTS = [ { 'url': 'https://watch.dropout.tv/dimension-20-fantasy-high/season:1', @@ -178,24 +179,6 @@ class DropoutSeasonIE(InfoExtractor): 'title': 'Dimension 20 Fantasy High - Season 1', }, }, - { - 'url': 'https://watch.dropout.tv/dimension-20-fantasy-high', - 'note': 'Multi-season series with the season not in the url', - 'playlist_count': 24, - 'info_dict': { - 'id': 'dimension-20-fantasy-high-season-1', - 'title': 'Dimension 20 Fantasy High - Season 1', - }, - }, - { - 'url': 'https://watch.dropout.tv/dimension-20-shriek-week', - 'note': 'Single-season series', - 'playlist_count': 4, - 'info_dict': { - 'id': 'dimension-20-shriek-week-season-1', - 'title': 'Dimension 20 Shriek Week - Season 1', - }, - }, { 'url': 'https://watch.dropout.tv/breaking-news-no-laugh-newsroom/season:3', 'note': 'Multi-season series with season in the url that requires pagination', @@ -222,3 +205,55 @@ class DropoutSeasonIE(InfoExtractor): return self.playlist_result( OnDemandPagedList(functools.partial(self._fetch_page, url, season_id), self._PAGE_SIZE), f'{season_id}-season-{season_num}', f'{season_title} - Season {season_num}') + + +class DropoutShowIE(InfoExtractor): + _VALID_URL = r'https?://(?:watch\.)?dropout\.tv/(?P[^\/$&?#]+)/?$' + _TESTS = [ + { + 'url': 'https://watch.dropout.tv/game-changer', + 'note': 'Multi-season series', + 'info_dict': { + 'id': 'game-changer', + 'title': 'Game Changer', + }, + 'playlist_mincount': 2, + }, + { + 'url': 'https://watch.dropout.tv/the-schining', + 'note': 'Single-season series', + 'info_dict': { + 'id': 'the-schining', + 'title': 'The Schining', + }, + 'playlist_count': 1, + }, + ] + + def _real_extract(self, url): + show_id = self._match_id(url) + webpage = self._download_webpage(url, show_id) + show_title = self._html_search_regex( + r']*>(.+?)', webpage, 'show title', + default=None) or show_id.replace('-', ' ').title() + + season_urls = re.findall(r'