01/09/2026 / WEB / DEV /

Alerty na Telegramie zamiast maila - jak zrobić kanał powiadomień, który ktoś czyta

Powiadomienia z monitoringu wysyłane przez bota Telegrama do wątków grupy

Każdy system monitoringu prędzej czy później staje przed tym samym pytaniem: jak dać znać człowiekowi. Domyślną odpowiedzią od dwudziestu lat jest mail. I to jest odpowiedź, która w praktyce nie działa.

Nie dlatego, że mail jest zły technicznie. Dlatego, że alert konkuruje w skrzynce z fakturami, newsletterami i korespondencją, przegrywa tę konkurencję, po tygodniu dostaje własną regułę i folder, a po miesiącu ten folder ma dwieście nieprzeczytanych wiadomości. Powiadomienie, które trafia do archiwum zamiast do uwagi, nie jest powiadomieniem.

Ten wpis opisuje alternatywę, której używam na co dzień: bota na Telegramie. Jak to zestawić, jak rozdzielić powiadomienia według wagi, jakie pułapki kryje ta z pozoru banalna integracja i kiedy Telegram na pewno nie wystarczy.

Dlaczego akurat Telegram

Powody są prozaiczne i dlatego mocne:

  • Push ląduje na telefonie, obok wiadomości od ludzi. Nie w folderze, do którego zagląda się raz na tydzień.
  • Grupa zamiast listy adresatów. Alerty widzi cały zespół, a dołączenie nowej osoby to zaproszenie do grupy, a nie edycja konfiguracji na serwerze.
  • Wątki (topiki) w grupie, dzięki którym awarie krytyczne i informacje porządkowe nie mieszają się w jednym strumieniu.
  • Bot API jest darmowe, stabilne i banalnie proste - jedno zapytanie HTTP, żadnych bibliotek, żadnego SDK.
  • Historia jest przeszukiwalna na każdym urządzeniu, więc „kiedy to ostatnio padło” to kwestia wpisania frazy w wyszukiwarkę czatu.

Alternatywy są sensowne i nie chcę ich deprecjonować: ntfy (świetne, gdy chcesz mieć całość u siebie), Discord czy Slack (dobre, gdy zespół i tak tam siedzi), SMS (drogie, ale niezależne od internetu). Telegram wygrywa u mnie stosunkiem nakładu do efektu.

Minimalny działający przykład

Całość sprowadza się do trzech kroków.

1. Załóż bota. Napisz do @BotFather komendę /newbot, podaj nazwę i dostaniesz token. Token to jedyne, co potwierdza tożsamość bota - traktuj go jak hasło.

2. Ustal identyfikator czatu. Napisz do bota (albo dodaj go do grupy i napisz cokolwiek), a potem odczytaj:

curl "https://api.telegram.org/bot<TOKEN>/getUpdates"

W odpowiedzi znajdziesz chat.id. Dla czatu prywatnego to liczba dodatnia, dla grupy ujemna.

3. Wyślij wiadomość.

curl -s "https://api.telegram.org/bot<TOKEN>/sendMessage" \
  -d chat_id=<CHAT_ID> \
  --data-urlencode "text=Test alertu"

To wszystko. Od tego momentu każdy skrypt, cron czy monitoring, który potrafi wykonać zapytanie HTTP, umie się z Tobą skontaktować.

Wątki, czyli sposób na to, żeby alerty dało się czytać

To jest funkcja, która moim zdaniem decyduje o użyteczności całego rozwiązania, a jest zaskakująco mało znana. Grupa na Telegramie może mieć włączone tematy (topics), a bot potrafi wysłać wiadomość do konkretnego wątku, dokładając jeden parametr:

-d message_thread_id=<ID_WATKU>

Dzięki temu jedna grupa obsługuje kilka strumieni naraz. U mnie podział idzie według wagi zdarzenia:

Krytyczne  ->  awaria łącza, utrata dostępu   (powiadomienia włączone)
Ostrzeżenia ->  progi, nietypowy ruch          (powiadomienia włączone)
Info       ->  raport dobowy, nowe urządzenie  (wyciszony wątek)

Efekt jest taki, że wyciszam informacje porządkowe, nie tracąc ich, a telefon wibruje wyłącznie przy rzeczach, które naprawdę tego wymagają. To jest różnica między kanałem, który się czyta, a kanałem, który się wycisza w całości po dwóch tygodniach.

Zasada, która przeżyła zderzenie z praktyką: trzy poziomy ważności, nie siedem. Przy siedmiu nikt nie pamięta różnicy między „alert” a „ostrzeżenie”, a przy trzech decyzja „czy to ma zawibrować w nocy” jest oczywista.

I jeszcze jeden szczegół, który warto zaprojektować od razu: jeśli Twój system kiedyś doda nowy poziom ważności, nieznana wartość powinna trafiać do wątku domyślnego. Powiadomienie w niewłaściwym miejscu jest kłopotliwe. Powiadomienie, które nie poszło nigdzie, jest niebezpieczne.

