From 683352e162863542a5860a21481f45f1d95d8b30 Mon Sep 17 00:00:00 2001 From: Alex Patterson Date: Tue, 3 Mar 2026 23:08:47 -0500 Subject: [PATCH] feat: add YOUTUBE_UPLOAD_VISIBILITY env var, default to private (#596) Co-authored-by: Miriad Co-authored-by: videopipe --- .env.example | 1 + lib/youtube-upload.ts | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 634ff9c2..24c919a3 100644 --- a/.env.example +++ b/.env.example @@ -56,6 +56,7 @@ CRON_SECRET= # Secret for authenticating cron job re # YouTube integration YOUTUBE_API_KEY= # YouTube Data API v3 key YOUTUBE_CHANNEL_ID= # YouTube channel ID to fetch videos from +YOUTUBE_UPLOAD_VISIBILITY= # YouTube upload privacy: "public", "private", or "unlisted" (default: "private") # Vercel VERCEL_PROJECT_PRODUCTION_URL= # Production URL (auto-set by Vercel) diff --git a/lib/youtube-upload.ts b/lib/youtube-upload.ts index 347c321d..9c576468 100644 --- a/lib/youtube-upload.ts +++ b/lib/youtube-upload.ts @@ -10,6 +10,14 @@ oauth2Client.setCredentials({ const youtube = google.youtube({ version: "v3", auth: oauth2Client }); +function getDefaultPrivacyStatus(): "public" | "private" | "unlisted" { + const envValue = process.env.YOUTUBE_UPLOAD_VISIBILITY?.toLowerCase(); + if (envValue === "public" || envValue === "private" || envValue === "unlisted") { + return envValue; + } + return "private"; // Default to private when not set +} + interface UploadOptions { title: string; description: string; @@ -27,6 +35,9 @@ export async function uploadVideo(opts: UploadOptions): Promise<{ videoId: strin const response = await fetch(opts.videoUrl); if (!response.ok) throw new Error(`Failed to fetch video: ${response.statusText}`); + const resolvedPrivacyStatus = opts.privacyStatus || getDefaultPrivacyStatus(); + console.log(`[youtube-upload] Uploading "${opts.title.slice(0, 60)}" with privacy: ${resolvedPrivacyStatus}`); + const res = await youtube.videos.insert({ part: ["snippet", "status"], requestBody: { @@ -38,7 +49,7 @@ export async function uploadVideo(opts: UploadOptions): Promise<{ videoId: strin defaultLanguage: "en", }, status: { - privacyStatus: opts.privacyStatus || "public", + privacyStatus: resolvedPrivacyStatus, selfDeclaredMadeForKids: opts.madeForKids ?? false, }, },