Prechádzať zdrojové kódy

Implement automatic YouTube RSS lookup

Automatically fetch RSS feed when YouTube channel URL is provided.
gpt-engineer-app[bot] 5 mesiacov pred
rodič
commit
fef5b0ba78

+ 27 - 17
src/components/FeedForm.tsx

@@ -16,6 +16,7 @@ import { Alert, AlertDescription } from '@/components/ui/alert';
 import { 
   convertYouTubeToRSS, 
   fetchYouTubeChannelName, 
+  fetchYouTubeRSSUrl,
   needsChannelIdLookup, 
   getChannelIdInstructions,
   isDirectRSSFeed
@@ -76,28 +77,37 @@ const FeedForm = ({ selectedType, onSubmit, onCancel, categories }: FeedFormProp
     setUrlWarning(null);
     setShowInstructions(false);
     
-    // If it's a YouTube URL and we don't have a name yet, try to fetch it
-    if (selectedType === 'youtube' && url && !form.getValues('name')) {
-      const isYouTubeUrl = url.includes('youtube.com');
-      if (isYouTubeUrl) {
-        setIsLoadingChannelName(true);
+    // If it's a YouTube URL, try to automatically fetch RSS URL and channel name
+    if (selectedType === 'youtube' && url && url.includes('youtube.com')) {
+      setIsLoadingChannelName(true);
+      
+      try {
+        // Try to automatically fetch the RSS URL and channel name
+        const result = await fetchYouTubeRSSUrl(url);
         
-        // Check if it's a direct RSS feed
-        if (isDirectRSSFeed(url)) {
+        if (result) {
+          // Update the URL field with the correct RSS URL
+          form.setValue('url', result.rssUrl);
+          
+          // Set the channel name if we don't have one yet
+          if (!form.getValues('name') && result.channelName) {
+            form.setValue('name', result.channelName);
+          }
+          
           setUrlWarning(null);
-        }
-        // Check if it's a custom username that might not work directly
-        else if (needsChannelIdLookup(url)) {
-          setUrlWarning('Cette URL pourrait ne pas fonctionner. Pour de meilleurs résultats, utilisez l\'ID de chaîne (UC...).');
+          setShowInstructions(false);
+        } else {
+          // Fallback to manual instructions if automatic detection fails
+          setUrlWarning('Impossible de détecter automatiquement le flux RSS. Veuillez utiliser les instructions ci-dessous.');
           setShowInstructions(true);
         }
-        
-        const channelName = await fetchYouTubeChannelName(url);
-        if (channelName) {
-          form.setValue('name', channelName);
-        }
-        setIsLoadingChannelName(false);
+      } catch (error) {
+        console.error('Error fetching YouTube RSS:', error);
+        setUrlWarning('Erreur lors de la détection automatique. Veuillez utiliser les instructions ci-dessous.');
+        setShowInstructions(true);
       }
+      
+      setIsLoadingChannelName(false);
     }
   };
 

+ 27 - 0
src/utils/youtube.ts

@@ -93,6 +93,33 @@ Méthode alternative :
 2. Utilisez l'URL : https://www.youtube.com/channel/UCxxxxx`;
 };
 
+// Function to automatically fetch YouTube channel RSS and name
+export const fetchYouTubeRSSUrl = async (url: string): Promise<{rssUrl: string, channelName: string} | null> => {
+  try {
+    const response = await fetch(`https://wftyukugedtojizgatwj.supabase.co/functions/v1/fetch-youtube-rss`, {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+        'Authorization': `Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6IndmdHl1a3VnZWR0b2ppemdhdHdqIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDkzNjIxNTEsImV4cCI6MjA2NDkzODE1MX0.KflrS6WiGksws1nO8NDm5i_Dav4u2JDSuEYtEnmKCRE`
+      },
+      body: JSON.stringify({ url })
+    });
+
+    if (!response.ok) {
+      const errorData = await response.json();
+      console.error('Failed to fetch YouTube RSS:', errorData.error);
+      return null;
+    }
+
+    const data = await response.json();
+    console.log('Successfully fetched YouTube RSS data:', data);
+    return data;
+  } catch (error) {
+    console.error('Error fetching YouTube RSS:', error);
+    return null;
+  }
+};
+
 // Function to fetch YouTube channel name from page metadata with fallback
 export const fetchYouTubeChannelName = async (url: string): Promise<string | null> => {
   // First, try to extract name from URL if it's an @username format

+ 88 - 0
supabase/functions/fetch-youtube-rss/index.ts

@@ -0,0 +1,88 @@
+import { serve } from "https://deno.land/std@0.177.0/http/server.ts"
+
+const corsHeaders = {
+  'Access-Control-Allow-Origin': '*',
+  'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
+}
+
+serve(async (req) => {
+  if (req.method === 'OPTIONS') {
+    return new Response('ok', { headers: corsHeaders })
+  }
+
+  try {
+    const { url } = await req.json()
+    
+    if (!url || !url.includes('youtube.com')) {
+      return new Response(
+        JSON.stringify({ error: 'Invalid YouTube URL' }),
+        { 
+          headers: { ...corsHeaders, 'Content-Type': 'application/json' },
+          status: 400
+        }
+      )
+    }
+
+    console.log('Fetching YouTube page:', url)
+    
+    // Fetch the YouTube page
+    const response = await fetch(url, {
+      headers: {
+        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
+      }
+    })
+    
+    if (!response.ok) {
+      throw new Error(`Failed to fetch page: ${response.status}`)
+    }
+    
+    const html = await response.text()
+    
+    // Look for the RSS feed link in the HTML
+    const rssLinkMatch = html.match(/<link[^>]+rel="alternate"[^>]+type="application\/rss\+xml"[^>]+href="([^"]+)"/i)
+    
+    if (!rssLinkMatch) {
+      return new Response(
+        JSON.stringify({ error: 'RSS feed not found on this YouTube page' }),
+        { 
+          headers: { ...corsHeaders, 'Content-Type': 'application/json' },
+          status: 404
+        }
+      )
+    }
+    
+    const rssUrl = rssLinkMatch[1]
+    
+    // Also try to extract the channel name from the page title
+    const titleMatch = html.match(/<title>([^<]+)<\/title>/i)
+    let channelName = null
+    
+    if (titleMatch) {
+      // Remove " - YouTube" from the end if present
+      channelName = titleMatch[1].replace(/ - YouTube$/, '')
+    }
+    
+    console.log('Found RSS URL:', rssUrl)
+    console.log('Found channel name:', channelName)
+    
+    return new Response(
+      JSON.stringify({ 
+        rssUrl,
+        channelName
+      }),
+      { 
+        headers: { ...corsHeaders, 'Content-Type': 'application/json' }
+      }
+    )
+    
+  } catch (error) {
+    console.error('Error:', error)
+    return new Response(
+      JSON.stringify({ error: error.message }),
+      { 
+        headers: { ...corsHeaders, 'Content-Type': 'application/json' },
+        status: 500
+      }
+    )
+  }
+})