myapps_remote_server_ui_app.../server/backend/routes/metadata.js
2026-01-05 22:50:31 +01:00

104 lines
2.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import express from "express";
import axios from "axios";
import * as cheerio from "cheerio";
import { URL } from "url";
const router = express.Router();
// Normalizza URL relativi → assoluti
function normalize(base, relative) {
try {
return new URL(relative, base).href;
} catch {
return null;
}
}
// Scarica HTML con fallback CORS
async function fetchHTML(url) {
try {
const res = await axios.get(url, {
timeout: 8000,
headers: {
"User-Agent": "Mozilla/5.0"
}
});
return res.data;
} catch (err) {
return null;
}
}
router.get("/", async (req, res) => {
const siteUrl = req.query.url;
if (!siteUrl) return res.json({ error: "Missing URL" });
const html = await fetchHTML(siteUrl);
if (!html) return res.json({ name: null, icon: null });
const $ = cheerio.load(html);
// -----------------------------------------
// 1. Trova il nome più corto
// -----------------------------------------
let names = [];
const title = $("title").text().trim();
if (title) names.push(title);
$('meta[name="application-name"]').each((i, el) => {
const v = $(el).attr("content");
if (v) names.push(v.trim());
});
$('meta[property="og:site_name"]').each((i, el) => {
const v = $(el).attr("content");
if (v) names.push(v.trim());
});
const shortestName = names.length
? names.sort((a, b) => a.length - b.length)[0]
: null;
// -----------------------------------------
// 2. Trova licona più grande
// -----------------------------------------
let icons = [];
$('link[rel="icon"], link[rel="shortcut icon"], link[rel="apple-touch-icon"], link[rel="apple-touch-icon-precomposed"]').each((i, el) => {
const href = $(el).attr("href");
if (!href) return;
const sizeAttr = $(el).attr("sizes");
let size = 0;
if (sizeAttr && sizeAttr.includes("x")) {
const parts = sizeAttr.split("x");
size = parseInt(parts[0]) || 0;
}
icons.push({
url: normalize(siteUrl, href),
size
});
});
// fallback favicon
icons.push({
url: normalize(siteUrl, "/favicon.ico"),
size: 16
});
// Ordina per dimensione
icons = icons.filter(i => i.url);
icons.sort((a, b) => b.size - a.size);
const bestIcon = icons.length ? icons[0].url : null;
res.json({
name: shortestName,
icon: bestIcon
});
});
export default router;