adminslog/tools/collector/link_collector.py

165 lines
5.9 KiB
Python
Raw Normal View History

2025-06-27 12:58:02 +02:00
#!/usr/bin/env python3
import os
import sys
import json
from pathlib import Path
# Gibt das Verzeichnis zurück, in dem dieses Skript liegt
def script_dir():
return Path(__file__).parent.resolve()
# Lädt die JSONC-Konfiguration (Kommentare via // werden ignoriert)
def load_config(filename="config.jsonc"):
config_path = script_dir() / filename
if not config_path.exists():
print(" ⚠ Konfigurationsdatei nicht gefunden:", config_path)
sys.exit(1)
with open(config_path, encoding="utf-8") as f:
# Entfernt //-Kommentare vor dem Parsen
return json.loads("".join(line for line in f if not line.strip().startswith("//")))
# Parsen der Kommandozeilenargumente
def parse_args():
args = sys.argv[1:]
parsed = {
"scan": None, # Verzeichnisse zum Scannen (List[str])
"ignore": [], # Verzeichnisse, die ignoriert werden sollen (List[str])
"reset": False, # Setzt das Logfile zurück
"hilfe": False, # Zeigt die Hilfe an
}
# Argumente durchgehen und zuweisen
while args:
arg = args.pop(0)
if arg in ("-h", "--hilfe"):
parsed["hilfe"] = True
elif arg == "--reset":
parsed["reset"] = True
elif arg in ("-s", "--scan") and args:
parsed["scan"] = [entry.strip() for entry in args.pop(0).split(",") if entry.strip()]
elif arg in ("-x", "--ignore") and args:
parsed["ignore"] = [entry.strip() for entry in args.pop(0).split(",") if entry.strip()]
else:
print(f" ⚠ Unbekannter Parameter: {arg}")
parsed["hilfe"] = True
break
return parsed
# Ausgabe der Hilfetexte für CLI-Nutzer
def show_help():
print("""
(C) 2025 - Adam Skotarczak (ionivation.com)
🛈 Tool das Verzeichnisse nach Markdown-Dateien durchsucht und diese an eine definierte Liste anhängt als Markdown-Link.
Verwendung: python3 link_collector.py [OPTIONEN]
-s, --scan Kommagetrennte Liste von Verzeichnissen zum Durchsuchen (relativ zum Aufrufpfad)
-x, --ignore Kommagetrennte Liste von Verzeichnissen, die ignoriert werden sollen
--reset Löscht das Logfile 'processed.log' und beendet sich
-h, --hilfe Zeigt diese Hilfe
Beispiel:
python3 link_collector.py -s docs,notes -x "docs/alt"
""")
# Generator: Findet Markdown-Dateien (rekursiv), ignoriert dabei definierte Pfade
def find_md_files(root_dirs, ignore_dirs, extensions):
for root in root_dirs:
for dirpath, _, filenames in os.walk(root):
# Ignorierpfade überspringen
if any(str(Path(dirpath)).startswith(str(ignored)) for ignored in ignore_dirs):
continue
for fname in filenames:
if any(fname.endswith(ext) for ext in extensions):
yield Path(dirpath) / fname
# Extrahiert den ersten Markdown-Titel (# ...) als Linktext
def extract_title(filepath):
try:
with open(filepath, encoding="utf-8") as f:
for line in f:
if line.strip().startswith("#"):
return line.strip("# ").strip()
except Exception as e:
print(f"⚠ Fehler beim Lesen von {filepath}: {e}")
# Fallback: Dateiname ohne Endung
return filepath.stem
# Liest bereits verarbeitete Dateien aus dem Log (Pfadangaben im POSIX-Format)
def load_processed(logfile):
if not logfile.exists():
return set()
with open(logfile, encoding="utf-8") as f:
# Vereinheitlichung auf POSIX-Konvention
return set(Path(line.strip()).as_posix() for line in f)
# Hängt neue Markdown-Links ans Output-Dokument an
def append_to_output(output_path, links):
with open(output_path, "a", encoding="utf-8") as f:
for line in links:
f.write(line + "\n")
# Ergänzt das Logfile um neu verarbeitete Dateien (POSIX-Format)
def update_processed(log_path, new_paths):
with open(log_path, "a", encoding="utf-8") as f:
for path in new_paths:
f.write(path.as_posix() + "\n")
# Hauptfunktion mit gesamtem Ablauf
def main():
config = load_config()
args = parse_args()
if args["hilfe"]:
show_help()
return
log_path = script_dir() / config.get("processed_log", "processed.log")
# Optionaler Reset des Logs
if args["reset"]:
if log_path.exists():
log_path.unlink()
print("🧹 Logfile gelöscht:", log_path)
else:
print(" Logfile existierte nicht:", log_path)
return
cwd = Path.cwd()
output_file = cwd / config.get("output_file", "output.md")
# Verzeichnisse aus CLI oder Konfiguration
root_dirs = args["scan"] or config.get("root_dirs", [])
root_dirs = [Path(d).resolve() for d in root_dirs if d.strip()]
ignore_dirs = [Path(x).resolve() for x in args["ignore"]]
extensions = config.get("extensions", [".md"])
processed = load_processed(log_path)
new_links = []
new_processed = []
# Dateien durchsuchen und neue Markdown-Dateien verlinken
for md_file in find_md_files(root_dirs, ignore_dirs, extensions):
if md_file.resolve() == output_file.resolve():
continue # nicht sich selbst verlinken
rel_path = md_file.relative_to(cwd)
rel_path_posix = rel_path.as_posix()
if rel_path_posix in processed:
continue # bereits im Logfile
title = extract_title(md_file)
new_links.append(f"- [{title}]({rel_path_posix})")
new_processed.append(rel_path)
# Ergebnisse schreiben
if new_links:
append_to_output(output_file, new_links)
update_processed(log_path, new_processed)
print(f"{len(new_links)} neue Links hinzugefügt.")
else:
print(" Keine neuen Dateien gefunden.")
if __name__ == "__main__":
main()