diff --git a/app/config.py b/app/config.py index f3650e5..0bd5119 100644 --- a/app/config.py +++ b/app/config.py @@ -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. diff --git a/app/notify/__init__.py b/app/notify/__init__.py deleted file mode 100644 index 95f98c5..0000000 --- a/app/notify/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Powiadomienia wychodzace (Slack).""" diff --git a/app/notify/slack.py b/app/notify/slack.py deleted file mode 100644 index c7397eb..0000000 --- a/app/notify/slack.py +++ /dev/null @@ -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 diff --git a/app/scheduler/ingest_watchdog.py b/app/scheduler/ingest_watchdog.py index f634fed..d750b94 100644 --- a/app/scheduler/ingest_watchdog.py +++ b/app/scheduler/ingest_watchdog.py @@ -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} diff --git a/app/scheduler/jobs.py b/app/scheduler/jobs.py index 4273d53..d21b455 100644 --- a/app/scheduler/jobs.py +++ b/app/scheduler/jobs.py @@ -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, diff --git a/app/scheduler/worker.py b/app/scheduler/worker.py index 9663c38..2bcf08f 100644 --- a/app/scheduler/worker.py +++ b/app/scheduler/worker.py @@ -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,