@botonic/plugin-flow-builder
Version:
Use Flow Builder to show your contents
165 lines • 8.32 kB
JavaScript
import { __awaiter } from "tslib";
import { INPUT, PROVIDER, } from '@botonic/core';
import { v7 as uuidv7 } from 'uuid';
import { FlowBuilderApi } from './api';
import { EMPTY_PAYLOAD, FLOW_BUILDER_API_URL_PROD, SEPARATOR, SOURCE_INFO_SEPARATOR, } from './constants';
import { HtNodeWithContentType, } from './content-fields/hubtype-fields';
import { FlowFactory } from './flow-factory';
import { CustomFunction, DEFAULT_FUNCTION_NAMES } from './functions';
import { FlowBuilderJSONVersion, } from './types';
import { getNodeByUserInput } from './user-input';
import { inputHasTextData, resolveGetAccessToken } from './utils';
// TODO: Create a proper service to wrap all calls and allow api versioning
export default class BotonicPluginFlowBuilder {
constructor(options) {
var _a, _b, _c;
this.apiUrl = options.apiUrl || FLOW_BUILDER_API_URL_PROD;
this.jsonVersion = options.jsonVersion || FlowBuilderJSONVersion.LATEST;
this.flow = options.flow;
this.getAccessToken = resolveGetAccessToken(options.getAccessToken);
this.trackEvent = options.trackEvent;
this.getKnowledgeBaseResponse = options.getKnowledgeBaseResponse;
this.getAiAgentResponse = options.getAiAgentResponse;
this.smartIntentsConfig = Object.assign(Object.assign({}, options === null || options === void 0 ? void 0 : options.smartIntentsConfig), { useLatest: this.jsonVersion === FlowBuilderJSONVersion.LATEST });
const customFunctions = options.customFunctions || {};
this.functions = customFunctions;
this.inShadowing = {
allowKeywords: ((_a = options.inShadowing) === null || _a === void 0 ? void 0 : _a.allowKeywords) || false,
allowSmartIntents: ((_b = options.inShadowing) === null || _b === void 0 ? void 0 : _b.allowSmartIntents) || false,
allowKnowledgeBases: ((_c = options.inShadowing) === null || _c === void 0 ? void 0 : _c.allowKnowledgeBases) || false,
};
this.contentFilters = options.contentFilters || [];
this.customRatingMessageEnabled =
options.customRatingMessageEnabled || false;
}
resolveFlowUrl(request) {
if (request.session.is_test_integration) {
return `${this.apiUrl}/v1/bot_flows/{bot_id}/versions/${FlowBuilderJSONVersion.DRAFT}/`;
}
return `${this.apiUrl}/v1/bot_flows/{bot_id}/versions/${this.jsonVersion}/`;
}
pre(request) {
return __awaiter(this, void 0, void 0, function* () {
// When AI Agent is executed in Whatsapp, button payloads come as referral and must be converted to text being processed by the agent.
this.convertWhatsappAiAgentEmptyPayloads(request);
this.currentRequest = request;
this.cmsApi = yield FlowBuilderApi.create({
flowUrl: this.resolveFlowUrl(request),
url: this.apiUrl,
flow: this.flow,
accessToken: this.getAccessToken(request.session),
request: this.currentRequest,
});
const checkUserTextInput = inputHasTextData(request.input) && !request.input.payload;
if (checkUserTextInput) {
const resolvedLocale = this.cmsApi.getResolvedLocale();
const nodeByUserInput = yield getNodeByUserInput(this.cmsApi, resolvedLocale, request, this.smartIntentsConfig);
request.input.payload = this.cmsApi.getPayload(nodeByUserInput === null || nodeByUserInput === void 0 ? void 0 : nodeByUserInput.target);
}
this.updateRequestBeforeRoutes(request);
});
}
convertWhatsappAiAgentEmptyPayloads(request) {
var _a;
if (request.session.user.provider === PROVIDER.WHATSAPP) {
const shouldUseReferral = request.input.referral &&
((_a = request.input.payload) === null || _a === void 0 ? void 0 : _a.startsWith(EMPTY_PAYLOAD));
if (shouldUseReferral) {
request.input.type = INPUT.TEXT;
request.input.data = request.input.referral;
}
}
}
updateRequestBeforeRoutes(request) {
if (request.input.payload) {
request.input.payload = this.removeSourceSuffix(request.input.payload);
if (this.cmsApi.isBotAction(request.input.payload)) {
const cmsBotAction = this.cmsApi.getNodeById(request.input.payload);
request.input.payload =
this.cmsApi.createPayloadWithParams(cmsBotAction);
}
}
}
removeSourceSuffix(payload) {
return payload.split(SOURCE_INFO_SEPARATOR)[0];
}
post(request) {
request.input.nluResolution = undefined;
}
getContentsByContentID(contentID, prevContents) {
return __awaiter(this, void 0, void 0, function* () {
const node = this.cmsApi.getNodeByContentID(contentID);
return yield this.getContentsByNode(node, prevContents);
});
}
getUUIDByContentID(contentID) {
const node = this.cmsApi.getNodeByContentID(contentID);
return node.id;
}
getContentsById(id, prevContents) {
return __awaiter(this, void 0, void 0, function* () {
const node = this.cmsApi.getNodeById(id);
return yield this.getContentsByNode(node, prevContents);
});
}
getStartContents() {
return __awaiter(this, void 0, void 0, function* () {
const startNode = this.cmsApi.getStartNode();
this.currentRequest.session.flow_thread_id = uuidv7();
return yield this.getContentsByNode(startNode);
});
}
getContentsByNode(node, prevContents) {
return __awaiter(this, void 0, void 0, function* () {
const contents = prevContents || [];
const resolvedLocale = this.cmsApi.getResolvedLocale();
if (node.type === HtNodeWithContentType.FUNCTION &&
!DEFAULT_FUNCTION_NAMES.includes(node.content.action)) {
const customFunctionResolver = new CustomFunction(this.functions, this.currentRequest, resolvedLocale);
const targetId = yield customFunctionResolver.call(node);
return this.getContentsById(targetId, contents);
}
const flowFactory = new FlowFactory(this.currentRequest, this.cmsApi, resolvedLocale);
const content = yield flowFactory.getFlowContent(node);
if (content) {
contents.push(content);
}
// If node is BOT_ACTION not add more contents to render, next nodes render after execute action
if (node.type === HtNodeWithContentType.BOT_ACTION) {
return contents;
}
// TODO: prevent infinite recursive calls
if (content && content.followUp) {
return this.getContentsById(content.followUp.id, contents);
}
else if (node.follow_up) {
console.log('FOLLOWUP FROM NODE-------> OLD SYSTEM');
return this.getContentsById(node.follow_up.id, contents);
}
return contents;
});
}
getPayloadParams(payload) {
const payloadParams = JSON.parse(payload.split(SEPARATOR)[1] || '{}');
return payloadParams;
}
getFlowName(flowId) {
return this.cmsApi.getFlowName(flowId);
}
getRatingSubmittedInfo(payload) {
const buttonId = payload === null || payload === void 0 ? void 0 : payload.split(SEPARATOR)[1];
const ratingNode = this.cmsApi.getRatingNodeByButtonId(buttonId);
const ratingButton = this.cmsApi.getRatingButtonById(ratingNode, buttonId);
const possibleOptions = ratingNode.content.buttons.map(button => button.text);
const possibleValues = ratingNode.content.buttons.map(button => button.value);
return Object.assign(Object.assign({}, ratingButton), { possibleOptions,
possibleValues });
}
}
export * from './action';
export { AGENT_RATING_PAYLOAD } from './constants';
export * from './content-fields';
export { trackFlowContent } from './tracking';
export { FlowBuilderJSONVersion, } from './types';
export * from './webview';
//# sourceMappingURL=index.js.map