from fastapi import APIRouter, HTTPException import feedparser import httpx from pydantic import BaseModel from typing import List, Optional from datetime import datetime router = APIRouter() RSS_FEED_URL = "https://rss.libsyn.com/shows/563180/destinations/4867845.xml" class PodcastEpisode(BaseModel): id: str title: str description: str audio_url: str published_at: str duration: Optional[str] = None image_url: Optional[str] = None class PodcastFeed(BaseModel): title: str description: str image_url: Optional[str] = None episodes: List[PodcastEpisode] @router.get("/", response_model=PodcastFeed) async def get_podcasts(): try: async with httpx.AsyncClient() as client: response = await client.get(RSS_FEED_URL) response.raise_for_status() rss_content = response.text feed = feedparser.parse(rss_content) if feed.bozo: # Log warning but try to proceed if possible, or raise error print(f"Warning: Feed parsing error: {feed.bozo_exception}") episodes = [] for entry in feed.entries: # Extract audio URL audio_url = "" for link in entry.links: if link.type == "audio/mpeg": audio_url = link.href break if not audio_url: continue # Skip episodes without audio # Extract image image_url = None if 'image' in entry: image_url = entry.image.href elif 'itunes_image' in entry: image_url = entry.itunes_image.href episodes.append(PodcastEpisode( id=entry.id, title=entry.title, description=entry.summary, audio_url=audio_url, published_at=entry.published, duration=entry.get('itunes_duration'), image_url=image_url )) feed_image = None if 'image' in feed.feed: feed_image = feed.feed.image.href elif 'itunes_image' in feed.feed: feed_image = feed.feed.itunes_image.href return PodcastFeed( title=feed.feed.title, description=feed.feed.description, image_url=feed_image, episodes=episodes ) except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to fetch podcasts: {str(e)}")