From 5639052df7f143aba7e424e2b00c214d72f2be64 Mon Sep 17 00:00:00 2001 From: mythilytm Date: Thu, 11 May 2023 11:44:17 -0400 Subject: [PATCH 01/13] Create control task for 'pre-survey' and clean up stale chat channel --- functions/captureChannelWithBot.protected.ts | 16 +++++++ functions/cleanupTaskForCapturedChannel.ts | 43 +++++++++++++++++++ .../janitorListener.private.ts | 22 +++++++--- 3 files changed, 76 insertions(+), 5 deletions(-) create mode 100644 functions/cleanupTaskForCapturedChannel.ts diff --git a/functions/captureChannelWithBot.protected.ts b/functions/captureChannelWithBot.protected.ts index 20b7c9d0..d5812ea6 100644 --- a/functions/captureChannelWithBot.protected.ts +++ b/functions/captureChannelWithBot.protected.ts @@ -1,3 +1,4 @@ +/* eslint-disable import/no-dynamic-require */ /** * Copyright (C) 2021-2023 Technology Matters * This program is free software: you can redistribute it and/or modify @@ -33,6 +34,8 @@ type EnvVars = { ASELO_APP_ACCESS_KEY: string; ASELO_APP_SECRET_KEY: string; AWS_REGION: string; + TWILIO_WORKSPACE_SID: string; + SURVEY_WORKFLOW_SID: string; }; type Body = { @@ -124,6 +127,19 @@ export const handler = async ( const updatedChannelAttributes = JSON.parse(updated.attributes); + // Cleanup task for captured channel by the bot + const task = await context + .getTwilioClient() + .taskrouter.workspaces(context.TWILIO_WORKSPACE_SID) + .tasks.create({ + workflowSid: context.SURVEY_WORKFLOW_SID, + attributes: JSON.stringify({ isChatbotCaptureControl: true }), + taskChannel: 'survey', + timeout: 3600, + }); + + console.log('>>>', task); + // ============== /** * TODO: Factor out shared chunk of code diff --git a/functions/cleanupTaskForCapturedChannel.ts b/functions/cleanupTaskForCapturedChannel.ts new file mode 100644 index 00000000..a496ba50 --- /dev/null +++ b/functions/cleanupTaskForCapturedChannel.ts @@ -0,0 +1,43 @@ +/* eslint-disable import/no-dynamic-require */ +/** + * Copyright (C) 2021-2023 Technology Matters + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +/* eslint-disable global-require */ +/* eslint-disable import/no-dynamic-require */ + +// const createTaskForCapturedChannel = async (channelSid, taskAttributes) => { +// try { +// // Create the Task using the Taskrouter REST API +// const task = await client.taskrouter.workspaces(workspaceSid).tasks.create({ +// attributes: JSON.stringify(taskAttributes), +// taskChannelUniqueName: channelSid, // Use the channelSid as the taskChannelUniqueName +// // Set other properties as needed, e.g., taskQueueSid or workflowSid +// }); + +// console.log('Task created:', task.sid); + +// // Associate the taskSid with the captured channel +// await client.chat +// .services(chatServiceSid) +// .channels(channelSid) +// .update({ taskSid: task.sid }); + +// console.log('Channel associated with task:', channelSid, '->', task.sid); +// } catch (error) { +// console.error('Error creating task for captured channel:', error); +// // Handle the error as needed +// } +// }; diff --git a/functions/taskrouterListeners/janitorListener.private.ts b/functions/taskrouterListeners/janitorListener.private.ts index ec420bb1..ea15ebd2 100644 --- a/functions/taskrouterListeners/janitorListener.private.ts +++ b/functions/taskrouterListeners/janitorListener.private.ts @@ -44,8 +44,13 @@ type EnvVars = { FLEX_PROXY_SERVICE_SID: string; }; -const isCleanupPostSurvey = (eventType: EventType, taskAttributes: { isSurveyTask?: boolean }) => - (eventType === TASK_CANCELED || eventType === TASK_WRAPUP) && taskAttributes.isSurveyTask; +// This applies to both pre-survey(due to external use of AWS) and post-survey +const isCleanupSurvey = ( + eventType: EventType, + taskAttributes: { isSurveyTask?: boolean; isChatbotCaptureControl?: boolean }, +) => + (eventType === TASK_CANCELED || eventType === TASK_WRAPUP) && + (taskAttributes.isSurveyTask || taskAttributes.isChatbotCaptureControl); const isCleanupCustomChannel = (eventType: EventType, taskAttributes: { channelType?: string }) => { if ( @@ -83,15 +88,22 @@ export const handleEvent = async (context: Context, event: EventFields) const taskAttributes = JSON.parse(taskAttributesString); - if (isCleanupPostSurvey(eventType, taskAttributes)) { - console.log('Handling clean up post-survey...'); + if (isCleanupSurvey(eventType, taskAttributes)) { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + taskAttributes.isChatbotCaptureControl === true + ? console.log('Handling clean up pre-survey...') + : console.log('Handling clean up post-survey...'); await wait(3000); // wait 3 seconds just in case some bot message is pending const handlerPath = Runtime.getFunctions()['helpers/chatChannelJanitor'].path; const chatChannelJanitor = require(handlerPath).chatChannelJanitor as ChatChannelJanitor; await chatChannelJanitor(context, { channelSid: taskAttributes.channelSid }); - console.log('Finished handling clean up post-survey.'); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + taskAttributes.isChatbotCaptureControl === true + ? console.log('Finished handling clean up pre-survey.') + : console.log('Finished handling clean up post-survey.'); + return; } From 8219f1525e03a4b3e34251c13fc97f0cdd66db84 Mon Sep 17 00:00:00 2001 From: mythilytm Date: Thu, 11 May 2023 12:14:20 -0400 Subject: [PATCH 02/13] Updated expirty to 720 minutes to match AWS Lex timeout --- functions/captureChannelWithBot.protected.ts | 2 +- functions/cleanupTaskForCapturedChannel.ts | 43 -------------------- 2 files changed, 1 insertion(+), 44 deletions(-) delete mode 100644 functions/cleanupTaskForCapturedChannel.ts diff --git a/functions/captureChannelWithBot.protected.ts b/functions/captureChannelWithBot.protected.ts index d5812ea6..49b1bb71 100644 --- a/functions/captureChannelWithBot.protected.ts +++ b/functions/captureChannelWithBot.protected.ts @@ -135,7 +135,7 @@ export const handler = async ( workflowSid: context.SURVEY_WORKFLOW_SID, attributes: JSON.stringify({ isChatbotCaptureControl: true }), taskChannel: 'survey', - timeout: 3600, + timeout: 45600, // 720 minutes or 12 hours }); console.log('>>>', task); diff --git a/functions/cleanupTaskForCapturedChannel.ts b/functions/cleanupTaskForCapturedChannel.ts deleted file mode 100644 index a496ba50..00000000 --- a/functions/cleanupTaskForCapturedChannel.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* eslint-disable import/no-dynamic-require */ -/** - * Copyright (C) 2021-2023 Technology Matters - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see https://www.gnu.org/licenses/. - */ - -/* eslint-disable global-require */ -/* eslint-disable import/no-dynamic-require */ - -// const createTaskForCapturedChannel = async (channelSid, taskAttributes) => { -// try { -// // Create the Task using the Taskrouter REST API -// const task = await client.taskrouter.workspaces(workspaceSid).tasks.create({ -// attributes: JSON.stringify(taskAttributes), -// taskChannelUniqueName: channelSid, // Use the channelSid as the taskChannelUniqueName -// // Set other properties as needed, e.g., taskQueueSid or workflowSid -// }); - -// console.log('Task created:', task.sid); - -// // Associate the taskSid with the captured channel -// await client.chat -// .services(chatServiceSid) -// .channels(channelSid) -// .update({ taskSid: task.sid }); - -// console.log('Channel associated with task:', channelSid, '->', task.sid); -// } catch (error) { -// console.error('Error creating task for captured channel:', error); -// // Handle the error as needed -// } -// }; From 43dac7b0aff1519d41bd4a6e5684dbdbac1da9a6 Mon Sep 17 00:00:00 2001 From: mythilytm Date: Fri, 12 May 2023 14:03:01 -0400 Subject: [PATCH 03/13] update chatbotCallback to complete control task --- functions/captureChannelWithBot.protected.ts | 4 +- .../janitorListener.private.ts | 28 ++++--- .../webhooks/chatbotCallback.protected.ts | 80 ++++++++++++------- 3 files changed, 71 insertions(+), 41 deletions(-) diff --git a/functions/captureChannelWithBot.protected.ts b/functions/captureChannelWithBot.protected.ts index 49b1bb71..61a02cc6 100644 --- a/functions/captureChannelWithBot.protected.ts +++ b/functions/captureChannelWithBot.protected.ts @@ -50,6 +50,7 @@ export const handler = async ( event: Body, callback: ServerlessCallback, ) => { + console.log('===== captureChannelWithBot handler ====='); const response = responseWithCors(); const resolve = bindResolve(callback)(response); @@ -135,7 +136,8 @@ export const handler = async ( workflowSid: context.SURVEY_WORKFLOW_SID, attributes: JSON.stringify({ isChatbotCaptureControl: true }), taskChannel: 'survey', - timeout: 45600, // 720 minutes or 12 hours + timeout: 10, // 720 minutes or 12 hours + // timeout: 45600, // 720 minutes or 12 hours }); console.log('>>>', task); diff --git a/functions/taskrouterListeners/janitorListener.private.ts b/functions/taskrouterListeners/janitorListener.private.ts index ea15ebd2..2efe1040 100644 --- a/functions/taskrouterListeners/janitorListener.private.ts +++ b/functions/taskrouterListeners/janitorListener.private.ts @@ -44,13 +44,19 @@ type EnvVars = { FLEX_PROXY_SERVICE_SID: string; }; -// This applies to both pre-survey(due to external use of AWS) and post-survey -const isCleanupSurvey = ( +// This applies to both pre-survey(isChatbotCaptureControl) and post-survey +const isCleanupBotCapture = ( eventType: EventType, taskAttributes: { isSurveyTask?: boolean; isChatbotCaptureControl?: boolean }, -) => - (eventType === TASK_CANCELED || eventType === TASK_WRAPUP) && - (taskAttributes.isSurveyTask || taskAttributes.isChatbotCaptureControl); +) => { + if (taskAttributes.isSurveyTask) { + return eventType === TASK_CANCELED || eventType === TASK_WRAPUP; + } + if (taskAttributes.isChatbotCaptureControl) { + return eventType === TASK_CANCELED; + } + return false; +}; const isCleanupCustomChannel = (eventType: EventType, taskAttributes: { channelType?: string }) => { if ( @@ -88,11 +94,11 @@ export const handleEvent = async (context: Context, event: EventFields) const taskAttributes = JSON.parse(taskAttributesString); - if (isCleanupSurvey(eventType, taskAttributes)) { + if (isCleanupBotCapture(eventType, taskAttributes)) { // eslint-disable-next-line @typescript-eslint/no-unused-expressions - taskAttributes.isChatbotCaptureControl === true - ? console.log('Handling clean up pre-survey...') - : console.log('Handling clean up post-survey...'); + const cleanupType = taskAttributes.isChatbotCaptureControl ? 'pre-survey' : 'post-survey'; + console.log(`Handling clean up ${cleanupType}...`); + await wait(3000); // wait 3 seconds just in case some bot message is pending const handlerPath = Runtime.getFunctions()['helpers/chatChannelJanitor'].path; @@ -100,9 +106,7 @@ export const handleEvent = async (context: Context, event: EventFields) await chatChannelJanitor(context, { channelSid: taskAttributes.channelSid }); // eslint-disable-next-line @typescript-eslint/no-unused-expressions - taskAttributes.isChatbotCaptureControl === true - ? console.log('Finished handling clean up pre-survey.') - : console.log('Finished handling clean up post-survey.'); + console.log(`Finished handling clean up ${cleanupType}.`); return; } diff --git a/functions/webhooks/chatbotCallback.protected.ts b/functions/webhooks/chatbotCallback.protected.ts index 36bcfc3a..e0825d0d 100644 --- a/functions/webhooks/chatbotCallback.protected.ts +++ b/functions/webhooks/chatbotCallback.protected.ts @@ -44,6 +44,8 @@ export const handler = async ( event: Body, callback: ServerlessCallback, ) => { + console.log('===== chatbotCallback handler ====='); + const response = responseWithCors(); const resolve = bindResolve(callback)(response); @@ -126,34 +128,56 @@ export const handler = async ( }; // const releasedChannelAttributes = omit(channelAttributes, 'channelCapturedByBot'); - await Promise.all([ - // Delete Lex session. This is not really needed as the session will expire, but that depends on the config of Lex. - Lex.deleteSession({ - botId: channelAttributes.channelCapturedByBot.botId, - botAliasId: channelAttributes.channelCapturedByBot.botAliasId, - localeId: channelAttributes.channelCapturedByBot.localeId, - sessionId: channel.sid, - }).promise(), - // Remove channelCapturedByBot from channel attributes - channel.update({ - attributes: JSON.stringify(releasedChannelAttributes), - }), - // Remove this webhook from the channel - channel - .webhooks() - .get(channelAttributes.channelCapturedByBot.chatbotCallbackWebhookSid) - .remove(), - // Trigger a new API type Studio Flow execution once the channel is released - client.studio.v2 - .flows(channelAttributes.channelCapturedByBot.studioFlowSid) - .executions.create({ - from: ChannelSid, - to: ChannelSid, - parameters: { - ChannelAttributes: releasedChannelAttributes, - }, - }), - ]); + await Promise.all( + [ + // Delete Lex session. This is not really needed as the session will expire, but that depends on the config of Lex. + () => { + console.log('>>> Lex.deleteSession'); + Lex.deleteSession({ + botId: channelAttributes.channelCapturedByBot.botId, + botAliasId: channelAttributes.channelCapturedByBot.botAliasId, + localeId: channelAttributes.channelCapturedByBot.localeId, + sessionId: channel.sid, + }).promise(); + }, + // Remove channelCapturedByBot from channel attributes + () => { + console.log('>>> Remove channelCapturedByBot from channel attributes'); + channel.update({ + attributes: JSON.stringify(releasedChannelAttributes), + }); + }, + // Move control task to complete state + () => { + console.log('>>> Move control task to complete state'); + client.taskrouter.v1 + .workspaces('WORKFLOW_SID') + .tasks(channelAttributes.controlTaskSid) + .update({ assignmentStatus: 'completed' }); + }, + // Remove this webhook from the channel + () => { + console.log('>>> Remove this webhook from the channel'); + channel + .webhooks() + .get(channelAttributes.channelCapturedByBot.chatbotCallbackWebhookSid) + .remove(); + }, + // Trigger a new API type Studio Flow execution once the channel is released + () => { + console.log('>>> Studio Flow execution once the channel is released'); + client.studio.v2 + .flows(channelAttributes.channelCapturedByBot.studioFlowSid) + .executions.create({ + from: ChannelSid, + to: ChannelSid, + parameters: { + ChannelAttributes: releasedChannelAttributes, + }, + }); + }, + ].map((func) => func()), + ); console.log('Channel unblocked and bot session deleted'); } From 18080502cc790333f7f6a322fcb14b31f0f30370 Mon Sep 17 00:00:00 2001 From: mythilytm Date: Mon, 29 May 2023 11:59:53 -0400 Subject: [PATCH 04/13] clgs --- functions/captureChannelWithBot.protected.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/functions/captureChannelWithBot.protected.ts b/functions/captureChannelWithBot.protected.ts index 61a02cc6..963341d3 100644 --- a/functions/captureChannelWithBot.protected.ts +++ b/functions/captureChannelWithBot.protected.ts @@ -54,6 +54,7 @@ export const handler = async ( const response = responseWithCors(); const resolve = bindResolve(callback)(response); + console.log('>>>', event); try { const { channelSid, message, fromServiceUser, studioFlowSid } = event; @@ -128,6 +129,7 @@ export const handler = async ( const updatedChannelAttributes = JSON.parse(updated.attributes); + console.log('>>> updatedChannelAttributes', updatedChannelAttributes); // Cleanup task for captured channel by the bot const task = await context .getTwilioClient() From c1f6001fcb2fd959872d8cb8c0d1f02e2f1707d4 Mon Sep 17 00:00:00 2001 From: mythilytm Date: Mon, 29 May 2023 12:41:26 -0400 Subject: [PATCH 05/13] channel & task clgs --- functions/captureChannelWithBot.protected.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/functions/captureChannelWithBot.protected.ts b/functions/captureChannelWithBot.protected.ts index 963341d3..6eda72b8 100644 --- a/functions/captureChannelWithBot.protected.ts +++ b/functions/captureChannelWithBot.protected.ts @@ -54,7 +54,9 @@ export const handler = async ( const response = responseWithCors(); const resolve = bindResolve(callback)(response); - console.log('>>>', event); + console.log('>>> event', event); + console.log('>>> response', response); + try { const { channelSid, message, fromServiceUser, studioFlowSid } = event; @@ -129,7 +131,9 @@ export const handler = async ( const updatedChannelAttributes = JSON.parse(updated.attributes); + console.log('>>> updated.attributes', updated.attributes); console.log('>>> updatedChannelAttributes', updatedChannelAttributes); + // Cleanup task for captured channel by the bot const task = await context .getTwilioClient() @@ -142,7 +146,7 @@ export const handler = async ( // timeout: 45600, // 720 minutes or 12 hours }); - console.log('>>>', task); + console.log('>>> task', task); // ============== /** From df3bc875c3315d3efdb181cfb747eb8451442ecd Mon Sep 17 00:00:00 2001 From: mythilytm Date: Mon, 29 May 2023 12:54:04 -0400 Subject: [PATCH 06/13] context & tasks clgs --- functions/captureChannelWithBot.protected.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/functions/captureChannelWithBot.protected.ts b/functions/captureChannelWithBot.protected.ts index 6eda72b8..8f807809 100644 --- a/functions/captureChannelWithBot.protected.ts +++ b/functions/captureChannelWithBot.protected.ts @@ -134,6 +134,14 @@ export const handler = async ( console.log('>>> updated.attributes', updated.attributes); console.log('>>> updatedChannelAttributes', updatedChannelAttributes); + console.log('>>> twilio workspace', context.TWILIO_WORKSPACE_SID); + console.log('>>> workflowSid', context.TWILIO_WORKSPACE_SID); + + const tasks = await context + .getTwilioClient() + .taskrouter.workspaces(context.TWILIO_WORKSPACE_SID).tasks; + console.log('>>> tasks', tasks); + // Cleanup task for captured channel by the bot const task = await context .getTwilioClient() From b95703c957b2d4653bf4290a5deb904eae4305f8 Mon Sep 17 00:00:00 2001 From: mythilytm Date: Mon, 29 May 2023 13:00:09 -0400 Subject: [PATCH 07/13] context & tasks clgs correction --- functions/captureChannelWithBot.protected.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/functions/captureChannelWithBot.protected.ts b/functions/captureChannelWithBot.protected.ts index 8f807809..f55df67b 100644 --- a/functions/captureChannelWithBot.protected.ts +++ b/functions/captureChannelWithBot.protected.ts @@ -135,11 +135,12 @@ export const handler = async ( console.log('>>> updatedChannelAttributes', updatedChannelAttributes); console.log('>>> twilio workspace', context.TWILIO_WORKSPACE_SID); - console.log('>>> workflowSid', context.TWILIO_WORKSPACE_SID); + console.log('>>> workflowSid', context.SURVEY_WORKFLOW_SID); const tasks = await context .getTwilioClient() - .taskrouter.workspaces(context.TWILIO_WORKSPACE_SID).tasks; + .taskrouter.workspaces(context.TWILIO_WORKSPACE_SID) + .fetch(); console.log('>>> tasks', tasks); // Cleanup task for captured channel by the bot From 63990ae62b21e186920b7217d87e1f7b2da28302 Mon Sep 17 00:00:00 2001 From: mythilytm Date: Mon, 29 May 2023 13:29:10 -0400 Subject: [PATCH 08/13] survey case correction --- functions/captureChannelWithBot.protected.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/functions/captureChannelWithBot.protected.ts b/functions/captureChannelWithBot.protected.ts index f55df67b..7933dad3 100644 --- a/functions/captureChannelWithBot.protected.ts +++ b/functions/captureChannelWithBot.protected.ts @@ -149,8 +149,11 @@ export const handler = async ( .taskrouter.workspaces(context.TWILIO_WORKSPACE_SID) .tasks.create({ workflowSid: context.SURVEY_WORKFLOW_SID, - attributes: JSON.stringify({ isChatbotCaptureControl: true }), - taskChannel: 'survey', + attributes: JSON.stringify({ + isChatbotCaptureControl: true, + channelSid, + }), + taskChannel: 'Survey', timeout: 10, // 720 minutes or 12 hours // timeout: 45600, // 720 minutes or 12 hours }); From ba438025bbe24c7151d75ab6a253faab923171f3 Mon Sep 17 00:00:00 2001 From: mythilytm Date: Mon, 29 May 2023 13:33:54 -0400 Subject: [PATCH 09/13] survey case back, timeout --- functions/captureChannelWithBot.protected.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/functions/captureChannelWithBot.protected.ts b/functions/captureChannelWithBot.protected.ts index 7933dad3..08e0fd0e 100644 --- a/functions/captureChannelWithBot.protected.ts +++ b/functions/captureChannelWithBot.protected.ts @@ -153,8 +153,8 @@ export const handler = async ( isChatbotCaptureControl: true, channelSid, }), - taskChannel: 'Survey', - timeout: 10, // 720 minutes or 12 hours + taskChannel: 'survey', + timeout: 1000, // 720 minutes or 12 hours // timeout: 45600, // 720 minutes or 12 hours }); From 7500c81966784eaba76cab641d38379893acbb4f Mon Sep 17 00:00:00 2001 From: mythilytm Date: Mon, 29 May 2023 13:38:40 -0400 Subject: [PATCH 10/13] isChatCaptureControl filter --- functions/captureChannelWithBot.protected.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functions/captureChannelWithBot.protected.ts b/functions/captureChannelWithBot.protected.ts index 08e0fd0e..a32a8f3d 100644 --- a/functions/captureChannelWithBot.protected.ts +++ b/functions/captureChannelWithBot.protected.ts @@ -150,7 +150,7 @@ export const handler = async ( .tasks.create({ workflowSid: context.SURVEY_WORKFLOW_SID, attributes: JSON.stringify({ - isChatbotCaptureControl: true, + isChatCaptureControl: true, channelSid, }), taskChannel: 'survey', From 7502f716aeee2c7f6aac17b30d65fd2e14bafe97 Mon Sep 17 00:00:00 2001 From: mythilytm Date: Mon, 29 May 2023 13:39:52 -0400 Subject: [PATCH 11/13] isChatCaptureControl filter name corrrection --- functions/taskrouterListeners/janitorListener.private.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/functions/taskrouterListeners/janitorListener.private.ts b/functions/taskrouterListeners/janitorListener.private.ts index 2efe1040..eb60bf38 100644 --- a/functions/taskrouterListeners/janitorListener.private.ts +++ b/functions/taskrouterListeners/janitorListener.private.ts @@ -44,15 +44,15 @@ type EnvVars = { FLEX_PROXY_SERVICE_SID: string; }; -// This applies to both pre-survey(isChatbotCaptureControl) and post-survey +// This applies to both pre-survey(isChatCaptureControl) and post-survey const isCleanupBotCapture = ( eventType: EventType, - taskAttributes: { isSurveyTask?: boolean; isChatbotCaptureControl?: boolean }, + taskAttributes: { isSurveyTask?: boolean; isChatCaptureControl?: boolean }, ) => { if (taskAttributes.isSurveyTask) { return eventType === TASK_CANCELED || eventType === TASK_WRAPUP; } - if (taskAttributes.isChatbotCaptureControl) { + if (taskAttributes.isChatCaptureControl) { return eventType === TASK_CANCELED; } return false; @@ -96,7 +96,7 @@ export const handleEvent = async (context: Context, event: EventFields) if (isCleanupBotCapture(eventType, taskAttributes)) { // eslint-disable-next-line @typescript-eslint/no-unused-expressions - const cleanupType = taskAttributes.isChatbotCaptureControl ? 'pre-survey' : 'post-survey'; + const cleanupType = taskAttributes.isChatCaptureControl ? 'pre-survey' : 'post-survey'; console.log(`Handling clean up ${cleanupType}...`); await wait(3000); // wait 3 seconds just in case some bot message is pending From 910f245eff1913f9575e34c17ca1ed8c4e713f7c Mon Sep 17 00:00:00 2001 From: mythilytm Date: Thu, 1 Jun 2023 23:14:55 -0400 Subject: [PATCH 12/13] Removed logs and clean up branch --- functions/captureChannelWithBot.protected.ts | 24 +----- .../janitorListener.private.ts | 5 +- .../webhooks/chatbotCallback.protected.ts | 83 ++++++++----------- 3 files changed, 37 insertions(+), 75 deletions(-) diff --git a/functions/captureChannelWithBot.protected.ts b/functions/captureChannelWithBot.protected.ts index a32a8f3d..9afe05da 100644 --- a/functions/captureChannelWithBot.protected.ts +++ b/functions/captureChannelWithBot.protected.ts @@ -54,9 +54,6 @@ export const handler = async ( const response = responseWithCors(); const resolve = bindResolve(callback)(response); - console.log('>>> event', event); - console.log('>>> response', response); - try { const { channelSid, message, fromServiceUser, studioFlowSid } = event; @@ -131,20 +128,8 @@ export const handler = async ( const updatedChannelAttributes = JSON.parse(updated.attributes); - console.log('>>> updated.attributes', updated.attributes); - console.log('>>> updatedChannelAttributes', updatedChannelAttributes); - - console.log('>>> twilio workspace', context.TWILIO_WORKSPACE_SID); - console.log('>>> workflowSid', context.SURVEY_WORKFLOW_SID); - - const tasks = await context - .getTwilioClient() - .taskrouter.workspaces(context.TWILIO_WORKSPACE_SID) - .fetch(); - console.log('>>> tasks', tasks); - // Cleanup task for captured channel by the bot - const task = await context + await context .getTwilioClient() .taskrouter.workspaces(context.TWILIO_WORKSPACE_SID) .tasks.create({ @@ -153,13 +138,10 @@ export const handler = async ( isChatCaptureControl: true, channelSid, }), - taskChannel: 'survey', - timeout: 1000, // 720 minutes or 12 hours - // timeout: 45600, // 720 minutes or 12 hours + taskChannel: 'Survey', + timeout: 45600, // 720 minutes or 12 hours }); - console.log('>>> task', task); - // ============== /** * TODO: Factor out shared chunk of code diff --git a/functions/taskrouterListeners/janitorListener.private.ts b/functions/taskrouterListeners/janitorListener.private.ts index eb60bf38..935dfd2f 100644 --- a/functions/taskrouterListeners/janitorListener.private.ts +++ b/functions/taskrouterListeners/janitorListener.private.ts @@ -95,9 +95,7 @@ export const handleEvent = async (context: Context, event: EventFields) const taskAttributes = JSON.parse(taskAttributesString); if (isCleanupBotCapture(eventType, taskAttributes)) { - // eslint-disable-next-line @typescript-eslint/no-unused-expressions const cleanupType = taskAttributes.isChatCaptureControl ? 'pre-survey' : 'post-survey'; - console.log(`Handling clean up ${cleanupType}...`); await wait(3000); // wait 3 seconds just in case some bot message is pending @@ -105,8 +103,7 @@ export const handleEvent = async (context: Context, event: EventFields) const chatChannelJanitor = require(handlerPath).chatChannelJanitor as ChatChannelJanitor; await chatChannelJanitor(context, { channelSid: taskAttributes.channelSid }); - // eslint-disable-next-line @typescript-eslint/no-unused-expressions - console.log(`Finished handling clean up ${cleanupType}.`); + console.log(`Finished handling clean up for ${cleanupType}.`); return; } diff --git a/functions/webhooks/chatbotCallback.protected.ts b/functions/webhooks/chatbotCallback.protected.ts index e0825d0d..fc0eba30 100644 --- a/functions/webhooks/chatbotCallback.protected.ts +++ b/functions/webhooks/chatbotCallback.protected.ts @@ -128,56 +128,39 @@ export const handler = async ( }; // const releasedChannelAttributes = omit(channelAttributes, 'channelCapturedByBot'); - await Promise.all( - [ - // Delete Lex session. This is not really needed as the session will expire, but that depends on the config of Lex. - () => { - console.log('>>> Lex.deleteSession'); - Lex.deleteSession({ - botId: channelAttributes.channelCapturedByBot.botId, - botAliasId: channelAttributes.channelCapturedByBot.botAliasId, - localeId: channelAttributes.channelCapturedByBot.localeId, - sessionId: channel.sid, - }).promise(); - }, - // Remove channelCapturedByBot from channel attributes - () => { - console.log('>>> Remove channelCapturedByBot from channel attributes'); - channel.update({ - attributes: JSON.stringify(releasedChannelAttributes), - }); - }, - // Move control task to complete state - () => { - console.log('>>> Move control task to complete state'); - client.taskrouter.v1 - .workspaces('WORKFLOW_SID') - .tasks(channelAttributes.controlTaskSid) - .update({ assignmentStatus: 'completed' }); - }, - // Remove this webhook from the channel - () => { - console.log('>>> Remove this webhook from the channel'); - channel - .webhooks() - .get(channelAttributes.channelCapturedByBot.chatbotCallbackWebhookSid) - .remove(); - }, - // Trigger a new API type Studio Flow execution once the channel is released - () => { - console.log('>>> Studio Flow execution once the channel is released'); - client.studio.v2 - .flows(channelAttributes.channelCapturedByBot.studioFlowSid) - .executions.create({ - from: ChannelSid, - to: ChannelSid, - parameters: { - ChannelAttributes: releasedChannelAttributes, - }, - }); - }, - ].map((func) => func()), - ); + await Promise.all([ + // Delete Lex session. This is not really needed as the session will expire, but that depends on the config of Lex. + Lex.deleteSession({ + botId: channelAttributes.channelCapturedByBot.botId, + botAliasId: channelAttributes.channelCapturedByBot.botAliasId, + localeId: channelAttributes.channelCapturedByBot.localeId, + sessionId: channel.sid, + }).promise(), + // Remove channelCapturedByBot from channel attributes + channel.update({ + attributes: JSON.stringify(releasedChannelAttributes), + }), + // Move control task to complete state + client.taskrouter.v1 + .workspaces('WORKFLOW_SID') + .tasks(channelAttributes.controlTaskSid) + .update({ assignmentStatus: 'completed' }), + // Remove this webhook from the channel + channel + .webhooks() + .get(channelAttributes.channelCapturedByBot.chatbotCallbackWebhookSid) + .remove(), + // Trigger a new API type Studio Flow execution once the channel is released + client.studio.v2 + .flows(channelAttributes.channelCapturedByBot.studioFlowSid) + .executions.create({ + from: ChannelSid, + to: ChannelSid, + parameters: { + ChannelAttributes: releasedChannelAttributes, + }, + }), + ]); console.log('Channel unblocked and bot session deleted'); } From ef17026cfff4ec0b38f97d556876288c04b58020 Mon Sep 17 00:00:00 2001 From: mythilytm Date: Thu, 1 Jun 2023 23:16:56 -0400 Subject: [PATCH 13/13] Correction to lowercase survey for declaring taskChannel --- functions/captureChannelWithBot.protected.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functions/captureChannelWithBot.protected.ts b/functions/captureChannelWithBot.protected.ts index 9afe05da..d766a8e7 100644 --- a/functions/captureChannelWithBot.protected.ts +++ b/functions/captureChannelWithBot.protected.ts @@ -138,7 +138,7 @@ export const handler = async ( isChatCaptureControl: true, channelSid, }), - taskChannel: 'Survey', + taskChannel: 'survey', timeout: 45600, // 720 minutes or 12 hours });