Pułapki, które kosztowały mnie wieczory

Wysyłka działa z przeglądarki, ale nie z crona

Klasyk, który potrafi zająć pół dnia. Skrypt testowany w przeglądarce wysyła wiadomości bez zarzutu, a ten sam kod uruchomiony z crona milczy. Powód bywa banalny: konfiguracja PHP dla linii poleceń różni się od tej dla serwera WWW i funkcja pobierająca zawartość adresu URL może być tam po prostu wyłączona.

Wniosek praktyczny: do integracji używaj cURL-a, nie funkcji typu file_get_contents. Działa tak samo w obu środowiskach i, co ważniejsze, potrafi powiedzieć, dlaczego się nie udało.

Cisza nie do odróżnienia od spokoju

Najgroźniejszy błąd w całej tej układance. Jeśli wyciszysz błędy wysyłki, to zły identyfikator czatu, bot wyrzucony z grupy albo skasowany wątek objawiają się dokładnie tak samo jak brak zdarzeń: ciszą. A ciszę człowiek interpretuje jako „wszystko w porządku”.

Telegram odpowiada czytelnym kodem HTTP i opisem błędu. Zapisuj obie te rzeczy do logu przy każdej nieudanej wysyłce - to jedyny sposób, żeby dowiedzieć się o zepsutym kanale wcześniej niż przy najbliższej awarii. Samej treści powiadomienia w logu nie umieszczaj.

Jeden znak podkreślenia i cała wiadomość przepada

Jeżeli wysyłasz z parse_mode=Markdown, to znaki _, * czy [ w treści są składnią, a nie tekstem. Wystarczy, że urządzenie w sieci nazywa się serwer_backup, a Telegram odrzuci całą wiadomość błędem parsowania. Alert nie dotrze, bo nazwa hosta zawierała podkreślenie.

Masz dwa wyjścia: albo czyścić dane wstawiane do treści, albo w ogóle nie ustawiać trybu formatowania. Jeśli formatowanie nie jest Ci naprawdę potrzebne, drugie wyjście jest bezpieczniejsze.

Polskie znaki wysyłane z linii poleceń

Przy skryptach powłoki potrafi wyskoczyć błąd o tym, że treść musi być zakodowana w UTF-8 - mimo że wygląda poprawnie. Zwykle winne jest kodowanie samego pliku skryptu albo konsoli, nie Telegram. Najprościej jest przekazać treść z pliku zapisanego w UTF-8, zamiast wklejać ją bezpośrednio w polecenie.

Wątki działają tylko w grupach z tematami

Parametr wskazujący wątek ma sens wyłącznie w grupie z włączonymi tematami. Wysłany do czatu prywatnego zostanie odrzucony. Jeśli budujesz to jako opcję konfiguracyjną, pusta wartość powinna oznaczać „nie dokładaj tego parametru w ogóle”, dzięki czemu ta sama instalacja obsłuży i grupę z wątkami, i zwykły czat.

Bezpieczeństwo, o którym trzeba pomyśleć od razu

Token to pełna kontrola nad botem. Kto go ma, może wysyłać wiadomości w Twoim imieniu do wszystkich czatów, w których bot się znajduje, i czytać to, co bot widzi. Nie umieszczaj go w repozytorium - to najczęstszy sposób, w jaki takie tokeny wyciekają. Trzymaj go poza kodem, a na współdzielonym hostingu rozważ przechowywanie go w postaci zaszyfrowanej, tak żeby sam odczyt pliku konfiguracyjnego nie wystarczył do przejęcia kanału.

Bot domyślnie nie czyta rozmów. W trybie prywatności widzi tylko komendy skierowane do siebie. To dobre ustawienie i nie ma powodu go zmieniać, jeśli bot ma wyłącznie wysyłać powiadomienia.

Uważaj, co wkładasz w treść. Alert nie musi zawierać adresów IP, nazw użytkowników ani szczegółów konfiguracji. Wystarczy tyle, żeby wiedzieć, co i gdzie się stało - resztę sprawdzisz w panelu. Wiadomości zostają w chmurze usługodawcy i na telefonach wszystkich członków grupy.

Nie dawaj botowi uprawnień administratora, jeśli tylko wysyła wiadomości. Wyjątkiem jest sytuacja, w której ma pisać do wątków - wtedy sprawdź, jakie minimalne uprawnienia są do tego potrzebne.

Higiena alertu, czyli jak nie zabić własnego kanału

Najlepiej skonfigurowany kanał powiadomień zabija zwykle nie awaria, tylko nadmiar. Cztery zasady, które u mnie się sprawdziły:

  • Powiadamiaj o zmianie stanu, nie o stanie. „Łącze padło” i później „łącze wróciło, przerwa 4 minuty” to dwie wiadomości. „Łącze nadal nie działa” co minutę to droga do wyciszenia grupy.
  • Odczekaj dwa cykle. Pojedynczy nieudany pomiar to najczęściej chwilowy timeout, a nie awaria.
  • Agreguj to, co nie wymaga reakcji. Nowe urządzenia, statystyki i podsumowania mają sens raz na dobę, w jednym raporcie, w wyciszonym wątku.
  • Zaplanuj ciszę nocną dla wszystkiego poniżej poziomu krytycznego. Alert, który budzi bez powodu, uczy ludzi ignorować alerty, które budzą słusznie.

Kiedy Telegram nie wystarczy

Uczciwie o ograniczeniach, bo to nie jest rozwiązanie na wszystko:

  • Nie jest to ślad audytowy. Jeśli musisz udokumentować, że incydent został wykryty i obsłużony, potrzebujesz systemu zgłoszeń z historią i rozliczalnością. Czat może być powiadomieniem o zdarzeniu, ale nie jego rejestrem.
  • To zewnętrzna zależność. Bez internetu nie ma powiadomienia. Przy awarii łącza w tej właśnie lokalizacji ratuje tylko kanał niezależny, na przykład SMS.
  • Dane wychodzą na zewnątrz. W środowisku z wysokimi wymaganiami na poufność rozsądniejszy będzie kanał utrzymywany we własnej infrastrukturze.
  • Brak potwierdzenia obsługi. Nie ma dyżurów ani eskalacji, gdy nikt nie zareaguje. Przy krytycznych usługach potrzebny jest system, który wie, że nikt nie odebrał, i zawoła następną osobę.

W kontekście regulacyjnym warto o tym pamiętać: pisaliśmy osobno o tym, jak nie pomylić trzech różnych systemów monitoringu pod NIS2 i DORA, a kanał powiadomień jest tylko jednym z ich elementów, nie zamiennikiem całości.

Podsumowanie

Zamiana maila na czat brzmi jak kosmetyka, a jest zmianą jakościową, bo przenosi alert z miejsca, do którego się zagląda, do miejsca, które samo się odzywa. Reszta to konsekwencja: trzy poziomy ważności, osobne wątki, cisza dla rzeczy nieistotnych i logowanie nieudanych wysyłek, żeby cisza zawsze znaczyła spokój, a nie awarię kanału.

W poprzednim wpisie opisałem drugą stronę tej układanki, czyli powody, dla których zbudowałem własny dashboard do sieci UniFi. Jeśli chcesz, żeby Twój monitoring odzywał się wtedy, kiedy trzeba, i do kogo trzeba - tym zajmujemy się w ramach administracji siecią.

Najczęściej zadawane pytania

Jak wysłać powiadomienie przez bota Telegrama?
Załóż bota komendą /newbot u @BotFather i zapisz token. Napisz do bota, odczytaj identyfikator czatu przez metodę getUpdates, a następnie wysyłaj wiadomości pojedynczym zapytaniem HTTP do metody sendMessage z parametrami chat_id i text.
Jak rozdzielić alerty według ważności?
Włącz tematy (topics) w grupie i dokładaj do wysyłki parametr message_thread_id wskazujący właściwy wątek. Trzy poziomy - krytyczne, ostrzeżenia i informacje - w zupełności wystarczą, a wątek informacyjny można wyciszyć bez utraty treści.
Dlaczego powiadomienia działają z przeglądarki, a nie z crona?
Bo konfiguracja PHP dla linii poleceń różni się od tej dla serwera WWW i pobieranie zawartości adresu URL bywa tam wyłączone. Do integracji używaj cURL-a zamiast file_get_contents - działa tak samo w obu środowiskach i zwraca powód niepowodzenia.
Dlaczego wiadomość z nazwą urządzenia nie dochodzi?
Przy parse_mode=Markdown znaki podkreślenia, gwiazdki i nawiasy kwadratowe są traktowane jako składnia. Nazwa w rodzaju serwer_backup powoduje błąd parsowania i odrzucenie całej wiadomości. Albo czyść wstawiane dane, albo w ogóle nie ustawiaj trybu formatowania.
Jak bezpiecznie przechowywać token bota?
Token daje pełną kontrolę nad botem, więc nie może trafić do repozytorium. Trzymaj go poza kodem, a na współdzielonym hostingu rozważ przechowywanie w postaci zaszyfrowanej, żeby sam odczyt pliku konfiguracyjnego nie wystarczył do przejęcia kanału.
Kiedy Telegram nie wystarczy jako kanał alertów?
Gdy potrzebujesz śladu audytowego incydentu, gdy dane nie mogą opuszczać własnej infrastruktury, gdy alert musi dotrzeć mimo braku internetu w lokalizacji (wtedy SMS) oraz gdy wymagana jest eskalacja w razie braku reakcji.