const fs = require('fs/promises'); const path = require('path'); const userAgent = "Jellyfin-Server/10.10.7"; // Required for some repositories const imagesDir = path.join(__dirname, 'images'); const imageBaseUrl = 'https://raw.githubusercontent.com/0belous/universal-plugin-repo/refs/heads/main/images/'; async function getSources(){ let sources = []; try { const fileContent = await fs.readFile('sources.txt', 'utf8'); sources = fileContent.split(/\r?\n/).filter(line => line.trim() !== ''); } catch (err) { console.error("Error reading sources.txt:", err); return []; } let mergedData = []; for(const url of sources){ try { console.log(`Fetching ${url}...`); const response = await fetch(url, { headers: { 'User-Agent': userAgent } }); if (!response.ok) { throw new Error(`Response status: ${response.status}`); } const json = await response.json(); mergedData.push(...json); console.log(` -> Merged ${json.length} plugins.`); } catch (error) { console.error(`Error processing ${url}: ${error.message}`); } } return mergedData; } async function clearImagesFolder() { try { await fs.rm(imagesDir, { recursive: true, force: true }); await fs.mkdir(imagesDir, { recursive: true }); } catch (err) { console.error('Error clearing images folder:', err); } } async function downloadImage(url, filename) { try { const res = await fetch(url, { headers: { 'User-Agent': userAgent } }); if (!res.ok) throw new Error(`Failed to fetch image: ${res.status}`); const buffer = await res.arrayBuffer(); await fs.writeFile(path.join(imagesDir, filename), Buffer.from(buffer)); return true; } catch (err) { console.error(`Error downloading image ${url}:`, err.message); return false; } } function getImageExtension(url) { const ext = path.extname(new URL(url).pathname); return ext || '.png'; } async function processImages(pluginData) { await clearImagesFolder(); for (const plugin of pluginData) { if (plugin.imageUrl) { const ext = getImageExtension(plugin.imageUrl); const filename = `${plugin.id}${ext}`; const success = await downloadImage(plugin.imageUrl, filename); if (success) { plugin.imageUrl = imageBaseUrl + filename; } } } } async function writeManifest(dataToWrite){ if (!dataToWrite || dataToWrite.length === 0) { console.log("No data to write to manifest. Aborting."); return; } try { const manifestJson = JSON.stringify(dataToWrite, null, 2); await fs.writeFile('manifest.json', manifestJson); } catch (err) { console.error('Error writing manifest file:', err); } console.log(`\nSuccessfully created manifest.json with ${dataToWrite.length} total plugins`); } async function main() { const plugins = await getSources(); await processImages(plugins); await writeManifest(plugins); } main();