Telegram бот + bash скрипт для ленивого меня. Опыт, мини-гайд и обсуждение
Приветствую всех, кого заинтересовал данный пост. В нём я хочу поделиться своим опытом использования Telegram бота для управления ПК. В тексте не будет чего-то особенно гениального. Даже более того, я надеюсь получить в обсуждении рекомендации относительно того, как это можно было бы сделать лучше. Текущего моего опыта недостаточно, что бы сделать из этого что-то боле-мене цельное. Надеюсь на помощь.
Но и некий гайд как реализовать то, что я сделал для себя - напишу.
Для начала кратко: я зарегистрировал бота и написал небольшой скрипт, который может например выключить ПК. Для этого я изначально и создавал бота. Позже я добавил функцию обновления DDNS записи. Кроме этого скрипт умеет отправлять сообщения в конкретный чат — между мной и ботом. Ну и само собой, он читает сообщения из этого же чата, таким образом я могу вызвать любую из перечисленных выше функций сообщением в чат.
Дальше последует гайд, как это сделать, если кто-то заинтересуется. Либо что бы кто-то нашёл в моём способе слабые места или указал мне на возможность улучшения.
Регистрация Telegram бота.
О том, как это сделать есть множество гайдов в интернете. По этому я не буду заострять на этом слишком много внимания. Вам надо:
1. Найти в телеграмме бота https://t.me/BotFather.
2. Написать этому боту /start, затем /newbot для создания своего нового бота.
3. Ответить на вопросы BotFather — указать имя своего бота, и его username, после чего — получить его данные. Ссылку на бота и его токен (<bot_token>).
4. Сохраните токен и никому не рассказывайте.
5. Готово! Вы восхитительны!
Идентификатор беседы с ботом.
Второе, что нужно сделать — получить идентификатор чата с ботом. Он так же будет использоваться. Это сделать так же не сложно:
1. Напишите что-то своему боту.
2. В браузере откройте ссылку:
https://api.telegram.org/bot<bot_token>/getUpdates
Используйте токен полученный в предыдущем шаге без кавычек и безничего вообще, как есть.
3. Вы получите json ответ. В нём надо найти id. У меня он нашёлся вот по такому пути: result>0>message>chat>id. Сохраните этот id — просто набор цифр (далее — <chat_id>).
Базовые функции
Так как я использую Linux на домашнем ПК, и публикую этот пост в лигу GNU/Linux, то мои примеры будут для этого семейства ОС. Если вы используете Windows или что-то ещё, вы наверняка сможете реализовать что-то подобное с некоторыми изменениями для вашей ОС. Советов на этот счёт у меня пока нет. От себя лишь пожелаю удачи.
Что ж, теперь пара примеров, что можно сделать имея токен бота и id чата с ним:
Отправка сообщения в чат из консоли:
curl -X POST -H 'Content-Type: application/json' -d '{"chat_id": "<chat_id>", "text": "Hello pikabu!" "disable_notification": false}' https://api.telegram.org/bot<bot_token>/sendMessage
Вместо "Hello pikabu!" пишите свой текст, или передавайте туда содержимое переменной. В чат с вашим ботом должно прийти сообщение от имени вашего бота.
Получение сообщения из чата. Того сообщения, которое вы напишите туда от себя. Эта функция уже упоминалась выше:
Ответ вы получите всё в том же json, но уже в консоль. Результат в консоли выглядит не очень красиво, по этому рекомендую использовать JSON процессор. Например jq.
Так же я столкнулся с тем, что в скрипте после первого вызова метода getUpdates, последующие вызовы из того же скрипта ломаются. Почему я не разобрался. Обошёл эту проблему использованием переменной, которую потом обрабатываю. Вот две команды - выводы из предыдущих двух абзацев:
var=$( curl -s https://api.telegram.org/bot<bot_token>/getUpdates )
echo "${var}" | jq
Так вывод будет немного красивее.
Можно вывести только текст одного сообщения:
echo "${var}" | jq ".result[0].message.text"
Так же, необходимо учитывать, что сообщения получаемые при помощи getUpdates хранятся какое то время, хотя и не вечно. И отправив пять или десять сообщений своему боту подряд, и применив getUpdates вы получите их все. И тогда последняя команда вам покажет текст только одного из них — первого.
Узнать сколько сообщений получено можно вот так:
count=$( echo "${var}" | jq '.result | length' )
Переменную $count теперь можно использовать, что бы проверить все сообщения в цикле:
if [ $count -gt 0 ]
then
for (( i=0; i < count; i++ ))
{
text[$i]=$( echo "${var}" | jq ".result[$i].message.text" | tr -d \")
echo ${text[$i]}
}
fi
Аналогичным образом можно обрабатывать различную информацию которая передаётся в json. Там не только текст сообщения, но и например его дата, различные id, один из которых нам может пригодиться позже, информация об отправителе и чате.
Обработанные сообщения можно удалять, для этого используется следующая конструкция:
curl -s https://api.telegram.org /bot<bot_token>/getUpdates?offset=<update_id>
Извините за пробел тут, пикабу упорно превращал всё в ссылку и резал строку. Вообще, было бы здорово если бы можно было использовать моноширинный шрифт. И что бы он не превращался в ссылки. Я сейчас не об этом.
Данная команда удалит все сообщения полученные ранее того, которое имеет id равным <update_id>! Сам чат в приложении останется без изменений. Но getUpdates потеряет доступ к более старым сообщениям.
Собственно, это все функции, которые я использую. С ними я написал скрипт, который на данный момент и использую.
Общая логика скрипта
Полный текст скрипта писать не буду. Там ничего фантастического - пара if, один или два цикла, case. И, как я писал ранее, несколько функций:
SendMessage — отправка сообщения в чат.
CleanMessages — очистка сообщений.
UpdateDNS — обновление DDNS записи.
ShutdownPC — выключение компьютера через 3 минуты (shutdown +3).
GetUpdates — получение всех доступных сообщений с дальнейшей их обработкой. Если это команды, которые скрипт может выполнять — он выполняет их. Если нет — игнорирует. Эта функция обычно вызывает другие, и после получения всех сообщений для обработки — всегда вызывает функцию CleanMessages.
Запуск скрипта без параметров и ключей вызывает функцию GetUpdates. На своём ПК я сделал юнит, который каждые несколько секунд запускает данный скрипт.
Для себя я таким образом решил задачу удалённого выключения ПК. Так же, используя этот скрипт с ключами я шлю сообщение о том, что ПК включился или о том, что новый torrent загружен.
Заключение
Собственно, к чему я это всё? Хотел поделиться опытом, вдруг кому пригодится, или просто будет интересно.
Так же, я надеюсь, что тут найдутся люди в теме и смогут подсказать мне, что ещё с этим можно сделать? Я закрыл минимальные потребности данной поделкой, но может быть я чего-то не придумал? Было бы здорово послушать советы и идеи.
Сам я думаю, что можно было бы избавиться от токена в тексте скрипта в явном виде. Или переписать бота на Python. Но по привычке — не шатаю то, что и так работает. Хотя признаюсь, заниматься этим было интересно.
На этом всё. Надеюсь пост заинтересует хоть кого-то. Спасибо вам за ваше время. Всем пока!
GNU/Linux
1K постов15.5K подписчик
Правила сообщества
Все дистрибутивы хороши.
Будьте людьми.