From df8f84c3b999eec23eb82c08374825c3a36f4c18 Mon Sep 17 00:00:00 2001 From: Haewon Kam Date: Sat, 4 Apr 2026 01:00:21 +0900 Subject: [PATCH] fix: YouTube channel ID (UC...) handling + handle-to-channelId resolution discover-channels: extractHandle('youtube') now detects UC* channel IDs and returns them without @ prefix (previously @UC... caused verify fail) verifyHandles: verifyYouTube uses cleanHandle for UC* check, requests part=id,snippet for richer data collect-channel-data: if channelId missing but handle present, resolves via forHandle/forUsername lookup or direct UC* detection before skipping Co-Authored-By: Claude Opus 4.6 (1M context) --- supabase/functions/_shared/verifyHandles.ts | 6 +++--- .../functions/collect-channel-data/index.ts | 17 ++++++++++++++++- supabase/functions/discover-channels/index.ts | 2 ++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/supabase/functions/_shared/verifyHandles.ts b/supabase/functions/_shared/verifyHandles.ts index da44462..1dd95c2 100644 --- a/supabase/functions/_shared/verifyHandles.ts +++ b/supabase/functions/_shared/verifyHandles.ts @@ -66,11 +66,11 @@ async function verifyYouTube(handle: string, apiKey: string): Promise { if (YOUTUBE_API_KEY && ytVerified?.verified) { tasks.push((async () => { const YT = "https://www.googleapis.com/youtube/v3"; - const channelId = (ytVerified?.channelId as string) || ""; + let channelId = (ytVerified?.channelId as string) || ""; + + // If no channelId, try to resolve from handle + if (!channelId && ytVerified?.handle) { + const h = (ytVerified.handle as string).replace(/^@/, ''); + if (h.startsWith('UC')) { + channelId = h; + } else { + for (const param of ['forHandle', 'forUsername']) { + const lookupRes = await fetch(`${YT}/channels?part=id&${param}=${h}&key=${YOUTUBE_API_KEY}`); + const lookupData = await lookupRes.json(); + channelId = lookupData.items?.[0]?.id || ''; + if (channelId) break; + } + } + } if (!channelId) return; const chRes = await fetch(`${YT}/channels?part=snippet,statistics,brandingSettings&id=${channelId}&key=${YOUTUBE_API_KEY}`); diff --git a/supabase/functions/discover-channels/index.ts b/supabase/functions/discover-channels/index.ts index d2fc291..5f5acaf 100644 --- a/supabase/functions/discover-channels/index.ts +++ b/supabase/functions/discover-channels/index.ts @@ -221,6 +221,8 @@ Deno.serve(async (req) => { h = h.replace(/^@/, ''); // Reject if it looks like a non-YouTube URL if (h.includes('http') || h.includes('/') || h.includes('.com')) return null; + // Channel IDs start with UC — don't add @ prefix + if (/^UC[a-zA-Z0-9_-]{20,}$/.test(h)) return h; if (/^[a-zA-Z0-9._-]+$/.test(h) && h.length >= 2) return `@${h}`; return null; }