Update
This commit is contained in:
19
server.ts
19
server.ts
@ -266,6 +266,25 @@ app.get("/api/feeds/:feedId/episodes", async (c) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.get("/api/episode-with-source/:episodeId", async (c) => {
|
||||||
|
try {
|
||||||
|
const episodeId = c.req.param("episodeId");
|
||||||
|
const { fetchEpisodeWithSourceInfo } = await import(
|
||||||
|
"./services/database.js"
|
||||||
|
);
|
||||||
|
const episode = await fetchEpisodeWithSourceInfo(episodeId);
|
||||||
|
|
||||||
|
if (!episode) {
|
||||||
|
return c.json({ error: "Episode not found" }, 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.json({ episode });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching episode with source info:", error);
|
||||||
|
return c.json({ error: "Failed to fetch episode with source info" }, 500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
app.get("/api/episodes-with-feed-info", async (c) => {
|
app.get("/api/episodes-with-feed-info", async (c) => {
|
||||||
try {
|
try {
|
||||||
const { fetchEpisodesWithFeedInfo } = await import(
|
const { fetchEpisodesWithFeedInfo } = await import(
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
import { promises as fs } from "fs";
|
import { promises as fs } from "fs";
|
||||||
import { dirname } from "path";
|
import { dirname } from "path";
|
||||||
import {
|
import { fetchEpisodesWithFeedInfo } from "./database.js";
|
||||||
Episode,
|
|
||||||
fetchAllEpisodes,
|
|
||||||
performDatabaseIntegrityFixes,
|
|
||||||
} from "./database.js";
|
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import fsSync from "node:fs";
|
import fsSync from "node:fs";
|
||||||
import { config } from "./config.js";
|
import { config } from "./config.js";
|
||||||
@ -18,7 +14,7 @@ function escapeXml(text: string): string {
|
|||||||
.replace(/'/g, "'");
|
.replace(/'/g, "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
function createItemXml(episode: Episode): string {
|
function createItemXml(episode: any): string {
|
||||||
const fileUrl = `${config.podcast.baseUrl}/podcast_audio/${path.basename(episode.audioPath)}`;
|
const fileUrl = `${config.podcast.baseUrl}/podcast_audio/${path.basename(episode.audioPath)}`;
|
||||||
const pubDate = new Date(episode.createdAt).toUTCString();
|
const pubDate = new Date(episode.createdAt).toUTCString();
|
||||||
|
|
||||||
@ -35,10 +31,28 @@ function createItemXml(episode: Episode): string {
|
|||||||
console.warn(`Could not get file size for ${episode.audioPath}:`, error);
|
console.warn(`Could not get file size for ${episode.audioPath}:`, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build enhanced description with feed and article info
|
||||||
|
let description = episode.title;
|
||||||
|
if (episode.feedTitle || episode.articleTitle || episode.articleLink) {
|
||||||
|
description += "\n\n";
|
||||||
|
if (episode.feedTitle) {
|
||||||
|
description += `フィード: ${episode.feedTitle}\n`;
|
||||||
|
}
|
||||||
|
if (episode.articleTitle && episode.articleTitle !== episode.title) {
|
||||||
|
description += `元記事: ${episode.articleTitle}\n`;
|
||||||
|
}
|
||||||
|
if (episode.articlePubDate) {
|
||||||
|
description += `記事公開日: ${new Date(episode.articlePubDate).toLocaleString("ja-JP")}\n`;
|
||||||
|
}
|
||||||
|
if (episode.articleLink) {
|
||||||
|
description += `元記事URL: ${episode.articleLink}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<item>
|
<item>
|
||||||
<title><![CDATA[${escapeXml(episode.title)}]]></title>
|
<title><![CDATA[${escapeXml(episode.title)}]]></title>
|
||||||
<description><![CDATA[${escapeXml(episode.title)}]]></description>
|
<description><![CDATA[${escapeXml(description)}]]></description>
|
||||||
<author>${escapeXml(config.podcast.author)}</author>
|
<author>${escapeXml(config.podcast.author)}</author>
|
||||||
<category>${escapeXml(config.podcast.categories)}</category>
|
<category>${escapeXml(config.podcast.categories)}</category>
|
||||||
<language>${config.podcast.language}</language>
|
<language>${config.podcast.language}</language>
|
||||||
@ -46,15 +60,17 @@ function createItemXml(episode: Episode): string {
|
|||||||
<enclosure url="${escapeXml(fileUrl)}" length="${fileSize}" type="audio/mpeg" />
|
<enclosure url="${escapeXml(fileUrl)}" length="${fileSize}" type="audio/mpeg" />
|
||||||
<guid>${escapeXml(fileUrl)}</guid>
|
<guid>${escapeXml(fileUrl)}</guid>
|
||||||
<pubDate>${pubDate}</pubDate>
|
<pubDate>${pubDate}</pubDate>
|
||||||
|
${episode.articleLink ? `<link>${escapeXml(episode.articleLink)}</link>` : ""}
|
||||||
</item>`;
|
</item>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updatePodcastRSS(): Promise<void> {
|
export async function updatePodcastRSS(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const episodes: Episode[] = await fetchAllEpisodes();
|
// Use episodes with feed info for enhanced descriptions
|
||||||
|
const episodesWithFeedInfo = await fetchEpisodesWithFeedInfo();
|
||||||
|
|
||||||
// Filter episodes to only include those with valid audio files
|
// Filter episodes to only include those with valid audio files
|
||||||
const validEpisodes = episodes.filter((episode) => {
|
const validEpisodes = episodesWithFeedInfo.filter((episode) => {
|
||||||
try {
|
try {
|
||||||
const audioPath = path.join(
|
const audioPath = path.join(
|
||||||
config.paths.podcastAudioDir,
|
config.paths.podcastAudioDir,
|
||||||
@ -68,7 +84,7 @@ export async function updatePodcastRSS(): Promise<void> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`Found ${episodes.length} episodes, ${validEpisodes.length} with valid audio files`,
|
`Found ${episodesWithFeedInfo.length} episodes, ${validEpisodes.length} with valid audio files`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const lastBuildDate = new Date().toUTCString();
|
const lastBuildDate = new Date().toUTCString();
|
||||||
|
Reference in New Issue
Block a user