generated from Dicken/dickendock
round31: Infrastruktur-Praefixe (lxc/vm/docker) aus Namen und Suche entfernt, Icon-Datenbank-Abgleich auch ohne erkannte Software, Sichtbarkeit bei eindeutigem Icon-Treffer
This commit is contained in:
@@ -172,6 +172,26 @@ export async function findBestIconMatch(name: string): Promise<string | null> {
|
||||
if (match) return `${CDN_BASE}/${match}.png`;
|
||||
}
|
||||
|
||||
// Letzter, bewusst noch immer präziser Versuch: ein Name wie "adguard"
|
||||
// trifft "adguard-home" nicht exakt (auch nicht nach Bindestrich-Vergleich),
|
||||
// ist aber ein eindeutiger Wortanfang-Treffer, wenn KEIN anderer Icon-Name
|
||||
// mit "<wort>-" beginnt. Nur dann automatisch übernehmen - bei mehreren
|
||||
// möglichen Treffern bleibt es bei "kein Favicon" (dafür gibt es die
|
||||
// interaktive Auswahl mit mehreren Kandidaten).
|
||||
for (const candidate of [wholeName, ...byPriority(words)]) {
|
||||
if (candidate.length < 3) continue;
|
||||
const prefixMatches = names.filter((n) => n === candidate || n.startsWith(`${candidate}-`));
|
||||
if (prefixMatches.length === 1) return `${CDN_BASE}/${prefixMatches[0]}.png`;
|
||||
if (prefixMatches.length > 1) {
|
||||
// Mehrere Treffer (z. B. "adguard-home" UND "adguard-home-sync" für
|
||||
// "adguard") - den kürzesten (meist der "Haupt"-Name der Software)
|
||||
// automatisch nehmen, aber NUR wenn er eindeutig der kürzeste ist,
|
||||
// sonst bleibt es zweideutig (dafür gibt es die interaktive Auswahl).
|
||||
const sorted = [...prefixMatches].sort((a, b) => a.length - b.length);
|
||||
if (sorted[0].length < sorted[1].length) return `${CDN_BASE}/${sorted[0]}.png`;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,12 +49,21 @@ function isIpAddress(value: string): boolean {
|
||||
* Liefert null, wenn der Hostname selbst keine brauchbare Information trägt
|
||||
* (leer oder reine IP) - dann bleibt nur der IP:Port-Fallback übrig.
|
||||
*/
|
||||
/**
|
||||
* Generische Infrastruktur-Präfixe/-Suffixe, die in Proxmox/Docker-Umfeld
|
||||
* üblich, aber inhaltlich bedeutungslos sind ("lxc-adguard" soll als
|
||||
* "Adguard" vorgeschlagen werden, nicht als "Lxc Adguard") - dieselbe Logik
|
||||
* wie die STOPWORDS in scanner/iconDb.ts, hier auf den Hostnamen angewendet.
|
||||
*/
|
||||
const GENERIC_INFRA_WORDS = new Set(["lxc", "vm", "ct", "docker", "container"]);
|
||||
|
||||
function humanizeHostname(hostname: string): string | null {
|
||||
if (!hostname || isIpAddress(hostname)) return null;
|
||||
const words = hostname
|
||||
.replace(/\.(home|local|fritz\.box)$/i, "")
|
||||
.split(/[-_.\s]+/)
|
||||
.filter(Boolean);
|
||||
.filter(Boolean)
|
||||
.filter((w) => !GENERIC_INFRA_WORDS.has(w.toLowerCase()));
|
||||
if (words.length === 0) return null;
|
||||
return words.map((w) => (w.length > 0 ? w[0].toUpperCase() + w.slice(1) : w)).join(" ");
|
||||
}
|
||||
@@ -227,11 +236,23 @@ export async function scanDeviceServices(
|
||||
// ein falsch zugeordnetes.
|
||||
for (const service of found) {
|
||||
if (service.favicon) continue;
|
||||
const nameToMatch = service.category ? service.suggestedDisplayName : null;
|
||||
if (!nameToMatch) continue;
|
||||
// Vorher: nur versucht, wenn Software erkannt wurde. Jetzt auch bei
|
||||
// einem aus dem Gerätenamen abgeleiteten Namen ("lxc-adguard" ->
|
||||
// "Adguard", siehe humanizeHostname) - blieb Softwareerkennung aus,
|
||||
// konnte trotzdem korrekt "adguard-home" gefunden werden. Nur der reine
|
||||
// IP:Port-Nietenwert (keine Information vorhanden) wird übersprungen.
|
||||
const isBareAddressFallback = /^[\d.:]+$/.test(service.suggestedDisplayName);
|
||||
if (isBareAddressFallback) continue;
|
||||
try {
|
||||
const match = await findBestIconMatch(nameToMatch);
|
||||
if (match) service.favicon = match;
|
||||
const match = await findBestIconMatch(service.suggestedDisplayName);
|
||||
if (match) {
|
||||
service.favicon = match;
|
||||
// Ein eindeutiger Icon-Datenbank-Treffer ist selbst ein starkes
|
||||
// Erkennungssignal - auch wenn Titel/Software-Erkennung nichts
|
||||
// Brauchbares geliefert haben (z. B. bei einer reinen
|
||||
// Client-seitig-gerenderten Login-Seite ohne Server-Titel).
|
||||
service.visible = true;
|
||||
}
|
||||
} catch {
|
||||
// Icon-Datenbank nicht erreichbar (kein Internetzugang o. ä.) - der
|
||||
// Scan soll deswegen nicht fehlschlagen, einfach ohne Favicon weiter.
|
||||
|
||||
@@ -60,7 +60,11 @@ export const SOFTWARE_SIGNATURES: SoftwareSignature[] = [
|
||||
{ name: "Jellyfin", category: "Medien", matches: (i) => bodyContains(i, /jellyfin/i) },
|
||||
{ name: "Nextcloud", category: "Cloud", matches: (i) => bodyContains(i, /nextcloud/i) },
|
||||
{ name: "Pi-hole", category: "DNS", matches: (i) => bodyContains(i, /pi-?hole/i) },
|
||||
{ name: "AdGuard Home", category: "DNS", matches: (i) => bodyContains(i, /adguard/i) },
|
||||
{
|
||||
name: "AdGuard Home",
|
||||
category: "DNS",
|
||||
matches: (i) => bodyContains(i, /adguard/i) || titleMatches(i, /adguard/i),
|
||||
},
|
||||
{ name: "UniFi Network", category: "Netzwerk", matches: (i) => bodyContains(i, /unifi/i) },
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user