Skip to content
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

chat-core-zendesk: workaround to inject ticket id to bot message #60

Merged
merged 2 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/chat-core-aws-connect/THIRD-PARTY-NOTICES
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ The following NPM packages may be included in this product:
- @types/[email protected]
- @types/[email protected]
- @types/[email protected]
- @types/[email protected].1
- @types/[email protected].2
- @types/[email protected]
- @types/[email protected]
- @types/[email protected]
Expand Down
2 changes: 1 addition & 1 deletion packages/chat-core-zendesk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@yext/chat-core-zendesk",
"version": "0.3.1",
"version": "0.4.0",
"description": "Typescript Networking Library for the Yext Chat API Integration with Zendesk",
"main": "./dist/commonjs/index.js",
"module": "./dist/esm/index.mjs",
Expand Down
37 changes: 23 additions & 14 deletions packages/chat-core-zendesk/src/infra/ChatCoreZendeskImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,21 @@ export class ChatCoreZendeskImpl implements ChatCoreZendesk {
}
this.conversationId = convo.id;
Smooch.loadConversation(convo.id);

// This is a temporary solution until Zendesk have a more robust way of fetching the ticket id.
// A Zendesk trigger is setup to make a Sunco API call, using this conversation ID placed inside
// a Zendesk custom field, to append the corresponding ticket id into the Sunco conversation's
// metadata. The bot then pull from metadata to inform the user of the ticket id when the messaging
// session ends.
const convoIdTicketField = Object.keys(ticketFields).find((key) => {
return ticketFields[key] === "SUNCO_CONVERSATION_ID_PLACEHOLDER";
});
if (convoIdTicketField) {
await Smooch.updateConversation(convo.id, {
metadata: { [convoIdTicketField]: convo.id },
});
}

Smooch.sendMessage(
`SUMMARY: ${
messageRsp.notes.conversationSummary ??
Expand All @@ -179,29 +194,23 @@ export class ChatCoreZendeskImpl implements ChatCoreZendesk {
if (data.conversation.id !== this.conversationId) {
return;
}
if (message.type !== "text" || message.role !== "business") {
if (
message.type !== "text" ||
message.role !== "business" ||
// @ts-ignore - metadata is not in the Smooch types but it's in the actual data
message["metadata"]?.type === "csat"
) {
return;
}
let msg: string = message.text;

// If the message is of type CSAT, indicating the agent has resolved the ticket, then omit this message.
// Instead, send a message to inform user and reset the session
// @ts-ignore - metadata is not in the Smooch types but it's in the actual data
if (message["metadata"]?.type === "csat") {
this.resetSession();
this.eventListeners["close"]?.forEach((cb) => cb(data));
msg =
"The agent has resolved the ticket. Further assistance will now be provided by the bot.";
}

// If the message is from a bot, indicating the agent has deleted the ticket, then reset the session
// If the message is from a bot, indicating the agent has ended the messaging session, then reset the session
// @ts-ignore - subroles is not in the Smooch types but it's in the actual data
if (message["subroles"]?.includes("AI")) {
this.resetSession();
this.eventListeners["close"]?.forEach((cb) => cb(data));
}

this.eventListeners["message"]?.forEach((cb) => cb(msg));
this.eventListeners["message"]?.forEach((cb) => cb(message.text));
this.eventListeners["typing"]?.forEach((cb) => cb(false));
}
);
Expand Down
29 changes: 29 additions & 0 deletions packages/chat-core-zendesk/tests/ChatCoreZendesk.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ jest.mock("smooch", () => ({
render: jest.fn(),
init: jest.fn(),
createConversation: jest.fn(),
updateConversation: jest.fn(),
loadConversation: jest.fn(),
sendMessage: jest.fn(),
on: jest.fn(),
Expand Down Expand Up @@ -300,3 +301,31 @@ it("sets ticket tags defined in config on handoff", async () => {
},
});
});

it("set conversation id to custom field on handoff", async () => {
const createConversationSpy = jest.spyOn(SmoochLib, "createConversation");
const updateConversationSpy = jest.spyOn(SmoochLib, "updateConversation");
const chatCoreZendesk = provideChatCoreZendesk(mockConfig);

await chatCoreZendesk.init({
...mockMessageResponse(),
integrationDetails: {
zendeskHandoff: {
ticketFields: '{"123456": "SUNCO_CONVERSATION_ID_PLACEHOLDER"}',
},
},
});
expect(createConversationSpy).toBeCalledWith({
metadata: {
"zen:ticket:tags": "yext-chat-agent-handoff",
YEXT_CHAT_SDK: true,
"zen:ticket_field:123456": "SUNCO_CONVERSATION_ID_PLACEHOLDER",
},
});

expect(updateConversationSpy).toBeCalledWith(mockConversationId, {
metadata: {
"zen:ticket_field:123456": mockConversationId,
},
});
});
2 changes: 1 addition & 1 deletion test-sites/test-browser-esm/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading