revert(watchdog): usuniecie integracji ze Slackiem

Na zyczenie uzytkownika. Alerty zostaja wylacznie w Sentry - z eskalacja poziomu i
kubelkami wieku w fingerprincie z poprzedniego commita, wiec sama poprawa
powiadamiania zostaje nienaruszona.

Usuniete: app/notify/ (caly pakiet), job watchdog-digest, parametr to_slack w
run_ingest_freshness_watchdog oraz klucze konfiguracji sched_watchdog_digest_hours,
slack_bot_token i slack_channel. Zadna wartosc SLACK nigdy nie trafila do .env ani do
compose, wiec nic nie bylo wysylane.

Po usunieciu watchdog dalej sprawdza 41 zrodel (sceny + filmy), scheduler rejestruje
juz tylko ingest-watchdog.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
goon-foss 2026-08-03 15:12:17 +02:00
parent 6e056b81c2
commit 6199577ae7
6 changed files with 2 additions and 110 deletions

View file

@ -129,14 +129,6 @@ class Settings(BaseSettings):
ingest_watchdog_movie_max_age_hours: int = Field(
default=72, validation_alias="GOON_INGEST_WATCHDOG_MOVIE_MAX_AGE_HOURS"
)
# Dobowy digest zamrożonych źródeł na Slacka. Sentry dostaje alert co 6h, ale
# tam sygnał ginął (patrz docstring ingest_watchdog). 0 = off.
sched_watchdog_digest_hours: int = Field(
default=24, validation_alias="GOON_SCHED_WATCHDOG_DIGEST_HOURS"
)
# Slack — bez OBU wartości powiadomienia są no-opem. Kanału nie zgadujemy.
slack_bot_token: str = Field(default="", validation_alias="GOON_SLACK_BOT_TOKEN")
slack_channel: str = Field(default="", validation_alias="GOON_SLACK_CHANNEL")
# Śmieciowi performerzy — kategorie i studia podszywające się pod osoby („Creampie",
# „Natural tits", „Brazzers"). Audyt 2026-07-27: 277 rekordów, 33 784 przypisania.
# Odrastają, bo tube-search dokleja performera po jednym tokenie. 24h. 0 = off.

View file

@ -1 +0,0 @@
"""Powiadomienia wychodzace (Slack)."""

View file

@ -1,50 +0,0 @@
"""Wysyłka powiadomień na Slacka — kanał, który człowiek realnie czyta.
Powód powstania (2026-08-03): watchdog świeżości poprawnie wykrywał zamrożone źródła
(vjav stał 12 dni, streamporn.vip 23), ale sygnał ginął. Szedł wyłącznie do Sentry ze
stabilnym fingerprintem i poziomem `warning`, więc powstawało JEDNO issue przy
pierwszym wystąpieniu i potem tylko rósł mu licznik Sentry powiadamia o nowych
i regresjach, nie o kolejnych wystąpieniach otwartego issue.
Domyślnie WYŁĄCZONE: bez `GOON_SLACK_BOT_TOKEN` i `GOON_SLACK_CHANNEL` funkcja jest
no-opem i nic nie próbuje wysyłać. Nie zgadujemy kanału.
"""
from __future__ import annotations
import logging
import httpx
from app.config import get_settings
log = logging.getLogger(__name__)
_API = "https://slack.com/api/chat.postMessage"
def send_slack(text: str, *, timeout: float = 15.0) -> bool:
"""Wyślij wiadomość na skonfigurowany kanał. Zwraca True gdy poszła.
Cicho zwraca False gdy brak konfiguracji to normalny stan, nie błąd.
"""
settings = get_settings()
token = getattr(settings, "slack_bot_token", "") or ""
channel = getattr(settings, "slack_channel", "") or ""
if not token or not channel:
return False
try:
r = httpx.post(
_API,
headers={"Authorization": f"Bearer {token}"},
json={"channel": channel, "text": text},
timeout=timeout,
)
data = r.json()
if not data.get("ok"):
# Slack zwraca 200 nawet przy błędzie logicznym — sprawdzamy `ok`.
log.warning("slack: wysyłka odrzucona: %s", data.get("error"))
return False
return True
except Exception as e:
log.warning("slack: wysyłka nieudana: %s", e)
return False

View file

