import { promises as fs } from "fs"; import { join, dirname } from "path"; import { Episode, fetchAllEpisodes } from "./database"; import path from "node:path"; import fsSync from "node:fs"; export async function updatePodcastRSS() { const episodes: Episode[] = await fetchAllEpisodes(); const channelTitle = import.meta.env["PODCAST_TITLE"] ?? "自動生成ポッドキャスト"; const channelLink = import.meta.env["PODCAST_LINK"] ?? "https://your-domain.com/podcast"; const channelDescription = import.meta.env["PODCAST_DESCRIPTION"] ?? "RSSフィードから自動生成された音声ポッドキャスト"; const channelLanguage = import.meta.env["PODCAST_LANGUAGE"] ?? "ja"; const channelAuthor = import.meta.env["PODCAST_AUTHOR"] ?? "管理者"; const channelCategories = import.meta.env["PODCAST_CATEGORIES"] ?? "Technology"; const channelTTL = import.meta.env["PODCAST_TTL"] ?? "60"; const lastBuildDate = new Date().toUTCString(); const baseUrl = import.meta.env["PODCAST_BASE_URL"] ?? "https://your-domain.com"; let itemsXml = ""; for (const ep of episodes) { const fileUrl = `${baseUrl}/podcast_audio/${path.basename(ep.audioPath)}`; const pubDate = new Date(ep.pubDate).toUTCString(); const fileSize = fsSync.statSync( path.join(import.meta.dir, "..", "public/podcast_audio", ep.audioPath), ).size; itemsXml += ` <![CDATA[${ep.title}]]> /g, "]]>").replace(/&/g, "&")}]]> ${channelAuthor} ${channelCategories} ${channelLanguage} ${channelTTL} ${fileUrl} ${pubDate} `; } const outputPath = join(__dirname, "../public/podcast.xml"); // 既存のRSSファイルの読み込み let existingXml = ""; try { existingXml = await fs.readFile(outputPath, "utf-8"); } catch (err) { // ファイルが存在しない場合は新規作成 console.log("既存のpodcast.xmlが見つかりません。新規作成します。"); } if (existingXml) { // 既存のitem部分を抽出 const existingItemsMatch = existingXml.match( /([\s\S]*?)<\/channel>/, ); if (existingItemsMatch) { const existingItems = existingItemsMatch[1]; const newItemStartIndex = existingItems!.lastIndexOf(""); // 新しいitemを追加 const updatedItems = existingItems + itemsXml; // lastBuildDateを更新 const updatedXml = existingXml.replace( /.*?<\/lastBuildDate>/, `${lastBuildDate}`, ); // items部分を置き換え const finalXml = updatedXml.replace( /[\s\S]*?<\/channel>/, `${updatedItems}`, ); // ファイルに書き込み await fs.writeFile(outputPath, finalXml.trim()); } else { // 不正なフォーマットの場合は新規作成 const rssXml = ` ${channelTitle} ${channelLink} ${channelDescription}]]> ${lastBuildDate} ${itemsXml} `; await fs.writeFile(outputPath, rssXml.trim()); } } else { // 新規作成 const rssXml = ` ${channelTitle} ${channelLink} ${lastBuildDate} ${itemsXml} `; // Ensure directory exists await fs.mkdir(dirname(outputPath), { recursive: true }); await fs.writeFile(outputPath, rssXml.trim()); } }