Привет, Хабр! Эту статью написал Тарас Голомозый, fullstack web-разработчик и преподаватель в школе программирования Elbrus Bootcamp. Хотя про ботов рассказано уже немало, эта тема по-прежнему интересует начинающих разработчиков, — и опыт наших студентов это подтверждает. Позволим себе написать еще одну инструкцию по созданию простого бота на JavaScript с возможностью расширения функционала. В базовом варианте его задача — показывать текущую погоду по геолокации пользователя.
Пару слов об уровне знаний, на который рассчитан этот текст. Для создания бота достаточно иметь базовое представления о JavaScript, а также знать, как работает API. Перед началом работы нужно установить библиотеку telegraf.js, которая работает на базе официального API Telegram, и библиотеку для выполнения HTTP-запросов (например, axios).
Шаг первый: базовый функционал
Откроем редактор кода и инициализируем проект через терминал с помощью команды npm -y. После этого в проекте появится файл package.json. Теперь мы можем добавить все необходимые библиотеки командой npm i, после которой через пробел прописываются названия необходимых нам библиотек. Все названия можно посмотреть в документации: в этом примере это будут telegraf и axios.
Стоит отметить, что API погоды отдельно устанавливать не нужно — она работает по архитектуре клиент-сервер, что позволяет просто отправлять запросы и получать ответы.
Пока устанавливаются библиотеки, можно прочитать документацию к ним. У telegraf.js есть несколько примеров готового бота. Можно взять первый пример и посмотреть, как он работает.
Для этого создадим новый файл с именем bot.js и добавим в него следующий код:
const { Telegraf } = require('telegraf');
const bot = new Telegraf(process.env.BOT_TOKEN);
bot.start((ctx) => ctx.reply('Welcome'));
bot.help((ctx) => ctx.reply('Send me a sticker'));
bot.on('sticker', (ctx) => ctx.reply('????'));
bot.hears('hi', (ctx) => ctx.reply('Hey there'));
bot.launch();
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));
В package.json пропишем стартовый скрипт для этого файла. Для этого в разделе scripts добавим новый пункт со следующим содержанием:
"start": "node bot.js"
Если мы запустим проект в терминале командой npm start, то увидим сообщение ”Bot token is required”. Получить токен можно через Telegram BotFather — официального бота мессенджера, который создает другие боты и управляет ими. В интерфейсе выбираем /start, затем — /newbot, и следом задаем имя и адрес. В этой инструкции это будет elbrusbootcampweatherbot.
После этого BotFather пришлет сообщение с токеном и ссылкой на бот. Копируем токен и вставляем его в третью строчку примера:
const bot = new Telegraf(process.env.BOT_TOKEN);
Для проверки находим бота в поиске в Telegram по имени. Теперь бот запускается, но пока не выполняет никаких полезных функций. Чтобы разобраться, что именно нужно добавить, построчно разберем код из примера.
Первая строка отвечает за подключение библиотеки telegraf, которая непосредственно взаимодействует с API Telegram и позволяет нам использовать определенные методы для работы с ботом. В следующей строке создаем нового бота и указываем ключ доступа к нему.
Далее указано, как бот будет реагировать на различные команды: при нажатии /start он отправит сообщение welcome, при отправке стрикера — эмодзи и так далее. Последние две строчки нужны для того, чтобы выполнение ботом команд правильно завершалось в облачных сервисах.
Другие методы кроме /start нам не понадобятся, поэтому их можно смело удалить:
const { Telegraf } = require('telegraf');
const bot = new Telegraf(process.env.BOT_TOKEN);
bot.start((ctx) => ctx.reply('Welcome'));
bot.launch();
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));
Добавим собственные методы: при отправке геолокации бот отвечает актуальном прогнозом погоды для этой территории. Первым делом напишем обработчик, который будет принимать сообщение от пользователя и выводить его в консоль.
bot.on ('message',(ctx) => {
console.log('ctx.message');
} )
Теперь при отправке боту геолокации в консоли мы увидим объект location, в котором содержится широта и долгота. Добавим проверку: если в сообщении пользователя содержится объект location, данные из него отправляются на сервер через API агрегатора прогнозов погоды.
bot.on ('message',(ctx) => {
if('ctx.message.location'){
console.log('ctx.message.location');
} )
Шаг второй: подключаем API
Как и в предыдущем случае, используем пример из официальной документации OpenWeather. Нам нужно обратиться на специальный адрес и передать туда широту, долготу и API-ключ. В ответ мы получим текущую погоду.
Вставим пример в код, используя результат проверки ctx.message.location с указанием широты и долготы:
bot.on('message', (ctx) => {
if (ctx.message.location) {
const weatherAPIUrl = `https://openweathermap.org/data/2.5/weather?lat=${ctx.message.location.latitude}&lon=${ctx.message.location.longitude}&appid=439d4b8O4bc8187953eb36d2a8c26a02`;
}
});
API-ключ можно создать в личном кабинете на сайте OpenWeather. Ключ указывается как параметр appid.
Следующим шагом нужно обратиться по адресу, предоставленному OpenWeather, и получить данные. Для этого используем библиотеку axios. Функция для подключения библиотеки указана в ее официальной документации и выглядит следующим образом:
const axios = require('axios');
Поскольку все операции со сторонним сервером выполняются асинхронно, добавим async и await в метод bot.on:
bot.on('message', async (ctx) => {
if (ctx.message.location) {
const weatherAPIUrl = `https://openweathermap.org/data/2.5/weather?lat=${ctx.message.location.latitude}&lon=${ctx.message.location.longitude}&appid=439d4b8O4bc8187953eb36d2a8c26a02`;
const response = await axios.get(weatherAPIUrl);
}
});
Теперь при отправке боту геолокации в консоли мы увидим информацию о погоде в текущем месте расположения пользователя. Остается только сформировать сообщение, которое бот отправит пользователю в качестве ответа. В тексте укажем название района и температуру в градусах Цельсия:
ctx.reply(`${response.data.name}: ${response.data.weather[0].main} ${response.data.main.temp} °C`);
Заключение
На этом все: итоговый код проекта можно найти в репозитории на GitHub.
При желании можно указать дополнительные параметры, которые бот будет выводить в сообщении. Например, облачно на улице или солнечно, есть осадки или нет и другие. Также к боту можно подключить переводчика и переводить состояние погоды на русский язык.
mobilz
в ваш буткамп es6 не завезли? ) ну т.е. по коду я вижу, что завезли, но
require
, серьезно? ну и где же пример с heroku, когда всё что нужно, чтобы развернуть своего бота -- просто прописать команду хероке или подобному сервису?