@ -66,15 +66,14 @@ def run_ingest_freshness_watchdog(
movie_max_age_hours: int = 72,
min_history: int = 100,
to_sentry: bool = True,
to_slack: bool = False,
) -> dict[str, Any]:
"""Sprawdź każde aktywne źródło: czy dostało nową treść < próg dla swojej klasy.
`min_history` odsiewa świeżo dodane źródła bez ustalonej kadencji (za mało pozycji,
by wiedzieć, czy cisza to anomalia).
`to_sentry` / `to_slack` sterują kanałami job co 6h woła Sentry, a osobny job
dobowy woła Slacka, żeby nie wysyłać tej samej listy cztery razy dziennie.
`to_sentry=False` daje sam odczyt (przydatne do ręcznego sprawdzenia bez
zaśmiecania issue).
"""
from app.connectors import get_movie_connectors # noqa: PLC0415
from app.connectors.direct_scrapers import ( # noqa: PLC0415
@ -169,16 +168,4 @@ def run_ingest_freshness_watchdog(
except Exception: # pragma: no cover - Sentry off / brak DSN
log.exception("ingest-watchdog: Sentry capture failed")
if to_slack:
from app.notify.slack import send_slack # noqa: PLC0415
lines = [f"*Zamrożone źródła ingestu* ({len(stale)}/{len(checks)})"]
for x in stale:
days = x["age_hours"] / 24.0
lines.append(
f"• `{x['origin']}` ({x['kind']}) — {days:.1f} dnia bez nowych treści "
f"(próg {x['max_age_hours']}h, {x['total']} pozycji w bazie)"
)
send_slack("\n".join(lines))
return {"checked": len(checks), "stale": stale}

View file

@ -338,7 +338,6 @@ def _job_ingest_watchdog(
max_age_hours=max_age_hours,
search_max_age_hours=search_max_age_hours,
movie_max_age_hours=movie_max_age_hours,
to_sentry=True,
)
if res["stale"]:
log.warning("[scheduler] ingest-watchdog: %d stale origin(s)", len(res["stale"]))
@ -346,26 +345,6 @@ def _job_ingest_watchdog(
log.exception("[scheduler] ingest-watchdog failed")
def _job_watchdog_digest(
max_age_hours: int, search_max_age_hours: int, movie_max_age_hours: int
) -> None:
"""Dobowy digest zamrożonych źródeł na Slacka. Osobno od joba co 6h, żeby nie
wysyłać tej samej listy cztery razy dziennie; Sentry zostaje kanałem maszynowym,
Slack ludzkim. Bez GOON_SLACK_BOT_TOKEN i GOON_SLACK_CHANNEL to no-op."""
try:
from app.scheduler.ingest_watchdog import run_ingest_freshness_watchdog
run_ingest_freshness_watchdog(
max_age_hours=max_age_hours,
search_max_age_hours=search_max_age_hours,
movie_max_age_hours=movie_max_age_hours,
to_sentry=False,
to_slack=True,
)
except Exception:
log.exception("[scheduler] watchdog-digest failed")
def _job_hetzner_monitor() -> None:
"""Hetzner Cloud bandwidth monitor — alert do Sentry przy progach % included_traffic.
No-op gdy brak HETZNER_API_TOKEN/SERVER_ID w env (loguje że wyłączony)."""
@ -576,19 +555,6 @@ def build_scheduler(cfg: dict[str, Any]) -> BlockingScheduler:
cfg["ingest_watchdog_hours"], wd_max_age, wd_search_max_age, wd_movie_max_age,
)
if cfg.get("watchdog_digest_hours"):
sched.add_job(
lambda: _job_watchdog_digest(wd_max_age, wd_search_max_age, wd_movie_max_age),
IntervalTrigger(
hours=cfg["watchdog_digest_hours"], start_date=INTERVAL_ANCHOR
),
id="watchdog_digest",
replace_existing=True,
max_instances=1,
coalesce=True,
)
log.info("scheduler: watchdog-digest (Slack) every %dh", cfg["watchdog_digest_hours"])
if cfg.get("hetzner_monitor_hours"):
sched.add_job(
_job_hetzner_monitor,

View file

@ -237,8 +237,6 @@ def run_forever() -> int:
"ingest_watchdog_movie_max_age_hours": getattr(
settings, "ingest_watchdog_movie_max_age_hours", 72
),
# Dobowy digest na Slacka (Sentry gubił sygnał na stabilnym fingerprincie).
"watchdog_digest_hours": getattr(settings, "sched_watchdog_digest_hours", 24) or None,
# Hetzner Cloud bandwidth monitor — alert do Sentry przy progach % included.
# No-op gdy brak HETZNER_API_TOKEN/SERVER_ID (sam job może być on).
"hetzner_monitor_hours": getattr(settings, "sched_hetzner_monitor_hours", 6) or None,