Skip to content

Fix: replace search.list with uploads playlist to reliably find recent videos#6

Merged
MetzinAround merged 4 commits into
mainfrom
MetzinAround/fix-youtube-uploads-playlist
May 14, 2026
Merged

Fix: replace search.list with uploads playlist to reliably find recent videos#6
MetzinAround merged 4 commits into
mainfrom
MetzinAround/fix-youtube-uploads-playlist

Conversation

@MetzinAround
Copy link
Copy Markdown
Contributor

Problem

The /youtubedigest command (and the weekly background task) returned no videos even when videos existed on the channel. The root cause was using search.list to discover channel uploads:

  • search.list has unpredictable indexing delays that can silently omit videos uploaded in the past few days
  • It also sometimes misses YouTube Shorts
  • It costs 100 quota units per call (out of a 10,000/day budget)

Fix

Replace search.list with the channel's uploads playlist (playlistItems.list):

  • The uploads playlist reflects new uploads immediately — no indexing lag
  • Includes all video types (Shorts, regular videos, premieres)
  • Costs 1 quota unit per call (100× more efficient)

The uploads playlist ID is derived from the channel ID by replacing the UC prefix with UU — a stable YouTube channel ID convention (UC7c3Kb6jYCRj4JOHHZTxKsAUU7c3Kb6jYCRj4JOHHZTxKsA).

The playlist is ordered newest-first, so we can break early once we hit a video older than the 7-day window.

Changes

  • utils/youtube_api.py: Replace search().list() with playlistItems().list() in search_recent. Add UC-prefix validation for channel IDs. Filter by videoPublishedAt client-side.
  • tests/test_youtube_api.py: Full rewrite of fake service infrastructure for the new API shape. New tests for UC channel ID validation and date-window early-stop behaviour. 20 tests total, all pass.

Testing

Ran 20 tests in 0.050s
OK

MetzinAround and others added 3 commits May 14, 2026 15:07
…t videos

search.list is unreliable for channel upload discovery — it can silently
omit recently-uploaded videos and YouTube Shorts due to indexing delays,
and it costs 100 quota units per call.

The correct approach is to use the channel's uploads playlist via
playlistItems.list (1 quota unit), which reflects new uploads immediately
and includes all video types (Shorts, regular uploads, premieres).

The uploads playlist ID is derived from the channel ID by replacing the
'UC' prefix with 'UU' — a stable YouTube channel ID convention.

Changes:
- utils/youtube_api.py: Replace search().list() call in search_recent
  with playlistItems().list() using the derived uploads playlist ID.
  Filter results client-side by published_after (playlist is newest-
  first so we can break early). Also validates that channel_id starts
  with 'UC'.
- tests/test_youtube_api.py: Rewrite fake service infrastructure for
  playlistItems API shape. Add tests for UC channel ID validation and
  the early-stop date filtering behaviour.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…hack

The UC->UU channel ID prefix swap is not universally reliable — GitHub's
channel (UC7c3Kb6jYCRj4JOHHZTxKsA) does not expose a UU-prefixed uploads
playlist, causing a 404 from the playlistItems API.

The correct approach is to call channels.list with part=contentDetails
and read contentDetails.relatedPlaylists.uploads. The result is cached
on the YouTubeClient instance to avoid a redundant API call on each run.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates YouTube video discovery to use the channel uploads playlist instead of search.list, aiming to make recent video digests more reliable and quota-efficient.

Changes:

  • Adds uploads playlist resolution via channels.list and uses playlistItems.list for recent videos.
  • Updates YouTube API tests and cog flow test fixtures for the new API shape.
  • Updates config/setup examples for the YouTube channel ID.
Show a summary per file
File Description
utils/youtube_api.py Replaces YouTube search API usage with uploads playlist retrieval and client-side publish-date filtering.
tests/test_youtube_api.py Updates fake YouTube service helpers and tests for playlist-based discovery.
tests/test_cog_flows.py Updates the YouTube channel ID used by the cog flow test fixture.
SETUP.md Updates setup documentation channel ID examples.
config/config.yaml Updates the configured GitHub YouTube channel ID.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comments suppressed due to low confidence (2)

SETUP.md:154

  • This example channel ID also uses the new ...KsQ value, which conflicts with the ...KsA channel ID referenced in the PR description. The note is meant to help users identify the correct YouTube ID format, so carrying the inconsistent value here can reinforce the wrong configuration.
> **Note:** YouTube channel IDs look like `UC7c3Kb6jYCRj4JOHHZTxKsQ`.  

utils/youtube_api.py:127

  • The PR description says search_recent adds UC-prefix validation, but this path still sends any channel_id directly to channels.list. If a user configures an uploads playlist ID (UU...) or a handle by mistake, the code spends an API call and reports only "channel not found" instead of the intended validation error.
        uploads_playlist_id = self._get_uploads_playlist_id(channel_id)
  • Files reviewed: 5/5 changed files
  • Comments generated: 4

Comment thread config/config.yaml
Comment thread SETUP.md
Comment thread utils/youtube_api.py
Comment thread utils/youtube_api.py
@MetzinAround MetzinAround merged commit 96b955b into main May 14, 2026
1 check passed
@MetzinAround MetzinAround deleted the MetzinAround/fix-youtube-uploads-playlist branch May 14, 2026 23:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants