feat(youtube): optional egress proxy for YouTube API calls
New youtube_api_proxy setting (env fallback + admin Config UI, env YOUTUBE_API_PROXY): when set, the YouTubeClient routes all its httpx traffic through that HTTP(S) proxy. Lets a dynamic-IP host send API calls through a fixed-IP host (e.g. the server over private tunnel) so an IP-restricted API key keeps working. Empty = direct.
This commit is contained in:
parent
6c4c33f956
commit
d047ed7e15
6 changed files with 13 additions and 1 deletions
|
|
@ -65,6 +65,10 @@ class Settings(BaseSettings):
|
|||
# Optional API key for public reads (channels/videos/playlistItems). When set it is
|
||||
# preferred for shared backfill/enrichment so it doesn't depend on a specific user.
|
||||
youtube_api_key: str = ""
|
||||
# Optional HTTP(S) proxy for outbound YouTube Data API calls. Set this to send the
|
||||
# scheduler's googleapis traffic through a fixed-IP host (e.g. the VPS over WireGuard) so an
|
||||
# IP-restricted API key keeps working even when this host's public IP is dynamic.
|
||||
youtube_api_proxy: str = ""
|
||||
# Daily quota budget (units). Default leaves headroom under the 10,000/day free limit.
|
||||
quota_daily_budget: int = 9000
|
||||
# Recent-first backfill: how far back to fetch on the first pass per channel.
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ SPECS: tuple[ConfigSpec, ...] = (
|
|||
ConfigSpec("autotag_title_sample", "int", "batch", "autotag_title_sample", min=1, max=1_000),
|
||||
# --- YouTube Data API key (secret; optional — public reads prefer it over OAuth) ---
|
||||
ConfigSpec("youtube_api_key", "str", "youtube", "youtube_api_key", secret=True),
|
||||
# Optional egress proxy for YouTube API calls (fixed-IP host for an IP-restricted key).
|
||||
ConfigSpec("youtube_api_proxy", "str", "youtube", "youtube_api_proxy"),
|
||||
# --- Google OAuth client (Sign in with Google; both encrypted, env fallback). Set from the
|
||||
# install wizard / Configuration page so no restart is needed when the creds change. ---
|
||||
ConfigSpec("google_client_id", "str", "google", "google_client_id", secret=True),
|
||||
|
|
|
|||
|
|
@ -44,7 +44,10 @@ class YouTubeClient:
|
|||
def __init__(self, db, user: User):
|
||||
self.db = db
|
||||
self.user = user
|
||||
self._http = httpx.Client(timeout=30.0)
|
||||
# Optionally route all YouTube traffic through a fixed-IP egress proxy (e.g. the VPS
|
||||
# over WireGuard) so an IP-restricted API key keeps working from a dynamic-IP host.
|
||||
proxy = sysconfig.get_str(db, "youtube_api_proxy") or None
|
||||
self._http = httpx.Client(timeout=30.0, proxy=proxy)
|
||||
|
||||
def __enter__(self) -> "YouTubeClient":
|
||||
return self
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
"enrich_batch_size": { "label": "Anreicherungs-Stapelgröße", "hint": "videos.list-IDs pro Aufruf (YouTube begrenzt auf 50)." },
|
||||
"autotag_title_sample": { "label": "Auto-Tag-Titelstichprobe", "hint": "Pro Kanal abgetastete aktuelle Videotitel zur Spracherkennung." },
|
||||
"youtube_api_key": { "label": "YouTube-API-Schlüssel", "hint": "Optional. Für öffentliche Lesezugriffe (Kanäle/Videos), damit gemeinsames Nachladen nicht vom OAuth eines Nutzers abhängt. Verschlüsselt gespeichert; nur schreibbar." },
|
||||
"youtube_api_proxy": { "label": "YouTube-API-Egress-Proxy", "hint": "Optional. HTTP(S)-Proxy-URL für ausgehende YouTube-API-Aufrufe — über einen Host mit fester IP leiten, damit ein IP-beschränkter Schlüssel von einem Server mit dynamischer IP funktioniert. Leer = direkt." },
|
||||
"google_client_id": { "label": "Google-Client-ID", "hint": "OAuth-2.0-Client-ID für die Google-Anmeldung. Verschlüsselt gespeichert; nur schreibbar. Beide Google-Felder leer lassen, um die Google-Anmeldung zu deaktivieren (E-Mail+Passwort funktioniert weiter)." },
|
||||
"google_client_secret": { "label": "Google-Client-Secret", "hint": "OAuth-2.0-Client-Secret. Verschlüsselt gespeichert; nur schreibbar." },
|
||||
"allow_registration": { "label": "Registrierung erlauben", "hint": "Wenn aktiviert, kann jeder eine E-Mail+Passwort-Registrierung einreichen. Für die Anmeldung sind weiterhin E-Mail-Bestätigung und Admin-Freigabe nötig." }
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
"enrich_batch_size": { "label": "Enrichment batch size", "hint": "videos.list ids per call (YouTube caps this at 50)." },
|
||||
"autotag_title_sample": { "label": "Auto-tag title sample", "hint": "Recent video titles sampled per channel for language detection." },
|
||||
"youtube_api_key": { "label": "YouTube API key", "hint": "Optional. Used for public reads (channels/videos) so shared backfill doesn't depend on a user's OAuth. Stored encrypted; write-only." },
|
||||
"youtube_api_proxy": { "label": "YouTube API egress proxy", "hint": "Optional. HTTP(S) proxy URL for outbound YouTube API calls — route them through a fixed-IP host so an IP-restricted key keeps working from a dynamic-IP server. Leave empty for direct." },
|
||||
"google_client_id": { "label": "Google client ID", "hint": "OAuth 2.0 client ID for Sign in with Google. Stored encrypted; write-only. Leave both Google fields empty to disable Google sign-in (email+password still works)." },
|
||||
"google_client_secret": { "label": "Google client secret", "hint": "OAuth 2.0 client secret. Stored encrypted; write-only." },
|
||||
"allow_registration": { "label": "Allow registration", "hint": "When on, anyone can submit an email+password registration. They still need to verify their email and be approved by an admin before they can sign in." }
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
"enrich_batch_size": { "label": "Gazdagítási kötegméret", "hint": "videos.list azonosítók hívásonként (a YouTube 50-ben maximálja)." },
|
||||
"autotag_title_sample": { "label": "Auto-címke címmintavétel", "hint": "Csatornánként ennyi friss videócímet mintázunk a nyelvfelismeréshez." },
|
||||
"youtube_api_key": { "label": "YouTube API-kulcs", "hint": "Opcionális. Publikus olvasásokhoz (csatornák/videók), hogy a megosztott letöltés ne függjön egy felhasználó OAuth-jától. Titkosítva tárolva; csak írható." },
|
||||
"youtube_api_proxy": { "label": "YouTube API egress proxy", "hint": "Opcionális. HTTP(S) proxy URL a kimenő YouTube API-hívásokhoz — fix IP-jű hoston átengedve egy IP-korlátozott kulcs dinamikus IP-jű szerverről is működik. Üresen = közvetlen." },
|
||||
"google_client_id": { "label": "Google kliens-azonosító", "hint": "OAuth 2.0 kliens-azonosító a Google-bejelentkezéshez. Titkosítva tárolva; csak írható. Hagyd üresen mindkét Google-mezőt a Google-bejelentkezés kikapcsolásához (az e-mail+jelszó továbbra is működik)." },
|
||||
"google_client_secret": { "label": "Google kliens-titok", "hint": "OAuth 2.0 kliens-titok. Titkosítva tárolva; csak írható." },
|
||||
"allow_registration": { "label": "Regisztráció engedélyezése", "hint": "Bekapcsolva bárki beküldhet email+jelszó regisztrációt. Belépéshez továbbra is email-igazolás és admin-jóváhagyás szükséges." }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue