goon/app/notify/slack.py
goon-foss 6e056b81c2 feat(watchdog): pokrycie filmow, eskalacja poziomu i dobowy digest na Slacka
Watchdog dzialal poprawnie - vjav i superporn wypisywal co 6h przez caly czas ich
ciszy. Zawiodlo POWIADOMIENIE, w trzech miejscach naraz.

1. Filmy nie byly pokryte w ogole. Watchdog skanowal tylko origins tube:<sitetag> ze
scen, wiec streamporn.vip stal 23 dni i zaden automat nie mial jak tego zauwazyc.
Doszlo 6 konektorow filmowych (35 -> 41 sprawdzanych zrodel), prog 72h. Zweryfikowane
przez celowe obnizenie progu do 1h: wszystkie 6 matchuje realne liczby pozycji, a nie
zwraca cicho zera - bo to dokladnie ta klasa bledu, ktora naprawiamy.

2. Stabilny fingerprint per origin tworzyl JEDNO issue przy pierwszym wystapieniu i
potem tylko licznik. Sentry powiadamia o nowych i regresjach, nie o kolejnych
wystapieniach otwartego issue. Teraz fingerprint zawiera kubelek wieku (2d+/7d+/30d+),
wiec przekroczenie kazdego progu zaklada nowe issue, ale w obrebie kubelka nadal nie
ma spamu co 6h.

3. Poziom byl zawsze warning, a reguly alertow celuja w error. Od 7 dni ciszy idzie
error. Sprawdzone: vjav i superporn eskaluja teraz do error, pornbusy/youperv/porndish
zostaja na warning.

Plus kanal, ktory czlowiek realnie czyta: dobowy digest na Slacka (osobny job, zeby
nie wysylac tej samej listy 4x dziennie). Domyslnie NO-OP - bez GOON_SLACK_BOT_TOKEN
i GOON_SLACK_CHANNEL nic nie probuje wysylac, kanalu nie zgadujemy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 15:03:27 +02:00

50 lines
1.8 KiB
Python

"""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