umbot
Version:
Мультиплатформенный фреймворк для создания голосовых навыков и чат-ботов с единой бизнес-логикой. Встроенная поддержка ВКонтакте, Telegram, Viber, MAX, Яндекс Алисы, Маруси и Сбера SmartApp. Архитектура на адаптерах позволяет подключать любые другие платф
182 lines (181 loc) • 8.47 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.VkAdapter = void 0;
const index_1 = require("../../../index");
const API_1 = require("../API");
const Base_1 = require("../Base/Base");
const Button_1 = require("./Button");
const Card_1 = require("./Card");
const Sound_1 = require("./Sound");
const constants_1 = require("./constants");
const utils_1 = require("../Base/utils");
/**
* Адаптер, обеспечивающий поддержку платформы VK. Позволяет разрабатывать чат-ботов для мессенджера ВК на TypeScript с использованием кросс-платформенного функционала: обработка текстовых запросов, работа с карточками и кнопками.
*
* Подключение адаптера не требует изменения существующей бизнес-логики: после интеграции
* все команды и обработчики, написанные для umbot, автоматически становятся доступны для VK.
* Единый интерфейс позволяет одновременно использовать одну бизнес-логику для нескольких
* платформ (Viber, VK, Алиса и др.) без дублирования кода.
*
* Этот адаптер автоматически обрабатывает входящие webhook`и от мессенджера VK,
* преобразует их в унифицированный формат фреймворка и формирует ответ,
* совместимый с требованиями платформы. Подключается одной строкой и
* не мешает работе других адаптеров (например, для Алисы или Маруси).
*
* Поддерживает:
* - голосовые и текстовые запросы;
* - карточки, кнопки;
*
* Подключается как любой другой адаптер: `bot.use(new VkAdapter(token))`.
* Несколько адаптеров могут работать одновременно — система сама выберет подходящий
* на основе заголовков и структуры входящего запроса.
* @example
* ```ts
* // Простейший бот для VK, который отвечает на приветствие
* import { Bot } from 'umbot';
* import { VkAdapter } from 'umbot/plugins';
*
* const bot = new Bot()
* .use(new VkAdapter('YOUR_VK_TOKEN', { vk_confirmation_token: 'YOUR_CONFIRMATION_TOKEN' }))
* .addCommand('start', ['привет'], (_text, ctx) => {
* ctx.text = 'Привет! Я твой первый бот для ВК';
* });
*
* bot.start('localhost', 3000);
* ```
*
* @see Bot
* @see BotController
* @see BasePlatform
*/
class VkAdapter extends Base_1.BasePlatform {
platformName = constants_1.T_VK;
isVoice = false;
limit = 30;
signatureName = 'x-vk-signature';
init(appContext) {
super.init(appContext);
if (this._token) {
appContext.appConfig.tokens[this.platformName].token = this._token;
}
if (this._platformOptions?.vk_confirmation_token) {
appContext.appConfig.tokens[this.platformName].confirmation_token = this
._platformOptions.vk_confirmation_token;
}
if (this._platformOptions?.vk_api_version) {
appContext.appConfig.tokens[this.platformName].api_version = this._platformOptions
.vk_api_version;
}
}
isPlatformOnQuery(query, headers) {
if (headers?.['x-vk-signature']) {
return true;
}
if (!query) {
this.appContext?.logWarn(`VkAdapter.isPlatformOnQuery(): ${Base_1.EMPTY_QUERY_ERROR}`);
return false;
}
return (query.type !== undefined &&
query.group_id !== undefined &&
(query.object !== undefined ||
query.secret !== undefined ||
query.type === 'confirmation'));
}
async setQueryData(query, controller) {
if (!this.appContext) {
console.error(`VkAdapter.setQueryData(): ${Base_1.EMPTY_CONTEXT_ERROR}`);
return false;
}
if (!query) {
controller.platformOptions.error = `VkAdapter.setQueryData(): ${Base_1.EMPTY_QUERY_ERROR}`;
return false;
}
controller.requestObject = query;
switch (query.type) {
case 'confirmation':
controller.platformOptions.sendInInit = this._platformOptions
?.vk_confirmation_token;
return true;
case 'message_new':
if (query.object !== undefined) {
const object = query.object;
controller.userId = object.message.from_id;
const rawText = object.message.text ?? '';
controller.userCommand = rawText.toLowerCase().trim();
controller.originalUserCommand = rawText.trim();
controller.messageId = object.message.id;
controller.payload = (0, utils_1.tryParse)(object.message.payload || null);
const user = await new API_1.VkRequest(this.appContext).usersGet(controller.userId);
if (user) {
const thisUser = {
username: null,
first_name: user.first_name || null,
last_name: user.last_name || null,
};
controller.nlu.setNlu({ thisUser });
}
return true;
}
return false;
case 'message_event':
if (query.object?.payload) {
controller.userCommand = (typeof query.object.payload === 'string'
? query.object.payload
: JSON.stringify(query.object.payload))?.toLowerCase();
controller.userId = query.object.user_id;
controller.payload = (0, utils_1.tryParse)(query.object.payload);
controller.messageId = query.object.conversation_message_id || 0;
return true;
}
return false;
default:
controller.platformOptions.error =
'VkAdapter:setQueryData(): Некорректный тип данных!';
break;
}
return false;
}
async getContent(controller) {
if (!controller.skipAutoReply) {
const keyboard = controller.isButtonsInit()
? controller.buttons.getButtonJson(Button_1.buttonProcessing)
: null;
const params = {};
if (keyboard) {
params.keyboard = keyboard;
}
if (controller.isCardInit() && controller.card.images.length) {
const attach = await controller.card.getCards(Card_1.cardProcessing, controller);
if (attach.type === undefined) {
params.attachments = attach;
}
else {
params.template = attach;
}
}
if (controller.isSoundInit() && controller.sound.sounds.length) {
const attach = await controller.sound.getSounds(controller.tts, Sound_1.soundProcessing, controller);
params.attachments = { ...attach, ...params.attachments };
}
const vkApi = new API_1.VkRequest(this.appContext);
await vkApi.messagesSend(controller.userId, index_1.Text.resize(controller.text, 4096), params);
}
return 'ok';
}
static isVoice() {
return false;
}
getQueryExample(query, userId, count) {
return {
type: 'message_new',
object: {
message: {
from_id: +userId,
text: query,
id: count,
},
},
};
}
}
exports.VkAdapter = VkAdapter;