@sberdevices/assistant-client
Version:
Модуль взаимодействия с виртуальным ассистентом
431 lines (413 loc) • 18.7 kB
JavaScript
import { c as createNanoEvents, _ as __spreadArrays, a as __rest, b as __assign, p as proto } from './typings-4aa98dc6.js';
// Unique ID creation requires a high quality random # generator. In the browser we therefore
// require the crypto API and do not support built-in fallback to lower quality random number
// generators (like Math.random()).
// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. Also,
// find the complete implementation of crypto (msCrypto) on IE11.
var getRandomValues = typeof crypto != 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto) || typeof msCrypto != 'undefined' && typeof msCrypto.getRandomValues == 'function' && msCrypto.getRandomValues.bind(msCrypto);
var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef
function rng() {
if (!getRandomValues) {
throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
}
return getRandomValues(rnds8);
}
/**
* Convert array of 16 byte values to UUID string format of the form:
* XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
*/
var byteToHex = [];
for (var i = 0; i < 256; ++i) {
byteToHex[i] = (i + 0x100).toString(16).substr(1);
}
function bytesToUuid(buf, offset) {
var i = offset || 0;
var bth = byteToHex; // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
return [bth[buf[i++]], bth[buf[i++]], bth[buf[i++]], bth[buf[i++]], '-', bth[buf[i++]], bth[buf[i++]], '-', bth[buf[i++]], bth[buf[i++]], '-', bth[buf[i++]], bth[buf[i++]], '-', bth[buf[i++]], bth[buf[i++]], bth[buf[i++]], bth[buf[i++]], bth[buf[i++]], bth[buf[i++]]].join('');
}
function v4(options, buf, offset) {
var i = buf && offset || 0;
if (typeof options == 'string') {
buf = options === 'binary' ? new Array(16) : null;
options = null;
}
options = options || {};
var rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
rnds[6] = rnds[6] & 0x0f | 0x40;
rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided
if (buf) {
for (var ii = 0; ii < 16; ++ii) {
buf[i + ii] = rnds[ii];
}
}
return buf || bytesToUuid(rnds);
}
var createNanoObservable = function (observerFunc) {
var _a = createNanoEvents(), on = _a.on, emit = _a.emit;
var subscribe = function (_a) {
var next = _a.next;
var unsubscribe = on('next', next);
return { unsubscribe: unsubscribe };
};
observerFunc({
next: function (data) {
emit('next', data);
},
});
return {
subscribe: subscribe,
};
};
var findCommandIndex = function (arr, command) {
var _a, _b;
var index = -1;
if (command.type === 'character') {
index = arr.findIndex(function (c) { return c.type === 'character' && c.character.id === command.character.id; });
}
else if (command.type === 'insets') {
index = arr.findIndex(function (c) { return c.type === 'insets'; });
}
else if (command.type === 'app_context') {
index = arr.findIndex(function (c) { return c.type === 'app_context'; });
}
else if (command.sdk_meta && ((_a = command.sdk_meta) === null || _a === void 0 ? void 0 : _a.mid) && ((_b = command.sdk_meta) === null || _b === void 0 ? void 0 : _b.mid) !== '-1') {
index = arr.findIndex(function (c) { var _a, _b; return ((_a = c.sdk_meta) === null || _a === void 0 ? void 0 : _a.mid) === ((_b = command.sdk_meta) === null || _b === void 0 ? void 0 : _b.mid); });
}
return index;
};
var appInitialData = (function () {
var isPulled = false;
var pulled = [];
var committed = [];
var diff = [];
var isCommandWasPulled = function (command) { return findCommandIndex(pulled, command) >= 0; };
return {
/**
* Прочитать appInitialData
* @returns Массив комманд
*/
pull: function () {
isPulled = true;
pulled = __spreadArrays((window.appInitialData || []));
return __spreadArrays(pulled);
},
/**
* Зафиксировать текущее состояние appInitialData
*/
commit: function () {
committed = __spreadArrays((window.appInitialData || []));
diff =
isPulled === true
? (window.appInitialData || []).filter(function (c) { return !isCommandWasPulled(c); })
: __spreadArrays((window.appInitialData || []));
},
/**
* Возвращает диф appInitialData между pull и commit
* @returns Массив комманд
*/
diff: function () {
return __spreadArrays(diff);
},
/**
* Возвращает флаг наличия command в appInitialData на момент commit
* @param command Команда, которую нужно проверить на наличие в appInitialData
* @returns true - если команда была в appInitialData
*/
isCommitted: function (command) {
var commandIndex = findCommandIndex(committed, command);
var isCommitted = commandIndex >= 0;
if (isCommitted) {
committed.splice(commandIndex, 1);
}
return isCommitted;
},
/**
* Возвращает первое сообщение из appInitialData, подходящее под фильтры param
* @param param Параметры: тип сообщения (например, smart_app_data)
* и тип команды (значение поля smart_app_data.type)
* @returns Первое сообщение, соответствующее параметрам или undefined
*/
find: function (_a) {
var type = _a.type, command = _a.command;
var data = __spreadArrays((window.appInitialData || []));
var result = data.find(function (data) {
if (!command && type && type === data.type) {
return true;
}
var isCommandInSmartAppData = command && 'smart_app_data' in data;
if (!isCommandInSmartAppData) {
return;
}
if (command === data.smart_app_data.command ||
command === data.smart_app_data.type) {
return true;
}
return false;
});
return (result && 'smart_app_data' in result ? result.smart_app_data : result);
},
};
})();
var excludeTags = ['A', 'AUDIO', 'BUTTON', 'INPUT', 'OPTION', 'SELECT', 'TEXTAREA', 'VIDEO'];
function inIframe() {
try {
return window.self !== window.top;
}
catch (e) {
return true;
}
}
if (typeof window !== 'undefined' && inIframe()) {
var postMessage_1 = function (action) {
var _a;
(_a = window.top) === null || _a === void 0 ? void 0 : _a.postMessage(JSON.stringify(action), '*');
};
var historyBack_1 = function () {
var prevPage = window.location.href;
window.history.back();
setTimeout(function () {
// закрываем страницу, если переход назад не поменял урл
if (window.location.href === prevPage) {
postMessage_1({ type: 'close' });
}
}, 500);
};
window.appInitialData = [];
window.AssistantHost = {
sendDataContainer: function (json) {
postMessage_1({ type: 'sendDataContainer', payload: json });
},
close: function () {
postMessage_1({ type: 'close' });
},
sendData: function (json) {
postMessage_1({ type: 'sendData', payload: json });
},
setSuggests: function (suggests) {
postMessage_1({ type: 'setSuggests', payload: suggests });
},
setHints: function (hints) {
postMessage_1({ type: 'setHints', payload: hints });
},
ready: function () {
postMessage_1({ type: 'ready' });
},
sendText: function (message) {
postMessage_1({ type: 'sendText', payload: message });
},
};
window.addEventListener('message', function (e) {
var _a, _b, _c, _d, _e, _f, _g, _h;
try {
if (typeof e.data === 'string') {
var data = JSON.parse(e.data);
switch (data.type) {
case 'onBack':
historyBack_1();
break;
case 'onData':
(_b = (_a = window.AssistantClient) === null || _a === void 0 ? void 0 : _a.onData) === null || _b === void 0 ? void 0 : _b.call(_a, data.payload);
break;
case 'onRequestState': {
var state = (_d = (_c = window.AssistantClient) === null || _c === void 0 ? void 0 : _c.onRequestState) === null || _d === void 0 ? void 0 : _d.call(_c);
postMessage_1({ type: 'state', payload: state, requestId: data.requestId });
break;
}
case 'onRequestRecoveryState': {
var recoverystate = (_f = (_e = window.AssistantClient) === null || _e === void 0 ? void 0 : _e.onRequestRecoveryState) === null || _f === void 0 ? void 0 : _f.call(_e);
postMessage_1({ type: 'recoveryState', payload: recoverystate });
break;
}
case 'onStart':
(_h = (_g = window.AssistantClient) === null || _g === void 0 ? void 0 : _g.onStart) === null || _h === void 0 ? void 0 : _h.call(_g);
break;
default:
// eslint-disable-next-line no-console
console.error(e, 'Unknown parsed message');
break;
}
}
}
catch (err) {
// eslint-disable-next-line no-console
console.error(err, 'Unknown message');
}
});
window.addEventListener('keydown', function (_a) {
var _b, _c;
var code = _a.code;
switch (code) {
case 'Enter':
if (document.activeElement && !excludeTags.includes(document.activeElement.tagName)) {
(_c = (_b = document.activeElement).click) === null || _c === void 0 ? void 0 : _c.call(_b);
}
break;
case 'Escape':
historyBack_1();
break;
}
});
}
var createAssistant = function (_a) {
var _b;
var getState = _a.getState, getRecoveryState = _a.getRecoveryState, _c = _a.ready, ready = _c === void 0 ? true : _c;
var currentGetState = getState;
var currentGetRecoveryState = getRecoveryState;
var isInitialCommandsEmitted = false;
var _d = createNanoEvents(), on = _d.on, emit = _d.emit;
var observables = new Map();
var emitCommand = function (command) {
if (command.type === 'smart_app_data') {
emit('command', command.smart_app_data);
}
if (command.type === 'smart_app_error') {
emit('error', command.smart_app_error);
}
return emit('data', command);
};
var cancelTts = typeof ((_b = window.AssistantHost) === null || _b === void 0 ? void 0 : _b.cancelTts) !== 'undefined'
? function () {
var _a, _b;
(_b = (_a = window.AssistantHost).cancelTts) === null || _b === void 0 ? void 0 : _b.call(_a, '');
}
: undefined;
var emitAppInitialData = function () {
if (!isInitialCommandsEmitted) {
appInitialData.diff().forEach(function (c) { return emitCommand(c); });
isInitialCommandsEmitted = true;
}
};
window.AssistantClient = {
onData: function (command) {
var _a, _b, _c;
if (appInitialData.isCommitted(command)) {
return;
}
/// фильтр команды 'назад'
/// может приходить type='system', но в типах это не отражаем
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
if (command.type === 'system' && ((_b = (_a = command.system) === null || _a === void 0 ? void 0 : _a.command) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === 'BACK') {
return;
}
if ((command.type === 'smart_app_data' || command.type === 'smart_app_error') && ((_c = command.sdk_meta) === null || _c === void 0 ? void 0 : _c.requestId) &&
observables.has(command.sdk_meta.requestId)) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
var _d = command.sdk_meta, realReqId = _d.requestId, meta = __rest(_d, ["requestId"]);
var _e = observables.get(command.sdk_meta.requestId) || {}, requestId = _e.requestId, next = _e.next;
if (Object.keys(meta).length > 0 || requestId) {
// eslint-disable-next-line @typescript-eslint/camelcase
command.sdk_meta = __assign({}, meta);
if (requestId) {
// eslint-disable-next-line @typescript-eslint/camelcase
command.sdk_meta = { requestId: requestId };
}
}
if (next) {
next(command.type === 'smart_app_data' ? command : command);
}
return;
}
emitCommand(command);
},
onRequestState: function () {
return currentGetState();
},
onRequestRecoveryState: function () {
if (currentGetRecoveryState) {
return currentGetRecoveryState();
}
return undefined;
},
onStart: function () {
emit('start');
emitAppInitialData();
},
};
var readyFn = function () {
var _a;
appInitialData.commit();
(_a = window.AssistantHost) === null || _a === void 0 ? void 0 : _a.ready();
};
if (ready) {
setTimeout(readyFn); // таймаут для подписки на start
}
var sendData = function (_a, onData) {
var _b, _c, _d;
var action = _a.action, name = _a.name, requestId = _a.requestId;
if ((_b = window.AssistantHost) === null || _b === void 0 ? void 0 : _b.sendDataContainer) {
if (onData == null) {
(_c = window.AssistantHost) === null || _c === void 0 ? void 0 : _c.sendDataContainer(
/* eslint-disable-next-line @typescript-eslint/camelcase */
JSON.stringify({ data: action, message_name: name || '', requestId: requestId }));
return function () { };
}
if (requestId && observables.has(requestId)) {
throw new Error('requestId должен быть уникальным');
}
var realRequestId_1 = requestId || v4();
var subscribe = createNanoObservable(function (_a) {
var _b;
var next = _a.next;
(_b = window.AssistantHost) === null || _b === void 0 ? void 0 : _b.sendDataContainer(
/* eslint-disable-next-line @typescript-eslint/camelcase */
JSON.stringify({ data: action, message_name: name || '', requestId: realRequestId_1 }));
observables.set(realRequestId_1, { next: next, requestId: requestId });
}).subscribe;
var unsubscribe_1 = subscribe({ next: onData }).unsubscribe;
return function () {
unsubscribe_1();
observables.delete(realRequestId_1);
};
}
if (onData != null) {
throw new Error('Не поддерживается в данной версии клиента');
}
(_d = window.AssistantHost) === null || _d === void 0 ? void 0 : _d.sendData(JSON.stringify(action), name || null);
return function () { };
};
return {
cancelTts: cancelTts,
close: function () { var _a; return (_a = window.AssistantHost) === null || _a === void 0 ? void 0 : _a.close(); },
getInitialData: appInitialData.pull,
findInInitialData: appInitialData.find,
getRecoveryState: function () { return window.appRecoveryState; },
on: on,
sendAction: function (action, onData, onError, _a) {
var _b = _a === void 0 ? {} : _a, name = _b.name, requestId = _b.requestId;
return sendData({ action: action, name: name, requestId: requestId }, function (data) {
if (data.type === 'smart_app_data' && onData) {
onData(data.smart_app_data);
return;
}
if (data.type === 'smart_app_error' && onError) {
onError(data.smart_app_error);
return;
}
emitCommand(data);
});
},
sendData: sendData,
setGetState: function (nextGetState) {
currentGetState = nextGetState;
},
setGetRecoveryState: function (nextGetRecoveryState) {
currentGetRecoveryState = nextGetRecoveryState;
},
setSuggests: function (suggestions) {
var _a;
(_a = window.AssistantHost) === null || _a === void 0 ? void 0 : _a.setSuggests(JSON.stringify({ suggestions: { buttons: suggestions } }));
},
setHints: function (hints) {
var _a;
(_a = window.AssistantHost) === null || _a === void 0 ? void 0 : _a.setHints(JSON.stringify({ hints: hints }));
},
sendText: function (message) { var _a; return (_a = window.AssistantHost) === null || _a === void 0 ? void 0 : _a.sendText(message); },
ready: readyFn,
};
};
if (typeof window !== 'undefined') {
// eslint-disable-next-line no-underscore-dangle
window.__ASSISTANT_CLIENT__ = { version: '5.0.2' };
}
export { createAssistant as c, v4 as v };