Node.js-бот для Телеграм: CRUD-L через аргументы команд
Я продолжаю описывать собственное погружение в мир телеграм-ботов, начатое в предыдущей публикации. Тогда я создал простого бота на Node.js с тремя стандартными командами (/start
, /help
, /settings
) с использованием библиотеки grammY, который мог работать в режимах long polling
и webhook
. В этот раз я разработал бота, который манипулирует данными в базе по шаблону CRUD + List (CRUDL) с помощью аргументов команд. Из-за своей простоты, граничащей с примитивностью, это решение не подходит для коммерческих проектов, но может быть полезным в персональных проектах.
Демонстрационный телеграм-бот @flancer64/tg-demo-crudl позволяет создавать в БД список контактов и номеров телефонов. Вот список соответствующих команд:
/create <имя> <номер телефона>
: добавляет новый контакт в список (/create John 123456789
)/read
: выводит информацию о контакте по указанному идентификатору (/read 1
)/update
: обновляет существующий контакт (<новое имя> <новый номер телефона> /update 1 Jane 987654321
)/delete
: удаляет контакт из списка (/delete 1
)/list
: отображает все сохранённые контакты
Основные технологии проекта
grammY — npm-пакет для взаимодействия с Telegram API из Node.js.
Knex.js — npm-пакет, который позволяет работать с различными СУБД (уровень абстракции базы данных, DBAL).
@teqfw/di — npm-пакет для внедрения зависимостей, обеспечивающий гибкость и расширяемость приложения.
@flancer32/teq-telegram-bot — npm-пакет для выполнения типовых операций телеграм-бота (запуск в режиме long polling и webhook, создание списка команд, настройка бота и т.п.).
Типовая команда
Создание каркаса бота, его регистрация в Телеграм, запуск и остановку я подробно рассмотрел в предыдущей публикации. Там же описана и архитектура проекта. Здесь я продемонстрирую реализацию типовой команды на примере /create
(Demo_Crudl_Back_Bot_Cmd_Create).
Внедрение зависимостей
ES6-модуль ./src/Back/Bot/Cmd/Create.js
обрабатывается контейнером объектов, который создаёт и внедряет необходимые зависимости:
Скрытый текст
export default class Demo_Crudl_Back_Bot_Cmd_Create {
constructor(
{
TeqFw_Core_Shared_Api_Logger$$: logger,
TeqFw_Db_Back_RDb_IConnect$: conn,
TeqFw_Db_Back_Api_RDb_CrudEngine$: crud,
Demo_Crudl_Back_Store_RDb_Schema_Phone$: rdbPhone,
}
) {}
}
TeqFw_Core_Shared_Api_Logger$$: logger
— логгер для трассировки выполнения команды.TeqFw_Db_Back_RDb_IConnect$: conn
— соединение с базой данных.TeqFw_Db_Back_Api_RDb_CrudEngine$: crud
— объект для выполнения базовых операций с БД.Demo_Crudl_Back_Store_RDb_Schema_Phone$: rdbPhone
— DTO для описания структуры данных, хранимых в базе данных.
Первые три зависимости являются стандартными инструментами из моего набора TeqFW, а последняя относится непосредственно к предметной области.
DTO для БД
DTO Demo_Crudl_Back_Store_RDb_Schema_Phone
описывает простую структуру из четырёх полей:
class Dto {
date_created;
id;
name;
phone;
}
которая соответствует следующей таблице в базе данных SQLite:
CREATE TABLE main.phone
(
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name VARCHAR(255) NOT NULL,
phone VARCHAR(255) NOT NULL,
date_created DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL
);
Этого достаточно, чтобы иметь представление о структуре данных в БД. Демо-бот работает с SQLite, но DBAL Knex.js позволяет также использовать PostgreSQL, MariaDB/MySQL, MS SQL и Oracle. Нужно лишь установить соответствующий npm-пакет для работы с выбранной СУБД.
Параметры подключения Knex.js к соответствующей СУБД прописываются в конфигурационном файле ./cfg/local.json
(шаблон настроек — в ./cfg/init.json). В демо-версии используется SQLite, файл в базой располагается в ./var/data.db
. Для работы с базой предназначены команды:
$ ./bin/tequila.mjs db-init
$ ./bin/tequila.mjs db-export -f ./var/data.json
$ ./bin/tequila.mjs db-import -f ./var/data.json
Назначения команд понятны из названия: создание структур данных (таблица), экспорт и импорт данных в JSON-формат.
Шаблон обработки Телеграм-команды
Так как наш бот для работы использует платформу grammY, то типовой обработчик команд работает с объектами кода этой платформы (ctx). Вот скелет обработчика:
const handler = async (ctx) => {
let msg = 'The command has failed.';
const from = ctx.message.from;
logger.info(`Command has been received from user '${from.username}' (id:${from.id})`);
const trx = await conn.startTransaction();
try {
// const parts = ctx.message.text.split(' ');
// ...
await trx.commit();
} catch (e) {
await trx.rollback();
msg = e.toString();
logger.error(msg);
}
// https://core.telegram.org/bots/api#sendmessage
await ctx.reply(msg, {
parse_mode: 'HTML',
});
};
Алгоритм действий в обработчике такой:
залогировать принятую команду
инициировать транзакцию для работы с БД
выполнить действия с БД в рамках транзакции и сформировать ответ на принятую команду
зафиксировать изменения в БД
сфомировать сообщение для пользователя об успешном завершении выполнения команды
в случае возникновения ошибок отдать пользователю сообщение об ошибке
Выполнение команды
Данный фрагмент кода демонстрирует непосредственно обработку самой команды create
— извлечение данных из команды и сохранение их в БД:
try {
const parts = ctx.message.text.split(' ');
const dto = rdbPhone.createDto();
dto.name = parts[1];
dto.phone = parts[2];
const {[A_PHONE.ID]: id} = await crud.create(trx, rdbPhone, dto);
await trx.commit();
msg = `New record #${id} has been created.`;
logger.info(msg);
} catch (e) {...}
Я использую свою собственную обёртку для DBAL Knex.js, которая позволяет мне выполнять базовые операции (CRUD) с DTO. Если у вас другая библиотека для работы с данными в БД (например, sequelize или prisma), то у вас здесь будет другой код. Но всю остальную обвязку можно оставлять (за исключением транзакций).
Пример работы бота
После создания бота в BotFather, получения API-ключа и конфигурировании бота (./cfg/local.json
) нужно создать таблицы в БД:
$ ./bin/tequila.mjs db-init
Запуск бота в режиме long polling:
$ ./bin/tequila.mjs tg-bot-start
или
$ npm start
Вызов справки
Create
Read
Update
List
Delete
Заключение
В данной статье я описал процесс создания простого телеграм-бота на Node.js с использованием библиотеки grammY, который поддерживает операции CRUD-L (создание, чтение, обновление, удаление и список). Мы рассмотрели, как с помощью команд с аргументами можно манипулировать данными в базе данных. Несмотря на простоту, данный подход открывает возможности для персональных проектов, где не требуется сложная бизнес-логика, но важна простота в реализации.
Если вы ищете простое, но мощное решение для работы с базами данных через телеграм-ботов, то данный проект может стать отличной отправной точкой для реализации ваших фантазий.