Хостинг SpaceWeb
Серверы Дизайн Сайты Безопасность Домены PHP Кейсы клиентов

Как создать чат-бота самостоятельно на Node.js

Чат-боты давно перестали быть просто развлечением — сегодня они помогают компаниям автоматизировать сервис, а пользователям экономить время. Один из самых удобных способов создать собственного бота — использовать Node.js. Этот инструмент позволяет быстро запускать проекты, легко подключать нужные библиотеки и работать с популярными платформами вроде Telegram.

В этой статье разберемся, как с нуля написать простого телеграм-бота на Node.js, какие инструменты для этого понадобятся и на что обратить внимание в процессе разработки.

Зачем создавать бота на Node.js

Node.js — один из самых популярных инструментов для разработки ботов, и на это есть несколько причин:

В каких случаях бот полезнее, чем приложение или сайт

Боты не заменяют приложения и сайты полностью, но во многих ситуациях они оказываются более удобным и быстрым решением:

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

Подготовка к созданию бота

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

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

Установка Node.js и настройка окружения

Первый шаг в создании бота — установка Node.js. Это среда выполнения JavaScript, которая позволит запускать ваш код вне браузера. Скачать Node.js можно с официального сайта nodejs.org, где доступны версии для Windows, macOS и Linux.

После установки проверьте, все ли прошло успешно, выполнив команды:

node -v
npm -v

Первая команда покажет текущую версию Node.js, а вторая — версию npm (менеджера пакетов, который устанавливается автоматически вместе с Node.js).

Теперь создайте рабочую директорию, где будет располагаться проект. Например, вы можете назвать ее weather-bot:
mkdir weather-bot
cd weather-bot

Затем запустите проект с помощью npm:

npm init

В командной строке система задаст несколько вопросов о проекте — имя, версию, описание и так далее. Для тестового бота можно оставить большинство значений по умолчанию. Можете изменить только имя пакета (например, weather-bot), а остальное прожмите через Enter.

После завершения процесса в корне проекта появится файл package.json. В нем будут сохранены все настройки проекта и список зависимостей, которые мы будем добавлять дальше:

{
  "name": "weather-bot",
  "version": "1.0.0",
  "description": "Telegram-бот для получения погоды",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "author": "",
  "license": "ISC"
}

Автоматизация перезапуска бота

Во время разработки неудобно вручную перезапускать бота после каждого изменения кода. Эту задачу можно автоматизировать с помощью пакета nodemon, который сам отслеживает изменения файлов и перезапускает приложение.

Установите его:

npm i nodemon --save-dev

Теперь в package.json можно изменить команду запуска:

"scripts": {
  "start": "nodemon src/index.js"
}

После этого достаточно выполнить:

npm start

Бот будет автоматически перезапускаться при каждом сохранении файла.

Выбор библиотек для разработки

Когда проект уже инициализирован, нужно подключить библиотеки, которые помогут нам быстро и удобно разработать погодного бота. Главная задача — упростить работу с Telegram API, чтобы не писать все вручную.

Для этого есть несколько популярных решений:

В качестве примера мы с вами создадим простого бота — Weather Helper, который будет присылать пользователю текущую погоду по названию города. Для него остановимся на grammY — он позволит писать чистый и короткий код без лишних конструкций.

Кроме того, нам нужно где-то хранить секретный токен, который выдает BotFather, поэтому понадобится использовать библиотеку dotenv. Она позволяет держать токены и ключи в файле .env, не добавляя их в код напрямую.

Установим необходимые пакеты:

npm i grammy dotenv

После установки в проекте появятся:

Создание структуры проекта

Чтобы код было удобно поддерживать и развивать, стоит заранее продумать структуру проекта. Даже у простого погодного бота со временем могут появиться новые функции — например, сохранение избранных городов, прогноз на несколько дней или уведомления.

Минимальная структура может выглядеть так:

