Телеграм-оповещалка или как быть в курсе всего

Мама, смотри, я сделал бота!
Ладно, вот настоящий КОНТЕНТ.

Суть проблемы:
Есть несколько серверов и хотелось бы получать с них уведомления о ходе выполнения задач, проверять логи, получать оповещения, когда кто-то входит на сервер, но при этом не заходить каждый раз по SSH и в принципе быть в курсе, когда что-то происходит, даже если нет возможности следить. 
Изначально я для этих целей использовал Pushbullet, но тут случилась некоторая оказия: уведомлений стало очень много и я начал упираться в лимит достаточно быстро. Учитывая, что больше ни для чего я сервисом не пользовался, а помимо лимита меня ждало ещё не очень удобное приложение и слабая гибкость всего этого добра, решение пришло как-то само собой: пора сделать бота для Telegram!


Вообще окончательно на эту мысль меня навела библиотека для работы с Telegram API для PHP и желание сделать что-нибудь ещё прикольное на ReactPHP. Тут и практическое применение подоспело, почему бы не заняться?

Как я позже выяснил, Telegram Bot API вообще строится на обычных HTTP GET/POST запросах, так что можно было и без библиотеки обойтись, там ничего супер сложного и не было, но уж ладно, по крайней мере это было полезно узнать.

Собственно, проблема получилась поделённой на четыре основные части:

  1. Нужно как-то отправлять сообщения в телеграм чат самому себе
  2. Нужно иметь канал для коммуникации между серверами - простой Socket сервер, например
  3. Нужно иметь скрипт для подключения к этому каналу и передачи сообщений дальше
  4. Нужно выпить чяю Нужно получать сообщения
Ну и на самом деле всё оказалось достаточно просто решаемо.

Ах, да, вот ссылка на Github, где лежит сам бот: https://github.com/leamare/spectral-notifier-bot-tg

Всё это добро на писано на PHP с ReactPHP и библиотекой для работы с Telegram Bot API от славного товарища unreal4u. На Github в readme написано, как всё это запустить (поставить Composer, сделать composer install, написать свой конфиг, запустить бота).

Ну да ладно. По сути мне понадобилось два отдельных Socket-сервера в одном: первый слушает порт (указанный в конфиге) и обрабатывает входящие сообщения. При обработке он смотрит в конфиг назначает сообщению теги по ключевым словам и отправляет сообщение. Изначально я думал сделать пересылку всего в один чат, но решил, что иметь возможность писать в несколько чатов всегда полезно. К тому же, обилие уведомлений, хоть и "тихих", не щадило мою батарею. Так что самым изящным решением было самое простое: сделать отдельный приватный канал, посадить туда бота и заставить пересылать туда вообще всё, что он получает. В личку же мне идут только важные уведомления. И, конечно же, всё это настраивается в конфиге.



Второй сервер по факту является web-сервером и на самом деле он и не всегда работает. Вариантов получения обновлений (сообщений и прочих событий) в telegram два: через getUpdates и через webhook. В первом случае нужно постоянно посылать запросы к API и смотреть, есть ли новые обновления. Само собой, запросов может быть много, а обновлений может не быть, так что этот вариант не очень удобный, но полезный при отладке или если на сервере нет возможности подцепить webhook.

Webhook же просто цепляется к HTTP(S) серверу и посылает на него POST запросы, когда случается какое-то событие. И именно для этого случая нужен второй socket сервер: на нём сидит тот самый HTTP сервер, который получает сообщения. Но как его вывести во внешний мир?

Можно было бы конечно повозиться самому и прицепить сертификат, но я решил пойти более простым путём, которым я воспользовался с Endless Nyan Cat: Nginx Proxy.


В readme написан пример конфигурации прокси, так что тут его приводить не буду. Общая суть простая: Nginx получает запросы по указанному пути и переправляет их на указанный адрес:порт, на котором сидит тот самый HTTP сервер, который слушает для обновлений. Есть, конечно, и вариант проще: сделать простенький скрипт, который обрабатывает сообщения и шлёт их в телегу, поместить его на основном веб сервере и дело с концом. Но так ведь не интересно :)

Ну и помимо основного сервера есть более простой скрипт "alert.php", который просто подключается к порту из конфига и пересылает сообщения, полученные в качестве аргументов командной строки.

Самая мякотка — конфиг. В нём есть всё то, что меня интересовало в первую очередь (не хватает только перезагрузки конфига при обновлении файла, но тут мне было просто лень). Опять же, как всё это настраивать я описал в readme для тех, кто захочет воспользоваться ботом. Великих технических решений тут тоже нет, это просто json файл. Но я перечислю, что в итоге было добавлено в эту конфигурацию, потому что это в каком-то смысле интересно:

  • Токен для Telegram Bot API
  • Адрес, на котором будет работать сокет сервер для получения сообщений (публичный или локальный)
  • Адрес сервера для alert.php (на него пойдут сообщения)
  • Подписывать ли откуда пришло сообщение
  • Список алиасов для серверов (чтобы вместо некрасивых IP-адресов были красивые подписи - например Mercurial Node на скриншоте выше)
  • Группа параметров для выбора способа получения обновлений и конфигурация для этого способа (polling или webhook)
  • Группы (теги) сообщений: для каждого тега есть определённая ключевая фраза, которая ищется в сообщении, а также флаг тихого уведомления, сообщение проверяется на соответствие этим тегам
  • Список пользователей и тегов, на которые они подписаны - пользователи получают только те сообщения, которые указаны в конфиге (там же можно указать и все сообщения)
  • Ну и самое сладкое: список команд. Каждая команда записана в формате "тип::команда[::количество аргументов]". Можно приписать пересылку информации с URL, можно сделать выполнение shell-команды, можно даже назначить аргументы (чтобы можно было, например, делать ls или tail прямо через бота). Все команды назначаются в конфиге и ограничены только фантазией конфигурируещего (а ещё, например, можно сделать команду, которая будет по ssh подключаться на другой сервер, выполняться и выводить результат через бота)
Как итог — бот, который умеет следить за всем и сообщать обо всём, а заодно через него можно проверить, что сломалось (ну или, например, сварить себе кофе).

Такие вот дела! Конечно, это не какой-то гигантский проект и он не отличается какой-то крутой сложностью, решением удивительных технических задач или чем-то ещё. Но это простое решение для бытовой проблемы, и это решение очень сильно упрощает жизнь: всегда проще жить, когда лишние задачи переходят на автоматику.

Ну и, должен сказать, оповещения от этого бота и возможность быстро заглянуть в логи на сервере уже несколько раз мне помогли узнать, что возникла проблема, узнать о её причине и решить её, даже не подключаясь к серверу самому и не подходя к компьютеру.

Мир вам!