42
									
								
								server.ts
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								server.ts
									
									
									
									
									
								
							@@ -6,7 +6,7 @@ import {
 | 
				
			|||||||
  fetchAllEpisodes, 
 | 
					  fetchAllEpisodes, 
 | 
				
			||||||
  fetchEpisodesWithArticles,
 | 
					  fetchEpisodesWithArticles,
 | 
				
			||||||
  getAllFeeds,
 | 
					  getAllFeeds,
 | 
				
			||||||
  getFeedByUrl,
 | 
					  getFeedByUrl
 | 
				
			||||||
} from "./services/database.js";
 | 
					} from "./services/database.js";
 | 
				
			||||||
import { batchProcess, addNewFeedUrl } from "./scripts/fetch_and_generate.js";
 | 
					import { batchProcess, addNewFeedUrl } from "./scripts/fetch_and_generate.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -36,11 +36,7 @@ app.post("/api/feeds", async (c) => {
 | 
				
			|||||||
  try {
 | 
					  try {
 | 
				
			||||||
    const { feedUrl } = await c.req.json<{ feedUrl: string }>();
 | 
					    const { feedUrl } = await c.req.json<{ feedUrl: string }>();
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if (
 | 
					    if (!feedUrl || typeof feedUrl !== "string" || !feedUrl.startsWith('http')) {
 | 
				
			||||||
      !feedUrl ||
 | 
					 | 
				
			||||||
      typeof feedUrl !== "string" ||
 | 
					 | 
				
			||||||
      !feedUrl.startsWith("http")
 | 
					 | 
				
			||||||
    ) {
 | 
					 | 
				
			||||||
      return c.json({ error: "Valid feed URL is required" }, 400);
 | 
					      return c.json({ error: "Valid feed URL is required" }, 400);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@@ -52,7 +48,7 @@ app.post("/api/feeds", async (c) => {
 | 
				
			|||||||
      return c.json({ 
 | 
					      return c.json({ 
 | 
				
			||||||
        result: "EXISTS", 
 | 
					        result: "EXISTS", 
 | 
				
			||||||
        message: "Feed URL already exists",
 | 
					        message: "Feed URL already exists",
 | 
				
			||||||
        feed: existingFeed,
 | 
					        feed: existingFeed 
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@@ -62,7 +58,7 @@ app.post("/api/feeds", async (c) => {
 | 
				
			|||||||
    return c.json({ 
 | 
					    return c.json({ 
 | 
				
			||||||
      result: "CREATED", 
 | 
					      result: "CREATED", 
 | 
				
			||||||
      message: "Feed URL added successfully",
 | 
					      message: "Feed URL added successfully",
 | 
				
			||||||
      feedUrl,
 | 
					      feedUrl 
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  } catch (error) {
 | 
					  } catch (error) {
 | 
				
			||||||
    console.error("Error adding feed:", error);
 | 
					    console.error("Error adding feed:", error);
 | 
				
			||||||
@@ -104,7 +100,7 @@ app.post("/api/episodes/:id/regenerate", async (c) => {
 | 
				
			|||||||
      result: "PENDING", 
 | 
					      result: "PENDING", 
 | 
				
			||||||
      episodeId: id,
 | 
					      episodeId: id,
 | 
				
			||||||
      status: "pending",
 | 
					      status: "pending",
 | 
				
			||||||
      message: "Regeneration feature will be implemented in a future update",
 | 
					      message: "Regeneration feature will be implemented in a future update"
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  } catch (error) {
 | 
					  } catch (error) {
 | 
				
			||||||
    console.error("Error requesting regeneration:", error);
 | 
					    console.error("Error requesting regeneration:", error);
 | 
				
			||||||
@@ -120,9 +116,9 @@ app.get("/api/stats", async (c) => {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    const stats = {
 | 
					    const stats = {
 | 
				
			||||||
      totalFeeds: feeds.length,
 | 
					      totalFeeds: feeds.length,
 | 
				
			||||||
      activeFeeds: feeds.filter((f) => f.active).length,
 | 
					      activeFeeds: feeds.filter(f => f.active).length,
 | 
				
			||||||
      totalEpisodes: episodes.length,
 | 
					      totalEpisodes: episodes.length,
 | 
				
			||||||
      lastUpdated: new Date().toISOString(),
 | 
					      lastUpdated: new Date().toISOString()
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    return c.json(stats);
 | 
					    return c.json(stats);
 | 
				
			||||||
@@ -137,14 +133,14 @@ app.post("/api/batch/trigger", async (c) => {
 | 
				
			|||||||
    console.log("🚀 Manual batch process triggered via API");
 | 
					    console.log("🚀 Manual batch process triggered via API");
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Run batch process in background
 | 
					    // Run batch process in background
 | 
				
			||||||
    runBatchProcess().catch((error) => {
 | 
					    runBatchProcess().catch(error => {
 | 
				
			||||||
      console.error("❌ Manual batch process failed:", error);
 | 
					      console.error("❌ Manual batch process failed:", error);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    return c.json({ 
 | 
					    return c.json({ 
 | 
				
			||||||
      result: "TRIGGERED",
 | 
					      result: "TRIGGERED",
 | 
				
			||||||
      message: "Batch process started in background",
 | 
					      message: "Batch process started in background",
 | 
				
			||||||
      timestamp: new Date().toISOString(),
 | 
					      timestamp: new Date().toISOString()
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  } catch (error) {
 | 
					  } catch (error) {
 | 
				
			||||||
    console.error("Error triggering batch process:", error);
 | 
					    console.error("Error triggering batch process:", error);
 | 
				
			||||||
@@ -185,10 +181,7 @@ app.get("/podcast_audio/*", async (c) => {
 | 
				
			|||||||
      return c.notFound();
 | 
					      return c.notFound();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    const audioFilePath = path.join(
 | 
					    const audioFilePath = path.join(config.paths.podcastAudioDir, audioFileName);
 | 
				
			||||||
      config.paths.podcastAudioDir,
 | 
					 | 
				
			||||||
      audioFileName,
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
    const file = Bun.file(audioFilePath);
 | 
					    const file = Bun.file(audioFilePath);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if (await file.exists()) {
 | 
					    if (await file.exists()) {
 | 
				
			||||||
@@ -225,13 +218,10 @@ app.get("/podcast.xml", async (c) => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Legacy endpoint - redirect to new one
 | 
					// Legacy endpoint - redirect to new one
 | 
				
			||||||
app.post("/api/add-feed", async (c) => {
 | 
					app.post("/api/add-feed", async (c) => {
 | 
				
			||||||
  return c.json(
 | 
					  return c.json({ 
 | 
				
			||||||
    {
 | 
					    error: "This endpoint is deprecated. Use POST /api/feeds instead.",
 | 
				
			||||||
      error: "This endpoint is deprecated. Use POST /api/feeds instead.",
 | 
					    newEndpoint: "POST /api/feeds"
 | 
				
			||||||
      newEndpoint: "POST /api/feeds",
 | 
					  }, 410);
 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    410,
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Frontend fallback routes
 | 
					// Frontend fallback routes
 | 
				
			||||||
@@ -277,7 +267,7 @@ function scheduleSixHourlyBatchProcess() {
 | 
				
			|||||||
  const SIX_HOURS_MS = 6 * 60 * 60 * 1000; // 6 hours in milliseconds
 | 
					  const SIX_HOURS_MS = 6 * 60 * 60 * 1000; // 6 hours in milliseconds
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  console.log(
 | 
					  console.log(
 | 
				
			||||||
    `🕕 Next batch process scheduled in 6 hours (${new Date(Date.now() + SIX_HOURS_MS).toLocaleString()})`,
 | 
					    `🕕 Next batch process scheduled in 6 hours (${new Date(Date.now() + SIX_HOURS_MS).toLocaleString()})`
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  setTimeout(async () => {
 | 
					  setTimeout(async () => {
 | 
				
			||||||
@@ -295,7 +285,7 @@ function scheduleSixHourlyBatchProcess() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
async function runBatchProcess(): Promise<void> {
 | 
					async function runBatchProcess(): Promise<void> {
 | 
				
			||||||
  try {
 | 
					  try {
 | 
				
			||||||
    Bun.spawn(["bun", "run", "scripts/fetch_and_generate.ts"]);
 | 
					    await batchProcess();
 | 
				
			||||||
  } catch (error) {
 | 
					  } catch (error) {
 | 
				
			||||||
    console.error("Batch process failed:", error);
 | 
					    console.error("Batch process failed:", error);
 | 
				
			||||||
    throw error;
 | 
					    throw error;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user