weather-bot/
│── src/
│   ├── index.js       # основной файл, точка входа
│   ├── config.js      # подключение dotenv и работа с переменными окружения
│   ├── bot.js         # логика бота (команды, обработчики сообщений)
│   └── services/
│       └── weather.js # отдельный модуль для работы с API погоды
│── .env               # секретные данные (токен бота, ключ API погоды)
│── package.json
│── package-lock.json
│── .gitignore

Где:

Создание Telegram-бота

Но прежде чем написать код, нужно зарегистрировать самого бота в Telegram. Для этого существует специальный сервисный бот — @BotFather. Он отвечает за создание и управление всеми ботами в экосистеме.

Если имя свободно, BotFather зарегистрирует бота и пришлет вам сообщение с токеном. Это длинная строка символов, которая используется для доступа к API. Храните его в секрете — по этому токену можно управлять вашим ботом.

Теперь у вас есть пустой бот в Telegram, который готов к работе. Дальше можно написать для него код. Но прежде чем писать хоть строчку кода для бота, нужно позаботиться о безопасности.

Разработка Telegram-бота

Шаг 1. Создайте файл .env и настройте .gitignore

Самое уязвимое место — это токен, который вы получили у BotFather. Если он случайно попадет в открытый доступ, ваш бот станет уязвим: кто угодно сможет управлять им.

Файл .env хранит секретные данные, которые мы не хотим прописывать в коде. Для нашего погодного бота это будет токен.

В корне проекта создайте файл с именем .env (без расширений). Запишите в него токен в формате:

BOT_TOKEN=1234567890:ABC-MySecretToken

Чтобы .env случайно не оказался в репозитории (например, на GitHub), добавьте файл .gitignore в корень проекта:

touch .gitignore 

Его задача — подсказать Git, какие файлы нужно игнорировать.

Содержимое файла будет следующим:

node_modules
.env

Здесь node_modules — это папка с установленными библиотеками, ее обычно не хранят в репозиториях, а .env содержит токен и другие приватные данные.

Шаг 2. Минимальный запуск бота в index.js

Теперь, когда токен хранится в .env, можно написать самый простой код для запуска бота. Наша цель — проверить, что бот отвечает хотя бы на команду /start.

В корне проекта заведите папку src и в ней файл index.js:

mkdir src
cd src
touch index.js

Перейдите в него:

nano index.js

Вставьте код:

// Загружаем переменные окружения из .env
require('dotenv').config();
// Подключаем класс Bot из библиотеки grammY
const { Bot } = require('grammy');
// Забираем токен из переменной окружения
const token = process.env.BOT_TOKEN;
// Проверяем наличие токена
if (!token) {
  console.error('BOT_TOKEN не найден. Укажите его в .env');
  process.exit(1);
}
// Создаем экземпляр бота
const bot = new Bot(token);
// Настраиваем реакцию на команду /start
bot.command('start', async (ctx) => {
  await ctx.reply(
    'Привет! Я погодный бот ????\n' +
    'Пока умею только здороваться, но скоро начну показывать погоду.'
  );
});
// Запускаем бота в режиме long polling
bot.start();
console.log('Бот запущен и ждет сообщений');

Затем откройте package.json и в раздел "scripts" добавьте:

"start": "node src/index.js"

В терминале выполните:

npm start

Если все настроено правильно, в консоли появится сообщение:

Бот запущен и ждет сообщений

Откройте чат с вашим ботом и отправьте команду «Старт». В ответ вы получите заданное приветствие.

Шаг 3. Добавьте команды /setcity и /weather

На этом этапе бот начнет выполнять первые полезные функции: запоминать выбранный город и показывать погоду по нему.

mkdir -p src/services
touch src/services/weather.js

В нем будет функция, которая обращается к API погоды. Чтобы было проще, можно использовать бесплатный сервис wttr.in, который работает без ключей.

Вставьте код:

// src/services/weather.js
async function getWeather(city) {
  const url = `https://wttr.in/${encodeURIComponent(city)}?format=3`;
  const res = await fetch(url);
  const text = await res.text();
  // Если сервис вернул ошибку
  if (!text || text.toLowerCase().includes('unknown location')) {
    return 'Не удалось найти такой город. Попробуйте другой.';
  }
  return text;
}
module.exports = { getWeather };
touch src/services/storage.js

