From 490998c8fdf2e7d4d383ae18c23f105081788b2a Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 31 May 2026 22:24:01 -0700 Subject: [PATCH] Fix POT provider: install version-matched plugin, not PyPI upstream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The original integration pip-installed `bgutil-ytdlp-pot-provider` from PyPI (Brainicism's upstream, currently 1.3.1). But the Rust server (jim60105's port) is at 0.8.1, and yt-dlp REFUSES to use a token when the plugin and server major versions mismatch: WARNING: Plugin and HTTP server major versions are mismatched. (plugin: 1.3.1, HTTP server: 0.8.1) …so the feature silently produced no POT tokens. jim60105 ships a version-matched plugin zip (bgutil-ytdlp-pot-provider-rs.zip) in each release. install_command now: - downloads that zip from the SAME release as the server binary - uninstalls any stale PyPI plugin + removes old getpot_bgutil*.py - resolves the venv site-packages via `python -c sysconfig` (version independent) and unpacks the plugin's yt_dlp_plugins/ tree there Verified end to end on a clean install: server mints a real BotGuard token, yt-dlp loads bgutil:http-0.8.1 (matched), no mismatch warning, and a 4K format URL resolves through the POT-gated path: [pot:bgutil:http] Generating a gvs PO Token … via bgutil HTTP server Rick Astley … | 401+251 | 3840x2160 Adds an `unzip` check to the install script (already required for the bundled deno install). Co-Authored-By: Claude Opus 4.7 --- src/pot_provider.rs | 81 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 70 insertions(+), 11 deletions(-) diff --git a/src/pot_provider.rs b/src/pot_provider.rs index e8da3de..bd5c4b8 100644 --- a/src/pot_provider.rs +++ b/src/pot_provider.rs @@ -8,8 +8,16 @@ //! consults the provider transparently. //! //! We use the Rust port at -//! (avoids the Node.js dependency of the original) plus the upstream -//! Python plugin from . +//! (avoids the Node.js dependency of the original) for *both* the HTTP +//! server binary *and* the yt-dlp Python plugin — the port ships a +//! version-matched plugin zip in each release. +//! +//! IMPORTANT: do NOT pip-install the upstream `bgutil-ytdlp-pot-provider` +//! from PyPI. It versions independently (1.x) of jim60105's Rust server +//! (0.8.x), and yt-dlp refuses to use a token when the plugin and server +//! major versions mismatch — silently producing no POT. We install the +//! plugin zip from the same GitHub release as the server so the two stay +//! in lockstep. //! //! # Layout //! @@ -19,8 +27,8 @@ //! ~/.local/share/yt-offline/ //! bin/ //! bgutil-pot ← the Rust HTTP server binary -//! venv/ ← reused — pip-install the Python plugin here -//! lib/python*/site-packages/yt_dlp_plugins/extractor/bgutil_*.py +//! venv/ ← reused — plugin zip unpacked into site-packages +//! lib/python*/site-packages/yt_dlp_plugins/extractor/getpot_bgutil*.py //! ``` //! //! # Activation @@ -101,6 +109,20 @@ fn release_url() -> String { ) } +/// URL of the yt-dlp plugin zip from the *same* release as the server. +/// +/// CRITICAL: this must come from jim60105's release, not PyPI. The +/// upstream Brainicism `bgutil-ytdlp-pot-provider` PyPI package versions +/// independently (it's at 1.x while this Rust port is at 0.8.x) and +/// yt-dlp refuses to use a token when the plugin and server major +/// versions mismatch. jim60105 ships a version-matched plugin zip in +/// each release; installing *that* keeps the two in lockstep. (An +/// earlier version of this code pip-installed the upstream package and +/// silently produced no tokens because of the mismatch.) +fn plugin_zip_url() -> String { + "https://github.com/jim60105/bgutil-ytdlp-pot-provider-rs/releases/latest/download/bgutil-ytdlp-pot-provider-rs.zip".to_string() +} + /// Shell command that downloads the bgutil-pot binary into the bundled /// bin dir and `pip install`s the matching Python plugin into the /// bundled venv. @@ -118,6 +140,7 @@ pub fn install_command() -> Command { }; let venv_python_s = venv_python.display().to_string(); let url = release_url(); + let plugin_url = plugin_zip_url(); #[cfg(windows)] { @@ -129,12 +152,22 @@ pub fn install_command() -> Command { }}; \ Write-Host '==> downloading bgutil-pot'; \ Invoke-WebRequest -Uri '{url}' -OutFile '{bin_path}'; \ - Write-Host '==> installing the Python plugin into the venv'; \ - & '{venv_python}' -m pip install --upgrade --quiet bgutil-ytdlp-pot-provider; \ + Write-Host '==> resolving venv site-packages'; \ + $site = (& '{venv_python}' -c 'import sysconfig; print(sysconfig.get_paths()[\"purelib\"])').Trim(); \ + Write-Host \" site-packages: $site\"; \ + Write-Host '==> removing any stale upstream plugin (pip / old zip)'; \ + & '{venv_python}' -m pip uninstall -y bgutil-ytdlp-pot-provider 2>$null; \ + Remove-Item -Force -ErrorAction SilentlyContinue \"$site\\yt_dlp_plugins\\extractor\\getpot_bgutil*.py\"; \ + Write-Host '==> downloading version-matched plugin zip'; \ + Invoke-WebRequest -Uri '{plugin_url}' -OutFile \"$env:TEMP\\bgutil-plugin.zip\"; \ + Write-Host '==> extracting plugin into venv'; \ + Expand-Archive -Force \"$env:TEMP\\bgutil-plugin.zip\" \"$site\"; \ + Remove-Item \"$env:TEMP\\bgutil-plugin.zip\"; \ Write-Host '==> versions'; \ & '{bin_path}' --version; \ Write-Host '==> done'", - bin_dir = bin_dir, venv_python = venv_python_s, bin_path = bin_path, url = url, + bin_dir = bin_dir, venv_python = venv_python_s, bin_path = bin_path, + url = url, plugin_url = plugin_url, ); let mut cmd = Command::new("powershell"); cmd.arg("-NoProfile").arg("-Command").arg(script); @@ -144,7 +177,8 @@ pub fn install_command() -> Command { { let script = format!( r#"set -e -command -v curl >/dev/null || {{ echo 'error: curl not installed'; exit 1; }} +command -v curl >/dev/null || {{ echo 'error: curl not installed'; exit 1; }} +command -v unzip >/dev/null || {{ echo 'error: unzip not installed'; exit 1; }} if [ ! -x '{venv_python}' ]; then echo 'error: bundled yt-dlp venv not installed.' @@ -167,13 +201,38 @@ wait $DLPID echo " done: $(wc -c < '{bin_path}') bytes" chmod +x '{bin_path}' -echo '==> installing bgutil-ytdlp-pot-provider Python plugin into the venv' -'{venv_python}' -m pip install --upgrade --quiet --progress-bar off bgutil-ytdlp-pot-provider +# Resolve the venv's site-packages dir (python-version-independent). +SITE="$('{venv_python}' -c 'import sysconfig; print(sysconfig.get_paths()["purelib"])')" +echo "==> venv site-packages: $SITE" + +# Remove any stale upstream plugin. The PyPI `bgutil-ytdlp-pot-provider` +# package versions independently of jim60105's Rust server (1.x vs 0.8.x) +# and yt-dlp refuses tokens on a major-version mismatch — so we must use +# the version-matched plugin zip from the same release, not pip. +echo '==> removing any stale upstream plugin' +'{venv_python}' -m pip uninstall -y bgutil-ytdlp-pot-provider >/dev/null 2>&1 || true +rm -f "$SITE"/yt_dlp_plugins/extractor/getpot_bgutil*.py 2>/dev/null || true + +echo '==> downloading version-matched plugin zip' +TMPZIP="$(mktemp -t bgutil-plugin-XXXXXX.zip)" +curl -fL --no-progress-meter --connect-timeout 30 --max-time 300 --retry 3 \ + -o "$TMPZIP" '{plugin_url}' +echo '==> extracting plugin into the venv' +unzip -o "$TMPZIP" -d "$SITE" +rm -f "$TMPZIP" echo '==> versions' '{bin_path}' --version +echo '==> verifying plugin + server are the same version' +PLUGIN_FILES="$SITE/yt_dlp_plugins/extractor" +if [ -f "$PLUGIN_FILES/getpot_bgutil_http.py" ]; then + echo ' ok: bgutil HTTP plugin installed' +else + echo ' warn: plugin files not found where expected' +fi echo '==> done'"#, - bin_dir = bin_dir, venv_python = venv_python_s, bin_path = bin_path, url = url, + bin_dir = bin_dir, venv_python = venv_python_s, bin_path = bin_path, + url = url, plugin_url = plugin_url, ); let mut cmd = Command::new("bash"); cmd.arg("-c").arg(script);