Web-Quellen: An/Aus-Schalter pro Quelle im UI + Einzel-Quellen-Sync

This commit is contained in:
Flo Hartmann
2026-08-25 01:10:36 +00:00
parent 8b38bc6c89
commit 667196a4ba
5 changed files with 176 additions and 14 deletions

View File

@@ -124,12 +124,23 @@ class WebQuellenSyncService:
# ---------- Gesamtdurchlauf ----------
def laufe(self) -> list[QuellenLaufZeile]:
def laufe(self, nur_quellen: set[str] | None = None) -> list[QuellenLaufZeile]:
"""Führt den Web-Quellen-Sync aus.
`nur_quellen`: optionaler Filter — nur diese Quellnamen laufen
(manueller Einzel-Quellen-Sync aus dem UI). Der An/Aus-Schalter
der Quelle wird dabei ignoriert, ein explizit angeforderter
Einzellauf läuft immer.
"""
zeilen: list[QuellenLaufZeile] = []
ki = self._ki_hilfe()
for klasse in self.adapter_klassen:
if nur_quellen is not None and klasse.name not in nur_quellen:
continue
try:
zeile = self._eine_quelle(klasse, ki)
zeile = self._eine_quelle(
klasse, ki, einzellauf=nur_quellen is not None
)
except Exception as exc: # letzte Verteidigungslinie pro Quelle
_logger.exception("Quellen-Sync fehlgeschlagen für %s", klasse.name)
zeile = QuellenLaufZeile(
@@ -142,6 +153,32 @@ class WebQuellenSyncService:
zeilen.append(zeile)
return zeilen
def schalter_gesetzt(self, name: str, wert: bool) -> None:
"""Setzt den UI-An/Aus-Schalter einer Quelle (persistiert).
Der Schalter übersteuert den Env-Standard; der Hintergrund-Sync
überspringt ausgeschaltete Quellen.
"""
with self.session_factory() as db:
eintrag = db.scalar(
select(QuellenStatus).where(QuellenStatus.quelle == name)
)
if eintrag is None:
eintrag = QuellenStatus(quelle=name, url="")
db.add(eintrag)
eintrag.aktiv_schalter = wert
db.commit()
def quelle_laeuft(self, name: str) -> bool:
"""Effektiver Aktiv-Status einer Quelle (Schalter übersteuert Env)."""
with self.session_factory() as db:
eintrag = db.scalar(
select(QuellenStatus).where(QuellenStatus.quelle == name)
)
if eintrag is not None and eintrag.aktiv_schalter is not None:
return eintrag.aktiv_schalter
return quelle_aktiv(name, self.umgebung)
def gesamt_text(self, zeilen: list[QuellenLaufZeile]) -> str:
"""Kompakte deutschsprachige Zusammenfassung für Banner/Protokoll."""
teile = [zeile.als_text() for zeile in zeilen]
@@ -169,11 +206,15 @@ class WebQuellenSyncService:
return None
def _eine_quelle(
self, klasse: type[QuellenAdapter], ki: KiHilfe | None = None
self,
klasse: type[QuellenAdapter],
ki: KiHilfe | None = None,
einzellauf: bool = False,
) -> QuellenLaufZeile:
zeile = QuellenLaufZeile(klasse.name, klasse.anzeigename)
zeile.url = klasse.start_urls[0] if klasse.start_urls else None
if not quelle_aktiv(klasse.name, self.umgebung):
# Einzellauf (nur_quellen) läuft immer; sonst entscheidet der Schalter.
if not einzellauf and not self.quelle_laeuft(klasse.name):
zeile.aktiv = False
return zeile