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) <noreply@anthropic.com>
claude/bold-hawking
parent
163751410f
commit
df8f84c3b9
|
|
@ -66,11 +66,11 @@ async function verifyYouTube(handle: string, apiKey: string): Promise<VerifiedCh
|
|||
}
|
||||
|
||||
// Try as channel ID directly (starts with UC)
|
||||
if (handle.startsWith('UC')) {
|
||||
const res = await fetch(`${YT_BASE}/channels?part=id&id=${handle}&key=${apiKey}`);
|
||||
if (cleanHandle.startsWith('UC')) {
|
||||
const res = await fetch(`${YT_BASE}/channels?part=id,snippet&id=${cleanHandle}&key=${apiKey}`);
|
||||
const data = await res.json();
|
||||
if (data.items?.[0]) {
|
||||
return { handle, verified: true, channelId: handle, url: `https://youtube.com/channel/${handle}` };
|
||||
return { handle: cleanHandle, verified: true, channelId: cleanHandle, url: `https://youtube.com/channel/${cleanHandle}` };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -109,7 +109,22 @@ Deno.serve(async (req) => {
|
|||
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}`);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue