import { writeFileSync, statSync, mkdirSync } from 'node:fs'; import { execFileSync } from 'node:child_process'; import { join, dirname, basename } from 'node:path'; import { fileURLToPath } from 'node:url'; const FEED_URL = 'https://kute.o-k-i.net/@annu_kute_cedric/feed'; const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..'); const EPISODES_DIR = join(ROOT, 'static', 'images', 'episodes'); const CHANNEL_COVER = join(ROOT, 'static', 'images', 'podcast-cover.webp'); mkdirSync(EPISODES_DIR, { recursive: true }); const xml = await (await fetch(FEED_URL)).text(); const urls = new Set(); const channel = xml.split(']*href="([^"]+)"/i) ?? channel.match(/([^<]+)<\/url>/i); if (channelMatch) urls.add(channelMatch[1]); for (const item of xml.split(/]/i).slice(1)) { const match = item.match(/]*href="([^"]+)"/i); if (match) urls.add(match[1]); } let total = 0; for (const url of urls) { const isChannel = url === channelMatch?.[1]; const out = isChannel ? CHANNEL_COVER : join(EPISODES_DIR, basename(url).replace(/\.(png|jpe?g|gif|webp)$/i, '.webp')); try { const res = await fetch(url); if (!res.ok) { console.warn(`[covers] HTTP ${res.status} pour ${url}`); continue; } const source = Buffer.from(await res.arrayBuffer()); const tmp = `/tmp/opencode/cover-${Date.now()}`; writeFileSync(tmp, source); execFileSync('convert', [tmp, '-resize', '512x512>', '-quality', '82', '-define', 'webp:method=6', out]); const size = statSync(out).size; total += size; console.log(`[covers] ${basename(out)} : ${Math.round(source.length / 1024)} Ko → ${Math.round(size / 1024)} Ko`); } catch (err) { console.warn(`[covers] échec pour ${url}:`, err.message); } } console.log(`[covers] total optimisé : ${Math.round(total / 1024)} Ko`);