Чтобы бот показывал погоду не только по введённому городу, но и запоминал выбор для каждого человека, нам нужно где-то хранить эти данные. Самый простой способ — использовать обычный объект в памяти.

В src/services/storage.js добавьте:
// src/services/storage.js
const users = {};
function setCity(userId, city) {
  users[userId] = city;
}
function getCity(userId) {
  return users[userId];
}
module.exports = { setCity, getCity };
require('dotenv').config();
const { Bot } = require('grammy');
const { getWeather } = require('./services/weather');
const { setCity, getCity } = require('./services/storage');
const token = process.env.BOT_TOKEN;
if (!token) {
  console.error('BOT_TOKEN не найден. Укажите его в .env');
  process.exit(1);
}
const bot = new Bot(token);
// /start
bot.command('start', async (ctx) => {
  await ctx.reply('Привет! Я погодный бот ????\nИспользуй /setcity, чтобы выбрать город.');
});
// /setcity
bot.command('setcity', async (ctx) => {
  // Достаем аргумент после команды
  const parts = ctx.message.text.split(' ');
  const city = parts.slice(1).join(' ');
  if (!city) {
    return ctx.reply('Укажите город после команды. Например: /setcity Москва');
  }
  setCity(ctx.from.id, city);
  await ctx.reply(`Город сохранен: ${city}`);
});
// /weather
bot.command('weather', async (ctx) => {
  const city = getCity(ctx.from.id);
  if (!city) {
    return ctx.reply('Сначала укажите город через /setcity');
  }
  const weather = await getWeather(city);
  await ctx.reply(`Погода для ${city}: ${weather}`);
});
// Запускаем
bot.start();
console.log('Бот запущен и ждет сообщений');
npm start
/setcity Москва

Ответ должен быть следующим:

Город сохранен: Москва
/weather

Ответ будет примерно таким:

Москва: ☀️ +8°C

Шаг 4. Добавьте обработку геолокации и удобную клавиатуру

Сейчас бот умеет показывать погоду только по сохраненному городу. Но Telegram позволяет пользователям отправлять свою геолокацию. Это удобнее: не нужно вручную вводить название города. Давайте сделаем кнопку, чтобы отправить геопозицию было проще.

// src/services/weather.js
async function getWeather(city) {
  const url = `https://wttr.in/${encodeURIComponent(city)}?format=3`;
  const res = await fetch(url);
  const text = await res.text();
  if (!text || text.toLowerCase().includes('unknown location')) {
    return 'Не удалось найти такой город. Попробуйте другой.';
  }
  return text;
}
// Новый метод для координат
async function getWeatherByCoords(lat, lon) {
  const url = `https://wttr.in/${lat},${lon}?format=3`;
  const res = await fetch(url);
  return await res.text();
}
module.exports = { getWeather, getWeatherByCoords };
require('dotenv').config();
const { Bot, Keyboard } = require('grammy');
const { getWeather, getWeatherByCoords } = require('./services/weather');
const { setCity, getCity } = require('./services/storage');
const token = process.env.BOT_TOKEN;
if (!token) {
  console.error('BOT_TOKEN не найден. Укажите его в .env');
  process.exit(1);
}
const bot = new Bot(token);
// /start
bot.command('start', async (ctx) => {
  const keyboard = new Keyboard()
    .requestLocation('???? Отправить геолокацию')
    .resized();
  await ctx.reply(
    'Привет! Я погодный бот ????\n' +
    '— Используй /setcity <город>, чтобы выбрать город\n' +
    '— Или нажми кнопку, чтобы отправить геолокацию',
    { reply_markup: keyboard }
  );
});
// /setcity
bot.command('setcity', async (ctx) => {
  const parts = ctx.message.text.split(' ');
  const city = parts.slice(1).join(' ');
  if (!city) {
    return ctx.reply('Укажите город после команды. Например: /setcity Казань');
  }
  setCity(ctx.from.id, city);
  await ctx.reply(`Город сохранен: ${city}`);
});
// /weather
bot.command('weather', async (ctx) => {
  const city = getCity(ctx.from.id);
  if (!city) {
    return ctx.reply('Сначала укажите город через /setcity или отправьте геолокацию.');
  }
  const weather = await getWeather(city);
  await ctx.reply(`Погода для ${city}: ${weather}`);
});
// Обработка геолокации
bot.on('message:location', async (ctx) => {
  const { latitude, longitude } = ctx.message.location;
  const weather = await getWeatherByCoords(latitude, longitude);
  await ctx.reply(`Погода по твоей геопозиции: ${weather}`);
});
// Запуск
bot.start();
console.log('Бот запущен и ждет сообщений');
npm start

