07.09.2016Телеграм-бот для Яндекс.ПДД
Введение
Увлечение чат-ботами докатилась и до меня. Как это может случиться наилучшим образом, — по необходимости. А необходимость возникла в совместном использовании Яндекс почты для домена. Оказалось, что веб-интерфейс для этого совершенно не приспособлен, но есть API. Но писать целый сайт для этого кажется накладным, а чат-бот — в самый раз. И вообще, мне кажется, это один из самых продуктивных способов использования технологии: интерфейс к API.
Ссылку на полный текст бота я приложу в конце. Сам бот не содержит в себе полного функционала всего API, а имеет лишь необходимую на данный момент часть. Сейчас хотел бы поделиться парой находок, которые пригодятся всем, кто захочет писать чат-ботов для Телеграм с помощью node.js.
Хуки в продакшне
У ботов Телеграм есть два способа работы: когда бот сам обращается за обновлениями по определённому адресу (polling) и с помощью веб-хуков, когда сервера сами дёргают заданный хук для передачи данных боту. В продакшне, конечно, удобнее работать с хуками, а при разработке — нет, поскольку сервер запускается на локальной машине. Кроме этого я рекомендую завести другого бота для разработки, чтобы те, кто пользуются вашим ботом в продакшне, не замечали, как вы разрабатываете. Возможность сделать это я нашёл пока только в одной библиотеке: node-telegram-bot-api с помощью недокументированной функции processUpdate. Делается это довольно просто. При инициализации бота в файле lib/bot.js:
if (process.env.NODE_ENV === 'production') {
bot = new TelegramBot(config.botToken, {polling: false});
bot.setWebHook(config.host + config.url);
} else {
bot = new TelegramBot(config.devBotToken, {polling: true});
}
А затем уже в серверной части, которая, хоть и запускается всегда, имеет значение только для продакшна, в файле lib/web.js:
app.post(config.url, function (req, res) {
options.bot.processUpdate(req.body);
res.status(200).send({}).end();
});
Весь остальной код для бота работает в обоих случаях одинаково и в изменениях не нуждается, что совершенно прекрасно!
Оповещение об остановке
Второе, что нужно делать, как мне кажется, это оповещать хоть кого-нибудь о том, что сервер остановлен или запущен. Также это нужно, если при перезапуске бота, например, меняется кастомизированная клавиатура.
Если вы запускаете приложения с помощью pm2, то этот менеджер использует для остановки процесса тот же сигнал SIGINT, что мы используем, когда останавливаем сервер в разработке с помощью Ctrl-C. Очень удобно! В файле index.js
process.on('SIGINT', function () {
Promise.all(config.permitUsers.map(function (userId) {
return bot.sendMessage(userId, 'Бот временно выключается. Только спокойствие!', {
reply_markup: {
hide_keyboard: true
}
});
})).then(gracefulClose).catch(function (err) {
console.log(err);
gracefulClose();
});
});
Таким образом, останавливая наш сервер через Ctrl-C мы видим то же, что увидит пользователь, когда перезапускается приложение на сервере.
Материалы для самостоятельного изучения
- Полный на текущий момент код Телеграм-бота для Яндекс.ПДД;
- API Яндекс.ПДД;
- Как установить приложение node.js на ubuntu 16.04.