diff --git a/scanner/__main__.py b/scanner/__main__.py index 39c4277..071d5a0 100644 --- a/scanner/__main__.py +++ b/scanner/__main__.py @@ -1061,8 +1061,83 @@ def cmd_approve(args: argparse.Namespace, cfg: dict) -> int: return 1 +def _print_diff_only(report: dict) -> None: + """Print a compact colored diff view of the latest report.""" + a = report.get("assessment", {}) + d = report.get("diff", {}) + level = a.get("level", "green") + symbol, _ = ampel(level) + use_color = sys.stdout.isatty() + + if use_color: + C = {"add": "\033[32m", "del": "\033[31m", "hdr": "\033[36m", + "url": "\033[1;34m", "rst": "\033[0m"} + else: + C = {k: "" for k in ("add", "del", "hdr", "url", "rst")} + + print(f"{symbol} Level: {level.upper()} Score: {a.get('score', 0)}") + print() + + for domain in d.get("new_external_domains", []): + print(f"{C['del']}+ Neue externe Domain: {domain}{C['rst']}") + for url in d.get("new_internal_urls", []): + print(f"{C['add']}+ Neue URL: {url}{C['rst']}") + for url in d.get("missing_internal_urls", []): + print(f"{C['del']}- Fehlende URL: {url}{C['rst']}") + for entry in d.get("new_broken_urls", []): + print(f"{C['del']}! Neuer kaputt Link [{entry['status']}]: {entry['url']}{C['rst']}") + + has_page_diffs = False + for pd in d.get("page_diffs", []): + text_diff = pd.get("text_diff", []) + link_diff = pd.get("link_diff", {}) + new_hidden = pd.get("new_hidden_content", []) + new_refresh = pd.get("new_meta_refresh", []) + new_scripts = pd.get("new_inline_scripts", []) + new_comments = pd.get("new_comment_links", []) + if not (text_diff or link_diff or new_hidden or new_refresh + or new_scripts or new_comments or pd.get("canonical_changed")): + continue + has_page_diffs = True + print(f"\n{C['url']}{'─' * 4} {pd['url']} {'─' * 4}{C['rst']}") + for line in text_diff: + if line.startswith("+"): + print(f"{C['add']}{line}{C['rst']}") + elif line.startswith("-"): + print(f"{C['del']}{line}{C['rst']}") + elif line.startswith("@"): + print(f"{C['hdr']}{line}{C['rst']}") + else: + print(line) + for ltype, ld in link_diff.items(): + for added in ld.get("added", []): + print(f"{C['add']}+ [{ltype}] {added}{C['rst']}") + for removed in ld.get("removed", []): + print(f"{C['del']}- [{ltype}] {removed}{C['rst']}") + for h in new_hidden: + print(f"{C['del']}! Hidden Content ({h.get('type')}): " + f"{', '.join(h.get('indicators', []))}{C['rst']}") + for mr in new_refresh: + print(f"{C['del']}! Meta-Refresh → {mr}{C['rst']}") + if pd.get("canonical_changed"): + print(f"{C['del']}! Canonical: {pd.get('old_canonical')} → {pd.get('new_canonical')}{C['rst']}") + for s in new_scripts: + print(f"{C['del']}! Inline-Script: {', '.join(s.get('patterns', []))}{C['rst']}") + for cl in new_comments: + print(f"{C['del']}! Kommentar-Link: {cl}{C['rst']}") + + nothing = ( + not d.get("new_external_domains") + and not d.get("new_internal_urls") + and not d.get("missing_internal_urls") + and not d.get("new_broken_urls") + and not has_page_diffs + ) + if nothing: + print("Keine Änderungen.") + + def cmd_report(args: argparse.Namespace, cfg: dict) -> int: - fmt = getattr(args, "format", "md") rd = Path(cfg["reports_dir"]) if not rd.exists(): print("Noch keine Reports vorhanden.") @@ -1074,11 +1149,17 @@ def cmd_report(args: argparse.Namespace, cfg: dict) -> int: return 0 latest = dirs[-1] - if fmt == "json": - p = latest / "report.json" - else: - p = latest / "report.md" + if getattr(args, "diff_only", False): + p = latest / "report.json" + if not p.exists(): + print(f"Report-Datei nicht gefunden: {p}", file=sys.stderr) + return 1 + _print_diff_only(json.loads(p.read_text(encoding="utf-8"))) + return 0 + + fmt = getattr(args, "format", "md") + p = latest / ("report.json" if fmt == "json" else "report.md") if not p.exists(): print(f"Report-Datei nicht gefunden: {p}", file=sys.stderr) return 1 @@ -1379,6 +1460,8 @@ def _build_parser() -> argparse.ArgumentParser: rp = sub.add_parser("report", help="Letzten Report anzeigen") rp.add_argument("--format", choices=["md", "json"], default="md") + rp.add_argument("--diff-only", action="store_true", + help="Nur Textdiffs geänderter Seiten anzeigen (farbig)") sub.add_parser("status", help="Übersichtsstatus anzeigen")