generated from Dicken/dickendock
round22: Startseite kompakter, Ping-Zeitstempel-Bug behoben, echte Favicon-Deduplizierung per Bildinhalt, automatischer Favicon-Abgleich aus Icon-Datenbank + Nachruest-Button
This commit is contained in:
@@ -79,3 +79,32 @@ export async function searchIconDb(query: string, limit = 24): Promise<IconSearc
|
||||
const matches = names.filter((n) => n.includes(q)).slice(0, limit);
|
||||
return matches.map((name) => ({ name, url: `${CDN_BASE}/${name}.png` }));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sucht den besten Treffer in der Icon-Datenbank für einen Dienst-/
|
||||
* Software-Namen ("Plex", "Pi-hole", "Adguard Home") - für den Fall, dass
|
||||
* der Scanner selbst kein Favicon gefunden hat (siehe networkScanner.ts).
|
||||
* Bewusst konservativ: nur ein Treffer, wenn der normalisierte Name exakt
|
||||
* (oder nach Entfernen von Bindestrichen) übereinstimmt - eine reine
|
||||
* Teilstring-Suche würde bei kurzen/generischen Namen zu viele falsche
|
||||
* Zuordnungen liefern (z. B. "nas" -> "nas4free" wäre noch plausibel, aber
|
||||
* "web" könnte alles Mögliche treffen).
|
||||
*/
|
||||
export async function findBestIconMatch(name: string): Promise<string | null> {
|
||||
const normalized = name
|
||||
.toLowerCase()
|
||||
.trim()
|
||||
.replace(/[^a-z0-9]+/g, "-")
|
||||
.replace(/^-+|-+$/g, "");
|
||||
if (normalized.length < 2) return null;
|
||||
|
||||
const names = await getIconNames();
|
||||
const nameSet = new Set(names);
|
||||
if (nameSet.has(normalized)) return `${CDN_BASE}/${normalized}.png`;
|
||||
|
||||
const collapsed = normalized.replace(/-/g, "");
|
||||
const exactCollapsed = names.find((n) => n.replace(/-/g, "") === collapsed);
|
||||
if (exactCollapsed) return `${CDN_BASE}/${exactCollapsed}.png`;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { resolveHostname, reverseLookup } from "./dns.js";
|
||||
import { isPortOpen, TYPICAL_PORTS } from "./ports.js";
|
||||
import { probeHttp } from "./http.js";
|
||||
import { detectSoftware } from "./softwareDetection.js";
|
||||
import { findBestIconMatch } from "./iconDb.js";
|
||||
|
||||
export interface ScanTarget {
|
||||
hostname: string;
|
||||
@@ -151,5 +152,23 @@ export async function scanDeviceServices(
|
||||
}
|
||||
}
|
||||
|
||||
// Bleibt danach IMMER NOCH kein Favicon übrig (kein bestätigtes eigenes,
|
||||
// kein Sibling), zuletzt versuchen, per erkanntem Software-/Anzeigenamen
|
||||
// ein passendes Icon aus der externen Icon-Datenbank zu finden (siehe
|
||||
// iconDb.ts). Nur bei eindeutigem Treffer - lieber gar kein Favicon als
|
||||
// ein falsch zugeordnetes.
|
||||
for (const service of found) {
|
||||
if (service.favicon) continue;
|
||||
const nameToMatch = service.category ? service.suggestedDisplayName : null;
|
||||
if (!nameToMatch) continue;
|
||||
try {
|
||||
const match = await findBestIconMatch(nameToMatch);
|
||||
if (match) service.favicon = match;
|
||||
} catch {
|
||||
// Icon-Datenbank nicht erreichbar (kein Internetzugang o. ä.) - der
|
||||
// Scan soll deswegen nicht fehlschlagen, einfach ohne Favicon weiter.
|
||||
}
|
||||
}
|
||||
|
||||
return { services: found, suggestedHostname };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user