mirror of
https://github.com/lrnselfreliance/wrolpi.git
synced 2026-10-26 02:48:38 -04:00
Deprecate "Most Views" download order
YouTube's new listing layout means yt-dlp no longer returns `view_count` in flat channel/playlist entries, so sorting by views raised KeyError and the download failed and retried forever. Sorting by views now requires per-video extraction (hundreds of requests per channel), so the feature is deprecated rather than degraded: - downloader: the 'views' branch raises UnrecoverableDownloadError so the download fails cleanly (no retry loop) with a message to switch to Newest/Oldest. May be revisited via the YouTube Data API. - schema: download_order validation drops 'views' (newest/oldest/null only). - UI: removed "Most Views" from the download-order dropdown. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e513e36496
commit
fcb64fed13
5 changed files with 45 additions and 6 deletions
|
|
@ -101,7 +101,7 @@ export const validUrlRegex = /^(http|https):\/\/[^ "]+$/;
|
|||
export const downloadOrderOptions = [
|
||||
{key: 'newest', text: 'Newest', value: 'newest'},
|
||||
{key: 'oldest', text: 'Oldest', value: 'oldest'},
|
||||
{key: 'views', text: 'Most Views', value: 'views'},
|
||||
// 'views'/'Most Views' was removed: YouTube no longer provides view counts in channel/playlist listings.
|
||||
];
|
||||
|
||||
export const downloadResolutionOptions = [
|
||||
|
|
|
|||
|
|
@ -720,9 +720,12 @@ class ChannelDownloader(Downloader, ABC):
|
|||
logger.debug(f'Downloading oldest videos from {download.url}')
|
||||
downloads = downloads.reverse()
|
||||
elif sort_key == 'views':
|
||||
# Download videos with most views.
|
||||
logger.debug(f'Downloading most viewed videos from {download.url}')
|
||||
downloads = sorted(downloads, key=lambda i: i['view_count'], reverse=True)
|
||||
# YouTube no longer exposes `view_count` in flat channel/playlist listings, so we can no longer
|
||||
# sort by views without fetching every video individually. This may become possible again if we
|
||||
# integrate the YouTube Data API.
|
||||
raise UnrecoverableDownloadError(
|
||||
'Downloading by "Most Views" is no longer supported because YouTube no longer provides view '
|
||||
'counts in channel/playlist listings. Please change this download to "Newest" or "Oldest".')
|
||||
|
||||
# Limit the videos that will be downloads (this allows the user to download the "top 100" videos of a Channel)
|
||||
if video_count_limit := settings.get('video_count_limit'):
|
||||
|
|
|
|||
|
|
@ -706,6 +706,27 @@ async def test_download_playlist(test_session, test_directory, mock_video_extrac
|
|||
}
|
||||
|
||||
|
||||
def test_get_missing_videos_views_order_deprecated(test_session):
|
||||
"""The 'views' download order was deprecated. YouTube no longer provides `view_count` in flat
|
||||
channel/playlist listings, so a download configured for 'views' raises an unrecoverable error rather
|
||||
than crashing with a KeyError or silently downloading in the wrong order."""
|
||||
from modules.videos.downloader import channel_downloader
|
||||
# Flat entries no longer contain a `view_count` key (matches current yt-dlp behavior).
|
||||
download = Download(
|
||||
url='https://www.youtube.com/@example/videos',
|
||||
settings={'download_order': 'views'},
|
||||
info_json={'entries': [
|
||||
{'_type': 'url', 'id': 'a', 'title': 'a', 'url': 'https://youtube.com/watch?v=a'},
|
||||
{'_type': 'url', 'id': 'b', 'title': 'b', 'url': 'https://youtube.com/watch?v=b'},
|
||||
]},
|
||||
)
|
||||
test_session.add(download)
|
||||
test_session.commit()
|
||||
|
||||
with pytest.raises(UnrecoverableDownloadError):
|
||||
channel_downloader.get_missing_videos(test_session, download)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_channel_download_crud(test_session, async_client, assert_downloads, tag_factory):
|
||||
"""Test creating more complex Channel Download."""
|
||||
|
|
|
|||
|
|
@ -301,8 +301,9 @@ class DownloadSettings:
|
|||
if not self.download_metadata_only:
|
||||
del self.download_metadata_only
|
||||
|
||||
if self.download_order not in (None, 'newest', 'oldest', 'views'):
|
||||
raise ValidationError(f'Download order must be one of newest, oldest, views, or null.')
|
||||
# 'views' was deprecated: YouTube no longer provides view counts in channel/playlist listings.
|
||||
if self.download_order not in (None, 'newest', 'oldest'):
|
||||
raise ValidationError(f'Download order must be one of newest, oldest, or null.')
|
||||
|
||||
if self.video_format not in (None, 'mp4', 'mkv', 'ogg', 'webm'):
|
||||
raise ValidationError(f'Video format must be one of mp4, mkv, ogg, webm, or null.')
|
||||
|
|
|
|||
|
|
@ -914,6 +914,20 @@ def test_download_settings_coerces_numeric_strings():
|
|||
assert 'max_pages' not in req.settings
|
||||
|
||||
|
||||
@pytest.mark.parametrize('order', ['newest', 'oldest', None])
|
||||
def test_download_settings_accepts_valid_download_order(order):
|
||||
from wrolpi.schema import DownloadSettings
|
||||
DownloadSettings(download_order=order)
|
||||
|
||||
|
||||
def test_download_settings_rejects_deprecated_views_order():
|
||||
"""'views' download order was deprecated; YouTube no longer provides view counts in listings."""
|
||||
from wrolpi.schema import DownloadSettings
|
||||
from wrolpi.errors import ValidationError
|
||||
with pytest.raises(ValidationError):
|
||||
DownloadSettings(download_order='views')
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_downloads_config(test_session, test_download_manager, test_download_manager_config,
|
||||
test_downloader, assert_downloads, tag_factory, await_switches):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue