浏览代码

Feat: Extract channel name from meta tags

Attempt to extract the YouTube channel name from the page's meta tags when adding a YouTube feed.
gpt-engineer-app[bot] 5 月之前
父节点
当前提交
a5a9e20333
共有 1 个文件被更改,包括 68 次插入3 次删除
  1. 68 3
      src/components/AddFeedModal.tsx

+ 68 - 3
src/components/AddFeedModal.tsx

@@ -98,8 +98,47 @@ const convertYouTubeToRSS = (url: string): string => {
   return url;
 };
 
+// Function to fetch YouTube channel name from page metadata
+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;
+      
+      // 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') {
+            return title;
+          }
+        }
+      }
+    }
+  } catch (error) {
+    console.error('Error fetching YouTube channel name:', error);
+  }
+  
+  return null;
+};
+
 const AddFeedModal = ({ isOpen, onClose, onAddFeed, categories }: AddFeedModalProps) => {
   const [selectedType, setSelectedType] = useState<string>('');
+  const [isLoadingChannelName, setIsLoadingChannelName] = useState(false);
   
   const form = useForm<FeedFormData>({
     defaultValues: {
@@ -142,6 +181,23 @@ const AddFeedModal = ({ isOpen, onClose, onAddFeed, categories }: AddFeedModalPr
     onClose();
   };
 
+  const handleUrlChange = async (url: string) => {
+    form.setValue('url', url);
+    
+    // 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);
+        const channelName = await fetchYouTubeChannelName(url);
+        if (channelName) {
+          form.setValue('name', channelName);
+        }
+        setIsLoadingChannelName(false);
+      }
+    }
+  };
+
   const selectedTypeOption = feedTypeOptions.find(option => option.value === selectedType);
 
   const getUrlPlaceholder = () => {
@@ -158,7 +214,7 @@ const AddFeedModal = ({ isOpen, onClose, onAddFeed, categories }: AddFeedModalPr
 
   const getUrlHelperText = () => {
     if (selectedType === 'youtube') {
-      return 'Collez le lien de la chaîne YouTube (sera automatiquement converti en flux RSS)';
+      return 'Collez le lien de la chaîne YouTube (nom détecté automatiquement)';
     }
     return null;
   };
@@ -214,12 +270,20 @@ const AddFeedModal = ({ isOpen, onClose, onAddFeed, categories }: AddFeedModalPr
                 name="name"
                 render={({ field }) => (
                   <FormItem>
-                    <FormLabel>Nom du flux</FormLabel>
+                    <FormLabel>
+                      Nom du flux
+                      {isLoadingChannelName && (
+                        <span className="text-xs text-muted-foreground ml-2">
+                          (détection automatique...)
+                        </span>
+                      )}
+                    </FormLabel>
                     <FormControl>
                       <Input 
                         placeholder="Nom du flux..." 
                         {...field} 
                         required
+                        disabled={isLoadingChannelName}
                       />
                     </FormControl>
                     <FormMessage />
@@ -238,6 +302,7 @@ const AddFeedModal = ({ isOpen, onClose, onAddFeed, categories }: AddFeedModalPr
                         placeholder={getUrlPlaceholder()}
                         type="url"
                         {...field} 
+                        onChange={(e) => handleUrlChange(e.target.value)}
                         required
                       />
                     </FormControl>
@@ -273,7 +338,7 @@ const AddFeedModal = ({ isOpen, onClose, onAddFeed, categories }: AddFeedModalPr
                 <Button type="button" variant="outline" onClick={handleCancel}>
                   Annuler
                 </Button>
-                <Button type="submit">
+                <Button type="submit" disabled={isLoadingChannelName}>
                   Ajouter le flux
                 </Button>
               </DialogFooter>