Node js javascript bot

Node.js: разрабатываем бота для Telegram

В данном туториале мы разработаем простого бота для Telegram. Сначала зарегистрируем и кастомизируем бота с помощью BotFather, затем напишем для него сервер на Express, развернем сервер на Heroku и подключим бота к серверу с помощью веб-хука.

Функционал бота будет следующим:

  • в ответ на сообщение joke возвращается программистская шутка, например: «Algorithm: a word used by programmers when they don’t want to explain how their code works.» (Алгоритм — это слово, используемое программистами, когда они не хотят объяснять, как работает их код));
  • в ответ на сообщение, представляющее собой дату в формате ДД.ММ, возвращается либо список дел, запланированных на эту дату в таблице Google (массив объектов), либо фраза «You have nothing to do on this day.», если на эту дату не запланировано никаких дел;
  • в ответ на любое другое сообщение возвращается фраза «I have nothing to say.».

При разработке бота я буду опираться в основном на официальную документацию.

Если вам это интересно, прошу под кат.

Регистрация и кастомизация бота

Для регистрации бота нужен только Telegram (я буду использовать десктопную версию). Находим в нем BotFather (BotFather):

Нажимаем на Start и получаем список команд:

Выполняем команду /newbot для создания бота, указываем имя и username бота (username должно быть уникальным в пределах Telegram), например: «Neo» и «aio350_reminder_bot».

Получаем токен доступа: 5372263544.

Выполняем команду /mybots для получения списка наших ботов, выбираем только что созданного бота и нажимаем Edit Bot:

Добавляем боту описание (Edit Description), характеристику (Edit About) и аватар (Edit Botpic):

Отлично, мы зарегистрировали бота в Telegram и кастомизировали его. Поздороваемся с ним:


Бот молчит, потому что у него пока нет «мозгов») Давайте это исправим.

Разработка и деплой сервера для бота

Создаем директорию, переходим в нее и инициализируем Node.js-проект:

mkdir telegram-bot-server cd telegram-bot-server yarn init -yp # or npm init -y
# производственные зависимости yarn add axios dotenv express fs-extra google-spreadsheet # зависимость для разработки yarn add -D nodemon
  • axios: клиент-серверная утилита для выполнения HTTP-запросов;
  • dotenv: утилита для работы с переменными среды окружения;
  • express: Node.js-фреймворк для разработки веб-серверов;
  • fs-extra: расширенный Node.js-модульfs;
  • google-spreadsheet: пакет для работы с гугл-таблицами;
  • nodemon: утилита для запуска сервера для разработки.

Определяем тип кода сервера (модуль) и команды для запуска сервера в производственном режиме (start) и режиме для разработки (dev) в файле package.json:

Создаем файл .env и записываем туда токен доступа:

TELEGRAM_API_TOKEN=5348751300. 

Прежде, чем приступать к разработке сервера, необходимо настроить гугл-таблицу, в которой будут храниться наши задачи.

Создаем таблицу в Google Spreadsheets следующего содержания:

Извлекаем идентификатор таблицы из адресной строки (набор символов между d/ и /edit) и записываем его в .env:

GOOGLE_SPREADSHEET_ID=1HG60. 

Идем в Google Cloud Platform, переходим в раздел IAM & Admin -> Service Accounts и создаем сервис-аккаунт (Create Service Account), например: Telegram Bot Spreadsheet.


Выбираем созданный сервис-аккаунт, переходим в раздел Keys и генерируем ключ (Add Key -> Create new key) в формате JSON:


В скачанном JSON-файле нас интересуют поля client_email и private_key. Записываем значения этих полей в .env:

GOOGLE_SERVICE_ACCOUNT_EMAIL=telegram-bot-spreadsheet@telegram-bot-spreadsheet.iam.gserviceaccount.com GOOGLE_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----\n. \n-----END PRIVATE KEY-----

Переходим в раздел APIs & Services -> Enabled APIs & services и подключаем интерфейс таблиц с сервис-аккаунту (Enable APIs and Services):


Обратите внимание: аналогичным образом можно настроить доступ к гугл-календарю (только для работы с ним потребуется другой пакет, например, @googleapis/calendar).

Теперь можно вернуться к разработке сервера.

Создаем файл index.js и импортируем зависимости:

import axios from 'axios' import < config >from 'dotenv' import express from 'express' import < GoogleSpreadsheet >from 'google-spreadsheet'

Получаем доступ к переменным среды окружения, создаем экземпляр приложения Express и определяем пути к шуткам и телеграмму:

