// functions/podcasts/[id].js const PODCASTINDEX_API_BASE = 'https://api.podcastindex.org/api/1.0'; const PODCAST_API_KEY = 'YU5HMSDYBQQVYDF6QN4P'; const PODCAST_API_SECRET = '8hCvpjSL7T$S7^5ftnf5MhqQwYUYVjM^fmUL3Ld$'; async function sha1(str) { const encoder = new TextEncoder(); const data = encoder.encode(str); const hashBuffer = await crypto.subtle.digest('SHA-1', data); const hashArray = Array.from(new Uint8Array(hashBuffer)); return hashArray.map((b) => b.toString(16).padStart(2, '0')).join(''); } async function getAuthHeaders() { const apiHeaderTime = Math.floor(Date.now() / 1000).toString(); const combined = PODCAST_API_KEY + PODCAST_API_SECRET + apiHeaderTime; const authHeader = await sha1(combined); return { 'User-Agent': 'MonochromeMusic/1.0', 'X-Auth-Key': PODCAST_API_KEY, 'X-Auth-Date': apiHeaderTime, Authorization: authHeader, }; } export async function onRequest(context) { const { request, params, env } = context; const userAgent = request.headers.get('User-Agent') || ''; const isBot = /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot|telegrambot|linkedinbot|mastodon|signal|snapchat|redditbot|skypeuripreview|viberbot|linebot|embedly|quora|outbrain|tumblr|duckduckbot|yandexbot|rogerbot|showyoubot|kakaotalk|naverbot|seznambot|mediapartners|adsbot|petalbot|applebot|ia_archiver/i.test( userAgent ); const podcastId = params.id; if (isBot && podcastId) { try { const headers = await getAuthHeaders(); const response = await fetch(`${PODCASTINDEX_API_BASE}/podcasts/byfeedid?id=${podcastId}&pretty`, { method: 'GET', headers, }); if (!response.ok) throw new Error(`PodcastIndex error: ${response.status}`); const data = await response.json(); const feed = data.status === 'true' && data.feed ? data.feed : null; if (feed && feed.title) { const title = feed.title; const author = feed.author || feed.ownerName || ''; const episodeCount = feed.episodeCount || 0; const rawDescription = feed.description || ''; const description = author ? `Podcast by ${author} • ${episodeCount} Episodes\nListen on Monochrome` : `Podcast • ${episodeCount} Episodes\nListen on Monochrome`; const imageUrl = feed.image || feed.artwork || 'https://monochrome.tf/assets/appicon.png'; const pageUrl = new URL(request.url).href; const metaHtml = `
${description}