#Telegram-бот для CRM
🤖 Сложность: medium | Скоупы: crm | Стек: Node.js, grammy
#Что делаем
Создаём Telegram-бота, который периодически опрашивает CRM через Вайбкод Entity API и уведомляет менеджера о новых сделках. Бот отправляет форматированное сообщение с названием сделки, суммой и контактом. Это позволяет моментально реагировать на входящие лиды, не заходя в Bitrix24.
#Необходимо
- API-ключ Вайбкод с правами
crm - Telegram Bot Token (получить у @BotFather)
- Node.js 18+
- Пакеты:
grammy,node-cron
#Полный код
// telegram-crm-bot.js
// Telegram-бот для уведомлений о новых сделках из Bitrix24
import { Bot } from 'grammy';
import cron from 'node-cron';
// Конфигурация из переменных окружения
const API_KEY = process.env.VIBE_API_KEY;
const BASE_URL = process.env.VIBE_BASE_URL; // например https://vibecode.bitrix24.tech
const BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN;
const CHAT_ID = process.env.TELEGRAM_CHAT_ID; // ID чата менеджера
const bot = new Bot(BOT_TOKEN);
const HEADERS = {
'X-Api-Key': API_KEY,
'Content-Type': 'application/json',
};
// Храним ID последней обработанной сделки
let lastSeenDealId = 0;
// Запрос новых сделок через Entity API
async function fetchNewDeals() {
try {
const response = await fetch(
`${BASE_URL}/v1/deals/search`,
{
method: 'POST',
headers: HEADERS,
body: JSON.stringify({
filter: {
id: { $gt: lastSeenDealId },
// Примечание: на порталах с несколькими воронками стадия может быть
// C2:NEW, C4:NEW и т.д. Используйте $contains или фильтрацию на клиенте.
stageId: 'NEW',
},
sort: 'id',
select: ['id', 'title', 'amount', 'currency', 'contactId', 'createdAt'],
}),
}
);
const { data } = await response.json();
return data || [];
} catch (error) {
console.error('Ошибка при получении сделок:', error.message);
return [];
}
}
// Получаем имя контакта по ID
async function fetchContactName(contactId) {
if (!contactId) return 'Не указан';
try {
const response = await fetch(`${BASE_URL}/v1/contacts/${contactId}`, {
headers: { 'X-Api-Key': API_KEY },
});
const { data } = await response.json();
return `${data.name || ''} ${data.lastName || ''}`.trim();
} catch {
return 'Не удалось загрузить';
}
}
// Форматируем сообщение для Telegram
function formatDealMessage(deal, contactName) {
return [
`🆕 <b>Новая сделка</b>`,
``,
`📋 <b>Название:</b> ${deal.title}`,
`💰 <b>Сумма:</b> ${deal.amount || '0'} ${deal.currency || 'RUB'}`,
`👤 <b>Контакт:</b> ${contactName}`,
`📅 <b>Создана:</b> ${new Date(deal.createdAt).toLocaleString('ru-RU')}`,
`🔗 <b>ID:</b> ${deal.id}`,
].join('\n');
}
// Проверяем новые сделки и отправляем уведомления
async function checkAndNotify() {
console.log(`[${new Date().toISOString()}] Проверяем новые сделки...`);
const deals = await fetchNewDeals();
for (const deal of deals) {
const contactName = await fetchContactName(deal.contactId);
const message = formatDealMessage(deal, contactName);
await bot.api.sendMessage(CHAT_ID, message, { parse_mode: 'HTML' });
console.log(`Уведомление отправлено: сделка #${deal.id}`);
// Обновляем последний обработанный ID
lastSeenDealId = Math.max(lastSeenDealId, deal.id);
}
if (deals.length === 0) {
console.log('Новых сделок нет');
}
}
// Команды бота
bot.command('start', (ctx) => {
ctx.reply('👋 Бот CRM-уведомлений запущен! Вы будете получать сообщения о новых сделках.');
});
bot.command('status', (ctx) => {
ctx.reply(`📊 Последний обработанный ID сделки: ${lastSeenDealId}`);
});
// Запускаем опрос каждые 2 минуты
cron.schedule('*/2 * * * *', checkAndNotify);
// Запускаем бота
bot.start();
console.log('🤖 Telegram CRM-бот запущен');
#Как это работает
- Бот запускается и подключается к Telegram API через библиотеку grammy.
- Каждые 2 минуты cron-задача вызывает функцию
checkAndNotify, которая запрашивает новые сделки через Entity API (POST /v1/deals/search) с фильтром по ID больше последнего обработанного. - Для каждой новой сделки бот загружает имя контакта через
GET /v1/contacts/:id. - Полученные данные форматируются в HTML-сообщение и отправляются в указанный Telegram-чат.
- ID последней обработанной сделки сохраняется в памяти, чтобы не отправлять дубликаты при следующем опросе.
#Что можно улучшить
- Сохранять
lastSeenDealIdв файл или Redis, чтобы не терять прогресс при перезапуске - Добавить инлайн-кнопки для быстрых действий прямо из Telegram (взять в работу, назначить ответственного)
- Поддержать несколько менеджеров: маршрутизировать уведомления по ответственному в сделке
- Добавить фильтры по сумме или типу сделки через команды бота