// checkApps.js import fs from "fs"; import path from "path"; import * as cheerio from "cheerio"; import axios from "axios"; const appsFile = path.join(process.cwd(), "apps.json"); function getShortName($) { return ( $('meta[property="og:site_name"]').attr('content') || $('meta[name="application-name"]').attr('content') || $('meta[property="og:title"]').attr('content') || $("title").text().trim() || null ); } async function findBestIconAndName(baseUrl) { try { const res = await axios.get(baseUrl, { timeout: 2000 }); const $ = cheerio.load(res.data); //let appName = $("title").text().trim() || null; let appName = getShortName($) || null; const icons = []; $("link[rel*='icon']").each((_, el) => { const href = $(el).attr("href"); const sizes = $(el).attr("sizes") || ""; if (href) icons.push({ href, sizes }); }); icons.sort((a, b) => { const sizeA = parseInt(a.sizes.split("x")[0]) || 0; const sizeB = parseInt(b.sizes.split("x")[0]) || 0; return sizeB - sizeA; }); let chosenIcon; if (icons.length > 0) { chosenIcon = new URL(icons[0].href, baseUrl).href; } else { chosenIcon = "./default.png"; } // Se non c’è nome, metti "no_name" return { name: appName || "no_name", icon: chosenIcon }; } catch { return { name: "no_name", icon: "/icons/error.png" }; } } async function main() { const apps = JSON.parse(fs.readFileSync(appsFile, "utf-8")); for (const app of apps) { if (app.controllato) { console.log(`Skip ${app.name} (${app.host}:${app.port}) già controllato`); continue; } const baseUrl = `http://${app.host}:${app.port}`; console.log(`Controllo ${baseUrl}...`); const result = await findBestIconAndName(baseUrl); // Aggiorna nome (anche se "no_name") app.name = result.name; // Aggiorna icona app.icon = result.icon; // Flag di controllo app.controllato = true; } fs.writeFileSync(appsFile, JSON.stringify(apps, null, 2)); console.log("apps.json aggiornato ✅"); } main().catch((err) => { console.error("Errore:", err); process.exit(1); });