import express from 'express'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { XMLParser } from 'fast-xml-parser'; const RSS_URL = 'https://anchor.fm/s/11068d290/podcast/rss'; const PORT = Number(process.env.PORT || 5181); const isProd = process.env.NODE_ENV === 'production'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const parser = new XMLParser({ ignoreAttributes: false, trimValues: true }); function toArray(value) { if (!value) return []; return Array.isArray(value) ? value : [value]; } function cleanText(input) { if (!input) return ''; return String(input) .replace(/<[^>]*>/g, ' ') .replace(/\s+/g, ' ') .trim(); } function normalizeItem(item, index) { const title = cleanText(item.title) || `Episode ${index + 1}`; const summary = cleanText(item['content:encoded'] || item.description) || 'New episode now available.'; const link = item.link || item.guid || RSS_URL; const date = item.pubDate ? new Date(item.pubDate) : null; const publishedAt = date && !Number.isNaN(date.getTime()) ? date.toISOString() : null; return { id: cleanText(item.guid) || link, title, summary, scripture: '', reflectionPrompt: '', prayerFocus: '', challenge: '', link, publishedAt }; } async function readFeedEpisodes() { const response = await fetch(RSS_URL, { headers: { 'User-Agent': 'Siteforge-Companion/1.0' } }); if (!response.ok) { throw new Error(`RSS request failed with ${response.status}`); } const xml = await response.text(); const parsed = parser.parse(xml); const items = toArray(parsed?.rss?.channel?.item); return items.map(normalizeItem).slice(0, 24); } const app = express(); app.get('/api/episodes', async (_req, res) => { try { const episodes = await readFeedEpisodes(); res.json({ source: 'rss', rssUrl: RSS_URL, updatedAt: new Date().toISOString(), episodes }); } catch (error) { res.status(502).json({ source: 'rss', rssUrl: RSS_URL, error: error instanceof Error ? error.message : 'Unable to load RSS feed', episodes: [] }); } }); if (isProd) { const distDir = path.resolve(__dirname, 'dist'); app.use(express.static(distDir)); app.get('*', (_req, res) => { res.sendFile(path.join(distDir, 'index.html')); }); } app.listen(PORT, () => { const mode = isProd ? 'production' : 'development'; console.log(`Companion API listening on http://localhost:${PORT} (${mode})`); });