diff --git a/app.json b/app.json index df6811e..1622ff8 100644 --- a/app.json +++ b/app.json @@ -19,5 +19,5 @@ "IPostLivechatRoomClosed", "IUIKitLivechatInteractionHandler" ], - "commitHash": "47a27ed35ee6fe974a5043fe82d49b6866a63827" + "commitHash": "2332c0c9abada4f27b9a3c3666f99c65883f1f99" } \ No newline at end of file diff --git a/endpoints/IncomingEndpoint.ts b/endpoints/IncomingEndpoint.ts index dc045f9..ecaad18 100644 --- a/endpoints/IncomingEndpoint.ts +++ b/endpoints/IncomingEndpoint.ts @@ -1,5 +1,6 @@ import { HttpStatusCode, IHttp, IModify, IPersistence, IRead } from '@rocket.chat/apps-engine/definition/accessors'; import { ApiEndpoint, IApiEndpointInfo, IApiRequest, IApiResponse } from '@rocket.chat/apps-engine/definition/api'; +import { IApp } from '@rocket.chat/apps-engine/definition/IApp'; import { ILivechatRoom } from '@rocket.chat/apps-engine/definition/livechat'; import { DialogflowRequestType, IDialogflowMessage } from '../enum/Dialogflow'; import { EndpointActionNames, IActionsEndpointContent } from '../enum/Endpoints'; @@ -25,7 +26,7 @@ export class IncomingEndpoint extends ApiEndpoint { this.app.getLogger().info(Logs.ENDPOINT_RECEIVED_REQUEST); try { - const { statusCode = HttpStatusCode.OK, data = null } = await this.processRequest(read, modify, persis, http, request.content); + const { statusCode = HttpStatusCode.OK, data = null } = await this.processRequest(this.app, read, modify, persis, http, request.content); return createHttpResponse(statusCode, { 'Content-Type': Headers.CONTENT_TYPE_JSON }, { ...data ? { ...data } : { result: Response.SUCCESS } }); } catch (error) { this.app.getLogger().error(Logs.ENDPOINT_REQUEST_PROCESSING_ERROR, error); @@ -33,7 +34,8 @@ export class IncomingEndpoint extends ApiEndpoint { } } - private async processRequest(read: IRead, + private async processRequest(app: IApp, + read: IRead, modify: IModify, persistence: IPersistence, http: IHttp, @@ -74,7 +76,13 @@ export class IncomingEndpoint extends ApiEndpoint { } try { - const response: IDialogflowMessage = await Dialogflow.sendRequest(http, read, modify, sessionId, event, DialogflowRequestType.EVENT); + const response: IDialogflowMessage = await Dialogflow.sendRequest(http, + read, + modify, + persistence, + sessionId, + event, + DialogflowRequestType.EVENT); // widechat specific change // await createDialogflowMessage(sessionId, read, modify, response, this.app); // await handlePayloadActions(this.app, read, modify, http, persistence, sessionId, vToken, response); diff --git a/handler/PostMessageSentHandler.ts b/handler/PostMessageSentHandler.ts index 7ca8208..86a1d94 100644 --- a/handler/PostMessageSentHandler.ts +++ b/handler/PostMessageSentHandler.ts @@ -6,12 +6,13 @@ import { AppSetting } from '../config/Settings'; import { DialogflowRequestType, IDialogflowMessage, IDialogflowQuickReplies, LanguageCode, Message } from '../enum/Dialogflow'; import { Logs } from '../enum/Logs'; +import { Global } from '../Global'; import { botTypingListener, removeBotTypingListener } from '../lib//BotTyping'; import { Dialogflow } from '../lib/Dialogflow'; -import { getErrorMessage } from '../lib/Helper'; +import { getError, getErrorMessage } from '../lib/Helper'; import { createDialogflowMessage, createMessage, removeQuotedMessage } from '../lib/Message'; import { handleResponse } from '../lib/payloadAction'; -import { getIsProcessingMessage, getIsQueueWindowActive, getRoomAssoc, retrieveDataByAssociation, setIsProcessingMessage, setQueuedMessage } from '../lib/Persistence'; +import { getIsProcessingMessage, getIsQueueWindowActive, getRoomAssoc, retrieveDataByAssociation, setIsProcessingMessage, setIsQueueWindowActive, setQueuedMessage } from '../lib/Persistence'; import { handleParameters } from '../lib/responseParameters'; import { closeChat, performHandover, updateRoomCustomFields } from '../lib/Room'; import { cancelAllEventSchedulerJobForSession, cancelAllSessionMaintenanceJobForSession } from '../lib/Scheduler'; @@ -126,7 +127,7 @@ export class PostMessageSentHandler { await setIsProcessingMessage(this.read, this.persistence, rid, true); await cancelAllEventSchedulerJobForSession(this.modify, rid); await botTypingListener(this.modify, rid, servedBy.username); - response = (await Dialogflow.sendRequest(this.http, this.read, this.modify, rid, messageText, DialogflowRequestType.MESSAGE)); + response = (await Dialogflow.sendRequest(this.http, this.read, this.modify, this.persistence, rid, messageText, DialogflowRequestType.MESSAGE)); await setIsProcessingMessage(this.read, this.persistence, rid, false); } catch (error) { await setIsProcessingMessage(this.read, this.persistence, rid, false); @@ -198,10 +199,16 @@ export class PostMessageSentHandler { const defaultLanguageCode = await getLivechatAgentConfig(read, rid, AppSetting.DialogflowAgentDefaultLanguage); let res: IDialogflowMessage; - res = (await Dialogflow.sendRequest(this.http, this.read, this.modify, rid, { - name: DialogflowChatClosedByVisitorEventName, - languageCode: data.custom_languageCode || defaultLanguageCode || LanguageCode.EN, - }, DialogflowRequestType.EVENT)); + res = (await Dialogflow.sendRequest(this.http, + this.read, + this.modify, + this.persistence, + rid, + { + name: DialogflowChatClosedByVisitorEventName, + languageCode: data.custom_languageCode || defaultLanguageCode || LanguageCode.EN, + }, + DialogflowRequestType.EVENT)); } catch (error) { const errorContent = `${Logs.DIALOGFLOW_REST_API_ERROR}: { roomID: ${rid} } ${getErrorMessage(error)}`; this.app.getLogger().error(errorContent); diff --git a/lib/Dialogflow.ts b/lib/Dialogflow.ts index ed98c41..2dd91d2 100644 --- a/lib/Dialogflow.ts +++ b/lib/Dialogflow.ts @@ -1,101 +1,48 @@ import { IHttp, IHttpRequest, IModify, IPersistence, IRead } from '@rocket.chat/apps-engine/definition/accessors'; import { ILivechatRoom } from '@rocket.chat/apps-engine/definition/livechat/ILivechatRoom'; import { IRoom } from '@rocket.chat/apps-engine/definition/rooms'; +// import { DialogFlowApi } from '@rocket.chat/apps-engine/lib/dialogflow-cx'; import { createSign } from 'crypto'; import { AppSetting } from '../config/Settings'; -import { DialogflowJWT, DialogflowRequestType, DialogflowUrl, IDialogflowAccessToken, IDialogflowCustomFields, IDialogflowEvent, IDialogflowMessage, IDialogflowPayload, IDialogflowQuickReplies, LanguageCode } from '../enum/Dialogflow'; +import { DialogflowJWT, DialogflowRequestType, DialogflowUrl, IDialogflowAccessToken, IDialogflowAction, IDialogflowCustomFields, IDialogflowEvent, IDialogflowImageCard, IDialogflowMessage, IDialogflowPayload, IDialogflowQuickReplies, LanguageCode } from '../enum/Dialogflow'; import { Headers } from '../enum/Http'; import { Logs } from '../enum/Logs'; +import { Global } from '../Global'; +import { removeBotTypingListener } from './BotTyping'; +import { handlePostPartialResponse } from './handleStreams'; import { base64urlEncode, getError } from './Helper'; import { createHttpRequest } from './Http'; -import { getRoomAssoc, retrieveDataByAssociation } from './Persistence'; +import { getRoomAssoc, retrieveDataByAssociation, setIsProcessingMessage, setIsQueueWindowActive, updatePersistentData } from './Persistence'; import { updateRoomCustomFields } from './Room'; import { getLivechatAgentConfig } from './Settings'; +// tslint:disable-next-line: no-var-requires +const DialogFlowApi = require('@rocket.chat/apps-engine/lib/dialogflow-cx'); + class DialogflowClass { private jwtExpiration: Date; + public async sendRequest(http: IHttp, read: IRead, modify: IModify, + persistence: IPersistence, sessionId: string, request: IDialogflowEvent | string, requestType: DialogflowRequestType): Promise { - const room = await read.getRoomReader().getById(sessionId) as ILivechatRoom; - const { id: rid, visitor: { livechatData, token: visitorToken, phone } } = room; - const appVersion = room.customFields ? room.customFields.appVersion : 'undefined'; - let { visitor: { username } } = room; - - if (phone && phone.length > 0) { - username = phone[0].phoneNumber; - } - - const serverURL = await this.getServerURL(read, modify, http, sessionId); - - const data = await retrieveDataByAssociation(read, getRoomAssoc(sessionId)); - - const defaultLanguageCode = await getLivechatAgentConfig(read, rid, AppSetting.DialogflowAgentDefaultLanguage); const dialogFlowVersion = await getLivechatAgentConfig(read, sessionId, AppSetting.DialogflowAgentVersion); if (dialogFlowVersion === 'CX') { - - const queryInput = { - ...requestType === DialogflowRequestType.EVENT && { event: { event: typeof request === 'string' ? request : request.name} }, - ...requestType === DialogflowRequestType.MESSAGE && { text: { text: request }}, - languageCode: data.custom_languageCode || defaultLanguageCode || LanguageCode.EN, - }; - - const queryParams = { - timeZone: 'America/Los_Angeles', - parameters: { - username, - roomId: rid, - visitorToken, - appVersion, - ...(livechatData || {}), - }, - }; - - if (requestType === DialogflowRequestType.EVENT && typeof request !== 'string') { - queryParams.parameters = {...queryParams.parameters, ...(request.parameters ? request.parameters : {})}; - } - - const accessToken = await this.getAccessToken(read, modify, http, sessionId); - if (!accessToken) { throw Error(Logs.ACCESS_TOKEN_ERROR); } - - const httpRequestContent: IHttpRequest = createHttpRequest( - { 'Content-Type': Headers.CONTENT_TYPE_JSON, 'Accept': Headers.ACCEPT_JSON, 'Authorization': 'Bearer ' + accessToken }, - { queryInput, queryParams }, - ); - try { - const response = await http.post(serverURL, httpRequestContent); - return await this.parseCXRequest(read, response.data, sessionId); + return await this.detectStreamingIntent(read, modify, http, persistence, sessionId, requestType, request); } catch (error) { const errorContent = `${Logs.HTTP_REQUEST_ERROR}: { roomID: ${sessionId} } ${getError(error)}`; console.error(errorContent); throw new Error(error); } } else { - - const queryInput = { - ...requestType === DialogflowRequestType.EVENT && { event: request }, - ...requestType === DialogflowRequestType.MESSAGE && { text: - { - languageCode: data.custom_languageCode || defaultLanguageCode || LanguageCode.EN, - text: request, - }, - }, - }; - - const httpRequestContent: IHttpRequest = createHttpRequest( - { 'Content-Type': Headers.CONTENT_TYPE_JSON, 'Accept': Headers.ACCEPT_JSON}, - { queryInput }, - ); - try { - const response = await http.post(serverURL, httpRequestContent); - return this.parseRequest(response.data, sessionId); + return this.detectESIntent(read, modify, http, sessionId, request, requestType); } catch (error) { const errorContent = `${Logs.HTTP_REQUEST_ERROR}: { roomID: ${sessionId} } ${getError(error)}`; console.error(errorContent); @@ -118,7 +65,7 @@ class DialogflowClass { try { const response = await http.post(authUrl, httpRequestContent); - if (!response || !response.content) { + if (!response.content) { const errorContent = `${Logs.INVALID_RESPONSE_FROM_DIALOGFLOW}: { roomID: ${sessionId || 'N/A'} }`; console.error(errorContent); throw new Error(errorContent); @@ -232,7 +179,6 @@ class DialogflowClass { } const { session, queryResult } = response; - if (queryResult) { const { responseMessages, match: { matchType }, diagnosticInfo } = queryResult; @@ -253,8 +199,10 @@ class DialogflowClass { if (responseMessages) { responseMessages.forEach((message) => { - const { text, payload: { quickReplies = null, customFields = null, action = null, isFallback = false } = {} } = message; - + const { text } = message; + const { payload: structPayload = {} } = message; + const payload = this.structProtoToJson(structPayload) as any; + const { quickReplies = null, customFields = null, action = null, isFallback = false } = payload; if (!text && previousMessageType === 'text') { if (intentConcatText !== '') { messages.push({ text: intentConcatText }); @@ -348,22 +296,42 @@ class DialogflowClass { } } - private async getServerURL(read: IRead, modify: IModify, http: IHttp, sessionId: string) { - const projectId = await getLivechatAgentConfig(read, sessionId, AppSetting.DialogflowAgentProjectId); - const environmentId = await getLivechatAgentConfig(read, sessionId, AppSetting.DialogflowAgentEnvironmentId); - const dialogFlowVersion = await getLivechatAgentConfig(read, sessionId, AppSetting.DialogflowAgentVersion); + public async detectESIntent( + read: IRead, + modify: IModify, + http: IHttp, + sessionId: string, + request: IDialogflowEvent | string, + requestType: DialogflowRequestType) { + const room = await read.getRoomReader().getById(sessionId) as ILivechatRoom; + const { id: rid, visitor: { livechatData, token: visitorToken } } = room; + const serverURL = await this.getServerURL(read, modify, http, sessionId); + const defaultLanguageCode = await getLivechatAgentConfig(read, sessionId, AppSetting.DialogflowAgentDefaultLanguage); + const data = await retrieveDataByAssociation(read, getRoomAssoc(sessionId)); - if (dialogFlowVersion === 'CX') { + const queryInput = { + ...requestType === DialogflowRequestType.EVENT && { event: request }, + ...requestType === DialogflowRequestType.MESSAGE && { text: + { + languageCode: data.custom_languageCode || defaultLanguageCode || LanguageCode.EN, + text: request, + }, + }, + }; - const regionId = await getLivechatAgentConfig(read, sessionId, AppSetting.DialogflowAgentRegion); - const agentId = await getLivechatAgentConfig(read, sessionId, AppSetting.DialogflowAgentId); + const httpRequestContent: IHttpRequest = createHttpRequest( + { 'Content-Type': Headers.CONTENT_TYPE_JSON, 'Accept': Headers.ACCEPT_JSON}, + { queryInput }, + ); - return `https://${regionId}-dialogflow.googleapis.com/v3/projects/${projectId}/locations/${regionId}/agents/${agentId}/environments/${environmentId || 'draft'}/sessions/${sessionId}:detectIntent`; + try { + const response = await http.post(serverURL, httpRequestContent); + return this.parseRequest(response.data, sessionId); + } catch (error) { + const errorContent = `${Logs.HTTP_REQUEST_ERROR}: { roomID: ${sessionId} } ${getError(error)}`; + console.error(errorContent); + throw new Error(error); } - - const accessToken = await this.getAccessToken(read, modify, http, sessionId); - if (!accessToken) { throw Error(Logs.ACCESS_TOKEN_ERROR); } - return `https://dialogflow.googleapis.com/v2/projects/${projectId}/agent/environments/${environmentId || 'draft'}/users/-/sessions/${sessionId}:detectIntent?access_token=${accessToken}`; } private async getAccessToken(read: IRead, modify: IModify, http: IHttp, sessionId: string) { @@ -402,6 +370,24 @@ class DialogflowClass { } } + private async getServerURL(read: IRead, modify: IModify, http: IHttp, sessionId: string) { + const projectId = await getLivechatAgentConfig(read, sessionId, AppSetting.DialogflowAgentProjectId); + const environmentId = await getLivechatAgentConfig(read, sessionId, AppSetting.DialogflowAgentEnvironmentId); + const dialogFlowVersion = await getLivechatAgentConfig(read, sessionId, AppSetting.DialogflowAgentVersion); + + if (dialogFlowVersion === 'CX') { + + const regionId = await getLivechatAgentConfig(read, sessionId, AppSetting.DialogflowAgentRegion); + const agentId = await getLivechatAgentConfig(read, sessionId, AppSetting.DialogflowAgentId); + + return `https://${regionId}-dialogflow.googleapis.com/v3/projects/${projectId}/locations/${regionId}/agents/${agentId}/environments/${environmentId || 'draft'}/sessions/${sessionId}:detectIntent`; + } + + const accessToken = await this.getAccessToken(read, modify, http, sessionId); + if (!accessToken) { throw Error(Logs.ACCESS_TOKEN_ERROR); } + return `https://dialogflow.googleapis.com/v2/projects/${projectId}/agent/environments/${environmentId || 'draft'}/users/-/sessions/${sessionId}:detectIntent?access_token=${accessToken}`; + } + private hasExpired(expiration: Date): boolean { if (!expiration) { return true; } return Date.now() >= expiration.getTime(); @@ -457,7 +443,8 @@ class DialogflowClass { return sign.sign(privateKey, DialogflowJWT.BASE_64).replace(/\+/g, '-').replace(/\//g, '_'); } - private getSourceType(text: any, info: any) { + private getSourceType(text: any, structInfo: any) { + const info = this.structProtoToJson(structInfo); const executionStep = info['Execution Sequence'][2] ? info['Execution Sequence'][2]['Step 3'] : info['Execution Sequence'][1]['Step 2']; if (executionStep) { @@ -475,6 +462,145 @@ class DialogflowClass { return 'page'; } + + private async detectStreamingIntent( + read: IRead, + modify: IModify, + http: IHttp, + persistence: IPersistence, + sessionId: string, + requestType: DialogflowRequestType, + request: IDialogflowEvent | string) { + const projectId = await getLivechatAgentConfig(read, sessionId, AppSetting.DialogflowAgentProjectId); + const environmentId = await getLivechatAgentConfig(read, sessionId, AppSetting.DialogflowAgentEnvironmentId); + const defaultLanguageCode = await getLivechatAgentConfig(read, sessionId, AppSetting.DialogflowAgentDefaultLanguage); + const regionId = await getLivechatAgentConfig(read, sessionId, AppSetting.DialogflowAgentRegion); + const agentId = await getLivechatAgentConfig(read, sessionId, AppSetting.DialogflowAgentId); + const privateKey = await getLivechatAgentConfig(read, sessionId, AppSetting.DialogflowAgentPrivateKey); + const clientEmail = await getLivechatAgentConfig(read, sessionId, AppSetting.DialogflowAgentClientEmail); + const room = await read.getRoomReader().getById(sessionId) as ILivechatRoom; + const { id: rid, visitor: { livechatData, token: visitorToken } } = room; + const assoc = getRoomAssoc(sessionId); + const data = await retrieveDataByAssociation(read, assoc); + + const accessToken = await this.getAccessToken(read, modify, http, sessionId); + if (!accessToken) { throw Error(Logs.ACCESS_TOKEN_ERROR); } + + const client = new DialogFlowApi.SessionsClient({ + apiEndpoint: `${regionId}-dialogflow.googleapis.com`, + credentials: { private_key: privateKey, client_email: clientEmail }, + }); + const sessionPath = `projects/${projectId}/locations/${regionId}/agents/${agentId}/environments/${environmentId || 'draft'}/sessions/${sessionId}`; + const queryInput = { + ...requestType === DialogflowRequestType.EVENT && { event: { event: typeof request === 'string' ? request : request.name} }, + ...requestType === DialogflowRequestType.MESSAGE && { text: { text: request }}, + languageCode: data.custom_languageCode || defaultLanguageCode || LanguageCode.EN, + }; + + const queryParams = { + timeZone: 'America/Los_Angeles', + parameters: { + username: room.visitor.username, + roomId: rid, + visitorToken, + ...(livechatData || {}), + }, + }; + + if (requestType === DialogflowRequestType.EVENT && typeof request !== 'string') { + queryParams.parameters = {...queryParams.parameters, ...(request.parameters ? request.parameters : {})}; + } + + return new Promise((resolve, reject) => { + try { + const detectStream = client + .streamingDetectIntent() + .on('error', console.error) + .on('data', async (streamData: any) => { + if (streamData.recognitionResult) { + console.log( + `Intermediate Transcript: ${streamData.recognitionResult.transcript}`, + ); + } else { + const response = streamData.detectIntentResponse; + if (response) { + if (response.responseType === 'PARTIAL') { + await setIsQueueWindowActive(read, persistence, sessionId, true); + const parsedResponse = await this.parseCXRequest(read, response, sessionId); + await handlePostPartialResponse(Global.app, read, modify, http, persistence, rid, visitorToken, parsedResponse); + } else { + try { + detectStream.end(); + resolve(await this.parseCXRequest(read, response, sessionId)); + } catch (e) { + console.error(e); + } + } + } + } + }) + .on('end', async () => { + await setIsQueueWindowActive(read, persistence, sessionId, false); + if (room.servedBy) { + await removeBotTypingListener(modify, rid, room.servedBy.username); + } + }); + const initialStreamRequest = { + session: sessionPath, + queryInput, + enablePartialResponse: true, + queryParams, + }; + detectStream.write(initialStreamRequest); + } catch (e) { + reject(e); + } + }); + } + + private structProtoToJson(proto: any) { + if (!proto || !proto.fields) { + return {}; + } + const json = {}; + for (const k in proto.fields) { + if (proto.fields[k]) { + console.log('a'); + console.log(proto.fields[k]); + json[k] = this.valueProtoToJson(proto.fields[k]); + } + } + return json; + } + + private valueProtoToJson(proto: any) { + if (!proto || !proto.kind) { + return null; + } + + const jsonValueKinds = new Set([ + 'numberValue', + 'stringValue', + 'boolValue', + ]); + + if (jsonValueKinds.has(proto.kind)) { + return proto[proto.kind]; + } else if (proto.kind === 'nullValue') { + return null; + } else if (proto.kind === 'listValue') { + if (!proto.listValue || !proto.listValue.values) { + console.warn('Invalid JSON list value proto: ', JSON.stringify(proto)); + } + console.log(proto); + return proto.listValue.values.map((value) => (this.structProtoToJson(value))); + } else if (proto.kind === 'structValue') { + return this.structProtoToJson(proto.structValue); + } else { + console.warn('Unsupported JSON value proto kind: ', proto.kind); + return null; + } + } } export const Dialogflow = new DialogflowClass(); diff --git a/lib/EventTimeoutProcessor.ts b/lib/EventTimeoutProcessor.ts index 5db7531..44c43e5 100644 --- a/lib/EventTimeoutProcessor.ts +++ b/lib/EventTimeoutProcessor.ts @@ -30,7 +30,7 @@ export class EventScheduler implements IProcessor { await setIsQueueWindowActive(read, persistence, sessionId, true); console.debug({rid: sessionId}, `Queue Window started`); - const response = await Dialogflow.sendRequest(http, read, modify, sessionId, event, DialogflowRequestType.EVENT); + const response = await Dialogflow.sendRequest(http, read, modify, persistence, sessionId, event, DialogflowRequestType.EVENT); const livechatRoom = await read.getRoomReader().getById(sessionId) as ILivechatRoom; if (!livechatRoom) { throw new Error(Logs.INVALID_ROOM_ID); } @@ -52,7 +52,13 @@ export class EventScheduler implements IProcessor { // Send Queued Message if (queuedMessage) { try { - const messageResponse = await Dialogflow.sendRequest(http, read, modify, sessionId, queuedMessage, DialogflowRequestType.MESSAGE); + const messageResponse = await Dialogflow.sendRequest(http, + read, + modify, + persistence, + sessionId, + queuedMessage, + DialogflowRequestType.MESSAGE); await handleResponse(Global.app, read, modify, http, persistence, sessionId, visitorToken, messageResponse); } catch (error) { console.error(`${Logs.DIALOGFLOW_REST_API_ERROR}: { roomID: ${sessionId} } ${getError(error)}`); diff --git a/lib/handleStreams.ts b/lib/handleStreams.ts new file mode 100644 index 0000000..e9b4e4d --- /dev/null +++ b/lib/handleStreams.ts @@ -0,0 +1,131 @@ +import { IHttp, IModify, IPersistence, IRead } from '@rocket.chat/apps-engine/definition/accessors'; +import { IApp } from '@rocket.chat/apps-engine/definition/IApp'; +import { ILivechatRoom } from '@rocket.chat/apps-engine/definition/livechat'; +import { AppSetting } from '../config/Settings'; +import { ActionIds } from '../enum/ActionIds'; +import { IDialogflowAction, IDialogflowImageCard, IDialogflowMessage, IDialogflowPayload, IDialogflowQuickReplies } from '../enum/Dialogflow'; +import { JobName } from '../enum/Scheduler'; +import { Global } from '../Global'; +import { removeBotTypingListener } from './BotTyping'; +import { createDialogflowMessage, createMessage } from './Message'; +import { getRoomAssoc, retrieveDataByAssociation, setIsProcessingMessage, setIsQueueWindowActive, setQueuedMessage, updatePersistentData } from './Persistence'; +import { getLivechatAgentConfig } from './Settings'; +import { incFallbackIntentAndSendResponse } from './SynchronousHandover'; + +export const handlePostPartialResponse = async (app: IApp, read: IRead, modify: IModify, http: IHttp, persistence: IPersistence, rid: string, visitorToken: string, response: any) => { + const room = await read.getRoomReader().getById(rid) as ILivechatRoom; + const { servedBy } = room; + + if (!servedBy) { + return; + } + + await setIsProcessingMessage(read, persistence, rid, false); + const createResponseMessage = async () => await createDialogflowMessage(rid, read, modify, response, Global.app); + + // synchronous handover check + + // await handleResponse(Global.app, read, modify, http, persistence, rid, visitorToken, response); + // await handleParameters(app, read, modify, persistence, http, rid, visitorToken, response); + + const { messages = [], isFallback = false } = response; + if (isFallback) { + await removeBotTypingListener(modify, rid, servedBy.username); + return incFallbackIntentAndSendResponse(Global.app, read, modify, rid, createResponseMessage); + } + for (const message of messages) { + const { action = null } = message as IDialogflowPayload; + const textMessages: Array = []; + textMessages.push(message); + const messagesToProcess: IDialogflowMessage = { + messages: textMessages, + isFallback, + }; + if (action) { + await handlePartialPayloadActions(app, read, modify, http, persistence, rid, visitorToken, messagesToProcess); + } else { + await createDialogflowMessage(rid, read, modify, messagesToProcess, app); + } + } + + await handlePartialParameters(Global.app, read, modify, persistence, http, rid, visitorToken, response); +}; + +export const handlePartialPayloadActions = async (app: IApp, read: IRead, modify: IModify, http: IHttp, persistence: IPersistence, rid: string, visitorToken: string, dialogflowMessage: IDialogflowMessage) => { + const { messages = [] } = dialogflowMessage; + for (const message of messages) { + const { action = null } = message as IDialogflowPayload; + if (action) { + const { name: actionName, params } = action as IDialogflowAction; + if (actionName) { + if (actionName === ActionIds.SET_TIMEOUT) { + + const task = { + id: JobName.EVENT_SCHEDULER, + when: `${Number(params.time)} seconds`, + data: { + eventName: params.eventName , + rid, + sessionId: rid, + jobName: JobName.EVENT_SCHEDULER, + }, + }; + + try { + await modify.getScheduler().scheduleOnce(task); + + // Start blackout window + if (params.continue_blackout) { + await setIsProcessingMessage(read, persistence, rid, true); + } + } catch (error) { + console.error(error); + const serviceUnavailable: string = await getLivechatAgentConfig(read, rid, AppSetting.DialogflowServiceUnavailableMessage); + await createMessage(rid, read, modify, { text: serviceUnavailable }, app); + return; + } + + } else if (actionName === ActionIds.CHANGE_LANGUAGE_CODE) { + const assoc = getRoomAssoc(rid); + const data = await retrieveDataByAssociation(read, assoc); + + if (data && data.custom_languageCode) { + if (data.custom_languageCode !== params.newLanguageCode) { + await updatePersistentData(read, persistence, assoc, {custom_languageCode: params.newLanguageCode}); + } + } else { + await persistence.createWithAssociation({custom_languageCode: params.newLanguageCode}, assoc); + } + } + if (actionName === ActionIds.DROP_QUEUE) { + await setIsQueueWindowActive(read, persistence, rid, false); + await setQueuedMessage(read, persistence, rid, ''); + console.debug({rid}, 'Queue Window dropped'); + } + } + } + } +}; + +export const handlePartialParameters = async (app: IApp, read: IRead, modify: IModify, persistence: IPersistence, http: IHttp, rid: string, visitorToken: string, dialogflowMessage: IDialogflowMessage) => { + const { parameters = [] } = dialogflowMessage; + try { + if (parameters && parameters.custom_languagecode) { + + const assoc = getRoomAssoc(rid); + const data = await retrieveDataByAssociation(read, assoc); + + if (data && data.custom_languageCode) { + if (data.custom_languageCode !== parameters.custom_languagecode) { + await persistence.updateByAssociation(assoc, {custom_languageCode: parameters.custom_languagecode}); + } + } else { + await persistence.createWithAssociation({custom_languageCode: parameters.custom_languagecode}, assoc); + } + + } + } catch (e: any) { + console.error(e); + } + +}; diff --git a/lib/payloadAction.ts b/lib/payloadAction.ts index f3e2f8d..968b803 100644 --- a/lib/payloadAction.ts +++ b/lib/payloadAction.ts @@ -106,7 +106,7 @@ const sendChangeLanguageEvent = async (app: IApp, read: IRead, modify: IModify, try { const event = { name: 'ChangeLanguage', languageCode, parameters: {} }; - const response: IDialogflowMessage = await Dialogflow.sendRequest(http, read, modify, rid, event, DialogflowRequestType.EVENT); + const response: IDialogflowMessage = await Dialogflow.sendRequest(http, read, modify, persis, rid, event, DialogflowRequestType.EVENT); await createDialogflowMessage(rid, read, modify, response, app); } catch (error) { @@ -158,7 +158,7 @@ export const sendWelcomeEventToDialogFlow = async (app: IApp, read: IRead, modif }; await createMessage(rid, read, modify, { customFields: disableInput }, app); - const response: IDialogflowMessage = await Dialogflow.sendRequest(http, read, modify, rid, event, DialogflowRequestType.EVENT); + const response: IDialogflowMessage = await Dialogflow.sendRequest(http, read, modify, persistence, rid, event, DialogflowRequestType.EVENT); await handleResponse(app, read, modify, http, persistence, rid, visitorToken, response); } catch (error) { console.error(`${Logs.DIALOGFLOW_REST_API_ERROR}: { roomID: ${rid} } ${getError(error)}`); diff --git a/lib/responseParameters.ts b/lib/responseParameters.ts index 772d08d..007014a 100644 --- a/lib/responseParameters.ts +++ b/lib/responseParameters.ts @@ -28,7 +28,7 @@ const sendChangeLanguageEvent = async (app: IApp, read: IRead, modify: IModify, try { const event = { name: 'ChangeLanguage', languageCode, parameters: {} }; - const response: IDialogflowMessage = await Dialogflow.sendRequest(http, read, modify, rid, event, DialogflowRequestType.EVENT); + const response: IDialogflowMessage = await Dialogflow.sendRequest(http, read, modify, persis, rid, event, DialogflowRequestType.EVENT); await createDialogflowMessage(rid, read, modify, response, app); } catch (error) { diff --git a/lib/sendEventToDialogFlow.ts b/lib/sendEventToDialogFlow.ts index 60f974b..f952ce6 100644 --- a/lib/sendEventToDialogFlow.ts +++ b/lib/sendEventToDialogFlow.ts @@ -18,7 +18,7 @@ export const sendEventToDialogFlow = async (app: IApp, read: IRead, modify: IMo languageCode: data.custom_languageCode || defaultLanguageCode || LanguageCode.EN, parameters: parameters || {}, }; - const response: IDialogflowMessage = await Dialogflow.sendRequest(http, read, modify, rid, event, DialogflowRequestType.EVENT); + const response: IDialogflowMessage = await Dialogflow.sendRequest(http, read, modify, persistence, rid, event, DialogflowRequestType.EVENT); await createDialogflowMessage(rid, read, modify, response, app); } catch (error) { console.error(`${Logs.DIALOGFLOW_REST_API_ERROR}: { roomID: ${rid} } ${getError(error)}`); diff --git a/lib/sendWelcomeEvent.ts b/lib/sendWelcomeEvent.ts new file mode 100644 index 0000000..c8e4b1a --- /dev/null +++ b/lib/sendWelcomeEvent.ts @@ -0,0 +1,38 @@ +import { IHttp, IModify, IPersistence, IRead } from '@rocket.chat/apps-engine/definition/accessors'; +import { IApp } from '@rocket.chat/apps-engine/definition/IApp'; +import { AppSetting } from '../config/Settings'; +import { DialogflowRequestType, IDialogflowCustomFields, IDialogflowMessage, LanguageCode } from '../enum/Dialogflow'; +import { Logs } from '../enum/Logs'; +import { getError } from '../lib/Helper'; +import { Dialogflow } from './Dialogflow'; +import { createDialogflowMessage, createMessage } from './Message'; +import { getRoomAssoc, retrieveDataByAssociation } from './Persistence'; +import { getLivechatAgentConfig } from './Settings'; + +export const WELCOME_EVENT_NAME = 'Welcome'; + +export const sendWelcomeEventToDialogFlow = async (app: IApp, read: IRead, modify: IModify, persistence: IPersistence, http: IHttp, rid: string, visitorToken: string, livechatData: any) => { + try { + const data = await retrieveDataByAssociation(read, getRoomAssoc(rid)); + const defaultLanguageCode = await getLivechatAgentConfig(read, rid, AppSetting.DialogflowAgentDefaultLanguage); + const event = { + name: WELCOME_EVENT_NAME, + languageCode: data.custom_languageCode || defaultLanguageCode || LanguageCode.EN, + parameters: {...(livechatData || {}), roomId: rid, visitorToken} || {}, + }; + const disableInput: IDialogflowCustomFields = { + disableInput: true, + disableInputMessage: 'Starting chat...', + displayTyping: true, + }; + + await createMessage(rid, read, modify, { customFields: disableInput }, app); + const response: IDialogflowMessage = await Dialogflow.sendRequest(http, read, modify, persistence, rid, event, DialogflowRequestType.EVENT); + await createDialogflowMessage(rid, read, modify, response, app); + } catch (error) { + console.error(`${Logs.DIALOGFLOW_REST_API_ERROR}: { roomID: ${rid} } ${getError(error)}`); + const serviceUnavailable: string = await getLivechatAgentConfig(read, rid, AppSetting.DialogflowServiceUnavailableMessage); + await createMessage(rid, read, modify, { text: serviceUnavailable }, app); + return; + } +}; diff --git a/lib/sessionMaintenance/SessionMaintenanceProcessor.ts b/lib/sessionMaintenance/SessionMaintenanceProcessor.ts index c4ab9a7..4afea2f 100644 --- a/lib/sessionMaintenance/SessionMaintenanceProcessor.ts +++ b/lib/sessionMaintenance/SessionMaintenanceProcessor.ts @@ -49,7 +49,7 @@ export class SessionMaintenanceProcessor implements IProcessor { name: sessionMaintenanceEventName, languageCode: data.custom_languageCode || defaultLanguageCode || LanguageCode.EN, }; - await Dialogflow.sendRequest(http, read, modify, sessionId, eventData, DialogflowRequestType.EVENT); + await Dialogflow.sendRequest(http, read, modify, persis, sessionId, eventData, DialogflowRequestType.EVENT); } catch (error) { console.error(`${Logs.DIALOGFLOW_REST_API_ERROR}: { roomID: ${sessionId} } ${getError(error)}`); } diff --git a/package-lock.json b/package-lock.json index 3b4d14b..9b06eec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,11 +28,116 @@ "js-tokens": "^4.0.0" } }, + "@google-cloud/dialogflow-cx": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/@google-cloud/dialogflow-cx/-/dialogflow-cx-2.15.0.tgz", + "integrity": "sha512-uZoX2AdpU9SuysNzvvSzk7iV2HhNxttvfTYeDkRgMMJSv/xf0tyiujcKybK/b628RVVNsAQhEFDR0NDykFs/4w==", + "dev": true, + "requires": { + "google-gax": "^2.24.1" + } + }, + "@grpc/grpc-js": { + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.5.7.tgz", + "integrity": "sha512-RAlSbZ9LXo0wNoHKeUlwP9dtGgVBDUbnBKFpfAv5iSqMG4qWz9um2yLH215+Wow1I48etIa1QMS+WAGmsE/7HQ==", + "dev": true, + "requires": { + "@grpc/proto-loader": "^0.6.4", + "@types/node": ">=12.12.47" + }, + "dependencies": { + "@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + } + } + }, + "@grpc/proto-loader": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.9.tgz", + "integrity": "sha512-UlcCS8VbsU9d3XTXGiEVFonN7hXk+oMXZtoHHG2oSA1/GcDP1q6OUgs20PzHDGizzyi8ufGSUDlk3O2NyY7leg==", + "dev": true, + "requires": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^6.10.0", + "yargs": "^16.2.0" + } + }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=", + "dev": true + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "dev": true + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "dev": true + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=", + "dev": true + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "dev": true, + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=", + "dev": true + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=", + "dev": true + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=", + "dev": true + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=", + "dev": true + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=", + "dev": true + }, "@rocket.chat/apps-engine": { - "version": "github:WideChat/Rocket.Chat.Apps-engine#3e5da1c2c996a27197f9de7ca2292e1d1545e9d5", - "from": "github:WideChat/Rocket.Chat.Apps-engine#v1.29.2", + "version": "git+https://github.com/WideChat/Rocket.Chat.Apps-engine.git#100783321beba256003c1745f51463a0ffa08549", + "from": "git+https://github.com/WideChat/Rocket.Chat.Apps-engine.git#dialogflow_branch", "dev": true, "requires": { + "@google-cloud/dialogflow-cx": "^2.15.0", "adm-zip": "^0.4.9", "cryptiles": "^4.1.3", "lodash.clonedeep": "^4.5.0", @@ -41,18 +146,48 @@ "uuid": "^3.2.1" } }, + "@types/long": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", + "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==", + "dev": true + }, "@types/node": { "version": "10.17.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.5.tgz", "integrity": "sha512-RElZIr/7JreF1eY6oD5RF3kpmdcreuQPjg5ri4oQ5g9sq7YWU8HkfB3eH8GwAwxf5OaCh0VPi7r4N/yoTGelrA==", "dev": true }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "requires": { + "event-target-shim": "^5.0.0" + } + }, "adm-zip": { "version": "0.4.16", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", "dev": true }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -71,12 +206,30 @@ "sprintf-js": "~1.0.2" } }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true + }, + "bignumber.js": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz", + "integrity": "sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==", + "dev": true + }, "boom": { "version": "7.3.0", "resolved": "https://registry.npmjs.org/boom/-/boom-7.3.0.tgz", @@ -96,6 +249,12 @@ "concat-map": "0.0.1" } }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", + "dev": true + }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", @@ -113,6 +272,17 @@ "supports-color": "^5.3.0" } }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -149,12 +319,63 @@ "boom": "7.x.x" } }, + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dev": true, + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -167,6 +388,24 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "fast-text-encoding": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz", + "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==", + "dev": true + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -179,6 +418,35 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "gaxios": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.2.tgz", + "integrity": "sha512-T+ap6GM6UZ0c4E6yb1y/hy2UB6hTrqhglp3XfmU9qbLCGRYhLVV5aRPpC4EmoG8N8zOnkYCgoBz+ScvGAARY6Q==", + "dev": true, + "requires": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.1" + } + }, + "gcp-metadata": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", + "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", + "dev": true, + "requires": { + "gaxios": "^4.0.0", + "json-bigint": "^1.0.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, "glob": { "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", @@ -193,6 +461,64 @@ "path-is-absolute": "^1.0.0" } }, + "google-auth-library": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.0.tgz", + "integrity": "sha512-or8r7qUqGVI3W8lVSdPh0ZpeFyQHeE73g5c0p+bLNTTUFXJ+GSeDQmZRZ2p4H8cF/RJYa4PNvi/A1ar1uVNLFA==", + "dev": true, + "requires": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^4.0.0", + "gcp-metadata": "^4.2.0", + "gtoken": "^5.0.4", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + } + }, + "google-gax": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.30.0.tgz", + "integrity": "sha512-JcZGDuSOzhPwOJfbK80cyyGLZkrlLBTiwfqrW46sC0I9h3FtFmbN7FwIQ3PHreYiE6iVK4InfEZiTp4laOmPfA==", + "dev": true, + "requires": { + "@grpc/grpc-js": "~1.5.0", + "@grpc/proto-loader": "^0.6.1", + "@types/long": "^4.0.0", + "abort-controller": "^3.0.0", + "duplexify": "^4.0.0", + "fast-text-encoding": "^1.0.3", + "google-auth-library": "^7.14.0", + "is-stream-ended": "^0.1.4", + "node-fetch": "^2.6.1", + "object-hash": "^3.0.0", + "proto3-json-serializer": "^0.1.8", + "protobufjs": "6.11.2", + "retry-request": "^4.0.0" + } + }, + "google-p12-pem": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.3.tgz", + "integrity": "sha512-MC0jISvzymxePDVembypNefkAQp+DRP7dBE+zNUPaIjEspIlYg0++OrsNr248V9tPbz6iqtZ7rX1hxWA5B8qBQ==", + "dev": true, + "requires": { + "node-forge": "^1.0.0" + } + }, + "gtoken": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", + "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", + "dev": true, + "requires": { + "gaxios": "^4.0.0", + "google-p12-pem": "^3.1.3", + "jws": "^4.0.0" + } + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -214,6 +540,16 @@ "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==", "dev": true }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -239,6 +575,24 @@ "has": "^1.0.3" } }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "is-stream-ended": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.4.tgz", + "integrity": "sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw==", + "dev": true + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -255,12 +609,63 @@ "esprima": "^4.0.0" } }, + "json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "dev": true, + "requires": { + "bignumber.js": "^9.0.0" + } + }, + "jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "dev": true, + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "dev": true, + "requires": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "dev": true + }, "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", "dev": true }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -285,6 +690,33 @@ "minimist": "^1.2.5" } }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "node-forge": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.2.1.tgz", + "integrity": "sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w==", + "dev": true + }, + "object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -312,6 +744,61 @@ "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", "dev": true }, + "proto3-json-serializer": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-0.1.8.tgz", + "integrity": "sha512-ACilkB6s1U1gWnl5jtICpnDai4VCxmI9GFxuEaYdxtDG2oVI3sVFIUsvUZcQbJgtPM6p+zqKbjTKQZp6Y4FpQw==", + "dev": true, + "requires": { + "protobufjs": "^6.11.2" + } + }, + "protobufjs": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", + "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", + "dev": true, + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "dependencies": { + "@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", + "dev": true + } + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, "resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", @@ -322,6 +809,22 @@ "path-parse": "^1.0.6" } }, + "retry-request": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-4.2.2.tgz", + "integrity": "sha512-xA93uxUD/rogV7BV59agW/JHPGXeREMWiZc9jhcwY4YdZ7QOtC7qbomYg0n4wyk2lJhggjvKvhNX8wln/Aldhg==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "extend": "^3.0.2" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -340,6 +843,41 @@ "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", "dev": true }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -349,6 +887,12 @@ "has-flag": "^3.0.0" } }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -391,17 +935,109 @@ "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", "dev": true }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, "uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "dev": true }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true } } } diff --git a/package.json b/package.json index e3eb982..cdbcb6b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "devDependencies": { - "@rocket.chat/apps-engine": "WideChat/Rocket.Chat.Apps-engine.git#v1.29.2", + "@rocket.chat/apps-engine": "git+https://github.com/WideChat/Rocket.Chat.Apps-engine.git#dialogflow_branch", "@types/node": "10.17.5", "prettier": "^2.5.1", "tslint": "^5.20.1",