Важно! Отправка геопозиции не доступна через Telegram Desktop. Но вы можете отправить ее через мобильное приложение.

Деплой бота на сервере

Чтобы бот работал не только на вашем компьютере, но и был доступен постоянно, его нужно развернуть на сервере. Мы рассмотрим вариант с VPS от SpaceWeb, где есть готовые образы с Node.js.

Шаг 1. Загрузка проекта на GitHub

Чтобы развернуть бота на сервере, сначала нужно перенести код в удаленный репозиторий. Удобнее всего использовать GitHub.

git init

Эта команда создаст скрытую папку .git, и проект станет репозиторием.

git add .
git commit -m "first commit"

Так вы зафиксируете текущее состояние проекта.

https://github.com/username/weather-bot.git
git branch -M main
git remote add origin https://github.com/username/weather-bot.git

6. Отправьте код на GitHub:

git push -u origin main

После этого ваш проект появится на GitHub.

Шаг 2. Создание сервера

Чтобы бот работал постоянно, нужен удаленный сервер. В SpaceWeb можно арендовать VDS с уже предустановленным Node.js, что значительно упрощает настройку.

Мы рекомендуем:

После активации в панели управления вы получите данные для подключения, включая IP-адрес, логин и пароль.

Шаг 3. Клонирование проекта и установка зависимостей

ssh root@<ваш-ip>
sudo apt-get update
cd /
sudo mkdir weather-bot
cd weather-bot
git --version

Если все в порядке, клонируйте свой репозиторий:

git clone https://github.com/username/weather-bot.git
cd weather-bot

Важно!

npm install
nano .env
BOT_TOKEN=1234567890:ABC-MySecretToken

Сохраните (Ctrl+O, затем Enter) и закройте (Ctrl+X).

npm start

В консоли должно появиться сообщение:

Бот запущен и ждет сообщений

Теперь можно открыть Telegram и убедиться, что бот отвечает.

Шаг 4. Автоматический запуск через pm2

Когда бот запущен напрямую через npm start, он перестает работать после выхода из консоли или перезагрузки сервера. Чтобы этого не происходило, используют менеджер процессов pm2. Он позволяет запускать бота в фоне и автоматически поднимать его при сбоях или перезапуске сервера.

sudo npm install pm2 -g
sudo pm2 start src/index.js --name "weather-bot" --watch

Где:

sudo pm2 startup
sudo pm2 save

Теперь ваш бот будет работать в фоне и автоматически запускаться при перезагрузке сервера. Это финальный штрих деплоя — бот готов к круглосуточной работе.

Как гарантировать безопасность бота

Даже простой Telegram-бот должен быть защищен, ведь токен или уязвимость в коде могут привести к тому, что злоумышленники получат доступ к управлению. Чтобы снизить риски, стоит соблюдать несколько правил:

Заключение

Мы прошли путь от установки Node.js и подготовки окружения до деплоя рабочего Telegram-бота на сервер. В качестве примера сделали погодного бота, который умеет запоминать город, показывать прогноз и принимать геолокацию. На его основе можно экспериментировать дальше: добавить другие источники данных, встроить клавиатуры или расширить список команд.

Главное, чтобы теперь вам был понятен общий процесс: как устроена структура проекта, какие библиотеки помогают в разработке и каким образом бот может работать круглосуточно. Этот пример можно взять за основу и адаптировать под свои задачи.

Перейти на оригинал