Telegram-бот для команды поверх API
Небольшой бот для чата поддержки в Telegram: сообщает о новом тикете и отвечает клиенту командой /reply T-1042 текст. Пример — для команды, не для клиентов.
Клиенты пишут в Telegram?
Для этого бот не нужен — подключите канал Telegram в кабинете, сообщения клиентов сразу станут тикетами: Мессенджеры, формы и приём по API.
Что понадобится
Бот от @BotFather и id чата команды.
Ключ API с правами
tickets:read,tickets:write,webhooksот сотрудника, от имени которого бот будет отвечать.Сервер с адресом https для вебхуков Дескуса и Telegram.
Код на Node.js
import crypto from "node:crypto";
import express from "express";
const { DESKUS_KEY, DESKUS_WEBHOOK_SECRET, TG_TOKEN, TG_CHAT } = process.env;
const deskus = (path, init = {}) =>
fetch(`https://app.deskus.ru/api/v1${path}`, {
...init,
headers: { Authorization: `Bearer ${DESKUS_KEY}`, "Content-Type": "application/json", ...init.headers },
});
const tg = (method, body) =>
fetch(`https://api.telegram.org/bot${TG_TOKEN}/${method}`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
const app = express();
// 1. Новый тикет → сообщение в чат команды
app.post("/deskus", express.raw({ type: "application/json" }), async (req, res) => {
const sign = "sha256=" + crypto.createHmac("sha256", DESKUS_WEBHOOK_SECRET).update(req.body).digest("hex");
const got = Buffer.from(req.get("X-Deskus-Signature") || "");
if (got.length !== sign.length || !crypto.timingSafeEqual(got, Buffer.from(sign))) return res.sendStatus(401);
res.sendStatus(200);
const event = JSON.parse(req.body.toString("utf8"));
if (event.type === "ticket.created") {
const { ticket, client } = event.data;
await tg("sendMessage", {
chat_id: TG_CHAT,
text: `Новый тикет ${ticket.number}: ${ticket.subject}\nОт: ${client?.name ?? "—"}\n${ticket.url}`,
});
}
});
// 2. /reply T-1042 текст → ответ клиенту
app.post("/telegram", express.json(), async (req, res) => {
res.sendStatus(200);
const text = req.body.message?.text ?? "";
const match = /^\/reply\s+(\S+)\s+([\s\S]+)/.exec(text);
if (!match || String(req.body.message.chat.id) !== TG_CHAT) return;
const [, number, reply] = match;
const answer = await deskus(`/tickets/${encodeURIComponent(number)}/messages`, {
method: "POST",
headers: { "Idempotency-Key": `tg-${req.body.message.message_id}` },
body: JSON.stringify({ type: "reply", text: reply }),
});
await tg("sendMessage", {
chat_id: TG_CHAT,
text: answer.ok ? `Ответ в ${number} отправлен` : `Не отправлен: ${(await answer.json()).error.message}`,
});
});
app.listen(3000);Подключить
Подпишите бота на события Дескуса: POST /webhooks с адресом
https://ваш-сервер/deskusи событиемticket.created. Секрет из ответа — вDESKUS_WEBHOOK_SECRET.Направьте Telegram на
https://ваш-сервер/telegram— методsetWebhookBot API.Напишите в чат
/reply T-1042 Посылка в пути— клиент получит ответ, а в ленте тикета он будет подписан сотрудником ключа.
Отвечать через бота может любой участник чата: ключ один на всех. Держите чат закрытым или сверяйте from.id отправителя со списком сотрудников.
