feat: M2 (part 1) — subscription import, YouTube client, quota guard
- Channel/Subscription/Video/ApiQuotaUsage models + migration 0002 - Synchronous YouTube Data API client with OAuth token refresh and per-call quota accounting (API key preferred for public reads when configured) - Subscription import: upsert channels + subscription links, prune unsubscribed, fetch channel details (uploads playlist, topics, stats, handle, country) - Central quota guard tracking units per US-Pacific day against a daily budget - POST /api/sync/subscriptions and GET /api/sync/status endpoints
This commit is contained in:
parent
3a774cf7d6
commit
24b6e0026d
10 changed files with 603 additions and 3 deletions
|
|
@ -24,6 +24,16 @@ class Settings(BaseSettings):
|
|||
# Origin of a separately served frontend dev server (enables CORS). Empty in production.
|
||||
frontend_origin: str = ""
|
||||
|
||||
# --- Sync / YouTube Data API ---
|
||||
# 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 = ""
|
||||
# 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.
|
||||
backfill_recent_max_videos: int = 200
|
||||
backfill_recent_max_days: int = 365
|
||||
|
||||
@property
|
||||
def allowed_email_set(self) -> set[str]:
|
||||
return {e.strip().lower() for e in self.allowed_emails.split(",") if e.strip()}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue