// appMetadata.js import axios from "axios"; import * as cheerio from "cheerio"; import sizeOf from "image-size"; import sharp from "sharp"; export async function getAppMetadata(baseUrl) { console.log(baseUrl); try { const res = await axios.get(baseUrl, { timeout: 3000 }); const $ = cheerio.load(res.data); // ------------------------------- // 1. Nome più corto // ------------------------------- const nameCandidates = [ $('meta[property="og:site_name"]').attr("content"), $('meta[name="application-name"]').attr("content"), $('meta[property="og:title"]').attr("content"), $("title").text().trim() ].filter(Boolean); const name = nameCandidates.length > 0 ? nameCandidates.sort((a, b) => a.length - b.length)[0] : "no_name"; // ------------------------------- // 2. Icone HTML // ------------------------------- const htmlIcons = []; $("link[rel*='icon']").each((_, el) => { const href = $(el).attr("href"); const sizes = $(el).attr("sizes") || ""; if (href) htmlIcons.push({ href, sizes }); }); // ------------------------------- // 3. Manifest.json // ------------------------------- let manifestIcons = []; const manifestHref = $('link[rel="manifest"]').attr("href"); if (manifestHref) { try { const manifestUrl = new URL(manifestHref, baseUrl).href; const manifestRes = await axios.get(manifestUrl, { timeout: 3000 }); const manifest = manifestRes.data; if (manifest.icons && Array.isArray(manifest.icons)) { manifestIcons = manifest.icons.map(icon => ({ href: icon.src, sizes: icon.sizes || "" })); } } catch {} } // ------------------------------- // 4. Fallback 4 icone // ------------------------------- const fallbackPaths = [ "/favicon.ico", "/favicon.png", "/icon.png", "/apple-touch-icon.png" ]; const fallbackIcons = fallbackPaths.map(p => ({ href: p, sizes: "" })); // ------------------------------- // 5. Unisci tutte le icone // ------------------------------- const allIcons = [...htmlIcons, ...manifestIcons, ...fallbackIcons]; // ------------------------------- // 6. Determina dimensione reale (PNG, ICO, SVG) // ------------------------------- const iconsWithRealSize = []; for (const icon of allIcons) { try { const url = new URL(icon.href, baseUrl).href; const imgRes = await axios.get(url, { responseType: "arraybuffer" }); let width = 0; // ---- PNG / JPG / ICO ---- try { const dim = sizeOf(imgRes.data); if (dim.width) width = dim.width; } catch { // Non è un formato supportato da image-size } // ---- SVG → converti in PNG e misura ---- if (width === 0) { try { const pngBuffer = await sharp(imgRes.data).png().toBuffer(); const dim = sizeOf(pngBuffer); if (dim.width) width = dim.width; } catch { // SVG non convertibile → ignora } } if (width > 0) { iconsWithRealSize.push({ url, size: width }); } } catch { // icona non accessibile → ignora } } // ------------------------------- // 7. Scegli la più grande // ------------------------------- iconsWithRealSize.sort((a, b) => b.size - a.size); const icon = iconsWithRealSize.length > 0 ? iconsWithRealSize[0].url : null; return { name, icon }; } catch { return { name: "no_name", icon: null }; } }