Browse Source

Fix: YouTube channel name fetch error

Fixes an error when fetching YouTube channel names.
gpt-engineer-app[bot] 5 months ago
parent
commit
cfef14fc6b
1 changed files with 88 additions and 26 deletions
  1. 88 26
      src/utils/youtube.ts

+ 88 - 26
src/utils/youtube.ts

@@ -46,40 +46,102 @@ export const convertYouTubeToRSS = (url: string): string => {
   return url;
 };
 
-// Function to fetch YouTube channel name from page metadata
+// Function to extract channel name from @username format URL
+export const extractChannelNameFromUrl = (url: string): string | null => {
+  // Try to extract from @username format
+  const atMatch = url.match(/youtube\.com\/@([a-zA-Z0-9_-]+)/);
+  if (atMatch && atMatch[1]) {
+    return atMatch[1];
+  }
+  
+  // Try to extract from /c/ format
+  const cMatch = url.match(/youtube\.com\/c\/([a-zA-Z0-9_-]+)/);
+  if (cMatch && cMatch[1]) {
+    return cMatch[1];
+  }
+  
+  // Try to extract from /user/ format
+  const userMatch = url.match(/youtube\.com\/user\/([a-zA-Z0-9_-]+)/);
+  if (userMatch && userMatch[1]) {
+    return userMatch[1];
+  }
+  
+  return null;
+};
+
+// Function to fetch YouTube channel name from page metadata with multiple fallbacks
 export const fetchYouTubeChannelName = async (url: string): Promise<string | null> => {
-  try {
-    // Use a CORS proxy to fetch the YouTube page
-    const proxyUrl = `https://api.allorigins.win/get?url=${encodeURIComponent(url)}`;
-    const response = await fetch(proxyUrl);
-    const data = await response.json();
-    
-    if (data.contents) {
-      const html = data.contents;
+  // First, try to extract name from URL if it's an @username format
+  const urlName = extractChannelNameFromUrl(url);
+  if (urlName) {
+    console.log('Extracted channel name from URL:', urlName);
+    return urlName;
+  }
+
+  // List of CORS proxy services to try
+  const proxies = [
+    'https://corsproxy.io/?',
+    'https://cors-anywhere.herokuapp.com/',
+    'https://api.allorigins.win/get?url='
+  ];
+  
+  for (const proxy of proxies) {
+    try {
+      console.log(`Trying proxy: ${proxy}`);
+      const proxyUrl = `${proxy}${encodeURIComponent(url)}`;
+      
+      const response = await fetch(proxyUrl, {
+        method: 'GET',
+        headers: {
+          'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
+        },
+        // Add timeout
+        signal: AbortSignal.timeout(10000) // 10 seconds timeout
+      });
       
-      // Try to extract channel name from various meta tags
-      const metaPatterns = [
-        /<meta property="og:title" content="([^"]+)"/,
-        /<meta name="twitter:title" content="([^"]+)"/,
-        /<title>([^<]+)<\/title>/,
-        /<meta property="og:site_name" content="([^"]+)"/
-      ];
+      if (!response.ok) {
+        console.log(`Proxy ${proxy} failed with status:`, response.status);
+        continue;
+      }
+      
+      let html = '';
+      
+      // Handle different proxy response formats
+      if (proxy.includes('allorigins.win')) {
+        const data = await response.json();
+        html = data.contents || '';
+      } else {
+        html = await response.text();
+      }
       
-      for (const pattern of metaPatterns) {
-        const match = html.match(pattern);
-        if (match && match[1]) {
-          let title = match[1].trim();
-          // Clean up the title (remove " - YouTube" suffix if present)
-          title = title.replace(/ - YouTube$/, '');
-          if (title && title !== 'YouTube') {
-            return title;
+      if (html) {
+        // Try to extract channel name from various meta tags
+        const metaPatterns = [
+          /<meta property="og:title" content="([^"]+)"/,
+          /<meta name="twitter:title" content="([^"]+)"/,
+          /<title>([^<]+)<\/title>/,
+          /<meta property="og:site_name" content="([^"]+)"/
+        ];
+        
+        for (const pattern of metaPatterns) {
+          const match = html.match(pattern);
+          if (match && match[1]) {
+            let title = match[1].trim();
+            // Clean up the title (remove " - YouTube" suffix if present)
+            title = title.replace(/ - YouTube$/, '');
+            if (title && title !== 'YouTube') {
+              console.log('Successfully extracted channel name:', title);
+              return title;
+            }
           }
         }
       }
+    } catch (error) {
+      console.log(`Proxy ${proxy} failed:`, error);
+      continue;
     }
-  } catch (error) {
-    console.error('Error fetching YouTube channel name:', error);
   }
   
+  console.log('All proxies failed, could not fetch channel name');
   return null;
 };