config() const app = express() const JOKE_API = 'https://v2.jokeapi.dev/joke/Programming?type=single' const TELEGRAM_URI = `https://api.telegram.org/bot$/sendMessage`

Подключаем посредников (middleware) Express и инициализируем таблицу:

app.use(express.json()) app.use( express.urlencoded(< extended: true >) ) const doc = new GoogleSpreadsheet(process.env.GOOGLE_SPREADSHEET_ID) await doc.useServiceAccountAuth(< client_email: process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL, private_key: process.env.GOOGLE_PRIVATE_KEY.replace(/\\n/g, '\n') >)

Определяем роут для POST-запроса к /new-message:

app.post('/new-message', async (req, res) => < // . >)

Извлекаем сообщение из тела запроса и проверяем, что сообщение содержит текст и идентификатор чата:

const < message >= req.body const messageText = message?.text?.toLowerCase()?.trim() const chatId = message?.chat?.id if (!messageText || !chatId)

Получаем данные из таблицы и формируем данные для ответа:

await doc.loadInfo() const sheet = doc.sheetsByIndex[0] const rows = await sheet.getRows() const dataFromSpreadsheet = rows.reduce((obj, row) => < if (row.date) < const todo = < text: row.text, done: row.done >obj[row.date] = obj[row.date] ? [. obj[row.date], todo] : [todo] > return obj >, <>)
let responseText = 'I have nothing to say.' if (messageText === 'joke') < try < const response = await axios(JOKE_API) responseText = response.data.joke >catch (e) < console.log(e) res.send(e) >> else if (/\d\d\.\d\d/.test(messageText))
try < await axios.post(TELEGRAM_URI, < chat_id: chatId, text: responseText >) res.send('Done') > catch (e)

Наконец, определяем порт и запускаем сервер:

const PORT = process.env.PORT || 3000 app.listen(PORT, () => < console.log(`Server running on port $`) >)

Бот не сможет взаимодействовать с сервером, запущенным локально, поэтому сервер необходимо где-нибудь развернуть, например, на Heroku.

Создаем там новое приложение, например: my-telegram-bot-server (название должно быть уникальным в пределах Heroku):


Глобально устанавливаем Heroku CLI и авторизуемся:

yarn global add heroku heroku login # далее следуем инструкциям

Находясь в корневой директории проекта, выполняем инициализацию Git-репозитория, подключаемся к Heroku, добавляем и фиксируем изменения и отправляем их в Heroku (не забудьте создать файл .gitignore с node_modules и .env):

git init # у вас название проекта будет другим heroku git:remote -a my-telegram-bot-server git add . git commit -m "create app" git push heroku master

После деплоя получаем URL приложения, например: https://my-telegram-bot-server.herokuapp.com/ (он нам еще пригодится).

Открываем вкладку Settings на странице приложения и добавляем переменные среды окружения в разделе Config Vars (Reveal Config Vars):

Отлично, на этом с разработкой и деплоем сервера мы закончили.

Осталось подключить к нему бота.

Подключение бота к серверу

Существует несколько способов подключения бота к серверу, но самым простым является использование веб-хука.

Открываем терминал и выполняем следующую команду:

# в строке ("url=. ") указываем `URL` проекта + `/new-message` # после `bot` указываем токен доступа из переменной `TELEGRAM_API_TOKEN` curl -F "url=https://my-telegram-bot-server.herokuapp.com/new-message" https://api.telegram.org/bot5372263544. /setWebhook

Получаем сообщение об успешной установке хука.

Нажимаем /start, получаем от бота сообщение «I have nothing to say.». Отправляем сообщение «joke», получаем шутку. Отправляем «11.05», получаем задачи в виде массива объектов. Отправляем «12.05», получаем «You have nothing to do on this day.».

Примечание: при разработке бота я немного опечатался (вместо «to do» написал «to to»), но уже исправился.

Пожалуй, это все, чем я хотел поделиться с вами в этой статье.

Надеюсь, вы нашли для себя что-то интересное и не зря потратили время.

Благодарю за внимание и happy coding!

Источник

Пишем телеграм бота на node.js

Сегодня мы будем разрабатывать телеграм бота на node js, который умеет выводить статистику зараженных коронавирусом по всем странам.

Прежде всего в контакт-лист телеграмма нужно добавить @botFather и написать ему команду /newBot. Далее задаем имя нашего бота и, если оно не занято, придумываем идентификатор бота, по которому его можно будет найти.

Вот и все, наш телеграмм бот готов и botfather поделился с нами API Token, благодаря которому мы сможем управлять ботом

Далее создадим новый проект, введем npm init и добавим файл bot.js в котором будет разрабатываться наш бот.

Затем я установлю telegraf — это один из популярных фреймворков для создания телеграмм бота. Смотрим документацию телеграфа, копируем в наш проект первоначальную настройку бота и быстро пройдемся по всем методам, которые указаны в примере:

const < Telegraf >= require('telegraf') const bot = new Telegraf(process.env.BOT_TOKEN) //сюда помещается токен, который дал botFather bot.start((ctx) => ctx.reply('Welcome')) //ответ бота на команду /start bot.help((ctx) => ctx.reply('Send me a sticker')) //ответ бота на команду /help bot.on('sticker', (ctx) => ctx.reply('')) //bot.on это обработчик введенного юзером сообщения, в данном случае он отслеживает стикер, можно использовать обработчик текста или голосового сообщения bot.hears('hi', (ctx) => ctx.reply('Hey there')) // bot.hears это обработчик конкретного текста, данном случае это - "hi" bot.launch() // запуск бота

Поместим api token в наш пример и запуcтим бота.

Проверим работу нашего бота:

Теперь разберемся что лежит в ctx

Для этого после объявления константы bot мы можем использовать log:

Перезапустим наш проект, введем команду /start и в консоли мы получим объект, в котором мы сможем посмотреть необходимые данные о юзере:

< "update_id": 375631294, "message": < "message_id": 11, "from": < "id": 222222, "is_bot": false, "first_name": "Женя", "username": "Evgenii", "language_code": "ru" >, "chat": < "id": 386342082, "first_name": "Женя", "username": "Evgenii", "type": "private" >, "date": 1593015188, "text": "/start", "entities": [ < "offset": 0, "length": 6, "type": "bot_command" >] > >

Нас будет интересовать объект message, из которого мы сможем достать имя юзера

И текст, который он отправил боту:

Мы знаем что лежит в ctx и теперь мы можем приступить к подключению стороннего api, с помощью которого мы сможем получать статистику по коронавирусу. Для этого я буду использовать библиотеку, которая называется covid19-api. Установим ее в наш проект и заимпортим в файл bot.js:

const covidApi = require('covid19-api')

Далее мы удалим наш обработчик стикеров и сделаем новый обработчик, который отслеживает текст и отправляет запрос, чтобы получить данные о коронавирусе, используя метод getReportsByCountries, который можно найти в документации covid19-api:

Давайте проверим какие данные мы получим. Для примера напишем нашему боту в телеграме: ‘russia’:

Отлично, мы получили целый ряд данных. Но если мы введем название страны с опечаткой наш бот прекратит работать и выдаст ошибку в консоль:

Чтобы это избежать нам нужно сделать обработчик ошибок и оповещать юзера, что такой страны не существует. Так же произведем небольшой рефакторинг кода и сделаем нашего бота более дружелюбным, изменим вывод сообщения, которое отправляется по команде /start, настроем корректное отображения данных о статистике и создадим в отдельном файле константу, которая будет содержать список всех стран на английском языке и будем выводить ее при использовании команды /help.

const < Telegraf >= require('telegraf'); const covidApi = require('covid19-api'); const COUNTRIES_LIST = require('./const') const bot = new Telegraf('1170363720:AAFJ4ALJebB8Luh5kt1DStmYYqV3TparhKc') bot.start( ctx => ctx.reply(` Привет $! Узнай статистику по Коронавирусу. Введи страну на английском языке и получи статистику. Получить весь список стран можно по команде /help." `)) bot.help( ctx => ctx.reply(COUNTRIES_LIST)) // список всех стран на английском языке можно взять в документации covid19-api bot.on('text', async (ctx) => < try < const userText = ctx.message.text const covidData = await covidApi.getReportsByCountries(userText) const countryData = covidData[0][0] const formatData = ` Страна: $, Случаи: $, Смерти: $, Выздоровело: $` ctx.reply(formatData) > catch(e) < ctx.reply('Такой страны не существует, для получения списка стран используй команду /help') >>) bot.launch()

Который срабатывает как нам нужно:

Поздравляю! Мы завершили настройку нашего телеграм бота, который выводит статистику заболевших коронавирусом.

Источник

Читайте также:  Запуск скрипта python через планировщик windows
Оцените статью