Update for static file serving
This commit is contained in:
		
							
								
								
									
										47
									
								
								server.ts
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								server.ts
									
									
									
									
									
								
							@@ -129,15 +129,33 @@ app.get("/podcast.xml", async (c) => {
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// Category-specific RSS feeds
 | 
			
		||||
// Category-specific RSS feeds - try static file first, then generate dynamically
 | 
			
		||||
app.get("/podcast/category/:category.xml", async (c) => {
 | 
			
		||||
  try {
 | 
			
		||||
    const category = decodeURIComponent(c.req.param("category") || "");
 | 
			
		||||
    if (!category) {
 | 
			
		||||
      return c.notFound();
 | 
			
		||||
    }
 | 
			
		||||
    const { generateCategoryRSS } = await import("./services/podcast.js");
 | 
			
		||||
 | 
			
		||||
    // Try to serve static file first
 | 
			
		||||
    const safeCategory = encodeURIComponent(category);
 | 
			
		||||
    const staticFilePath = path.join(
 | 
			
		||||
      config.paths.publicDir,
 | 
			
		||||
      `podcast_category_${safeCategory}.xml`,
 | 
			
		||||
    );
 | 
			
		||||
    const staticFile = Bun.file(staticFilePath);
 | 
			
		||||
 | 
			
		||||
    if (await staticFile.exists()) {
 | 
			
		||||
      const blob = await staticFile.arrayBuffer();
 | 
			
		||||
      return c.body(blob, 200, {
 | 
			
		||||
        "Content-Type": "application/xml; charset=utf-8",
 | 
			
		||||
        "Cache-Control": "public, max-age=3600", // Cache for 1 hour
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Fallback to dynamic generation
 | 
			
		||||
    console.log(`📄 Static category RSS not found for "${category}", generating dynamically...`);
 | 
			
		||||
    const { generateCategoryRSS } = await import("./services/podcast.js");
 | 
			
		||||
    const rssXml = await generateCategoryRSS(category);
 | 
			
		||||
 | 
			
		||||
    return c.body(rssXml, 200, {
 | 
			
		||||
@@ -146,22 +164,39 @@ app.get("/podcast/category/:category.xml", async (c) => {
 | 
			
		||||
    });
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.error(
 | 
			
		||||
      `Error generating category RSS for "${c.req.param("category")}":`,
 | 
			
		||||
      `Error serving category RSS for "${c.req.param("category")}":`,
 | 
			
		||||
      error,
 | 
			
		||||
    );
 | 
			
		||||
    return c.notFound();
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// Feed-specific RSS feeds
 | 
			
		||||
// Feed-specific RSS feeds - try static file first, then generate dynamically
 | 
			
		||||
app.get("/podcast/feed/:feedId.xml", async (c) => {
 | 
			
		||||
  try {
 | 
			
		||||
    const feedId = c.req.param("feedId");
 | 
			
		||||
    if (!feedId) {
 | 
			
		||||
      return c.notFound();
 | 
			
		||||
    }
 | 
			
		||||
    const { generateFeedRSS } = await import("./services/podcast.js");
 | 
			
		||||
 | 
			
		||||
    // Try to serve static file first
 | 
			
		||||
    const staticFilePath = path.join(
 | 
			
		||||
      config.paths.publicDir,
 | 
			
		||||
      `podcast_feed_${feedId}.xml`,
 | 
			
		||||
    );
 | 
			
		||||
    const staticFile = Bun.file(staticFilePath);
 | 
			
		||||
 | 
			
		||||
    if (await staticFile.exists()) {
 | 
			
		||||
      const blob = await staticFile.arrayBuffer();
 | 
			
		||||
      return c.body(blob, 200, {
 | 
			
		||||
        "Content-Type": "application/xml; charset=utf-8",
 | 
			
		||||
        "Cache-Control": "public, max-age=3600", // Cache for 1 hour
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Fallback to dynamic generation
 | 
			
		||||
    console.log(`📄 Static feed RSS not found for "${feedId}", generating dynamically...`);
 | 
			
		||||
    const { generateFeedRSS } = await import("./services/podcast.js");
 | 
			
		||||
    const rssXml = await generateFeedRSS(feedId);
 | 
			
		||||
 | 
			
		||||
    return c.body(rssXml, 200, {
 | 
			
		||||
@@ -170,7 +205,7 @@ app.get("/podcast/feed/:feedId.xml", async (c) => {
 | 
			
		||||
    });
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.error(
 | 
			
		||||
      `Error generating feed RSS for "${c.req.param("feedId")}":`,
 | 
			
		||||
      `Error serving feed RSS for "${c.req.param("feedId")}":`,
 | 
			
		||||
      error,
 | 
			
		||||
    );
 | 
			
		||||
    return c.notFound();
 | 
			
		||||
 
 | 
			
		||||
@@ -139,20 +139,118 @@ export async function updatePodcastRSS(): Promise<void> {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Generate all category RSS files as static files
 | 
			
		||||
 */
 | 
			
		||||
export async function generateAllCategoryRSSFiles(): Promise<void> {
 | 
			
		||||
  try {
 | 
			
		||||
    const { getAllEpisodeCategories } = await import("./database.js");
 | 
			
		||||
    const categories = await getAllEpisodeCategories();
 | 
			
		||||
    
 | 
			
		||||
    console.log(`🔄 Generating ${categories.length} category RSS files...`);
 | 
			
		||||
    
 | 
			
		||||
    for (const category of categories) {
 | 
			
		||||
      try {
 | 
			
		||||
        await saveCategoryRSSFile(category);
 | 
			
		||||
      } catch (error) {
 | 
			
		||||
        console.error(`❌ Failed to generate RSS for category "${category}":`, error);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    console.log(`✅ Generated category RSS files for ${categories.length} categories`);
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.error("❌ Error generating category RSS files:", error);
 | 
			
		||||
    throw error;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Generate all feed RSS files as static files
 | 
			
		||||
 */
 | 
			
		||||
export async function generateAllFeedRSSFiles(): Promise<void> {
 | 
			
		||||
  try {
 | 
			
		||||
    const { fetchActiveFeeds } = await import("./database.js");
 | 
			
		||||
    const feeds = await fetchActiveFeeds();
 | 
			
		||||
    
 | 
			
		||||
    console.log(`🔄 Generating ${feeds.length} feed RSS files...`);
 | 
			
		||||
    
 | 
			
		||||
    for (const feed of feeds) {
 | 
			
		||||
      try {
 | 
			
		||||
        await saveFeedRSSFile(feed.id);
 | 
			
		||||
      } catch (error) {
 | 
			
		||||
        console.error(`❌ Failed to generate RSS for feed "${feed.id}":`, error);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    console.log(`✅ Generated feed RSS files for ${feeds.length} feeds`);
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.error("❌ Error generating feed RSS files:", error);
 | 
			
		||||
    throw error;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Save category RSS as static file with URL-safe filename
 | 
			
		||||
 */
 | 
			
		||||
export async function saveCategoryRSSFile(category: string): Promise<void> {
 | 
			
		||||
  try {
 | 
			
		||||
    const rssXml = await generateCategoryRSS(category);
 | 
			
		||||
    const safeCategory = encodeURIComponent(category);
 | 
			
		||||
    const outputPath = path.join(
 | 
			
		||||
      config.paths.publicDir,
 | 
			
		||||
      `podcast_category_${safeCategory}.xml`,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // Ensure directory exists
 | 
			
		||||
    await fs.mkdir(dirname(outputPath), { recursive: true });
 | 
			
		||||
    await fs.writeFile(outputPath, rssXml);
 | 
			
		||||
 | 
			
		||||
    console.log(`📄 Category RSS saved: podcast_category_${safeCategory}.xml`);
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.error(`❌ Error saving category RSS for "${category}":`, error);
 | 
			
		||||
    throw error;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Save feed RSS as static file
 | 
			
		||||
 */
 | 
			
		||||
export async function saveFeedRSSFile(feedId: string): Promise<void> {
 | 
			
		||||
  try {
 | 
			
		||||
    const rssXml = await generateFeedRSS(feedId);
 | 
			
		||||
    const outputPath = path.join(
 | 
			
		||||
      config.paths.publicDir,
 | 
			
		||||
      `podcast_feed_${feedId}.xml`,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // Ensure directory exists
 | 
			
		||||
    await fs.mkdir(dirname(outputPath), { recursive: true });
 | 
			
		||||
    await fs.writeFile(outputPath, rssXml);
 | 
			
		||||
 | 
			
		||||
    console.log(`📄 Feed RSS saved: podcast_feed_${feedId}.xml`);
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.error(`❌ Error saving feed RSS for "${feedId}":`, error);
 | 
			
		||||
    throw error;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Regenerate all static files on startup
 | 
			
		||||
 * This ensures that podcast.xml and other generated files are up-to-date
 | 
			
		||||
 */
 | 
			
		||||
export async function regenerateStartupFiles(): Promise<void> {
 | 
			
		||||
  try {
 | 
			
		||||
    console.log("🔄 Regenerating static files on startup...");
 | 
			
		||||
    console.log("🔄 Regenerating all static files on startup...");
 | 
			
		||||
    
 | 
			
		||||
    // Regenerate main podcast.xml
 | 
			
		||||
    await updatePodcastRSS();
 | 
			
		||||
    console.log("✅ podcast.xml regenerated successfully");
 | 
			
		||||
    
 | 
			
		||||
    // Note: Category and feed-specific RSS files are generated dynamically on request
 | 
			
		||||
    // This is more efficient and ensures they're always up-to-date with current data
 | 
			
		||||
    // Generate all category RSS files
 | 
			
		||||
    await generateAllCategoryRSSFiles();
 | 
			
		||||
    
 | 
			
		||||
    // Generate all feed RSS files
 | 
			
		||||
    await generateAllFeedRSSFiles();
 | 
			
		||||
    
 | 
			
		||||
    console.log("✅ All startup files regenerated successfully");
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user