mirror of
https://github.com/0belous/universal-plugin-repo.git
synced 2025-12-20 03:31:18 -03:00
159 lines
5 KiB
JavaScript
159 lines
5 KiB
JavaScript
const fs = require('fs/promises');
|
|
const path = require('path');
|
|
const crypto = require('crypto');
|
|
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) {
|
|
console.log(`Downloading image: ${url} as ${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';
|
|
}
|
|
|
|
function getPluginId(plugin) {
|
|
return plugin.id || plugin.Id || plugin.pluginId || plugin.name || null;
|
|
}
|
|
|
|
function hashString(str) {
|
|
return crypto.createHash('md5').update(str).digest('hex');
|
|
}
|
|
|
|
function findGithubUrl(obj) {
|
|
if (!obj) return null;
|
|
for (const key in obj) {
|
|
if (typeof obj[key] === 'string') {
|
|
const match = obj[key].match(/https?:\/\/github\.com\/[^\/]+\/[^\/]+/);
|
|
if (match) {
|
|
return match[0];
|
|
}
|
|
} else if (typeof obj[key] === 'object' && obj[key] !== null) {
|
|
const url = findGithubUrl(obj[key]);
|
|
if (url) return url;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
async function processDescriptions(pluginData) {
|
|
try {
|
|
for (const plugin of pluginData) {
|
|
const repoUrl = findGithubUrl(plugin);
|
|
if (repoUrl) {
|
|
const sourceLink = `\n\n[Source Code](${repoUrl})`;
|
|
const descriptionProp = ['description', 'Description', 'overview'].find(p => plugin[p]);
|
|
|
|
if (descriptionProp) {
|
|
if (!plugin[descriptionProp].includes(repoUrl)) {
|
|
plugin[descriptionProp] += sourceLink;
|
|
}
|
|
} else {
|
|
plugin.description = sourceLink.trim();
|
|
}
|
|
}
|
|
}
|
|
console.log(`Sucessfully injected source URLs`);
|
|
} catch (err) {
|
|
console.error('Error processing descriptions:', err);
|
|
}
|
|
}
|
|
|
|
async function processImages(pluginData) {
|
|
await clearImagesFolder();
|
|
for (const plugin of pluginData) {
|
|
if (plugin.imageUrl) {
|
|
const ext = getImageExtension(plugin.imageUrl);
|
|
let pluginId = getPluginId(plugin);
|
|
if (!pluginId) {
|
|
pluginId = hashString(plugin.imageUrl);
|
|
}
|
|
const filename = `${pluginId}${ext}`;
|
|
const success = await downloadImage(plugin.imageUrl, filename);
|
|
if (success) {
|
|
plugin.imageUrl = imageBaseUrl + filename;
|
|
console.log(` -> Updated manifest imageUrl for plugin ${pluginId}`);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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`);
|
|
console.log('Manifest updated with new image URLs.');
|
|
}
|
|
|
|
async function main() {
|
|
const plugins = await getSources();
|
|
await processDescriptions(plugins);
|
|
await processImages(plugins);
|
|
await writeManifest(plugins);
|
|
}
|
|
|
|
main();
|