Skip to content

chore: Move chatbot handlers to Lambda [CHI-3218] #2929

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
fe38574
chore: added channel capture handlers
GPaoloni Apr 18, 2025
58f8df1
chore: expose handlers via router
GPaoloni Apr 18, 2025
5b8b7b9
fix: routing
GPaoloni Apr 21, 2025
c48da3a
fix: routing
GPaoloni Apr 21, 2025
c9baa40
chore: add dbg
GPaoloni Apr 21, 2025
0999205
chore: add dbg
GPaoloni Apr 21, 2025
86e8953
chore: add dbg
GPaoloni Apr 22, 2025
0a66399
fix: webhook creation payload
GPaoloni Apr 22, 2025
228e8e2
fix: accomodate webhook creation params for conversation or chat
GPaoloni Apr 22, 2025
238a833
chore: add dbg
GPaoloni Apr 22, 2025
935be8d
fix: chatbot callback url includes acctscp
GPaoloni Apr 22, 2025
6f1e3c7
fix: facepalm
GPaoloni Apr 22, 2025
e1d8fdc
fix: facepalm
GPaoloni Apr 22, 2025
1c10113
chore: parse url form encoded request body
GPaoloni Apr 22, 2025
13c4b3d
fix: include accountSid in chatbot callback
GPaoloni Apr 22, 2025
f892a72
chore: fix unit tests
GPaoloni Apr 23, 2025
c6a19b0
Merge remote-tracking branch 'origin/master' into gian_CHI-3218
GPaoloni Apr 23, 2025
a645bf7
chore: add postSurveyListener taskrouter webhook
GPaoloni Apr 23, 2025
0f2af09
chore: bypass post survey handler if flag is not set
GPaoloni Apr 24, 2025
8e70acd
fix: import post survey listener so it's subscribed
GPaoloni Apr 24, 2025
086cda1
fix: correct destructuring of service config attributes
GPaoloni Apr 24, 2025
fcde79f
chore: add PostSurvey definition to forms
GPaoloni Apr 24, 2025
730d8f9
chore: dbg
GPaoloni Apr 25, 2025
732c6e2
fix: use config spec without parsing
GPaoloni Apr 25, 2025
69a56b1
Merge remote-tracking branch 'origin/master' into gian_CHI-3218
GPaoloni Apr 28, 2025
4ba5cee
fix: TS
GPaoloni Apr 28, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions hrm-form-definitions/form-definitions/as/v1/PostSurvey.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"insightsObject": "conversations",
"attributeName": "conversation_attribute_9",
"questions": ["wasHelpful"]
},
{
"insightsObject": "conversations",
"attributeName": "conversation_attribute_10",
"questions": ["wouldRecommend"]
}
]
2 changes: 2 additions & 0 deletions lambdas/account-scoped/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
"test": "jest"
},
"dependencies": {
"@aws-sdk/client-lex-runtime-service": "^3.787.0",
"@aws-sdk/client-lex-runtime-v2": "^3.787.0",
"@aws-sdk/client-ssm": "^3.716.0",
"@twilio-labs/serverless-runtime-types": "^4.0.1",
"date-fns": "^4.1.0",
Expand Down
107 changes: 107 additions & 0 deletions lambdas/account-scoped/src/channelCapture/captureChannelWithBot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/* 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/.
*/

import twilio from 'twilio';
import { handleChannelCapture } from './channelCaptureHandlers';
import { AccountScopedHandler, HttpError } from '../httpTypes';
import { isErr, newErr, newOk, Result } from '../Result';
import {
getAccountAuthToken,
getChatServiceSid,
getHelplineCode,
getSurveyWorkflowSid,
getTwilioWorkspaceSid,
} from '../configuration/twilioConfiguration';

export const handleCaptureChannelWithBot: AccountScopedHandler = async (
request,
accountSid,
): Promise<Result<HttpError, {}>> => {
try {
const authToken = await getAccountAuthToken(accountSid);
const twilioClient = twilio(accountSid, authToken);

const environment = process.env.NODE_ENV!;
const webhookBaseUrl = process.env.WEBHOOK_BASE_URL!;

const {
channelSid,
message,
triggerType,
releaseType,
studioFlowSid,
language,
botSuffix,
additionControlTaskAttributes,
controlTaskTTL,
memoryAttribute,
releaseFlag,
isConversation: isConversationValue,
channelType,
} = request.body;

const isConversation =
(typeof isConversationValue === 'string' && isConversationValue === 'true') ||
(typeof isConversationValue === 'boolean' && isConversationValue);

const chatServiceSid = await getChatServiceSid(accountSid);
const helplineCode = await getHelplineCode(accountSid);
const surveyWorkflowSid = await getSurveyWorkflowSid(accountSid);
const twilioWorkspaceSid = await getTwilioWorkspaceSid(accountSid);

const result = await handleChannelCapture(twilioClient, {
accountSid,
channelSid,
conversationSid: isConversation ? channelSid : '',
message,
language,
botSuffix,
triggerType,
releaseType,
studioFlowSid,
memoryAttribute,
releaseFlag,
additionControlTaskAttributes,
controlTaskTTL,
channelType,
environment,
webhookBaseUrl,
chatServiceSid,
helplineCode,
surveyWorkflowSid,
twilioWorkspaceSid,
});

if (isErr(result)) {
if (result.error instanceof Error) {
return newErr({
message: result.message,
error: { statusCode: 500, cause: result.error },
});
} else {
return newErr({
message: result.message,
error: { statusCode: 400, cause: new Error(result.message) },
});
}
}
console.info(`[${accountSid}] channel ${channelSid} captured`);
return newOk({});
} catch (error: any) {
return newErr({ message: error.message, error: { statusCode: 500, cause: error } });
}
};
Loading
Loading