Skip to content

Support members-only videos behind an opt-in flag - #5

Merged
reecemiao merged 3 commits into
mainfrom
claude/youtube-members-only-content-3gozik
Aug 20, 2026
Merged

reecemiao merged 3 commits into
mainfrom
claude/youtube-members-only-content-3gozik

Conversation

@reecemiao

Copy link
Copy Markdown
Owner

Members-only videos appear in a channel's uploads listing, so a run walked straight into

ERROR: [youtube] 58iGVbvDu9Q: Join this channel to get access to members-only content like this video, and other exclusive perks.

and recorded a failure it could never recover from — retried on every later run, exit code 1 each time.

What changed

  • Video.members_only is read off the listing's "Members only" badge (yt-dlp puts availability: "subscriber_only" on flat playlist entries, so it costs no extra request).
  • Such videos are passed over by default and counted in the run report instead of failing: skipped 1 members-only video(s); pass --members-only …. Nothing is written to the state file, so they get picked up normally once the membership starts.
  • include_members_only = true (--members-only / --no-members-only) takes them instead. That needs cookies from an account holding the membership, so a new cookies_from_browser setting (--cookies-from-browser BROWSER[+KEYRING][:PROFILE][::CONTAINER]) reads them straight out of a browser, alongside the existing cookies_file (now also reachable as --cookies FILE).
  • validate() refuses include_members_only with neither cookie setting — every one of those downloads would fail.
  • download_audio refuses a flagged video before making a request when there are no cookies, and maps yt-dlp's membership error to the same message for a video whose badge was missing from the listing (or that became members-only after it was listed).
  • ytscript list always shows members-only videos, marked [members only], whatever the setting says.

Notes

  • Verified by unit tests (79 pass) and against yt-dlp's own extractor, which sets availability: "subscriber_only" on flat entries. A live check against YouTube was not possible from this sandbox — its proxy refuses the connection — so the end-to-end signed-in download is untested here.
  • The cookie settings are a live login; the README says to keep the file out of version control and notes that Chromium locks its cookie store while running.

Generated by Claude Code

claude added 3 commits August 20, 2026 13:39
A channel's members-only videos sit in its uploads listing, so a run walked
into "Join this channel to get access to members-only content" and recorded a
failure it could never recover from.

They now carry a flag read off the listing's "Members only" badge (yt-dlp's
`availability: subscriber_only`) and are passed over by default, counted in the
run report rather than failed. `include_members_only = true` takes them
instead, which needs cookies from an account that holds the membership:
`cookies_from_browser` reads them out of a browser, alongside the existing
`cookies_file`. Turning the flag on without either is refused up front, since
every such download would fail.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQGeprPNAu7gzs5JJaDQGQ
The uv and ruff adoption documented the commands but not how a dependency
change lands: `uv lock --check` gates the push hook and the CI lint job, so a
`pyproject.toml` edit without a regenerated lockfile fails before review.

Also aligns the hook install command with the `uv run` form used everywhere
else, notes that the hooks take their tool versions from the lockfile, and
mentions the manual workflow_dispatch trigger the CI section left out.

Ignores cookies.txt, so the "these are a live login" warning next to the new
members-only settings is backed by a rule rather than a reader's care.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQGeprPNAu7gzs5JJaDQGQ
The install instructions told the reader to `pip install "ytscript[local]"`,
which cannot work: nothing publishes this package to PyPI. Every documented
route now goes through uv, which the project already depends on for its pinned
lockfile.

A checkout is the primary path — clone, `uv sync --extra local`, `uv run
ytscript`. For a copy on PATH without a checkout, `uv tool install` takes the
package straight from git; both forms were run against this repository to check
they resolve. The CUDA libraries follow the same split: `uv add` for a machine
that always runs on the GPU, `uv run --with` for a one-off, `--with` again for
a tool install.

The three "install it with pip" messages in the code move to the matching
`uv sync` commands, and the development section no longer repeats what the
install section now says about the conflicting extras.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQGeprPNAu7gzs5JJaDQGQ
@reecemiao
reecemiao marked this pull request as ready for review August 20, 2026 13:58
@reecemiao
reecemiao merged commit 305190e into main Aug 20, 2026
9 checks passed
@reecemiao
reecemiao deleted the claude/youtube-members-only-content-3gozik branch August 20, 2026 13:58
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.

2 participants