UNPKG

umbot

Version:

Мультиплатформенный фреймворк для создания голосовых навыков и чат-ботов с единой бизнес-логикой. Встроенная поддержка ВКонтакте, Telegram, Viber, MAX, Яндекс Алисы, Маруси и Сбера SmartApp. Архитектура на адаптерах позволяет подключать любые другие платф

220 lines (219 loc) 9.41 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MarusiaAdapter = void 0; const index_1 = require("../../../index"); 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"); /** * Адаптер, обеспечивающий полную поддержку платформы Маруси от ВК. Позволяет разрабатывать навыки для Маруси на TypeScript с использованием всего функционала платформы: от обработки голосовых запросов до работы с карточками и кнопками. * * Этот адаптер автоматически обрабатывает входящие webhook`и от Маруси, * преобразует их в унифицированный формат фреймворка и формирует ответ, * совместимый с требованиями платформы. Подключается одной строкой и * не мешает работе других адаптеров (например, для Telegram или VK). * * Поддерживает: * - голосовые и текстовые запросы; * - сохранение состояния (user/application/session); * - карточки, кнопки, TTS-эффекты; * - health-check (`ping` → `pong`); * * Подключается как любой другой адаптер: `bot.use(new MarusiaAdapter(token))`. * Несколько адаптеров могут работать одновременно — система сама выберет подходящий * на основе заголовков и структуры входящего запроса. * @example * ```ts * // Простейший навык, который отвечает на приветствие * import { Bot } from 'umbot'; * import { MarusiaAdapter } from 'umbot/plugins'; * * const bot = new Bot() * .use(new MarusiaAdapter('YOUR_MARUSIA_TOKEN')) * .addCommand('start', ['привет'], (_text, ctx) => { * ctx.text = 'Привет! Я твой первый навык для Маруси'; * }); * * bot.start('localhost', 3000); * ``` * * @see Bot * @see BotController * @see BasePlatform */ class MarusiaAdapter extends Base_1.BasePlatform { platformName = constants_1.T_MARUSIA; init(appContext) { super.init(appContext); if (this._token) { appContext.appConfig.tokens[this.platformName].token = this._token; } } isPlatformOnQuery(query, headers) { if (headers?.['x-marusia-signature']) { return true; } if (!query) { this.appContext?.logWarn(`MarusiaAdapter:isPlatformOnQuery(): ${Base_1.EMPTY_QUERY_ERROR}`); return false; } if (query.request && query.version && query.session) { if (query.meta?.client_id?.includes('MailRu')) { return true; } else if (query.session.application?.application_id) { return (query.session.application?.application_id == query.session.application?.application_id.toLowerCase()); } } return false; } /** * Инициализирует команду пользователя от Маруси. * Обрабатывает различные типы запросов и сохраняет команду в контроллере * @param request Объект запроса от пользователя * @param controller Контроллер приложения */ #initUserCommand(request, controller) { (0, utils_1.initUserCommand)(request, controller); } /** * Устанавливает состояние приложения. * Определяет тип хранилища и сохраняет состояние в контроллере * @param controller Контроллер приложения * @param state Объект состояния из запроса Маруси (`user` или `session`) */ #setState(controller, state) { if (state.user) { controller.state = state.user; controller.platformOptions.stateName = 'user_state_update'; } else if (state.session) { controller.state = state.session; controller.platformOptions.stateName = 'session_state'; } } setQueryData(query, controller) { if (this.appContext) { if (query) { if (query.session === undefined && query.request === undefined) { if (query.account_linking_complete_event) { controller.userEvents = { auth: { status: true, }, }; return true; } controller.platformOptions.error = 'MarusiaAdapter:setQueryData(): Переданы некорректные данные!'; return false; } controller.requestObject = query; this.#initUserCommand(query.request, controller); if (query.state !== undefined) { this.#setState(controller, query.state); } controller.platformOptions.session = query.session; controller.userId = query.session.user_id + ''; controller.nlu.setNlu(query.request.nlu || {}); controller.userMeta = query.meta || {}; controller.messageId = query.session.message_id; controller.platformOptions.appId = query.session.skill_id; controller.isScreen = controller.userMeta.interfaces.screen !== undefined; return true; } else { controller.platformOptions.error = `MarusiaAdapter:setQueryData(): ${Base_1.EMPTY_QUERY_ERROR}`; } } else { console.error(`MarusiaAdapter:setQueryData(): ${Base_1.EMPTY_CONTEXT_ERROR}`); } return false; } /** * Формирует ответ для пользователя. * Собирает текст, TTS, карточки и кнопки в единый объект ответа * @returns {Promise<IMarusiaResponse>} Объект ответа для Маруси */ async _getResponse(controller) { const response = { text: index_1.Text.resize(controller.text, 1024), tts: index_1.Text.resize(controller.tts, 1024), end_session: controller.isEnd, }; if (controller.isScreen) { if (controller.isCardInit() && controller.card.images.length) { response.card = (await controller.card.getCards(Card_1.cardProcessing, controller)); if (!response.card) { response.card = undefined; } } response.buttons = controller.isButtonsInit() ? controller.buttons.getButtons(Button_1.buttonProcessing) : []; } return response; } async getContent(controller, stateData) { const result = { version: constants_1.VERSION, }; await this._initTTS(controller); result.response = await this._getResponse(controller); result.session = controller.platformOptions.session; if (controller.platformOptions.stateName && stateData) { result[controller.platformOptions.stateName] = stateData; } this._timeLimitLog(controller); return result; } async soundProcessing(controller) { // eslint-disable-next-line require-atomic-updates controller.tts = await controller.sound.getSounds(controller.tts, Sound_1.soundProcessing, controller); } getLocalStorage(controller) { return controller.state; } isLocalStorage(controller) { return controller.state !== null; } send() { return false; } getQueryExample(query, userId, count, state) { return { meta: { locale: 'ru-Ru', timezone: 'UTC', client_id: 'MailRu_local', interfaces: { payments: null, account_linking: null, }, }, session: { message_id: count, session_id: 'local', skill_id: 'local_test', user_id: userId, new: count === 0, }, request: { command: query.toLowerCase(), original_utterance: query, type: 'SimpleUtterance', }, state: { session: state, }, version: '1.0', }; } } exports.MarusiaAdapter = MarusiaAdapter;