diff --git a/examples/simple-examples/README.md b/examples/simple-examples/README.md index 975aa2c9..55e9e2e6 100644 --- a/examples/simple-examples/README.md +++ b/examples/simple-examples/README.md @@ -174,54 +174,69 @@ yarn run numbers:regions:list ### Conversation -| Service | Sample application name and location | Required parameters | -|--------------|--------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------| -| App | [./src/conversation/app/create.ts](./src/conversation/app/create.ts) | `MESSENGER_TOKEN` | -| | [./src/conversation/app/delete.ts](./src/conversation/app/delete.ts) | `CONVERSATION_APP_ID` | -| | [./src/conversation/app/get.ts](./src/conversation/app/get.ts) | `CONVERSATION_APP_ID` | -| | [./src/conversation/app/list.ts](./src/conversation/app/list.ts) | | -| | [./src/conversation/app/update.ts](./src/conversation/app/update.ts) | `CONVERSATION_APP_ID` | -| Capability | [./src/conversation/capability/lookup.ts](./src/conversation/capability/lookup.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | -| Contact | [./src/conversation/contact/create.ts](./src/conversation/contact/create.ts) | `CONVERSATION_APP_ID` + `MESSENGER_USER_ID` + `PHONE_NUMBER` | -| | [./src/conversation/contact/delete.ts](./src/conversation/contact/delete.ts) | `CONVERSATION_CONTACT_ID` | -| | [./src/conversation/contact/get.ts](./src/conversation/contact/get.ts) | `CONVERSATION_CONTACT_ID` | -| | [./src/conversation/contact/getChannelProfile.ts](./src/conversation/contact/getChannelProfile.ts) | `CONVERSATION_CONTACT_ID` + `MESSENGER_USER_ID` | -| | [./src/conversation/contact/list.ts](./src/conversation/contact/list.ts) | | -| | [./src/conversation/contact/merge.ts](./src/conversation/contact/merge.ts) | `PHONE_NUMBER` | -| | [./src/conversation/contact/update.ts](./src/conversation/contact/update.ts) | `CONVERSATION_CONTACT_ID` | -| Conversation | [./src/conversation/conversation/create.ts](./src/conversation/conversation/create.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | -| | [./src/conversation/conversation/delete.ts](./src/conversation/conversation/delete.ts) | `CONVERSATION_ID` | -| | [./src/conversation/conversation/get.ts](./src/conversation/conversation/get.ts) | `CONVERSATION_ID` | -| | [./src/conversation/conversation/injectEvent.ts](./src/conversation/conversation/injectEvent.ts) | `CONVERSATION_ID` + `CONVERSATION_CONTACT_ID` | -| | [./src/conversation/conversation/injectMessage.ts](./src/conversation/conversation/injectMessage.ts) | `CONVERSATION_ID` + `MESSENGER_USER_ID`+ `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | -| | [./src/conversation/conversation/list.ts](./src/conversation/conversation/list.ts) | `CONVERSATION_APP_ID` | -| | [./src/conversation/conversation/listRecent.ts](./src/conversation/conversation/listRecent.ts) | `CONVERSATION_APP_ID` | -| | [./src/conversation/conversation/stop.ts](./src/conversation/conversation/stop.ts) | `CONVERSATION_ID` | -| | [./src/conversation/conversation/update.ts](./src/conversation/conversation/update.ts) | `CONVERSATION_ID` | -| Events | [./src/conversation/events/send.ts](./src/conversation/events/send.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | -| | [./src/conversation/events/get.ts](./src/conversation/events/get.ts) | `EVENT_ID` | -| | [./src/conversation/events/list.ts](./src/conversation/events/list.ts) | `CONVERSATION_ID` + `CONVERSATION_CONTACT_ID` | -| | [./src/conversation/events/delete.ts](./src/conversation/events/delete.ts) | `EVENT_ID` | -| Messages | [./src/conversation/messages/delete.ts](./src/conversation/messages/delete.ts) | `MESSAGE_ID` | -| | [./src/conversation/messages/get.ts](./src/conversation/messages/get.ts) | `MESSAGE_ID` | -| | [./src/conversation/messages/list.ts](./src/conversation/messages/list.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` + `CONVERSATION_ID` | -| | [./src/conversation/messages/send.ts](./src/conversation/messages/send.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | -| | [./src/conversation/messages/update.ts](./src/conversation/messages/update.ts) | `MESSAGE_ID` | -| TemplatesV1 | [./src/conversation/templates-v1/create.ts](./src/conversation/templates-v1/create.ts) | | -| | [./src/conversation/templates-v1/delete.ts](./src/conversation/templates-v1/delete.ts) | `TEMPLATE_ID` | -| | [./src/conversation/templates-v1/get.ts](./src/conversation/templates-v1/get.ts) | `TEMPLATE_ID` | -| | [./src/conversation/templates-v1/list.ts](./src/conversation/templates-v1/list.ts) | | -| | [./src/conversation/templates-v1/update.ts](./src/conversation/templates-v1/update.ts) | `TEMPLATE_ID` | -| TemplatesV2 | [./src/conversation/templates-v2/create.ts](./src/conversation/templates-v2/create.ts) | | -| | [./src/conversation/templates-v2/delete.ts](./src/conversation/templates-v2/delete.ts) | `TEMPLATE_ID` | -| | [./src/conversation/templates-v2/get.ts](./src/conversation/templates-v2/get.ts) | `TEMPLATE_ID` | -| | [./src/conversation/templates-v2/list.ts](./src/conversation/templates-v2/list.ts) | | -| | [./src/conversation/templates-v2/list-translations.ts](./src/conversation/templates-v2/list-translations.ts) | `TEMPLATE_ID` | -| | [./src/conversation/templates-v2/update.ts](./src/conversation/templates-v2/update.ts) | `TEMPLATE_ID` | -| Transcoding | [./src/conversation/transcoding/transcode.ts](./src/conversation/transcoding/transcode.ts) | `CONVERSATION_APP_ID` | -| Webhooks | [./src/conversation/webhooks/create.ts](./src/conversation/webhooks/create.ts) | `CONVERSATION_APP_ID` + `WEBHOOK_TARGET` | -| | [./src/conversation/webhooks/delete.ts](./src/conversation/webhooks/delete.ts) | `WEBHOOK_ID` | -| | [./src/conversation/webhooks/get.ts](./src/conversation/webhooks/get.ts) | `WEBHOOK_ID` | -| | [./src/conversation/webhooks/list.ts](./src/conversation/webhooks/list.ts) | `CONVERSATION_APP_ID` | -| | [./src/conversation/webhooks/update.ts](./src/conversation/webhooks/update.ts) | `CONVERSATION_APP_ID` + `WEBHOOK_ID` | +| Service | Sample application name and location | Required parameters | +|--------------|----------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------| +| App | [./src/conversation/app/create.ts](./src/conversation/app/create.ts) | `MESSENGER_TOKEN` | +| | [./src/conversation/app/delete.ts](./src/conversation/app/delete.ts) | `CONVERSATION_APP_ID` | +| | [./src/conversation/app/get.ts](./src/conversation/app/get.ts) | `CONVERSATION_APP_ID` | +| | [./src/conversation/app/list.ts](./src/conversation/app/list.ts) | | +| | [./src/conversation/app/update.ts](./src/conversation/app/update.ts) | `CONVERSATION_APP_ID` | +| Capability | [./src/conversation/capability/lookup.ts](./src/conversation/capability/lookup.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | +| Contact | [./src/conversation/contact/create.ts](./src/conversation/contact/create.ts) | `CONVERSATION_APP_ID` + `MESSENGER_USER_ID` + `PHONE_NUMBER` | +| | [./src/conversation/contact/delete.ts](./src/conversation/contact/delete.ts) | `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/contact/get.ts](./src/conversation/contact/get.ts) | `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/contact/getChannelProfile.ts](./src/conversation/contact/getChannelProfile.ts) | `CONVERSATION_CONTACT_ID` + `MESSENGER_USER_ID` | +| | [./src/conversation/contact/list.ts](./src/conversation/contact/list.ts) | | +| | [./src/conversation/contact/merge.ts](./src/conversation/contact/merge.ts) | `PHONE_NUMBER` | +| | [./src/conversation/contact/update.ts](./src/conversation/contact/update.ts) | `CONVERSATION_CONTACT_ID` | +| Conversation | [./src/conversation/conversation/create.ts](./src/conversation/conversation/create.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/conversation/delete.ts](./src/conversation/conversation/delete.ts) | `CONVERSATION_ID` | +| | [./src/conversation/conversation/get.ts](./src/conversation/conversation/get.ts) | `CONVERSATION_ID` | +| | [./src/conversation/conversation/injectEvent.ts](./src/conversation/conversation/injectEvent.ts) | `CONVERSATION_ID` + `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/conversation/injectMessage.ts](./src/conversation/conversation/injectMessage.ts) | `CONVERSATION_ID` + `MESSENGER_USER_ID`+ `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/conversation/list.ts](./src/conversation/conversation/list.ts) | `CONVERSATION_APP_ID` | +| | [./src/conversation/conversation/listRecent.ts](./src/conversation/conversation/listRecent.ts) | `CONVERSATION_APP_ID` | +| | [./src/conversation/conversation/stop.ts](./src/conversation/conversation/stop.ts) | `CONVERSATION_ID` | +| | [./src/conversation/conversation/update.ts](./src/conversation/conversation/update.ts) | `CONVERSATION_ID` | +| Events | [./src/conversation/events/sendComposingEvent.ts](./src/conversation/events/sendComposingEvent.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/events/sendComposingEndEvent.ts](./src/conversation/events/sendComposingEndEvent.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/events/sendCommentReplyEvent.ts](./src/conversation/events/sendCommentReplyEvent.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/events/sendAgentJoinedEvent.ts](./src/conversation/events/sendAgentJoinedEvent.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/events/sendAgentLeftEvent.ts](./src/conversation/events/sendAgentLeftEvent.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/events/sendGenericEvent.ts](./src/conversation/events/sendGenericEvent.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/events/get.ts](./src/conversation/events/get.ts) | `EVENT_ID` | +| | [./src/conversation/events/list.ts](./src/conversation/events/list.ts) | `CONVERSATION_ID` + `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/events/delete.ts](./src/conversation/events/delete.ts) | `EVENT_ID` | +| Messages | [./src/conversation/messages/delete.ts](./src/conversation/messages/delete.ts) | `MESSAGE_ID` | +| | [./src/conversation/messages/get.ts](./src/conversation/messages/get.ts) | `MESSAGE_ID` | +| | [./src/conversation/messages/list.ts](./src/conversation/messages/list.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` + `CONVERSATION_ID` | +| | [./src/conversation/messages/send.ts](./src/conversation/messages/send.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/messages/send.ts](./src/conversation/messages/send.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/messages/sendCardMessage.ts](./src/conversation/messages/sendCardMessage.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/messages/sendCarouselMessage.ts](./src/conversation/messages/sendCarouselMessage.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/messages/sendChoiceMessage.ts](./src/conversation/messages/sendChoiceMessage.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/messages/sendContactInfoMessage.ts](./src/conversation/messages/sendContactInfoMessage.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/messages/sendListMessage.ts](./src/conversation/messages/sendListMessage.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/messages/sendLocationMessage.ts](./src/conversation/messages/sendLocationMessage.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/messages/sendMediaMessage.ts](./src/conversation/messages/sendMediaMessage.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/messages/sendTemplateMessage.ts](./src/conversation/messages/sendTemplateMessage.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/messages/sendTextMessage.ts](./src/conversation/messages/sendTextMessage.ts) | `CONVERSATION_APP_ID` + `CONVERSATION_CONTACT_ID` | +| | [./src/conversation/messages/update.ts](./src/conversation/messages/update.ts) | `MESSAGE_ID` | +| TemplatesV1 | [./src/conversation/templates-v1/create.ts](./src/conversation/templates-v1/create.ts) | | +| | [./src/conversation/templates-v1/delete.ts](./src/conversation/templates-v1/delete.ts) | `TEMPLATE_ID` | +| | [./src/conversation/templates-v1/get.ts](./src/conversation/templates-v1/get.ts) | `TEMPLATE_ID` | +| | [./src/conversation/templates-v1/list.ts](./src/conversation/templates-v1/list.ts) | | +| | [./src/conversation/templates-v1/update.ts](./src/conversation/templates-v1/update.ts) | `TEMPLATE_ID` | +| TemplatesV2 | [./src/conversation/templates-v2/create.ts](./src/conversation/templates-v2/create.ts) | | +| | [./src/conversation/templates-v2/delete.ts](./src/conversation/templates-v2/delete.ts) | `TEMPLATE_ID` | +| | [./src/conversation/templates-v2/get.ts](./src/conversation/templates-v2/get.ts) | `TEMPLATE_ID` | +| | [./src/conversation/templates-v2/list.ts](./src/conversation/templates-v2/list.ts) | | +| | [./src/conversation/templates-v2/list-translations.ts](./src/conversation/templates-v2/list-translations.ts) | `TEMPLATE_ID` | +| | [./src/conversation/templates-v2/update.ts](./src/conversation/templates-v2/update.ts) | `TEMPLATE_ID` | +| Transcoding | [./src/conversation/transcoding/transcode.ts](./src/conversation/transcoding/transcode.ts) | `CONVERSATION_APP_ID` | +| Webhooks | [./src/conversation/webhooks/create.ts](./src/conversation/webhooks/create.ts) | `CONVERSATION_APP_ID` + `WEBHOOK_TARGET` | +| | [./src/conversation/webhooks/delete.ts](./src/conversation/webhooks/delete.ts) | `WEBHOOK_ID` | +| | [./src/conversation/webhooks/get.ts](./src/conversation/webhooks/get.ts) | `WEBHOOK_ID` | +| | [./src/conversation/webhooks/list.ts](./src/conversation/webhooks/list.ts) | `CONVERSATION_APP_ID` | +| | [./src/conversation/webhooks/update.ts](./src/conversation/webhooks/update.ts) | `CONVERSATION_APP_ID` + `WEBHOOK_ID` | diff --git a/examples/simple-examples/package.json b/examples/simple-examples/package.json index a57a2a6a..107d2d62 100644 --- a/examples/simple-examples/package.json +++ b/examples/simple-examples/package.json @@ -21,6 +21,15 @@ "conversation:contact:getChannelProfile": "ts-node src/conversation/contact/getChannelProfile.ts", "conversation:contact:delete": "ts-node src/conversation/contact/delete.ts", "conversation:messages:send": "ts-node src/conversation/messages/send.ts", + "conversation:messages:sendCardMessage": "ts-node src/conversation/messages/sendCardMessage.ts", + "conversation:messages:sendCarouselMessage": "ts-node src/conversation/messages/sendCarouselMessage.ts", + "conversation:messages:sendChoiceMessage": "ts-node src/conversation/messages/sendChoiceMessage.ts", + "conversation:messages:sendContactInfoMessage": "ts-node src/conversation/messages/sendContactInfoMessage.ts", + "conversation:messages:sendListMessage": "ts-node src/conversation/messages/sendListMessage.ts", + "conversation:messages:sendLocationMessage": "ts-node src/conversation/messages/sendLocationMessage.ts", + "conversation:messages:sendMediaMessage": "ts-node src/conversation/messages/sendMediaMessage.ts", + "conversation:messages:sendTemplateMessage": "ts-node src/conversation/messages/sendTemplateMessage.ts", + "conversation:messages:sendTextMessage": "ts-node src/conversation/messages/sendTextMessage.ts", "conversation:messages:get": "ts-node src/conversation/messages/get.ts", "conversation:messages:list": "ts-node src/conversation/messages/list.ts", "conversation:messages:update": "ts-node src/conversation/messages/update.ts", @@ -35,6 +44,12 @@ "conversation:conversation:stop": "ts-node src/conversation/conversation/stop.ts", "conversation:conversation:delete": "ts-node src/conversation/conversation/delete.ts", "conversation:events:send": "ts-node src/conversation/events/send.ts", + "conversation:events:sendComposingEvent": "ts-node src/conversation/events/sendComposingEvent.ts", + "conversation:events:sendComposingEndEvent": "ts-node src/conversation/events/sendComposingEndEvent.ts", + "conversation:events:sendCommentReplyEvent": "ts-node src/conversation/events/sendCommentReplyEvent.ts", + "conversation:events:sendAgentJoinedEvent": "ts-node src/conversation/events/sendAgentJoinedEvent.ts", + "conversation:events:sendAgentLeftEvent": "ts-node src/conversation/events/sendAgentLeftEvent.ts", + "conversation:events:sendGenericEvent": "ts-node src/conversation/events/sendGenericEvent.ts", "conversation:events:get": "ts-node src/conversation/events/get.ts", "conversation:events:list": "ts-node src/conversation/events/list.ts", "conversation:events:delete": "ts-node src/conversation/events/delete.ts", @@ -53,7 +68,7 @@ "conversation:templatev2:create": "ts-node src/conversation/templates-v2/create.ts", "conversation:templatev2:get": "ts-node src/conversation/templates-v2/get.ts", "conversation:templatev2:list": "ts-node src/conversation/templates-v2/list.ts", - "conversation:templatev2:listTranslations": "ts-node src/conversation/templates-v2/list-translations.ts pretty", + "conversation:templatev2:listTranslations": "ts-node src/conversation/templates-v2/list-translations.ts", "conversation:templatev2:update": "ts-node src/conversation/templates-v2/update.ts", "conversation:templatev2:delete": "ts-node src/conversation/templates-v2/delete.ts", "numbers:regions:list": "ts-node src/numbers/regions/list.ts", diff --git a/examples/simple-examples/src/conversation/capability/lookup.ts b/examples/simple-examples/src/conversation/capability/lookup.ts index ee1b5145..549a5ef7 100644 --- a/examples/simple-examples/src/conversation/capability/lookup.ts +++ b/examples/simple-examples/src/conversation/capability/lookup.ts @@ -1,4 +1,4 @@ -import { LookupCapabilityRequestData } from '@sinch/sdk-core'; +import { ContactId, LookupCapabilityRequestData } from '@sinch/sdk-core'; import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullResponse } from '../../config'; (async () => { @@ -9,7 +9,7 @@ import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullRespon const appId = getAppIdFromConfig(); const contactId = getContactIdFromConfig(); - const requestData: LookupCapabilityRequestData = { + const requestData: LookupCapabilityRequestData = { lookupCapabilityRequestBody: { app_id: appId, recipient: { diff --git a/examples/simple-examples/src/conversation/contact/getChannelProfile.ts b/examples/simple-examples/src/conversation/contact/getChannelProfile.ts index 4febbca6..24098155 100644 --- a/examples/simple-examples/src/conversation/contact/getChannelProfile.ts +++ b/examples/simple-examples/src/conversation/contact/getChannelProfile.ts @@ -1,4 +1,4 @@ -import { GetChannelProfileRequestData } from '@sinch/sdk-core'; +import { GetChannelProfileRequestData, IdentifiedBy } from '@sinch/sdk-core'; import { getAppIdFromConfig, getMessengerUserIdFromConfig, @@ -14,7 +14,7 @@ import { const appId = getAppIdFromConfig(); const messengerUserId = getMessengerUserIdFromConfig(); - const requestData: GetChannelProfileRequestData = { + const requestData: GetChannelProfileRequestData = { getChannelProfileRequestBody: { app_id: appId, channel: 'MESSENGER', diff --git a/examples/simple-examples/src/conversation/events/send.ts b/examples/simple-examples/src/conversation/events/send.ts index 6aed9db1..767296a3 100644 --- a/examples/simple-examples/src/conversation/events/send.ts +++ b/examples/simple-examples/src/conversation/events/send.ts @@ -1,4 +1,4 @@ -import { SendEventRequestData } from '@sinch/sdk-core'; +import { ContactId, SendEventRequestData } from '@sinch/sdk-core'; import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullResponse } from '../../config'; (async () => { @@ -9,7 +9,7 @@ import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullRespon const appId = getAppIdFromConfig(); const contactId = getContactIdFromConfig(); - const requestData: SendEventRequestData = { + const requestData: SendEventRequestData = { sendEventRequestBody: { app_id: appId, recipient: { diff --git a/examples/simple-examples/src/conversation/events/sendAgentJoinedEvent.ts b/examples/simple-examples/src/conversation/events/sendAgentJoinedEvent.ts new file mode 100644 index 00000000..3baf50dc --- /dev/null +++ b/examples/simple-examples/src/conversation/events/sendAgentJoinedEvent.ts @@ -0,0 +1,34 @@ +import { ContactId, SendAgentJoinedEventRequestData } from '@sinch/sdk-core'; +import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('********************'); + console.log('* Events_SendEvent *'); + console.log('********************'); + + const appId = getAppIdFromConfig(); + const contactId = getContactIdFromConfig(); + + const requestData: SendAgentJoinedEventRequestData = { + sendEventRequestBody: { + app_id: appId, + recipient: { + contact_id: contactId, + }, + event: { + agent_joined_event: { + agent: { + display_name: 'Agent bot name', + type: 'BOT', + }, + }, + }, + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.events.sendAgentJoinedEvent(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/events/sendAgentLeftEvent.ts b/examples/simple-examples/src/conversation/events/sendAgentLeftEvent.ts new file mode 100644 index 00000000..3c4d9973 --- /dev/null +++ b/examples/simple-examples/src/conversation/events/sendAgentLeftEvent.ts @@ -0,0 +1,34 @@ +import { ContactId, SendAgentLeftEventRequestData } from '@sinch/sdk-core'; +import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('********************'); + console.log('* Events_SendEvent *'); + console.log('********************'); + + const appId = getAppIdFromConfig(); + const contactId = getContactIdFromConfig(); + + const requestData: SendAgentLeftEventRequestData = { + sendEventRequestBody: { + app_id: appId, + recipient: { + contact_id: contactId, + }, + event: { + agent_left_event: { + agent: { + display_name: 'Agent bot name', + type: 'BOT', + }, + }, + }, + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.events.sendAgentLeftEvent(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/events/sendCommentReplyEvent.ts b/examples/simple-examples/src/conversation/events/sendCommentReplyEvent.ts new file mode 100644 index 00000000..b8acb586 --- /dev/null +++ b/examples/simple-examples/src/conversation/events/sendCommentReplyEvent.ts @@ -0,0 +1,31 @@ +import { ContactId, SendCommentReplyEventRequestData } from '@sinch/sdk-core'; +import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('********************'); + console.log('* Events_SendEvent *'); + console.log('********************'); + + const appId = getAppIdFromConfig(); + const contactId = getContactIdFromConfig(); + + const requestData: SendCommentReplyEventRequestData = { + sendEventRequestBody: { + app_id: appId, + recipient: { + contact_id: contactId, + }, + event: { + comment_reply_event: { + text: 'Comment data', + }, + }, + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.events.sendCommentReplyEvent(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/events/sendComposingEndEvent.ts b/examples/simple-examples/src/conversation/events/sendComposingEndEvent.ts new file mode 100644 index 00000000..7ecc8907 --- /dev/null +++ b/examples/simple-examples/src/conversation/events/sendComposingEndEvent.ts @@ -0,0 +1,29 @@ +import { ContactId, SendComposingEndEventRequestData } from '@sinch/sdk-core'; +import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('********************'); + console.log('* Events_SendEvent *'); + console.log('********************'); + + const appId = getAppIdFromConfig(); + const contactId = getContactIdFromConfig(); + + const requestData: SendComposingEndEventRequestData = { + sendEventRequestBody: { + app_id: appId, + recipient: { + contact_id: contactId, + }, + event: { + composing_end_event: {}, + }, + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.events.sendComposingEndEvent(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/events/sendComposingEvent.ts b/examples/simple-examples/src/conversation/events/sendComposingEvent.ts new file mode 100644 index 00000000..bef2d5f6 --- /dev/null +++ b/examples/simple-examples/src/conversation/events/sendComposingEvent.ts @@ -0,0 +1,29 @@ +import { ContactId, SendComposingEventRequestData } from '@sinch/sdk-core'; +import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('********************'); + console.log('* Events_SendEvent *'); + console.log('********************'); + + const appId = getAppIdFromConfig(); + const contactId = getContactIdFromConfig(); + + const requestData: SendComposingEventRequestData = { + sendEventRequestBody: { + app_id: appId, + recipient: { + contact_id: contactId, + }, + event: { + composing_event: {}, + }, + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.events.sendComposingEvent(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/events/sendGenericEvent.ts b/examples/simple-examples/src/conversation/events/sendGenericEvent.ts new file mode 100644 index 00000000..28b08b49 --- /dev/null +++ b/examples/simple-examples/src/conversation/events/sendGenericEvent.ts @@ -0,0 +1,33 @@ +import { ContactId, SendGenericEventRequestData } from '@sinch/sdk-core'; +import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('********************'); + console.log('* Events_SendEvent *'); + console.log('********************'); + + const appId = getAppIdFromConfig(); + const contactId = getContactIdFromConfig(); + + const requestData: SendGenericEventRequestData = { + sendEventRequestBody: { + app_id: appId, + recipient: { + contact_id: contactId, + }, + event: { + generic_event: { + payload: { + key: 'value for the generic event', + }, + }, + }, + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.events.sendGenericEvent(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/messages/send.ts b/examples/simple-examples/src/conversation/messages/send.ts index 6f4468c9..fee7337b 100644 --- a/examples/simple-examples/src/conversation/messages/send.ts +++ b/examples/simple-examples/src/conversation/messages/send.ts @@ -1,4 +1,4 @@ -import { SendMessageRequestData } from '@sinch/sdk-core'; +import { ContactId, SendMessageRequestData } from '@sinch/sdk-core'; import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullResponse } from '../../config'; (async () => { @@ -9,7 +9,7 @@ import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullRespon const appId = getAppIdFromConfig(); const contactId = getContactIdFromConfig(); - const requestData: SendMessageRequestData = { + const requestData: SendMessageRequestData = { sendMessageRequestBody: { app_id: appId, message: { @@ -20,7 +20,7 @@ import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullRespon recipient: { contact_id: contactId, }, - correlation_id: 'correlator', + correlation_id: 'correlatorId', queue: 'HIGH_PRIORITY', processing_strategy: 'DEFAULT', channel_priority_order: ['MESSENGER'], diff --git a/examples/simple-examples/src/conversation/messages/sendCardMessage.ts b/examples/simple-examples/src/conversation/messages/sendCardMessage.ts new file mode 100644 index 00000000..b393ccf3 --- /dev/null +++ b/examples/simple-examples/src/conversation/messages/sendCardMessage.ts @@ -0,0 +1,37 @@ +import { ContactId, SendCardMessageRequestData } from '@sinch/sdk-core'; +import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('****************************'); + console.log('* Messages_SendCardMessage *'); + console.log('****************************'); + + const appId = getAppIdFromConfig(); + const contactId = getContactIdFromConfig(); + + const requestData: SendCardMessageRequestData = { + sendMessageRequestBody: { + app_id: appId, + message: { + card_message: { + title: 'Card message title', + description: 'Card message description', + height: 'MEDIUM', + }, + }, + recipient: { + contact_id: contactId, + }, + correlation_id: 'correlatorId', + queue: 'HIGH_PRIORITY', + processing_strategy: 'DEFAULT', + channel_priority_order: ['MESSENGER'], + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.messages.sendCardMessage(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/messages/sendCarouselMessage.ts b/examples/simple-examples/src/conversation/messages/sendCarouselMessage.ts new file mode 100644 index 00000000..4a525d85 --- /dev/null +++ b/examples/simple-examples/src/conversation/messages/sendCarouselMessage.ts @@ -0,0 +1,46 @@ +import { ContactId, SendCarouselMessageRequestData } from '@sinch/sdk-core'; +import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('********************************'); + console.log('* Messages_SendCarouselMessage *'); + console.log('********************************'); + + const appId = getAppIdFromConfig(); + const contactId = getContactIdFromConfig(); + + const requestData: SendCarouselMessageRequestData = { + sendMessageRequestBody: { + app_id: appId, + message: { + carousel_message: { + cards: [ + { + title: 'Card #1 title', + description: 'Card #1 description', + height: 'TALL', + }, + { + title: 'Card #2 title', + description: 'Card #2 description', + height: 'TALL', + }, + ], + }, + }, + recipient: { + contact_id: contactId, + }, + correlation_id: 'correlatorId', + queue: 'HIGH_PRIORITY', + processing_strategy: 'DEFAULT', + channel_priority_order: ['MESSENGER'], + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.messages.sendCarouselMessage(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/messages/sendChoiceMessage.ts b/examples/simple-examples/src/conversation/messages/sendChoiceMessage.ts new file mode 100644 index 00000000..af46a421 --- /dev/null +++ b/examples/simple-examples/src/conversation/messages/sendChoiceMessage.ts @@ -0,0 +1,51 @@ +import { ContactId, SendChoiceMessageRequestData } from '@sinch/sdk-core'; +import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('******************************'); + console.log('* Messages_SendChoiceMessage *'); + console.log('******************************'); + + const appId = getAppIdFromConfig(); + const contactId = getContactIdFromConfig(); + + const requestData: SendChoiceMessageRequestData = { + sendMessageRequestBody: { + app_id: appId, + message: { + choice_message: { + text_message: { + text: 'Make your choice', + }, + choices: [ + { + call_message: { + title: 'Option #1', + phone_number: '+1111111111', + }, + }, + { + call_message: { + title: 'Option #2', + phone_number: '+2222222222', + }, + }, + ], + }, + }, + recipient: { + contact_id: contactId, + }, + correlation_id: 'correlatorId', + queue: 'HIGH_PRIORITY', + processing_strategy: 'DEFAULT', + channel_priority_order: ['MESSENGER'], + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.messages.sendChoiceMessage(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/messages/sendContactInfoMessage.ts b/examples/simple-examples/src/conversation/messages/sendContactInfoMessage.ts new file mode 100644 index 00000000..966446ae --- /dev/null +++ b/examples/simple-examples/src/conversation/messages/sendContactInfoMessage.ts @@ -0,0 +1,49 @@ +import { ContactId, SendContactInfoMessageRequestData } from '@sinch/sdk-core'; +import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('***********************************'); + console.log('* Messages_SendContactInfoMessage *'); + console.log('***********************************'); + + const appId = getAppIdFromConfig(); + const contactId = getContactIdFromConfig(); + + const requestData: SendContactInfoMessageRequestData = { + sendMessageRequestBody: { + app_id: appId, + message: { + contact_info_message: { + name: { + full_name: 'Contact name', + }, + phone_numbers: [ + { + phone_number: '+111111111', + type: 'HOME', + }, + ], + organization: { + title: 'Software developer', + company: 'Sinch', + department: 'Developer Experience', + }, + birthday: '1990-01-01', + }, + }, + recipient: { + contact_id: contactId, + }, + correlation_id: 'correlatorId', + queue: 'HIGH_PRIORITY', + processing_strategy: 'DEFAULT', + channel_priority_order: ['MESSENGER'], + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.messages.sendContactInfoMessage(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/messages/sendListMessage.ts b/examples/simple-examples/src/conversation/messages/sendListMessage.ts new file mode 100644 index 00000000..be5df7df --- /dev/null +++ b/examples/simple-examples/src/conversation/messages/sendListMessage.ts @@ -0,0 +1,62 @@ +import { ContactId, SendListMessageRequestData } from '@sinch/sdk-core'; +import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('****************************'); + console.log('* Messages_SendListMessage *'); + console.log('****************************'); + + const appId = getAppIdFromConfig(); + const contactId = getContactIdFromConfig(); + + const requestData: SendListMessageRequestData = { + sendMessageRequestBody: { + app_id: appId, + message: { + list_message: { + title: 'List message title', + description: 'List message description', + sections: [ + { + title: 'Section #1', + items: [ + { + choice: { + title: 'Choice 1.1', + description: 'Description for choice 1.1', + postback_data: '1.1', + }, + }, + ], + }, + { + title: 'Section #2', + items: [ + { + choice: { + title: 'Choice 2.1', + description: 'Description for choice 2.1', + postback_data: '2.1', + }, + }, + ], + }, + ], + }, + }, + recipient: { + contact_id: contactId, + }, + correlation_id: 'correlatorId', + queue: 'HIGH_PRIORITY', + processing_strategy: 'DEFAULT', + channel_priority_order: ['MESSENGER'], + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.messages.sendListMessage(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/messages/sendLocationMessage.ts b/examples/simple-examples/src/conversation/messages/sendLocationMessage.ts new file mode 100644 index 00000000..acea382c --- /dev/null +++ b/examples/simple-examples/src/conversation/messages/sendLocationMessage.ts @@ -0,0 +1,40 @@ +import { ContactId, SendLocationMessageRequestData } from '@sinch/sdk-core'; +import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('********************************'); + console.log('* Messages_SendLocationMessage *'); + console.log('********************************'); + + const appId = getAppIdFromConfig(); + const contactId = getContactIdFromConfig(); + + const requestData: SendLocationMessageRequestData = { + sendMessageRequestBody: { + app_id: appId, + message: { + location_message: { + title: 'Phare d\'Eckmühl', + label: 'Pointe de Penmarch', + coordinates: { + latitude: 47.7981899, + longitude: -4.3727685, + }, + }, + }, + recipient: { + contact_id: contactId, + }, + correlation_id: 'correlatorId', + queue: 'HIGH_PRIORITY', + processing_strategy: 'DEFAULT', + channel_priority_order: ['MESSENGER'], + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.messages.sendLocationMessage(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/messages/sendMediaMessage.ts b/examples/simple-examples/src/conversation/messages/sendMediaMessage.ts new file mode 100644 index 00000000..c90f683e --- /dev/null +++ b/examples/simple-examples/src/conversation/messages/sendMediaMessage.ts @@ -0,0 +1,35 @@ +import { ContactId, SendMediaMessageRequestData } from '@sinch/sdk-core'; +import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('*****************************'); + console.log('* Messages_SendMediaMessage *'); + console.log('*****************************'); + + const appId = getAppIdFromConfig(); + const contactId = getContactIdFromConfig(); + + const requestData: SendMediaMessageRequestData = { + sendMessageRequestBody: { + app_id: appId, + message: { + media_message: { + url: 'https://media.url', + }, + }, + recipient: { + contact_id: contactId, + }, + correlation_id: 'correlatorId', + queue: 'HIGH_PRIORITY', + processing_strategy: 'DEFAULT', + channel_priority_order: ['MESSENGER'], + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.messages.sendMediaMessage(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/messages/sendTemplateMessage.ts b/examples/simple-examples/src/conversation/messages/sendTemplateMessage.ts new file mode 100644 index 00000000..b968aea6 --- /dev/null +++ b/examples/simple-examples/src/conversation/messages/sendTemplateMessage.ts @@ -0,0 +1,39 @@ +import { ContactId, SendTemplateMessageRequestData } from '@sinch/sdk-core'; +import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('********************************'); + console.log('* Messages_SendTemplateMessage *'); + console.log('********************************'); + + const appId = getAppIdFromConfig(); + const contactId = getContactIdFromConfig(); + + const requestData: SendTemplateMessageRequestData = { + sendMessageRequestBody: { + app_id: appId, + message: { + template_message: { + omni_template: { + template_id: 'templateId', + version: '1', + language_code: 'en-US', + }, + }, + }, + recipient: { + contact_id: contactId, + }, + correlation_id: 'correlatorId', + queue: 'HIGH_PRIORITY', + processing_strategy: 'DEFAULT', + channel_priority_order: ['MESSENGER'], + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.messages.sendTemplateMessage(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/messages/sendTextMessage.ts b/examples/simple-examples/src/conversation/messages/sendTextMessage.ts new file mode 100644 index 00000000..0c8fa2f5 --- /dev/null +++ b/examples/simple-examples/src/conversation/messages/sendTextMessage.ts @@ -0,0 +1,35 @@ +import { ContactId, SendTextMessageRequestData } from '@sinch/sdk-core'; +import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('****************************'); + console.log('* Messages_SendTextMessage *'); + console.log('****************************'); + + const appId = getAppIdFromConfig(); + const contactId = getContactIdFromConfig(); + + const requestData: SendTextMessageRequestData = { + sendMessageRequestBody: { + app_id: appId, + message: { + text_message: { + text: 'Text message', + }, + }, + recipient: { + contact_id: contactId, + }, + correlation_id: 'correlatorId', + queue: 'HIGH_PRIORITY', + processing_strategy: 'DEFAULT', + channel_priority_order: ['MESSENGER'], + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.messages.sendTextMessage(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/webhooks/src/services/conversation.service.ts b/examples/webhooks/src/services/conversation.service.ts index 6d2d1244..17ab9d2c 100644 --- a/examples/webhooks/src/services/conversation.service.ts +++ b/examples/webhooks/src/services/conversation.service.ts @@ -3,8 +3,9 @@ import { SinchClient, ConversationWebhookEventParsed, ContactMessage, - SendMessageRequestData, messageBuilder, + ContactId, + SendMessageRequestData, } from '@sinch/sdk-core'; @Injectable() @@ -48,7 +49,7 @@ export class ConversationService { const contactMessage = event.message.contact_message; const channelIdentityTo = event.message.channel_identity; console.log(`A new message has been received on the channel '${channelIdentityTo.channel}' (identity: ${channelIdentityTo.identity}) from the contact ID '${event.message.contact_id}':\n${JSON.stringify(contactMessage, null, 2)}`); - const requestData: SendMessageRequestData = { + const requestData: SendMessageRequestData = { sendMessageRequestBody: { app_id: event.app_id, recipient: { diff --git a/packages/conversation/src/models/v1/get-channel-profile-request/get-channel-profile-request.ts b/packages/conversation/src/models/v1/get-channel-profile-request/get-channel-profile-request.ts index 0baafd70..253a3931 100644 --- a/packages/conversation/src/models/v1/get-channel-profile-request/get-channel-profile-request.ts +++ b/packages/conversation/src/models/v1/get-channel-profile-request/get-channel-profile-request.ts @@ -1,12 +1,12 @@ import { Recipient } from '../recipient'; import { GetChannelProfileConversationChannel } from '../enums'; -export interface GetChannelProfileRequest { +export interface GetChannelProfileRequest { /** The ID of the app. */ app_id: string; /** @see Recipient */ - recipient: Recipient; + recipient: T; /** @see GetChannelProfileConversationChannel */ channel: GetChannelProfileConversationChannel; } diff --git a/packages/conversation/src/models/v1/helper.ts b/packages/conversation/src/models/v1/helper.ts index ebdf48c5..724a58b2 100644 --- a/packages/conversation/src/models/v1/helper.ts +++ b/packages/conversation/src/models/v1/helper.ts @@ -2,6 +2,7 @@ import { TextMessage, TextMessageItem } from './text-message'; import { CardMessage, CardMessageItem } from './card-message'; import { CarouselMessage, CarouselMessageItem } from './carousel-message'; import { ChoiceMessage, ChoiceMessageItem } from './choice-message'; +import { ContactInfoMessage, ContactInfoMessageItem } from './contact-info-message'; import { LocationMessage, LocationMessageItem } from './location-message'; import { MediaMessage, MediaMessageItem } from './media-message'; import { TemplateMessage, TemplateMessageItem } from './template-message'; @@ -24,6 +25,11 @@ export const messageBuilder = { choice_message: choiceMessageItem, } as ChoiceMessage; }, + contactInfo: (contactInfoMessageItem: ContactInfoMessageItem): ContactInfoMessage => { + return { + contact_info_message: contactInfoMessageItem, + } as ContactInfoMessage; + }, list: (listMessageItem: ListMessageItem): ListMessage => { return { list_message: listMessageItem, @@ -64,6 +70,9 @@ export const templateV1Helper = { buildChoiceMessageContent: (choiceMessageItem: ChoiceMessageItem): string => { return JSON.stringify(messageBuilder.choice(choiceMessageItem)); }, + buildContactInfoMessageContent: (contactInfoMessageItem: ContactInfoMessageItem): string => { + return JSON.stringify(messageBuilder.contactInfo(contactInfoMessageItem)); + }, buildLocationMessageContent: (locationMessageItem: LocationMessageItem): string => { return JSON.stringify(messageBuilder.location(locationMessageItem)); }, @@ -92,6 +101,9 @@ export const templateV2Helper = { buildChoiceMessageContent: (choiceMessageItem: ChoiceMessageItem): ChoiceMessage => { return messageBuilder.choice(choiceMessageItem); }, + buildContactInfoMessageContent: (contactInfoMessageItem: ContactInfoMessageItem): ContactInfoMessage => { + return messageBuilder.contactInfo(contactInfoMessageItem); + }, buildLocationMessageContent: (locationMessageItem: LocationMessageItem): LocationMessage => { return messageBuilder.location(locationMessageItem); }, @@ -105,25 +117,25 @@ export const templateV2Helper = { return messageBuilder.list(listMessageItem); }, getMessageFromTranslation: (translation: V2TemplateTranslation) => { - if('text_message' in translation) { - return { - type: MessageType.TEXT, - content: translation.text_message, - }; - } else if ('card_message' in translation) { + if ('card_message' in translation) { return { type: MessageType.CARD, content: translation.card_message, }; + } else if ('carousel_message' in translation) { + return { + type: MessageType.CAROUSEL, + content: translation.carousel_message, + }; } else if ('choice_message' in translation) { return { type: MessageType.CHOICE, content: translation.choice_message, }; - } else if ('carousel_message' in translation) { + } else if ('contact_info_message' in translation) { return { - type: MessageType.CAROUSEL, - content: translation.carousel_message, + type: MessageType.CONTACT_INFO, + content: translation.contact_info_message, }; } else if ('list_message' in translation) { return { @@ -145,6 +157,11 @@ export const templateV2Helper = { type: MessageType.TEMPLATE, content: translation.template_message, }; + } else if('text_message' in translation) { + return { + type: MessageType.TEXT, + content: translation.text_message, + }; } else { return { type: MessageType.UNDEFINED, @@ -163,8 +180,9 @@ export const templateV2Helper = { export const enum MessageType { CARD = 'CardMessage', - CHOICE = 'ChoiceMessage', CAROUSEL = 'CarouselMessage', + CHOICE = 'ChoiceMessage', + CONTACT_INFO = 'ContactInfoMessage', LIST = 'ListMessage', LOCATION = 'LocationMessage', MEDIA = 'MediaMessage', diff --git a/packages/conversation/src/models/v1/index.ts b/packages/conversation/src/models/v1/index.ts index 865c0693..640923a1 100644 --- a/packages/conversation/src/models/v1/index.ts +++ b/packages/conversation/src/models/v1/index.ts @@ -63,8 +63,8 @@ export * from './merge-contact-request'; export * from './message-retry-settings'; export * from './product'; export * from './error-detail'; -export * from './lookup-capability'; -export * from './query-capability-response'; +export * from './lookup-capability-request'; +export * from './lookup-capability-response'; export * from './queue-stats'; export * from './rate-limits'; export * from './reason'; diff --git a/packages/conversation/src/models/v1/lookup-capability-request/index.ts b/packages/conversation/src/models/v1/lookup-capability-request/index.ts new file mode 100644 index 00000000..936032da --- /dev/null +++ b/packages/conversation/src/models/v1/lookup-capability-request/index.ts @@ -0,0 +1 @@ +export type { LookupCapabilityRequest } from './lookup-capability-request'; diff --git a/packages/conversation/src/models/v1/lookup-capability/lookup-capability.ts b/packages/conversation/src/models/v1/lookup-capability-request/lookup-capability-request.ts similarity index 78% rename from packages/conversation/src/models/v1/lookup-capability/lookup-capability.ts rename to packages/conversation/src/models/v1/lookup-capability-request/lookup-capability-request.ts index 14dce31d..0c104d9a 100644 --- a/packages/conversation/src/models/v1/lookup-capability/lookup-capability.ts +++ b/packages/conversation/src/models/v1/lookup-capability-request/lookup-capability-request.ts @@ -1,11 +1,11 @@ import { Recipient } from '../recipient'; -export interface LookupCapability { +export interface LookupCapabilityRequest { /** The ID of the app to use for capability lookup. */ app_id: string; /** @see Recipient */ - recipient: Recipient; + recipient: T; /** ID for the asynchronous response, will be generated if not set. Currently, this field is not used for idempotency. */ request_id?: string; } diff --git a/packages/conversation/src/models/v1/lookup-capability-response/index.ts b/packages/conversation/src/models/v1/lookup-capability-response/index.ts new file mode 100644 index 00000000..e22c8c50 --- /dev/null +++ b/packages/conversation/src/models/v1/lookup-capability-response/index.ts @@ -0,0 +1 @@ +export type { LookupCapabilityResponse } from './lookup-capability-response'; diff --git a/packages/conversation/src/models/v1/query-capability-response/query-capability-response.ts b/packages/conversation/src/models/v1/lookup-capability-response/lookup-capability-response.ts similarity index 89% rename from packages/conversation/src/models/v1/query-capability-response/query-capability-response.ts rename to packages/conversation/src/models/v1/lookup-capability-response/lookup-capability-response.ts index b36f7c5b..34e29d79 100644 --- a/packages/conversation/src/models/v1/query-capability-response/query-capability-response.ts +++ b/packages/conversation/src/models/v1/lookup-capability-response/lookup-capability-response.ts @@ -3,7 +3,7 @@ import { Recipient } from '../recipient'; /** * An CapabilityResponse contains the identity of the recipient for which will be perform a capability lookup. */ -export interface QueryCapabilityResponse { +export interface LookupCapabilityResponse { /** The ID of the app to use for capability lookup. */ app_id?: string; diff --git a/packages/conversation/src/models/v1/lookup-capability/index.ts b/packages/conversation/src/models/v1/lookup-capability/index.ts deleted file mode 100644 index 3c8b1e25..00000000 --- a/packages/conversation/src/models/v1/lookup-capability/index.ts +++ /dev/null @@ -1 +0,0 @@ -export type { LookupCapability } from './lookup-capability'; diff --git a/packages/conversation/src/models/v1/query-capability-response/index.ts b/packages/conversation/src/models/v1/query-capability-response/index.ts deleted file mode 100644 index 691d5884..00000000 --- a/packages/conversation/src/models/v1/query-capability-response/index.ts +++ /dev/null @@ -1 +0,0 @@ -export type { QueryCapabilityResponse } from './query-capability-response'; diff --git a/packages/conversation/src/models/v1/send-event-request/index.ts b/packages/conversation/src/models/v1/send-event-request/index.ts index 9548df3c..a30e0adc 100644 --- a/packages/conversation/src/models/v1/send-event-request/index.ts +++ b/packages/conversation/src/models/v1/send-event-request/index.ts @@ -1 +1,9 @@ -export type { SendEventRequest } from './send-event-request'; +export type { + SendEventRequest, + SendComposingEventRequest, + SendComposingEndEventRequest, + SendCommentReplyEventRequest, + SendAgentJoinedEventRequest, + SendAgentLeftEventRequest, + SendGenericEventRequest, +} from './send-event-request'; diff --git a/packages/conversation/src/models/v1/send-event-request/send-event-request.ts b/packages/conversation/src/models/v1/send-event-request/send-event-request.ts index 4e8f6494..6dd98991 100644 --- a/packages/conversation/src/models/v1/send-event-request/send-event-request.ts +++ b/packages/conversation/src/models/v1/send-event-request/send-event-request.ts @@ -1,9 +1,15 @@ -import { AppEvent } from '../app-event'; import { ConversationChannel } from '../conversation-channel'; import { Recipient } from '../recipient'; import { MessageQueue } from '../enums'; +import { ComposingEvent } from '../composing-event'; +import { ComposingEndEvent } from '../composing-end-event'; +import { CommentReplyEvent } from '../comment-reply-event'; +import { AgentJoinedEvent } from '../agent-joined-event'; +import { AgentLeftEvent } from '../agent-left-event'; +import { GenericEvent } from '../generic-event'; +import { AppEvent } from '../app-event'; -export interface SendEventRequest { +export interface SendEventRequestBase { /** The ID of the app sending the event. */ app_id: string; @@ -11,12 +17,44 @@ export interface SendEventRequest { callback_url?: string; /** Optional. A single element array that dictates on what channel should the Conversation API try to send the event. It overrides any default set on the contact. Providing more than one option has no effect. */ channel_priority_order?: ConversationChannel[]; - /** @see AppEvent */ - event: AppEvent; /** Optional. Eventual metadata that should be associated to the event. */ event_metadata?: string; /** @see MessageQueue */ queue?: MessageQueue; /** @see Recipient */ - recipient: Recipient; + recipient: T; +} + +export interface SendEventRequest extends SendEventRequestBase { + /** @see AppEvent */ + event: AppEvent; +} +export interface SendComposingEventRequest extends SendEventRequestBase { + /** @see ComposingEvent */ + event: ComposingEvent; +} + +export interface SendComposingEndEventRequest extends SendEventRequestBase { + /** @see ComposingEndEvent */ + event: ComposingEndEvent; +} + +export interface SendCommentReplyEventRequest extends SendEventRequestBase { + /** @see CommentReplyEvent */ + event: CommentReplyEvent; +} + +export interface SendAgentJoinedEventRequest extends SendEventRequestBase { + /** @see AgentJoinedEvent */ + event: AgentJoinedEvent; +} + +export interface SendAgentLeftEventRequest extends SendEventRequestBase { + /** @see AgentLeftEvent */ + event: AgentLeftEvent; +} + +export interface SendGenericEventRequest extends SendEventRequestBase { + /** @see GenericEvent */ + event: GenericEvent; } diff --git a/packages/conversation/src/models/v1/send-message-request/index.ts b/packages/conversation/src/models/v1/send-message-request/index.ts index 2012d0b0..52d173e9 100644 --- a/packages/conversation/src/models/v1/send-message-request/index.ts +++ b/packages/conversation/src/models/v1/send-message-request/index.ts @@ -1 +1,12 @@ -export type { SendMessageRequest } from './send-message-request'; +export type { + SendMessageRequest, + SendCardMessageRequest, + SendCarouselMessageRequest, + SendChoiceMessageRequest, + SendContactInfoMessageRequest, + SendLocationMessageRequest, + SendMediaMessageRequest, + SendTemplateMessageRequest, + SendTextMessageRequest, + SendListMessageRequest, +} from './send-message-request'; diff --git a/packages/conversation/src/models/v1/send-message-request/send-message-request.ts b/packages/conversation/src/models/v1/send-message-request/send-message-request.ts index 87220e38..05484b5b 100644 --- a/packages/conversation/src/models/v1/send-message-request/send-message-request.ts +++ b/packages/conversation/src/models/v1/send-message-request/send-message-request.ts @@ -1,12 +1,21 @@ import { ConversationChannel } from '../conversation-channel'; import { Recipient } from '../recipient'; -import { AppMessageMessage } from '../app-message-message'; import { ConversationMetadataUpdateStrategy, MessageQueue, ProcessingStrategy } from '../enums'; +import { CardMessage } from '../card-message'; +import { CarouselMessage } from '../carousel-message'; +import { ChoiceMessage } from '../choice-message'; +import { LocationMessage } from '../location-message'; +import { MediaMessage } from '../media-message'; +import { TemplateMessage } from '../template-message'; +import { TextMessage } from '../text-message'; +import { ListMessage } from '../list-message'; +import { ContactInfoMessage } from '../contact-info-message'; +import { AppMessageMessage } from '../app-message-message'; /** * This is the request body for sending a message. `app_id`, `recipient`, and `message` are all required fields. */ -export interface SendMessageRequest { +export interface SendMessageRequestBase { /** The ID of the app sending the message. */ app_id: string; @@ -16,8 +25,6 @@ export interface SendMessageRequest { channel_priority_order?: ConversationChannel[]; /** Channel-specific properties. The key in the map must point to a valid channel property key as defined by the enum ChannelPropertyKeys. The maximum allowed property value length is 1024 characters. */ channel_properties?: { [K in ChannelPropertyKey]?: string; }; - /** @see AppMessage */ - message: AppMessageMessage; /** Metadata that should be associated with the message. Returned in the `metadata` field of a [Message Delivery Receipt](https://developers.sinch.com/docs/conversation/callbacks/#message-delivery-receipt). Up to 1024 characters long. */ message_metadata?: string; /** Metadata that should be associated with the conversation. This metadata will be propagated on MO callbacks associated with this conversation. Up to 1024 characters long. Note that the MO callback will always use the last metadata available in the conversation. Important notes: - If you send a message with the `conversation_metadata` field populated, and then send another message without populating the `conversation_metadata` field, the original metadata will continue be propagated on the related MO callbacks. - If you send a message with the `conversation_metadata` field populated, and then send another message with a different value for `conversation_metadata` in the same conversation, the latest metadata value overwrites the existing one. So, future MO callbacks will include the new metadata. - The `conversation_metadata` only accepts json objects. Currently only returned in the `message_metadata` field of an [Inbound Message](/docs/conversation/callbacks/#inbound-message) callback. */ @@ -25,7 +32,7 @@ export interface SendMessageRequest { /** @see MessageQueue */ queue?: MessageQueue; /** @see Recipient */ - recipient: Recipient; + recipient: T; /** The timeout allotted for sending the message, expressed in seconds. Passed to channels which support it and emulated by the Conversation API for channels without ttl support but with message retract/unsend functionality. Channel failover will not be performed for messages with an expired TTL. The format is an integer with the suffix `s` (for seconds). Valid integer range is 3 to 315,576,000,000 (inclusive). Example values include `10s` (10 seconds) and `86400s` (24 hours). */ ttl?: string; /** Overrides the app\'s [Processing Mode](../../../../../conversation/processing-modes/). Default value is `DEFAULT`. */ @@ -50,5 +57,55 @@ export type ChannelPropertyKey = | 'MMS_STRICT_VALIDATION' | 'KAKAOTALK_AUTHENTICATION' | 'LINE_VIDEO_TRACKING_ID' - | 'SMS_MAX_NUMBER_OF_MESSAGE_PARTS'; + | 'SMS_MAX_NUMBER_OF_MESSAGE_PARTS' + | string; // Wildcard for new channel events not yet documented + +export interface SendMessageRequest extends SendMessageRequestBase { + /** @see AppMessageMessage */ + message: AppMessageMessage; +} + +export interface SendCardMessageRequest extends SendMessageRequestBase { + /** @see CardMessage */ + message: CardMessage; +} + +export interface SendCarouselMessageRequest extends SendMessageRequestBase { + /** @see CarouselMessage */ + message: CarouselMessage; +} + +export interface SendChoiceMessageRequest extends SendMessageRequestBase { + /** @see CarouselMessage */ + message: ChoiceMessage; +} +export interface SendLocationMessageRequest extends SendMessageRequestBase { + /** @see LocationMessage */ + message: LocationMessage; +} + +export interface SendMediaMessageRequest extends SendMessageRequestBase { + /** @see MediaMessage */ + message: MediaMessage; +} + +export interface SendTemplateMessageRequest extends SendMessageRequestBase { + /** @see TemplateMessage */ + message: TemplateMessage; +} + +export interface SendTextMessageRequest extends SendMessageRequestBase { + /** @see TextMessage */ + message: TextMessage; +} + +export interface SendListMessageRequest extends SendMessageRequestBase { + /** @see ListMessage */ + message: ListMessage; +} + +export interface SendContactInfoMessageRequest extends SendMessageRequestBase { + /** @see ContactInfoMessage */ + message: ContactInfoMessage; +} diff --git a/packages/conversation/src/models/v1/v2-template-translation/v2-template-translation.ts b/packages/conversation/src/models/v1/v2-template-translation/v2-template-translation.ts index 66d8f4ea..14b663aa 100644 --- a/packages/conversation/src/models/v1/v2-template-translation/v2-template-translation.ts +++ b/packages/conversation/src/models/v1/v2-template-translation/v2-template-translation.ts @@ -8,6 +8,7 @@ import { LocationMessage } from '../location-message'; import { MediaMessage } from '../media-message'; import { TemplateMessage } from '../template-message'; import { ListMessage } from '../list-message'; +import { ContactInfoMessage } from '../contact-info-message'; export type V2TemplateTranslation = V2TemplateTranslationCardMessage @@ -17,7 +18,8 @@ export type V2TemplateTranslation = | V2TemplateTranslationLocationMessage | V2TemplateTranslationMediaMessage | V2TemplateTranslationTemplateMessage - | V2TemplateTranslationTextMessage; + | V2TemplateTranslationTextMessage + | V2TemplateTranslationContactInfoMessage; export interface V2TemplateTranslationBase { @@ -43,3 +45,4 @@ export type V2TemplateTranslationLocationMessage = V2TemplateTranslationBase & L export type V2TemplateTranslationMediaMessage = V2TemplateTranslationBase & MediaMessage; export type V2TemplateTranslationTemplateMessage = V2TemplateTranslationBase & TemplateMessage; export type V2TemplateTranslationListMessage = V2TemplateTranslationBase & ListMessage; +export type V2TemplateTranslationContactInfoMessage = V2TemplateTranslationBase & ContactInfoMessage; diff --git a/packages/conversation/src/rest/v1/capability/capability-api.jest.fixture.ts b/packages/conversation/src/rest/v1/capability/capability-api.jest.fixture.ts index d1277f14..863c2a1b 100644 --- a/packages/conversation/src/rest/v1/capability/capability-api.jest.fixture.ts +++ b/packages/conversation/src/rest/v1/capability/capability-api.jest.fixture.ts @@ -1,11 +1,15 @@ -import { QueryCapabilityResponse } from '../../../models'; +import { LookupCapabilityResponse, Recipient } from '../../../models'; import { CapabilityApi, LookupCapabilityRequestData } from './capability-api'; export class CapabilityApiFixture implements Partial> { /** - * Fixture associated to function lookup + * Fixture associated to function lookupForContactId */ - public lookup: jest.Mock, [LookupCapabilityRequestData]> = jest.fn(); + public lookup: jest.Mock< + Promise, + [LookupCapabilityRequestData] + > = jest.fn(); + } diff --git a/packages/conversation/src/rest/v1/capability/capability-api.ts b/packages/conversation/src/rest/v1/capability/capability-api.ts index 768d323a..2822783f 100644 --- a/packages/conversation/src/rest/v1/capability/capability-api.ts +++ b/packages/conversation/src/rest/v1/capability/capability-api.ts @@ -3,14 +3,15 @@ import { SinchClientParameters, } from '@sinch/sdk-client'; import { - LookupCapability, - QueryCapabilityResponse, + LookupCapabilityRequest, + LookupCapabilityResponse, + Recipient, } from '../../../models'; import { ConversationDomainApi } from '../conversation-domain-api'; -export interface LookupCapabilityRequestData { +export interface LookupCapabilityRequestData { /** The lookup capability request. */ - 'lookupCapabilityRequestBody': LookupCapability; + 'lookupCapabilityRequestBody': LookupCapabilityRequest; } export class CapabilityApi extends ConversationDomainApi { @@ -27,11 +28,12 @@ export class CapabilityApi extends ConversationDomainApi { /** * Capability lookup * This method is asynchronous - it immediately returns the requested Capability registration. Capability check is then delivered as a callback to registered webhooks with trigger CAPABILITY for every reachable channel. - * @param { LookupCapabilityRequestData } data - The data to provide to the API call. + * @param { LookupCapabilityRequestData } data - The data to provide to the API call. */ - public async lookup(data: LookupCapabilityRequestData): Promise { + public async lookup(data: LookupCapabilityRequestData): Promise { this.client = this.getSinchClient(); - const getParams = this.client.extractQueryParams(data, [] as never[]); + const getParams = this.client.extractQueryParams>( + data, [] as never[]); const headers: { [key: string]: string | undefined } = { 'Content-Type': 'application/json', 'Accept': 'application/json', @@ -45,7 +47,7 @@ export class CapabilityApi extends ConversationDomainApi { const requestOptions = await this.client.prepareOptions(basePathUrl, 'POST', getParams, headers, body || undefined); const url = this.client.prepareUrl(requestOptions.basePath, requestOptions.queryParams); - return this.client.processCall({ + return this.client.processCall({ url, requestOptions, apiName: this.apiName, diff --git a/packages/conversation/src/rest/v1/contact/contact-api.jest.fixture.ts b/packages/conversation/src/rest/v1/contact/contact-api.jest.fixture.ts index 5cb3ca3c..87fa1fa1 100644 --- a/packages/conversation/src/rest/v1/contact/contact-api.jest.fixture.ts +++ b/packages/conversation/src/rest/v1/contact/contact-api.jest.fixture.ts @@ -1,6 +1,15 @@ -import { Contact } from '../../../models'; +import { Contact, Recipient } from '../../../models'; import { GetChannelProfileResponse } from '../../../models'; -import { ContactApi, CreateContactRequestData, DeleteContactRequestData, GetChannelProfileRequestData, GetContactRequestData, ListContactsRequestData, MergeContactRequestData, UpdateContactRequestData } from './contact-api'; +import { + ContactApi, + CreateContactRequestData, + DeleteContactRequestData, + GetChannelProfileRequestData, + GetContactRequestData, + ListContactsRequestData, + MergeContactRequestData, + UpdateContactRequestData, +} from './contact-api'; import { ApiListPromise } from '@sinch/sdk-client'; export class ContactApiFixture implements Partial> { @@ -16,7 +25,10 @@ export class ContactApiFixture implements Partial> { /** * Fixture associated to function getChannelProfile */ - public getChannelProfile: jest.Mock, [GetChannelProfileRequestData]> = jest.fn(); + public getChannelProfile: jest.Mock< + Promise, + [GetChannelProfileRequestData] + > = jest.fn(); /** * Fixture associated to function get */ diff --git a/packages/conversation/src/rest/v1/contact/contact-api.ts b/packages/conversation/src/rest/v1/contact/contact-api.ts index 45a65e2e..42ffb68a 100644 --- a/packages/conversation/src/rest/v1/contact/contact-api.ts +++ b/packages/conversation/src/rest/v1/contact/contact-api.ts @@ -14,6 +14,7 @@ import { GetChannelProfileRequest, GetChannelProfileResponse, MergeContactRequest, + Recipient, } from '../../../models'; import { ConversationDomainApi } from '../conversation-domain-api'; @@ -25,9 +26,9 @@ export interface DeleteContactRequestData { /** The unique ID of the contact. */ 'contact_id': string; } -export interface GetChannelProfileRequestData { +export interface GetChannelProfileRequestData { /** */ - 'getChannelProfileRequestBody': GetChannelProfileRequest; + 'getChannelProfileRequestBody': GetChannelProfileRequest; } export interface GetContactRequestData { /** The unique ID of the contact. */ @@ -129,12 +130,14 @@ export class ContactApi extends ConversationDomainApi { /** * Get Channel Profile - * Get user profile from a specific channel. Only supported on `MESSENGER`, `INSTAGRAM`, `VIBER` and `LINE` channels. Note that, in order to retrieve a WhatsApp display name, you can use the Get a Contact or List Contacts operations, which will populate the `display_name` field of each returned contact with the WhatsApp display name (if the name is already stored on the server and the `display_name` field has not been overwritten by the user). - * @param { GetChannelProfileRequestData } data - The data to provide to the API call. + * Get user profile from a specific channel. Only supported on 'MESSENGER', 'INSTAGRAM', 'VIBER' and LINE' channels. + * Note that, in order to retrieve a WhatsApp display name, you can use the Get a Contact or List Contacts operations, which will populate the 'display_name' field of each returned contact with the WhatsApp display name (if the name is already stored on the server and the 'display_name' field has not been overwritten by the user). + * @param { GetChannelProfileRequestData } data - The data to provide to the API call. */ - public async getChannelProfile(data: GetChannelProfileRequestData): Promise { + public async getChannelProfile(data: GetChannelProfileRequestData): Promise { this.client = this.getSinchClient(); - const getParams = this.client.extractQueryParams(data, [] as never[]); + const getParams = this.client.extractQueryParams>( + data, [] as never[]); const headers: { [key: string]: string | undefined } = { 'Content-Type': 'application/json', 'Accept': 'application/json', diff --git a/packages/conversation/src/rest/v1/events/events-api.jest.fixture.ts b/packages/conversation/src/rest/v1/events/events-api.jest.fixture.ts index c28f9efa..2abf5497 100644 --- a/packages/conversation/src/rest/v1/events/events-api.jest.fixture.ts +++ b/packages/conversation/src/rest/v1/events/events-api.jest.fixture.ts @@ -1,10 +1,16 @@ -import { ConversationEvent, SendEventResponse } from '../../../models'; +import { ConversationEvent, Recipient, SendEventResponse } from '../../../models'; import { DeleteEventRequestData, EventsApi, GetEventRequestData, ListEventsRequestData, + SendAgentJoinedEventRequestData, + SendAgentLeftEventRequestData, + SendCommentReplyEventRequestData, + SendComposingEndEventRequestData, + SendComposingEventRequestData, SendEventRequestData, + SendGenericEventRequestData, } from './events-api'; import { ApiListPromise } from '@sinch/sdk-client'; @@ -25,6 +31,48 @@ export class EventsApiFixture implements Partial> { /** * Fixture associated to function send */ - public send: jest.Mock, [SendEventRequestData]> = jest.fn(); + public send: jest.Mock, [SendEventRequestData]> = jest.fn(); + /** + * Fixture associated to function sendComposingEvent + */ + public sendComposingEvent: jest.Mock< + Promise, + [SendComposingEventRequestData] + > = jest.fn(); + /** + * Fixture associated to function sendComposingEndEvent + */ + public sendComposingEndEvent: jest.Mock< + Promise, + [SendComposingEndEventRequestData] + > = jest.fn(); + /** + * Fixture associated to function sendCommentReplyEvent + */ + public sendCommentReplyEvent: jest.Mock< + Promise, + [SendCommentReplyEventRequestData] + > = jest.fn(); + /** + * Fixture associated to function sendAgentJoinedEvent + */ + public sendAgentJoinedEvent: jest.Mock< + Promise, + [SendAgentJoinedEventRequestData] + > = jest.fn(); + /** + * Fixture associated to function sendAgentLeftEvent + */ + public sendAgentLeftEvent: jest.Mock< + Promise, + [SendAgentLeftEventRequestData] + > = jest.fn(); + /** + * Fixture associated to function sendGenericEvent + */ + public sendGenericEvent: jest.Mock< + Promise, + [SendGenericEventRequestData] + > = jest.fn(); } diff --git a/packages/conversation/src/rest/v1/events/events-api.ts b/packages/conversation/src/rest/v1/events/events-api.ts index 16fefa49..63f3a716 100644 --- a/packages/conversation/src/rest/v1/events/events-api.ts +++ b/packages/conversation/src/rest/v1/events/events-api.ts @@ -10,8 +10,15 @@ import { import { Conversation, ConversationEvent, + Recipient, + SendAgentJoinedEventRequest, + SendAgentLeftEventRequest, + SendCommentReplyEventRequest, + SendComposingEndEventRequest, + SendComposingEventRequest, SendEventRequest, SendEventResponse, + SendGenericEventRequest, } from '../../../models'; import { ConversationDomainApi } from '../conversation-domain-api'; @@ -33,9 +40,33 @@ export interface ListEventsRequestData { /** Next page token previously returned if any. When specifying this token, make sure to use the same values for the other parameters from the request that originated the token, otherwise the paged results may be inconsistent. */ 'page_token'?: string; } -export interface SendEventRequestData { +export interface SendEventRequestData { /** The event to be sent. */ - 'sendEventRequestBody': SendEventRequest; + 'sendEventRequestBody': SendEventRequest; +} +export interface SendComposingEventRequestData { + /** The event to be sent. */ + 'sendEventRequestBody': SendComposingEventRequest; +} +export interface SendComposingEndEventRequestData { + /** The event to be sent. */ + 'sendEventRequestBody': SendComposingEndEventRequest; +} +export interface SendCommentReplyEventRequestData { + /** The event to be sent. */ + 'sendEventRequestBody': SendCommentReplyEventRequest; +} +export interface SendAgentJoinedEventRequestData { + /** The event to be sent. */ + 'sendEventRequestBody': SendAgentJoinedEventRequest; +} +export interface SendAgentLeftEventRequestData { + /** The event to be sent. */ + 'sendEventRequestBody': SendAgentLeftEventRequest; +} +export interface SendGenericEventRequestData { + /** The event to be sent. */ + 'sendEventRequestBody': SendGenericEventRequest; } export class EventsApi extends ConversationDomainApi { @@ -154,17 +185,81 @@ export class EventsApi extends ConversationDomainApi { /** * Send an event * Sends an event to the referenced contact from the referenced app. Note that this operation enqueues the event in a queue so a successful response only indicates that the event has been queued. - * @param { SendEventRequestData } data - The data to provide to the API call. + * @param { SendEventRequestData } data - The data to provide to the API call. + */ + public async send(data: SendEventRequestData): Promise { + return this.sendEvent(data, 'SendEvent'); + } + + /** + * Send a composing event + * Sends an event to the referenced contact from the referenced app. Note that this operation enqueues the event in a queue so a successful response only indicates that the event has been queued. + * @param { SendComposingEventRequestData } data - The data to provide to the API call. + */ + public async sendComposingEvent(data: SendComposingEventRequestData): Promise { + return this.sendEvent(data, 'SendComposingEvent'); + } + + /** + * Send a composing end event + * Sends an event to the referenced contact from the referenced app. Note that this operation enqueues the event in a queue so a successful response only indicates that the event has been queued. + * @param { SendComposingEndEventRequestData } data - The data to provide to the API call. */ - public async send(data: SendEventRequestData): Promise { + public async sendComposingEndEvent(data: SendComposingEndEventRequestData): Promise { + return this.sendEvent(data, 'SendComposingEndEvent'); + } + + /** + * Send a composing reply event + * Sends an event to the referenced contact from the referenced app. Note that this operation enqueues the event in a queue so a successful response only indicates that the event has been queued. + * @param {SendCommentReplyEventRequestData} data - The data to provide to the API call. + */ + public async sendCommentReplyEvent(data: SendCommentReplyEventRequestData): Promise { + return this.sendEvent(data, 'SendCommentReplyEvent'); + } + + /** + * Send an agent joined event + * Sends an event to the referenced contact from the referenced app. Note that this operation enqueues the event in a queue so a successful response only indicates that the event has been queued. + * @param {SendAgentJoinedEventRequestData} data - The data to provide to the API call. + */ + public async sendAgentJoinedEvent(data: SendAgentJoinedEventRequestData): Promise { + return this.sendEvent(data, 'SendAgentJoinedEvent'); + } + + /** + * Send an agent left event + * Sends an event to the referenced contact from the referenced app. Note that this operation enqueues the event in a queue so a successful response only indicates that the event has been queued. + * @param {SendAgentLeftEventRequestData} data - The data to provide to the API call. + */ + public async sendAgentLeftEvent(data: SendAgentLeftEventRequestData): Promise { + return this.sendEvent(data, 'SendAgentLeftEvent'); + } + + /** + * Send a generic event + * Sends an event to the referenced contact from the referenced app. Note that this operation enqueues the event in a queue so a successful response only indicates that the event has been queued. + * @param {SendGenericEventRequestData} data - The data to provide to the API call. + */ + public async sendGenericEvent(data: SendGenericEventRequestData): Promise { + return this.sendEvent(data, 'SendGenericEvent'); + } + + private async sendEvent( + data: SendEventRequestData, + operationId: string, + ): Promise { this.client = this.getSinchClient(); - const getParams = this.client.extractQueryParams(data, [] as never[]); + const getParams = this.client.extractQueryParams>( + data, [] as never[]); const headers: { [key: string]: string | undefined } = { 'Content-Type': 'application/json', 'Accept': 'application/json', }; - const body: RequestBody = data['sendEventRequestBody'] ? JSON.stringify(data['sendEventRequestBody']) : '{}'; + const body: RequestBody = data['sendEventRequestBody'] + ? JSON.stringify(data['sendEventRequestBody']) + : '{}'; const basePathUrl = `${this.client.apiClientOptions.basePath}/v1/projects/${this.client.apiClientOptions.projectId}/events:send`; const requestOptions = await this.client.prepareOptions(basePathUrl, 'POST', getParams, headers, body || undefined); @@ -174,7 +269,7 @@ export class EventsApi extends ConversationDomainApi { url, requestOptions, apiName: this.apiName, - operationId: 'SendEvent', + operationId, }); } diff --git a/packages/conversation/src/rest/v1/messages/messages-api.jest.fixture.ts b/packages/conversation/src/rest/v1/messages/messages-api.jest.fixture.ts index 144ef78f..62e4a839 100644 --- a/packages/conversation/src/rest/v1/messages/messages-api.jest.fixture.ts +++ b/packages/conversation/src/rest/v1/messages/messages-api.jest.fixture.ts @@ -1,11 +1,20 @@ -import { ConversationMessage, SendMessageResponse } from '../../../models'; +import { ConversationMessage, Recipient, SendMessageResponse } from '../../../models'; import { MessagesApi, DeleteMessageRequestData, GetMessageRequestData, ListMessagesRequestData, - SendMessageRequestData, UpdateMessageRequestData, + SendCardMessageRequestData, + SendTextMessageRequestData, + SendCarouselMessageRequestData, + SendChoiceMessageRequestData, + SendContactInfoMessageRequestData, + SendListMessageRequestData, + SendLocationMessageRequestData, + SendMediaMessageRequestData, + SendTemplateMessageRequestData, + SendMessageRequestData, } from './messages-api'; import { ApiListPromise } from '@sinch/sdk-client'; @@ -23,10 +32,76 @@ export class MessagesApiFixture implements Partial> { * Fixture associated to function list */ public list: jest.Mock, [ListMessagesRequestData]> = jest.fn(); + /** + * Fixture associated to function sendCardMessage + */ + public sendCardMessage: jest.Mock< + Promise, + [SendCardMessageRequestData] + > = jest.fn(); + /** + * Fixture associated to function sendTextMessage + */ + public sendCarouselMessage: jest.Mock< + Promise, + [SendCarouselMessageRequestData] + > = jest.fn(); + /** + * Fixture associated to function sendTextMessage + */ + public sendChoiceMessage: jest.Mock< + Promise, + [SendChoiceMessageRequestData] + > = jest.fn(); + /** + * Fixture associated to function sendTextMessage + */ + public sendContactInfoMessage: jest.Mock< + Promise, + [SendContactInfoMessageRequestData] + > = jest.fn(); + /** + * Fixture associated to function sendTextMessage + */ + public sendListMessage: jest.Mock< + Promise, + [SendListMessageRequestData] + > = jest.fn(); + /** + * Fixture associated to function sendTextMessage + */ + public sendLocationMessage: jest.Mock< + Promise, + [SendLocationMessageRequestData] + > = jest.fn(); + /** + * Fixture associated to function sendTextMessage + */ + public sendMediaMessage: jest.Mock< + Promise, + [SendMediaMessageRequestData] + > = jest.fn(); + /** + * Fixture associated to function sendTextMessage + */ + public sendTemplateMessage: jest.Mock< + Promise, + [SendTemplateMessageRequestData] + > = jest.fn(); + /** + * Fixture associated to function sendTextMessage + */ + public sendTextMessage: jest.Mock< + Promise, + [SendTextMessageRequestData] + > = jest.fn(); /** * Fixture associated to function send */ - public send: jest.Mock, [SendMessageRequestData]> = jest.fn(); + public send: jest.Mock< + Promise, + [SendMessageRequestData] + > = jest.fn(); /** * Fixture associated to function update */ diff --git a/packages/conversation/src/rest/v1/messages/messages-api.ts b/packages/conversation/src/rest/v1/messages/messages-api.ts index 7ad02616..5cca2ac1 100644 --- a/packages/conversation/src/rest/v1/messages/messages-api.ts +++ b/packages/conversation/src/rest/v1/messages/messages-api.ts @@ -11,8 +11,18 @@ import { ConversationChannel, ConversationMessage, ConversationMessagesView, + Recipient, + SendCardMessageRequest, + SendCarouselMessageRequest, + SendChoiceMessageRequest, + SendContactInfoMessageRequest, + SendListMessageRequest, + SendLocationMessageRequest, + SendMediaMessageRequest, SendMessageRequest, SendMessageResponse, + SendTemplateMessageRequest, + SendTextMessageRequest, UpdateMessageRequest, } from '../../../models'; import { ConversationDomainApi } from '../conversation-domain-api'; @@ -56,9 +66,45 @@ export interface ListMessagesRequestData { /** Only fetch messages from the `channel`. */ 'channel'?: ConversationChannel; } -export interface SendMessageRequestData { +export interface SendMessageRequestData { /** This is the request body for sending a message. `app_id`, `recipient`, and `message` are all required fields. */ - 'sendMessageRequestBody': SendMessageRequest; + 'sendMessageRequestBody': SendMessageRequest; +} +export interface SendCardMessageRequestData { + /** This is the request body for sending a message. `app_id`, `recipient`, and `message` are all required fields. */ + 'sendMessageRequestBody': SendCardMessageRequest; +} +export interface SendCarouselMessageRequestData { + /** This is the request body for sending a message. `app_id`, `recipient`, and `message` are all required fields. */ + 'sendMessageRequestBody': SendCarouselMessageRequest; +} +export interface SendChoiceMessageRequestData { + /** This is the request body for sending a message. `app_id`, `recipient`, and `message` are all required fields. */ + 'sendMessageRequestBody': SendChoiceMessageRequest; +} +export interface SendContactInfoMessageRequestData { + /** This is the request body for sending a message. `app_id`, `recipient`, and `message` are all required fields. */ + 'sendMessageRequestBody': SendContactInfoMessageRequest; +} +export interface SendListMessageRequestData { + /** This is the request body for sending a message. `app_id`, `recipient`, and `message` are all required fields. */ + 'sendMessageRequestBody': SendListMessageRequest; +} +export interface SendLocationMessageRequestData { + /** This is the request body for sending a message. `app_id`, `recipient`, and `message` are all required fields. */ + 'sendMessageRequestBody': SendLocationMessageRequest; +} +export interface SendMediaMessageRequestData { + /** This is the request body for sending a message. `app_id`, `recipient`, and `message` are all required fields. */ + 'sendMessageRequestBody': SendMediaMessageRequest; +} +export interface SendTemplateMessageRequestData { + /** This is the request body for sending a message. `app_id`, `recipient`, and `message` are all required fields. */ + 'sendMessageRequestBody': SendTemplateMessageRequest; +} +export interface SendTextMessageRequestData { + /** This is the request body for sending a message. `app_id`, `recipient`, and `message` are all required fields. */ + 'sendMessageRequestBody': SendTextMessageRequest; } export interface UpdateMessageRequestData { /** The unique ID of the message. */ @@ -196,17 +242,128 @@ export class MessagesApi extends ConversationDomainApi { /** * Send a message * You can send a message from a Conversation app to a contact associated with that app. If the recipient is not associated with an existing contact, a new contact will be created. The message is added to the active conversation with the contact if a conversation already exists. If no active conversation exists a new one is started automatically. You can find all of your IDs and authentication credentials on the [Sinch Customer Dashboard](https://dashboard.sinch.com/convapi/overview). - * @param { SendMessageRequestData } data - The data to provide to the API call. + * @param { SendCardMessageRequestData } data - The data to provide to the API call. + */ + public async send( + data: SendMessageRequestData, + ): Promise { + return this.sendMessage(data, 'SendMessage'); + } + + /** + * Send a card message + * You can send a message from a Conversation app to a contact associated with that app. If the recipient is not associated with an existing contact, a new contact will be created. The message is added to the active conversation with the contact if a conversation already exists. If no active conversation exists a new one is started automatically. You can find all of your IDs and authentication credentials on the [Sinch Customer Dashboard](https://dashboard.sinch.com/convapi/overview). + * @param { SendCardMessageRequestData } data - The data to provide to the API call. + */ + public async sendCardMessage( + data: SendCardMessageRequestData, + ): Promise { + return this.sendMessage(data, 'SendCardMessage'); + } + + /** + * Send a carousel message + * You can send a message from a Conversation app to a contact associated with that app. If the recipient is not associated with an existing contact, a new contact will be created. The message is added to the active conversation with the contact if a conversation already exists. If no active conversation exists a new one is started automatically. You can find all of your IDs and authentication credentials on the [Sinch Customer Dashboard](https://dashboard.sinch.com/convapi/overview). + * @param { SendCarouselMessageRequestData } data - The data to provide to the API call. + */ + public async sendCarouselMessage( + data: SendCarouselMessageRequestData, + ): Promise { + return this.sendMessage(data, 'SendCarouselMessage'); + } + + /** + * Send a choice message + * You can send a message from a Conversation app to a contact associated with that app. If the recipient is not associated with an existing contact, a new contact will be created. The message is added to the active conversation with the contact if a conversation already exists. If no active conversation exists a new one is started automatically. You can find all of your IDs and authentication credentials on the [Sinch Customer Dashboard](https://dashboard.sinch.com/convapi/overview). + * @param { SendChoiceMessageRequestData } data - The data to provide to the API call. */ - public async send(data: SendMessageRequestData): Promise { + public async sendChoiceMessage( + data: SendChoiceMessageRequestData, + ): Promise { + return this.sendMessage(data, 'SendChoiceMessage'); + } + + /** + * Send a contact info message + * You can send a message from a Conversation app to a contact associated with that app. If the recipient is not associated with an existing contact, a new contact will be created. The message is added to the active conversation with the contact if a conversation already exists. If no active conversation exists a new one is started automatically. You can find all of your IDs and authentication credentials on the [Sinch Customer Dashboard](https://dashboard.sinch.com/convapi/overview). + * @param { SendContactInfoMessageRequestData } data - The data to provide to the API call. + */ + public async sendContactInfoMessage( + data: SendContactInfoMessageRequestData, + ): Promise { + return this.sendMessage(data, 'SendContactInfoMessage'); + } + + /** + * Send a list message + * You can send a message from a Conversation app to a contact associated with that app. If the recipient is not associated with an existing contact, a new contact will be created. The message is added to the active conversation with the contact if a conversation already exists. If no active conversation exists a new one is started automatically. You can find all of your IDs and authentication credentials on the [Sinch Customer Dashboard](https://dashboard.sinch.com/convapi/overview). + * @param { SendListMessageRequestData } data - The data to provide to the API call. + */ + public async sendListMessage( + data: SendListMessageRequestData, + ): Promise { + return this.sendMessage(data, 'SendListMessage'); + } + + /** + * Send a location message + * You can send a message from a Conversation app to a contact associated with that app. If the recipient is not associated with an existing contact, a new contact will be created. The message is added to the active conversation with the contact if a conversation already exists. If no active conversation exists a new one is started automatically. You can find all of your IDs and authentication credentials on the [Sinch Customer Dashboard](https://dashboard.sinch.com/convapi/overview). + * @param { SendLocationMessageRequestData } data - The data to provide to the API call. + */ + public async sendLocationMessage( + data: SendLocationMessageRequestData, + ): Promise { + return this.sendMessage(data, 'SendLocationMessage'); + } + + /** + * Send a media message + * You can send a message from a Conversation app to a contact associated with that app. If the recipient is not associated with an existing contact, a new contact will be created. The message is added to the active conversation with the contact if a conversation already exists. If no active conversation exists a new one is started automatically. You can find all of your IDs and authentication credentials on the [Sinch Customer Dashboard](https://dashboard.sinch.com/convapi/overview). + * @param { SendCardMessageRequestData } data - The data to provide to the API call. + */ + public async sendMediaMessage( + data: SendMediaMessageRequestData, + ): Promise { + return this.sendMessage(data, 'SendMediaMessage'); + } + + /** + * Send a template message + * You can send a message from a Conversation app to a contact associated with that app. If the recipient is not associated with an existing contact, a new contact will be created. The message is added to the active conversation with the contact if a conversation already exists. If no active conversation exists a new one is started automatically. You can find all of your IDs and authentication credentials on the [Sinch Customer Dashboard](https://dashboard.sinch.com/convapi/overview). + * @param { SendCardMessageRequestData } data - The data to provide to the API call. + */ + public async sendTemplateMessage( + data: SendTemplateMessageRequestData, + ): Promise { + return this.sendMessage(data, 'SendTemplateMessage'); + } + + /** + * Send a text message + * You can send a message from a Conversation app to a contact associated with that app. If the recipient is not associated with an existing contact, a new contact will be created. The message is added to the active conversation with the contact if a conversation already exists. If no active conversation exists a new one is started automatically. You can find all of your IDs and authentication credentials on the [Sinch Customer Dashboard](https://dashboard.sinch.com/convapi/overview). + * @param { SendTextMessageRequestData } data - The data to provide to the API call. + */ + public async sendTextMessage( + data: SendTextMessageRequestData, + ): Promise { + return this.sendMessage(data, 'SendTextMessage'); + } + + private async sendMessage( + data: SendMessageRequestData, + operationId: string, + ): Promise { this.client = this.getSinchClient(); - const getParams = this.client.extractQueryParams(data, [] as never[]); + const getParams = this.client.extractQueryParams>( + data, [] as never[]); const headers: { [key: string]: string | undefined } = { 'Content-Type': 'application/json', 'Accept': 'application/json', }; - const body: RequestBody = data['sendMessageRequestBody'] ? JSON.stringify(data['sendMessageRequestBody']) : '{}'; + const body: RequestBody = data['sendMessageRequestBody'] + ? JSON.stringify(data['sendMessageRequestBody']) + : '{}'; const basePathUrl = `${this.client.apiClientOptions.basePath}/v1/projects/${this.client.apiClientOptions.projectId}/messages:send`; const requestOptions = await this.client.prepareOptions(basePathUrl, 'POST', getParams, headers, body || undefined); @@ -216,7 +373,7 @@ export class MessagesApi extends ConversationDomainApi { url, requestOptions, apiName: this.apiName, - operationId: 'SendMessage', + operationId, }); } diff --git a/packages/conversation/tests/events-mocks.ts b/packages/conversation/tests/events-mocks.ts new file mode 100644 index 00000000..c4e99420 --- /dev/null +++ b/packages/conversation/tests/events-mocks.ts @@ -0,0 +1,48 @@ +import { + AgentJoinedEvent, + AgentLeftEvent, + CommentReplyEvent, + ComposingEndEvent, + ComposingEvent, + GenericEvent, +} from '../src'; + +export const composingEvent: ComposingEvent = { + composing_event: {}, +}; + +export const composingEndEvent: ComposingEndEvent = { + composing_end_event: {}, +}; + +export const commentReplyEvent: CommentReplyEvent = { + comment_reply_event: { + text: 'Reply comment content', + }, +}; + +export const agentJoinedEvent: AgentJoinedEvent = { + agent_joined_event: { + agent: { + display_name: 'Agent name', + type: 'HUMAN', + }, + }, +}; + +export const agentLeftEvent: AgentLeftEvent = { + agent_left_event: { + agent: { + display_name: 'Agent name', + type: 'HUMAN', + }, + }, +}; + +export const genericEvent: GenericEvent = { + generic_event: { + payload: { + some: 'data', + }, + }, +}; diff --git a/packages/conversation/tests/messages-mocks.ts b/packages/conversation/tests/messages-mocks.ts new file mode 100644 index 00000000..14655d22 --- /dev/null +++ b/packages/conversation/tests/messages-mocks.ts @@ -0,0 +1,236 @@ +import { + CardMessage, + CardMessageItem, + CarouselMessage, + CarouselMessageItem, + ChoiceMessage, + ChoiceMessageItem, + ContactInfoMessage, + ContactInfoMessageItem, + ListMessage, + ListMessageItem, + LocationMessage, + LocationMessageItem, + MediaMessage, + MediaMessageItem, + TemplateMessage, + TemplateMessageItem, + TextMessage, + TextMessageItem, +} from '../src'; + +export const textMessageItem: TextMessageItem = { + text: 'text message', +}; + +export const textMessage: TextMessage = { + text_message: textMessageItem, +}; + +export const cardMessageItem: CardMessageItem = { + title: 'title', + description: 'description', + media_message: { + url: 'url', + }, + height: 'MEDIUM', + choices: [ + { + text_message: { + text: 'Strawberry', + }, + }, + { + text_message: { + text: 'Blueberry', + }, + }, + ], +}; + +export const cardMessage: CardMessage = { + card_message: cardMessageItem, +}; + +export const carouselMessageItem: CarouselMessageItem = { + cards: [ + { + title: 'card #1', + description: 'description #1', + media_message: { + url: 'https://url1.com', + }, + choices: [ + { + text_message: { + text: 'This is the card #1', + }, + }, + ], + }, + { + title: 'card #2', + description: 'description #2', + media_message: { + url: 'https://url2.com', + }, + choices: [ + { + url_message: { + title: 'Website', + url: 'https://website.com', + }, + }, + ], + }, + { + title: 'card #3', + description: 'description #3', + media_message: { + url: 'https://url3.com', + }, + choices: [ + { + call_message: { + title: 'Support line', + phone_number: '46732000000', + }, + }, + ], + }, + ], +}; + +export const carouselMessage: CarouselMessage = { + carousel_message: carouselMessageItem, +}; + +export const choiceMessageItem: ChoiceMessageItem = { + text_message: { + text: 'Choose your icecream flavor', + }, + choices: [ + { + text_message: { + text: 'Strawberry', + }, + }, + { + text_message: { + text: 'Blueberry', + }, + }, + ], +}; + +export const choiceMessage: ChoiceMessage = { + choice_message: choiceMessageItem, +}; + +export const contactInfoMessageItem: ContactInfoMessageItem = { + name: { + full_name: 'Full Name', + }, + phone_numbers: [ + { + phone_number: '+17811234123', + type: 'WORK', + }, + ], +}; + +export const contactInfoMessage: ContactInfoMessage = { + contact_info_message: contactInfoMessageItem, +}; + +export const locationMessageItem: LocationMessageItem = { + title: 'Phare d\'Eckmühl', + label: 'Pointe de Penmarch', + coordinates: { + latitude: 47.7981899, + longitude: -4.3727685, + }, +}; + +export const locationMessage: LocationMessage = { + location_message: locationMessageItem, +}; + +export const mediaMessageItem: MediaMessageItem = { + url: 'https://url-to-media.com', + thumbnail_url: 'https://url-to-thumbnail.com', +}; + +export const mediaMessage: MediaMessage = { + media_message: mediaMessageItem, +}; + +export const templateMessageItem: TemplateMessageItem = { + omni_template: { + template_id: 'templateId', + version: '1', + language_code: 'en-US', + parameters: { + name: 'Value for the "name" parameter used in the version 1 and language "en-US" of the template', + }, + }, + channel_template: { + 'KAKAOTALK': { + template_id: 'templateIdForKakaoTalk', + version: '1', + language_code: 'en-US', + }, + }, +}; + +export const templateMessage: TemplateMessage = { + template_message: templateMessageItem, +}; + +export const listMessageItem: ListMessageItem = { + title: 'Choose your icecream flavor', + description: 'The best icecream in town!', + sections: [ + { + title: 'Fruit flavors', + items: [ + { + choice: { + title: 'Strawberry', + postback_data: 'Strawberry postback', + }, + }, + { + choice: { + title: 'Blueberry', + postback_data: 'Blueberry postback', + }, + }, + ], + }, + { + title: 'Other flavors', + items: [ + { + choice: { + title: 'Chocolate', + postback_data: 'Chocolate postback', + }, + }, + { + choice: { + title: 'Vanilla', + postback_data: 'Vanilla postback', + }, + }, + ], + }, + ], + message_properties: { + menu: 'menu text', + }, +}; + +export const listMessage: ListMessage = { + list_message: listMessageItem, +}; diff --git a/packages/conversation/tests/models/v1/helper.test.ts b/packages/conversation/tests/models/v1/helper.test.ts index 50331272..05065280 100644 --- a/packages/conversation/tests/models/v1/helper.test.ts +++ b/packages/conversation/tests/models/v1/helper.test.ts @@ -1,223 +1,36 @@ import { - CardMessage, CardMessageItem, - CarouselMessage, CarouselMessageItem, - ChoiceMessage, ChoiceMessageItem, - ListMessage, ListMessageItem, - LocationMessage, LocationMessageItem, - MediaMessage, MediaMessageItem, - TemplateMessage, TemplateMessageItem, - TextMessage, TextMessageItem, V2TemplateTranslation, MessageType, templateV1Helper, - templateV2Helper, messageBuilder, + templateV2Helper, + messageBuilder, } from '../../../src'; - -const textItem: TextMessageItem = { - text: 'text message', -}; - -const textMessage: TextMessage = { - text_message: textItem, -}; - -const cardMessageItem: CardMessageItem = { - title: 'title', - description: 'description', - media_message: { - url: 'url', - }, - height: 'MEDIUM', - choices: [ - { - text_message: { - text: 'Strawberry', - }, - }, - { - text_message: { - text: 'Blueberry', - }, - }, - ], -}; - -const cardMessage: CardMessage = { - card_message: cardMessageItem, -}; - -const carouselMessageItem: CarouselMessageItem = { - cards: [ - { - title: 'card #1', - description: 'description #1', - media_message: { - url: 'https://url1.com', - }, - choices: [ - { - text_message: { - text: 'This is the card #1', - }, - }, - ], - }, - { - title: 'card #2', - description: 'description #2', - media_message: { - url: 'https://url2.com', - }, - choices: [ - { - url_message: { - title: 'Website', - url: 'https://website.com', - }, - }, - ], - }, - { - title: 'card #3', - description: 'description #3', - media_message: { - url: 'https://url3.com', - }, - choices: [ - { - call_message: { - title: 'Support line', - phone_number: '46732000000', - }, - }, - ], - }, - ], -}; - -const carouselMessage: CarouselMessage = { - carousel_message: carouselMessageItem, -}; - -const choiceMessageItem: ChoiceMessageItem = { - text_message: { - text: 'Choose your icecream flavor', - }, - choices: [ - { - text_message: { - text: 'Strawberry', - }, - }, - { - text_message: { - text: 'Blueberry', - }, - }, - ], -}; - -const choiceMessage: ChoiceMessage = { - choice_message: choiceMessageItem, -}; - -const locationMessageItem: LocationMessageItem = { - title: 'Phare d\'Eckmühl', - label: 'Pointe de Penmarch', - coordinates: { - latitude: 47.7981899, - longitude: -4.3727685, - }, -}; - -const locationMessage: LocationMessage = { - location_message: locationMessageItem, -}; - -const mediaMessageItem: MediaMessageItem = { - url: 'https://url-to-media.com', - thumbnail_url: 'https://url-to-thumbnail.com', -}; - -const mediaMessage: MediaMessage = { - media_message: mediaMessageItem, -}; - -const templateMessageItem: TemplateMessageItem = { - omni_template: { - template_id: 'templateId', - version: '1', - language_code: 'en-US', - parameters: { - name: 'Value for the "name" parameter used in the version 1 and language "en-US" of the template', - }, - }, - channel_template: { - 'KAKAOTALK': { - template_id: 'templateIdForKakaoTalk', - version: '1', - language_code: 'en-US', - }, - }, -}; - -const templateMessage: TemplateMessage = { - template_message: templateMessageItem, -}; - -const listMessageItem: ListMessageItem = { - title: 'Choose your icecream flavor', - description: 'The best icecream in town!', - sections: [ - { - title: 'Fruit flavors', - items: [ - { - choice: { - title: 'Strawberry', - postback_data: 'Strawberry postback', - }, - }, - { - choice: { - title: 'Blueberry', - postback_data: 'Blueberry postback', - }, - }, - ], - }, - { - title: 'Other flavors', - items: [ - { - choice: { - title: 'Chocolate', - postback_data: 'Chocolate postback', - }, - }, - { - choice: { - title: 'Vanilla', - postback_data: 'Vanilla postback', - }, - }, - ], - }, - ], - message_properties: { - menu: 'menu text', - }, -}; - -const listMessage: ListMessage = { - list_message: listMessageItem, -}; +import { + cardMessage, + cardMessageItem, + carouselMessage, + carouselMessageItem, + choiceMessage, + choiceMessageItem, + contactInfoMessage, + contactInfoMessageItem, + listMessage, + listMessageItem, + locationMessage, + locationMessageItem, + mediaMessage, + mediaMessageItem, + templateMessage, + templateMessageItem, + textMessageItem, + textMessage, +} from '../../messages-mocks'; describe('Conversation models helpers', () => { describe('Templates V1 helper', () => { it('should build a TextMessage', () => { - const builtMessage = templateV1Helper.buildTextMessageContent(textItem); + const builtMessage = templateV1Helper.buildTextMessageContent(textMessageItem); expect(builtMessage).toBe(JSON.stringify(textMessage)); }); @@ -236,6 +49,11 @@ describe('Conversation models helpers', () => { expect(builtMessage).toBe(JSON.stringify(choiceMessage)); }); + it('should build a ContactInfoMessage', () => { + const builtMessage = templateV1Helper.buildContactInfoMessageContent(contactInfoMessageItem); + expect(builtMessage).toEqual(JSON.stringify(contactInfoMessage)); + }); + it('should build a LocationMessage', () => { const builtMessage = templateV1Helper.buildLocationMessageContent(locationMessageItem); expect(builtMessage).toBe(JSON.stringify(locationMessage)); @@ -259,7 +77,7 @@ describe('Conversation models helpers', () => { describe('Templates V2 helper', () => { it('should build a TextMessage', () => { - const builtTextMessage = templateV2Helper.buildTextMessageContent(textItem); + const builtTextMessage = templateV2Helper.buildTextMessageContent(textMessageItem); expect(builtTextMessage).toEqual(textMessage); }); @@ -278,6 +96,11 @@ describe('Conversation models helpers', () => { expect(builtMessage).toEqual(choiceMessage); }); + it('should build a ContactInfoMessage', () => { + const builtMessage = templateV2Helper.buildContactInfoMessageContent(contactInfoMessageItem); + expect(builtMessage).toEqual(contactInfoMessage); + }); + it('should build a LocationMessage', () => { const builtMessage = templateV2Helper.buildLocationMessageContent(locationMessageItem); expect(builtMessage).toEqual(locationMessage); @@ -328,6 +151,12 @@ describe('Conversation models helpers', () => { }; expect(templateV2Helper.getMessageFromTranslation(templateTranslation).type).toBe(MessageType.CAROUSEL); + templateTranslation = { + ...translationIdentifier, + ...contactInfoMessage, + }; + expect(templateV2Helper.getMessageFromTranslation(templateTranslation).type).toBe(MessageType.CONTACT_INFO); + templateTranslation = { ...translationIdentifier, ...listMessage, @@ -377,7 +206,7 @@ describe('Conversation models helpers', () => { describe('Message builder helper', () => { it('should build a TextMessage', () => { - const builtTextMessage = messageBuilder.text(textItem); + const builtTextMessage = messageBuilder.text(textMessageItem); expect(builtTextMessage).toEqual(textMessage); }); diff --git a/packages/conversation/tests/rest/v1/capability/capability-api.test.ts b/packages/conversation/tests/rest/v1/capability/capability-api.test.ts index e94f2d4c..c64a21c0 100644 --- a/packages/conversation/tests/rest/v1/capability/capability-api.test.ts +++ b/packages/conversation/tests/rest/v1/capability/capability-api.test.ts @@ -1,6 +1,14 @@ import { SinchClientParameters } from '@sinch/sdk-client'; -import { LookupCapabilityRequestData, QueryCapabilityResponse } from '../../../../src'; +import { + ContactId, + IdentifiedBy, + LookupCapabilityRequest, + LookupCapabilityRequestData, + LookupCapabilityResponse, + Recipient, +} from '../../../../src'; import { CapabilityApi, CapabilityApiFixture } from '../../../../src'; +import { recipientChannelIdentities, recipientContactId } from '../mocks'; describe('CapabilityApi', () => { let capabilityApi: CapabilityApi; @@ -19,35 +27,40 @@ describe('CapabilityApi', () => { describe ('queryCapability', () => { - it('should make a POST request to ...', async () => { - // Given - const requestData: LookupCapabilityRequestData = { - lookupCapabilityRequestBody: { - app_id: 'app_id', - recipient: { - identified_by: { - channel_identities: [ - { - identity: 'Whatsapp identity', - channel: 'WHATSAPP', - }, - ], - }, - }, - }, - }; - const expectedResponse: QueryCapabilityResponse = { - app_id: 'app_id', - }; + // Given + const lookupCapabilityRequest: Omit, 'recipient'> = { + app_id: 'app_id', + }; + const requestDataWithContactId: LookupCapabilityRequestData = { + lookupCapabilityRequestBody: { + ...lookupCapabilityRequest, + ...recipientContactId, + }, + }; + const requestDataWithChannelIdentity: LookupCapabilityRequestData = { + lookupCapabilityRequestBody: { + ...lookupCapabilityRequest, + ...recipientChannelIdentities, + }, + }; + const expectedResponse: LookupCapabilityResponse = { + app_id: 'app_id', + }; - // When - fixture.lookup.mockResolvedValue(expectedResponse); - capabilityApi.lookup = fixture.lookup; - const response = await capabilityApi.lookup(requestData); + test.each([ + ['contact ID', requestDataWithContactId, expectedResponse], + ['channel identities', requestDataWithChannelIdentity, expectedResponse], + ])('should make a POST request to trigger a CAPABILITY event for a recipient identified by its %s', + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async (_identification, requestData, expectedResponse) => { + // When + fixture.lookup.mockResolvedValue(expectedResponse); + capabilityApi.lookup = fixture.lookup; + const response = await capabilityApi.lookup(requestData); - // Then - expect(response).toEqual(expectedResponse); - expect(fixture.lookup).toHaveBeenCalledWith(requestData); - }); + // Then + expect(response).toEqual(expectedResponse); + expect(fixture.lookup).toHaveBeenCalledWith(requestData); + }); }); }); diff --git a/packages/conversation/tests/rest/v1/contact/contact-api.test.ts b/packages/conversation/tests/rest/v1/contact/contact-api.test.ts index d235f626..f5d8f799 100644 --- a/packages/conversation/tests/rest/v1/contact/contact-api.test.ts +++ b/packages/conversation/tests/rest/v1/contact/contact-api.test.ts @@ -3,14 +3,20 @@ import { Contact, CreateContactRequestData, DeleteContactRequestData, - GetChannelProfileRequestData, GetContactRequestData, ListContactsRequestData, MergeContactRequestData, UpdateContactRequestData, GetChannelProfileResponse, - ContactApi, ContactApiFixture, + ContactApi, + ContactApiFixture, + GetChannelProfileRequestData, + ContactId, + IdentifiedBy, + GetChannelProfileRequest, + Recipient, } from '../../../../src'; +import { recipientChannelIdentities, recipientContactId } from '../mocks'; describe('ContactApi', () => { let contactApi: ContactApi; @@ -79,37 +85,42 @@ describe('ContactApi', () => { }); describe ('getChannelProfile', () => { - it('should make a POST request to get a user profile from a specific channel', async () => { - // Given - const requestData: GetChannelProfileRequestData = { - getChannelProfileRequestBody: { - app_id: 'app_id', - channel: 'MESSENGER', - recipient: { - identified_by: { - channel_identities: [ - { - identity: '', - channel: 'WHATSAPP', - }, - ], - }, - }, - }, - }; - const expectedResponse: GetChannelProfileResponse = { - profile_name: 'Profile Name', - }; - - // When - fixture.getChannelProfile.mockResolvedValue(expectedResponse); - contactApi.getChannelProfile = fixture.getChannelProfile; - const response = await contactApi.getChannelProfile(requestData); + // Given + const getChannelProfileRequest: Omit, 'recipient'> = { + app_id: 'app_id', + channel: 'MESSENGER', + }; + const requestDataWithContactId: GetChannelProfileRequestData = { + getChannelProfileRequestBody: { + ...getChannelProfileRequest, + ...recipientContactId, + }, + }; + const requestDataWithChannelIdentity: GetChannelProfileRequestData = { + getChannelProfileRequestBody: { + ...getChannelProfileRequest, + ...recipientChannelIdentities, + }, + }; + const expectedResponse: GetChannelProfileResponse = { + profile_name: 'Profile Name', + }; - // Then - expect(response).toEqual(expectedResponse); - expect(fixture.getChannelProfile).toHaveBeenCalledWith(requestData); - }); + test.each([ + ['contact ID', requestDataWithContactId, expectedResponse], + ['channel identities', requestDataWithChannelIdentity, expectedResponse], + ])('should make a POST request to get a user profile from a specific channel for a recipient identified by its %s', + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async (_identification, requestData, expectedResponse) => { + // When + fixture.getChannelProfile.mockResolvedValue(expectedResponse); + contactApi.getChannelProfile = fixture.getChannelProfile; + const response = await contactApi.getChannelProfile(requestData); + + // Then + expect(response).toEqual(expectedResponse); + expect(fixture.getChannelProfile).toHaveBeenCalledWith(requestData); + }); }); describe ('getContact', () => { diff --git a/packages/conversation/tests/rest/v1/events/events-api.test.ts b/packages/conversation/tests/rest/v1/events/events-api.test.ts index 5d60b631..f13f31cb 100644 --- a/packages/conversation/tests/rest/v1/events/events-api.test.ts +++ b/packages/conversation/tests/rest/v1/events/events-api.test.ts @@ -1,15 +1,39 @@ import { SinchClientParameters } from '@sinch/sdk-client'; import { + ContactId, ConversationEvent, DeleteEventRequestData, EventsApi, EventsApiFixture, - GenericEvent, GetEventRequestData, + IdentifiedBy, ListEventsRequestData, + Recipient, + SendAgentJoinedEventRequest, + SendAgentJoinedEventRequestData, + SendAgentLeftEventRequest, + SendAgentLeftEventRequestData, + SendCommentReplyEventRequest, + SendCommentReplyEventRequestData, + SendComposingEndEventRequest, + SendComposingEndEventRequestData, + SendComposingEventRequest, + SendComposingEventRequestData, + SendEventRequest, SendEventRequestData, SendEventResponse, + SendGenericEventRequest, + SendGenericEventRequestData, } from '../../../../src'; +import { recipientChannelIdentities, recipientContactId } from '../mocks'; +import { + agentJoinedEvent, + agentLeftEvent, + commentReplyEvent, + composingEndEvent, + composingEvent, + genericEvent, +} from '../../../events-mocks'; describe('EventsApi', () => { let eventsApi: EventsApi; @@ -160,37 +184,297 @@ describe('EventsApi', () => { }); }); - describe ('sendEvent', () => { - it('should make a POST request to send an event to the referenced contact from the referenced app', async () => { - // Given - const requestData: SendEventRequestData = { - sendEventRequestBody: { - app_id: 'app_id', - recipient: { - contact_id: 'contact_id', - }, - event: { - generic_event: { - payload: { - some: 'data', - }, - }, - } as GenericEvent, - }, - }; - const expectedResponse: SendEventResponse = { - accepted_time: new Date('2019-08-24T14:15:22Z'), - event_id: 'event_id', - }; + describe ('send', () => { + // Given + const sendEventRequest: Omit, 'recipient'> = { + app_id: 'app_id', + event: { + ...composingEvent, + }, + }; + const requestDataWithContactId: SendEventRequestData = { + sendEventRequestBody: { + ...sendEventRequest, + ...recipientContactId, + }, + }; + const requestDataWithChannelIdentity: SendEventRequestData = { + sendEventRequestBody: { + ...sendEventRequest, + ...recipientChannelIdentities, + }, + }; + const expectedResponse: SendEventResponse = { + accepted_time: new Date('2019-08-24T14:15:22Z'), + event_id: 'event_id', + }; - // When - fixture.send.mockResolvedValue(expectedResponse); - eventsApi.send = fixture.send; - const response = await eventsApi.send(requestData); + test.each([ + ['contact ID', requestDataWithContactId, expectedResponse], + ['channel identities', requestDataWithChannelIdentity, expectedResponse], + ])('should make a POST request to send any event to a recipient identified by its %s', + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async (_identification, requestData, expectedResponse) => { + // When + fixture.send.mockResolvedValue(expectedResponse); + eventsApi.send = fixture.send; + const response = await eventsApi.send(requestData); - // Then - expect(response).toEqual(expectedResponse); - expect(fixture.send).toHaveBeenCalledWith(requestData); - }); + // Then + expect(response).toEqual(expectedResponse); + expect(fixture.send).toHaveBeenCalledWith(requestData); + }); + }); + + describe ('sendComposingEvent', () => { + // Given + const sendEventRequest: Omit, 'recipient'> = { + app_id: 'app_id', + event: { + ...composingEvent, + }, + }; + const requestDataWithContactId: SendComposingEventRequestData = { + sendEventRequestBody: { + ...sendEventRequest, + ...recipientContactId, + }, + }; + const requestDataWithChannelIdentity: SendComposingEventRequestData = { + sendEventRequestBody: { + ...sendEventRequest, + ...recipientChannelIdentities, + }, + }; + const expectedResponse: SendEventResponse = { + accepted_time: new Date('2019-08-24T14:15:22Z'), + event_id: 'event_id', + }; + + test.each([ + ['contact ID', requestDataWithContactId, expectedResponse], + ['channel identities', requestDataWithChannelIdentity, expectedResponse], + ])('should make a POST request to send a composing event to a recipient identified by its %s', + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async (_identification, requestData, expectedResponse) => { + // When + fixture.sendComposingEvent.mockResolvedValue(expectedResponse); + eventsApi.sendComposingEvent = fixture.sendComposingEvent; + const response = await eventsApi.sendComposingEvent(requestData); + + // Then + expect(response).toEqual(expectedResponse); + expect(fixture.sendComposingEvent).toHaveBeenCalledWith(requestData); + }); + }); + + describe ('sendComposingEndEvent', () => { + // Given + const sendEventRequest: Omit, 'recipient'> = { + app_id: 'app_id', + event: { + ...composingEndEvent, + }, + }; + const requestDataWithContactId: SendComposingEndEventRequestData = { + sendEventRequestBody: { + ...sendEventRequest, + ...recipientContactId, + }, + }; + const requestDataWithChannelIdentity: SendComposingEndEventRequestData = { + sendEventRequestBody: { + ...sendEventRequest, + ...recipientChannelIdentities, + }, + }; + const expectedResponse: SendEventResponse = { + accepted_time: new Date('2019-08-24T14:15:22Z'), + event_id: 'event_id', + }; + + test.each([ + ['contact ID', requestDataWithContactId, expectedResponse], + ['channel identities', requestDataWithChannelIdentity, expectedResponse], + ])('should make a POST request to send a composing end event to a recipient identified by its %s', + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async (_identification, requestData, expectedResponse) => { + // When + fixture.sendComposingEndEvent.mockResolvedValue(expectedResponse); + eventsApi.sendComposingEndEvent = fixture.sendComposingEndEvent; + const response = await eventsApi.sendComposingEndEvent(requestData); + + // Then + expect(response).toEqual(expectedResponse); + expect(fixture.sendComposingEndEvent).toHaveBeenCalledWith(requestData); + }); + }); + + describe ('sendCommentReplyEvent', () => { + // Given + const sendEventRequest: Omit, 'recipient'> = { + app_id: 'app_id', + event: { + ...commentReplyEvent, + }, + }; + const requestDataWithContactId: SendCommentReplyEventRequestData = { + sendEventRequestBody: { + ...sendEventRequest, + ...recipientContactId, + }, + }; + const requestDataWithChannelIdentity: SendCommentReplyEventRequestData = { + sendEventRequestBody: { + ...sendEventRequest, + ...recipientChannelIdentities, + }, + }; + const expectedResponse: SendEventResponse = { + accepted_time: new Date('2019-08-24T14:15:22Z'), + event_id: 'event_id', + }; + + test.each([ + ['contact ID', requestDataWithContactId, expectedResponse], + ['channel identities', requestDataWithChannelIdentity, expectedResponse], + ])('should make a POST request to send a comment reply event to a recipient identified by its %s', + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async (_identification, requestData, expectedResponse) => { + // When + fixture.sendCommentReplyEvent.mockResolvedValue(expectedResponse); + eventsApi.sendCommentReplyEvent = fixture.sendCommentReplyEvent; + const response = await eventsApi.sendCommentReplyEvent(requestData); + + // Then + expect(response).toEqual(expectedResponse); + expect(fixture.sendCommentReplyEvent).toHaveBeenCalledWith(requestData); + }); + }); + + describe ('sendAgentJoinedEvent', () => { + // Given + const sendEventRequest: Omit, 'recipient'> = { + app_id: 'app_id', + event: { + ...agentJoinedEvent, + }, + }; + const requestDataWithContactId: SendAgentJoinedEventRequestData = { + sendEventRequestBody: { + ...sendEventRequest, + ...recipientContactId, + }, + }; + const requestDataWithChannelIdentity: SendAgentJoinedEventRequestData = { + sendEventRequestBody: { + ...sendEventRequest, + ...recipientChannelIdentities, + }, + }; + const expectedResponse: SendEventResponse = { + accepted_time: new Date('2019-08-24T14:15:22Z'), + event_id: 'event_id', + }; + + test.each([ + ['contact ID', requestDataWithContactId, expectedResponse], + ['channel identities', requestDataWithChannelIdentity, expectedResponse], + ])('should make a POST request to send an agent joined event to a recipient identified by its %s', + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async (_identification, requestData, expectedResponse) => { + // When + fixture.sendAgentJoinedEvent.mockResolvedValue(expectedResponse); + eventsApi.sendAgentJoinedEvent = fixture.sendAgentJoinedEvent; + const response = await eventsApi.sendAgentJoinedEvent(requestData); + + // Then + expect(response).toEqual(expectedResponse); + expect(fixture.sendAgentJoinedEvent).toHaveBeenCalledWith(requestData); + }); + }); + + describe ('sendAgentLeftEvent', () => { + // Given + const sendEventRequest: Omit, 'recipient'> = { + app_id: 'app_id', + event: { + ...agentLeftEvent, + }, + }; + const requestDataWithContactId: SendAgentLeftEventRequestData = { + sendEventRequestBody: { + ...sendEventRequest, + ...recipientContactId, + }, + }; + const requestDataWithChannelIdentity: SendAgentLeftEventRequestData = { + sendEventRequestBody: { + ...sendEventRequest, + ...recipientChannelIdentities, + }, + }; + const expectedResponse: SendEventResponse = { + accepted_time: new Date('2019-08-24T14:15:22Z'), + event_id: 'event_id', + }; + + test.each([ + ['contact ID', requestDataWithContactId, expectedResponse], + ['channel identities', requestDataWithChannelIdentity, expectedResponse], + ])('should make a POST request to send an agent left event to a recipient identified by its %s', + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async (_identification, requestData, expectedResponse) => { + // When + fixture.sendAgentLeftEvent.mockResolvedValue(expectedResponse); + eventsApi.sendAgentLeftEvent = fixture.sendAgentLeftEvent; + const response = await eventsApi.sendAgentLeftEvent(requestData); + + // Then + expect(response).toEqual(expectedResponse); + expect(fixture.sendAgentLeftEvent).toHaveBeenCalledWith(requestData); + }); + }); + + describe ('sendGenericEvent', () => { + // Given + const sendEventRequest: Omit, 'recipient'> = { + app_id: 'app_id', + event: { + ...genericEvent, + }, + }; + const requestDataWithContactId: SendGenericEventRequestData = { + sendEventRequestBody: { + ...sendEventRequest, + ...recipientContactId, + }, + }; + const requestDataWithChannelIdentity: SendGenericEventRequestData = { + sendEventRequestBody: { + ...sendEventRequest, + ...recipientChannelIdentities, + }, + }; + const expectedResponse: SendEventResponse = { + accepted_time: new Date('2019-08-24T14:15:22Z'), + event_id: 'event_id', + }; + + test.each([ + ['contact ID', requestDataWithContactId, expectedResponse], + ['channel identities', requestDataWithChannelIdentity, expectedResponse], + ])('should make a POST request to send a generic event to a recipient identified by its %s', + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async (_identification, requestData, expectedResponse) => { + // When + fixture.sendGenericEvent.mockResolvedValue(expectedResponse); + eventsApi.sendGenericEvent = fixture.sendGenericEvent; + const response = await eventsApi.sendGenericEvent(requestData); + + // Then + expect(response).toEqual(expectedResponse); + expect(fixture.sendGenericEvent).toHaveBeenCalledWith(requestData); + }); }); }); diff --git a/packages/conversation/tests/rest/v1/messages/messages-api.test.ts b/packages/conversation/tests/rest/v1/messages/messages-api.test.ts index 36d787f1..9e3b8e69 100644 --- a/packages/conversation/tests/rest/v1/messages/messages-api.test.ts +++ b/packages/conversation/tests/rest/v1/messages/messages-api.test.ts @@ -1,15 +1,50 @@ import { SinchClientParameters } from '@sinch/sdk-client'; import { + ContactId, ConversationMessage, DeleteMessageRequestData, GetMessageRequestData, + IdentifiedBy, ListMessagesRequestData, + messageBuilder, MessagesApi, MessagesApiFixture, + Recipient, + SendCardMessageRequest, + SendCardMessageRequestData, + SendCarouselMessageRequest, + SendCarouselMessageRequestData, + SendChoiceMessageRequest, + SendChoiceMessageRequestData, + SendContactInfoMessageRequest, + SendContactInfoMessageRequestData, + SendListMessageRequest, + SendListMessageRequestData, + SendLocationMessageRequest, + SendLocationMessageRequestData, + SendMediaMessageRequest, + SendMediaMessageRequestData, + SendMessageRequest, SendMessageRequestData, SendMessageResponse, + SendTemplateMessageRequest, + SendTemplateMessageRequestData, + SendTextMessageRequest, + SendTextMessageRequestData, UpdateMessageRequestData, } from '../../../../src'; +import { recipientChannelIdentities, recipientContactId } from '../mocks'; +import { + cardMessageItem, + carouselMessageItem, + choiceMessageItem, + contactInfoMessageItem, + listMessageItem, + locationMessageItem, + mediaMessageItem, + templateMessageItem, + textMessageItem, +} from '../../../messages-mocks'; describe('MessagesApi', () => { let messagesApi: MessagesApi; @@ -205,35 +240,425 @@ describe('MessagesApi', () => { }); describe ('sendMessage', () => { - it('should make a POST request to send a request from a conversation app to a contact', async () => { - // Given - const requestData: SendMessageRequestData = { - sendMessageRequestBody: { - app_id: 'app_id', - recipient: { - contact_id: 'contact_id', - }, - message: { - text_message: { - text: 'text', - }, - }, - }, - }; - const expectedResponse: SendMessageResponse = { - accepted_time: new Date('2019-08-24T14:15:22Z'), - message_id: 'message_id', - }; + // Given + const sendMessageRequest: Omit, 'recipient'> = { + app_id: 'app_id', + message: { + ...messageBuilder.text(textMessageItem), + }, + }; + const requestDataWithContactId: SendMessageRequestData = { + sendMessageRequestBody: { + ...sendMessageRequest, + ...recipientContactId, + }, + }; + const requestDataWithChannelIdentity: SendMessageRequestData = { + sendMessageRequestBody: { + ...sendMessageRequest, + ...recipientChannelIdentities, + }, + }; + const expectedResponse: SendMessageResponse = { + accepted_time: new Date('2019-08-24T14:15:22Z'), + message_id: 'message_id', + }; + + test.each([ + ['contact ID', requestDataWithContactId, expectedResponse], + ['channel identities', requestDataWithChannelIdentity, expectedResponse], + // eslint-disable-next-line max-len + ])('should make a POST request to send any message request from a conversation app to a recipient identified by its %s', + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async (_identification, requestData, expectedResponse) => { + // When + fixture.send.mockResolvedValue(expectedResponse); + messagesApi.send = fixture.send; + const response = await messagesApi.send(requestData); + + // Then + expect(response).toEqual(expectedResponse); + expect(fixture.send).toHaveBeenCalledWith(requestData); + }); + }); + + describe ('sendCardMessage', () => { + // Given + const sendCardMessageRequest: Omit, 'recipient'> = { + app_id: 'app_id', + message: { + ...messageBuilder.card(cardMessageItem), + }, + }; + const requestDataWithContactId: SendCardMessageRequestData = { + sendMessageRequestBody: { + ...sendCardMessageRequest, + ...recipientContactId, + }, + }; + const requestDataWithChannelIdentity: SendCardMessageRequestData = { + sendMessageRequestBody: { + ...sendCardMessageRequest, + ...recipientChannelIdentities, + }, + }; + const expectedResponse: SendMessageResponse = { + accepted_time: new Date('2019-08-24T14:15:22Z'), + message_id: 'message_id', + }; + + test.each([ + ['contact ID', requestDataWithContactId, expectedResponse], + ['channel identities', requestDataWithChannelIdentity, expectedResponse], + // eslint-disable-next-line max-len + ])('should make a POST request to send a card message request from a conversation app to a recipient identified by its %s', + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async (_identification, requestData, expectedResponse) => { + // When + fixture.sendCardMessage.mockResolvedValue(expectedResponse); + messagesApi.sendCardMessage = fixture.sendCardMessage; + const response = await messagesApi.sendCardMessage(requestData); + // Then + expect(response).toEqual(expectedResponse); + expect(fixture.sendCardMessage).toHaveBeenCalledWith(requestData); + }); + }); + + describe ('sendCarouselMessage', () => { + const sendCarouselMessageRequest: Omit, 'recipient'> = { + app_id: 'app_id', + message: { + ...messageBuilder.carousel(carouselMessageItem), + }, + }; + const requestDataWithContactId: SendCarouselMessageRequestData = { + sendMessageRequestBody: { + ...sendCarouselMessageRequest, + ...recipientContactId, + }, + }; + const requestDataWithChannelIdentity: SendCarouselMessageRequestData = { + sendMessageRequestBody: { + ...sendCarouselMessageRequest, + ...recipientChannelIdentities, + }, + }; + const expectedResponse: SendMessageResponse = { + accepted_time: new Date('2019-08-24T14:15:22Z'), + message_id: 'message_id', + }; + + test.each([ + ['contact ID', requestDataWithContactId, expectedResponse], + ['channel identities', requestDataWithChannelIdentity, expectedResponse], + // eslint-disable-next-line max-len + ])('should make a POST request to send a carousel message request from a conversation app to a recipient identified by its %s', + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async (_identification, requestData, expectedResponse) => { + // When + fixture.sendCarouselMessage.mockResolvedValue(expectedResponse); + messagesApi.sendCarouselMessage = fixture.sendCarouselMessage; + const response = await messagesApi.sendCarouselMessage(requestData); + + // Then + expect(response).toEqual(expectedResponse); + expect(fixture.sendCarouselMessage).toHaveBeenCalledWith(requestData); + }); + }); + + describe ('sendChoiceMessage', () => { + const sendChoiceMessageRequest: Omit, 'recipient'> = { + app_id: 'app_id', + message: { + ...messageBuilder.choice(choiceMessageItem), + }, + }; + const requestDataWithContactId: SendChoiceMessageRequestData = { + sendMessageRequestBody: { + ...sendChoiceMessageRequest, + ...recipientContactId, + }, + }; + const requestDataWithChannelIdentity: SendChoiceMessageRequestData = { + sendMessageRequestBody: { + ...sendChoiceMessageRequest, + ...recipientChannelIdentities, + }, + }; + const expectedResponse: SendMessageResponse = { + accepted_time: new Date('2019-08-24T14:15:22Z'), + message_id: 'message_id', + }; + + test.each([ + ['contact ID', requestDataWithContactId, expectedResponse], + ['channel identities', requestDataWithChannelIdentity, expectedResponse], + // eslint-disable-next-line max-len + ])('should make a POST request to send a choice message request from a conversation app to a recipient identified by its %s', + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async (_identification, requestData, expectedResponse) => { + // When + fixture.sendChoiceMessage.mockResolvedValue(expectedResponse); + messagesApi.sendChoiceMessage = fixture.sendChoiceMessage; + const response = await messagesApi.sendChoiceMessage(requestData); + + // Then + expect(response).toEqual(expectedResponse); + expect(fixture.sendChoiceMessage).toHaveBeenCalledWith(requestData); + }); + }); + + describe ('sendContactInfoMessage', () => { + const sendContactInfoMessageRequest: Omit, 'recipient'> = { + app_id: 'app_id', + message: { + ...messageBuilder.contactInfo(contactInfoMessageItem), + }, + }; + const requestDataWithContactId: SendContactInfoMessageRequestData = { + sendMessageRequestBody: { + ...sendContactInfoMessageRequest, + ...recipientContactId, + }, + }; + const requestDataWithChannelIdentity: SendContactInfoMessageRequestData = { + sendMessageRequestBody: { + ...sendContactInfoMessageRequest, + ...recipientChannelIdentities, + }, + }; + const expectedResponse: SendMessageResponse = { + accepted_time: new Date('2019-08-24T14:15:22Z'), + message_id: 'message_id', + }; + + test.each([ + ['contact ID', requestDataWithContactId, expectedResponse], + ['channel identities', requestDataWithChannelIdentity, expectedResponse], + // eslint-disable-next-line max-len + ])('should make a POST request to send a contact info message request from a conversation app to a recipient identified by its %s', + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async (_identification, requestData, expectedResponse) => { + // When + fixture.sendContactInfoMessage.mockResolvedValue(expectedResponse); + messagesApi.sendContactInfoMessage = fixture.sendContactInfoMessage; + const response = await messagesApi.sendContactInfoMessage(requestData); + + // Then + expect(response).toEqual(expectedResponse); + expect(fixture.sendContactInfoMessage).toHaveBeenCalledWith(requestData); + }); + }); + + describe ('sendListMessage', () => { + const sendListMessageRequest: Omit, 'recipient'> = { + app_id: 'app_id', + message: { + ...messageBuilder.list(listMessageItem), + }, + }; + const requestDataWithContactId: SendListMessageRequestData = { + sendMessageRequestBody: { + ...sendListMessageRequest, + ...recipientContactId, + }, + }; + const requestDataWithChannelIdentity: SendListMessageRequestData = { + sendMessageRequestBody: { + ...sendListMessageRequest, + ...recipientChannelIdentities, + }, + }; + const expectedResponse: SendMessageResponse = { + accepted_time: new Date('2019-08-24T14:15:22Z'), + message_id: 'message_id', + }; + + test.each([ + ['contact ID', requestDataWithContactId, expectedResponse], + ['channel identities', requestDataWithChannelIdentity, expectedResponse], + // eslint-disable-next-line max-len + ])('should make a POST request to send a list message request from a conversation app to a recipient identified by its %s', + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async (_identification, requestData, expectedResponse) => { + // When + fixture.sendListMessage.mockResolvedValue(expectedResponse); + messagesApi.sendListMessage = fixture.sendListMessage; + const response = await messagesApi.sendListMessage(requestData); + + // Then + expect(response).toEqual(expectedResponse); + expect(fixture.sendListMessage).toHaveBeenCalledWith(requestData); + }); + }); + + describe ('sendLocationMessage', () => { + const sendLocationMessageRequest: Omit, 'recipient'> = { + app_id: 'app_id', + message: { + ...messageBuilder.location(locationMessageItem), + }, + }; + const requestDataWithContactId: SendLocationMessageRequestData = { + sendMessageRequestBody: { + ...sendLocationMessageRequest, + ...recipientContactId, + }, + }; + const requestDataWithChannelIdentity: SendLocationMessageRequestData = { + sendMessageRequestBody: { + ...sendLocationMessageRequest, + ...recipientChannelIdentities, + }, + }; + const expectedResponse: SendMessageResponse = { + accepted_time: new Date('2019-08-24T14:15:22Z'), + message_id: 'message_id', + }; + + test.each([ + ['contact ID', requestDataWithContactId, expectedResponse], + ['channel identities', requestDataWithChannelIdentity, expectedResponse], + // eslint-disable-next-line max-len + ])('should make a POST request to send a location message request from a conversation app to a recipient identified by its %s', + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async (_identification, requestData, expectedResponse) => { + // When + fixture.sendLocationMessage.mockResolvedValue(expectedResponse); + messagesApi.sendLocationMessage = fixture.sendLocationMessage; + const response = await messagesApi.sendLocationMessage(requestData); + + // Then + expect(response).toEqual(expectedResponse); + expect(fixture.sendLocationMessage).toHaveBeenCalledWith(requestData); + }); + }); + + describe ('sendMediaMessage', () => { + const sendMediaMessageRequest: Omit, 'recipient'> = { + app_id: 'app_id', + message: { + ...messageBuilder.media(mediaMessageItem), + }, + }; + const requestDataWithContactId: SendMediaMessageRequestData = { + sendMessageRequestBody: { + ...sendMediaMessageRequest, + ...recipientContactId, + }, + }; + const requestDataWithChannelIdentity: SendMediaMessageRequestData = { + sendMessageRequestBody: { + ...sendMediaMessageRequest, + ...recipientChannelIdentities, + }, + }; + const expectedResponse: SendMessageResponse = { + accepted_time: new Date('2019-08-24T14:15:22Z'), + message_id: 'message_id', + }; + + test.each([ + ['contact ID', requestDataWithContactId, expectedResponse], + ['channel identities', requestDataWithChannelIdentity, expectedResponse], + // eslint-disable-next-line max-len + ])('should make a POST request to send a media message request from a conversation app to a recipient identified by its %s', + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async (_identification, requestData, expectedResponse) => { + // When + fixture.sendMediaMessage.mockResolvedValue(expectedResponse); + messagesApi.sendMediaMessage = fixture.sendMediaMessage; + const response = await messagesApi.sendMediaMessage(requestData); + + // Then + expect(response).toEqual(expectedResponse); + expect(fixture.sendMediaMessage).toHaveBeenCalledWith(requestData); + }); + }); + + describe ('sendTemplateMessage', () => { + const sendTemplateMessageRequest: Omit, 'recipient'> = { + app_id: 'app_id', + message: { + ...messageBuilder.template(templateMessageItem), + }, + }; + const requestDataWithContactId: SendTemplateMessageRequestData = { + sendMessageRequestBody: { + ...sendTemplateMessageRequest, + ...recipientContactId, + }, + }; + const requestDataWithChannelIdentity: SendTemplateMessageRequestData = { + sendMessageRequestBody: { + ...sendTemplateMessageRequest, + ...recipientChannelIdentities, + }, + }; + const expectedResponse: SendMessageResponse = { + accepted_time: new Date('2019-08-24T14:15:22Z'), + message_id: 'message_id', + }; + + test.each([ + ['contact ID', requestDataWithContactId, expectedResponse], + ['channel identities', requestDataWithChannelIdentity, expectedResponse], + // eslint-disable-next-line max-len + ])('should make a POST request to send a template message request from a conversation app to a recipient identified by its %s', + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async (_identification, requestData, expectedResponse) => { + // When + fixture.sendTemplateMessage.mockResolvedValue(expectedResponse); + messagesApi.sendTemplateMessage = fixture.sendTemplateMessage; + const response = await messagesApi.sendTemplateMessage(requestData); + + // Then + expect(response).toEqual(expectedResponse); + expect(fixture.sendTemplateMessage).toHaveBeenCalledWith(requestData); + }); + }); + + describe ('sendTextMessage', () => { + const sendTextMessageRequest: Omit, 'recipient'> = { + app_id: 'app_id', + message: { + ...messageBuilder.text(textMessageItem), + }, + }; + const requestDataWithContactId: SendTextMessageRequestData = { + sendMessageRequestBody: { + ...sendTextMessageRequest, + ...recipientContactId, + }, + }; + const requestDataWithChannelIdentity: SendTextMessageRequestData = { + sendMessageRequestBody: { + ...sendTextMessageRequest, + ...recipientChannelIdentities, + }, + }; + const expectedResponse: SendMessageResponse = { + accepted_time: new Date('2019-08-24T14:15:22Z'), + message_id: 'message_id', + }; + + test.each([ + ['contact ID', requestDataWithContactId, expectedResponse], + ['channel identities', requestDataWithChannelIdentity, expectedResponse], + // eslint-disable-next-line max-len + ])('should make a POST request to send a text message request from a conversation app to a recipient identified by its %s', + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async (_identification, requestData, expectedResponse) => { // When - fixture.send.mockResolvedValue(expectedResponse); - messagesApi.send = fixture.send; - const response = await messagesApi.send(requestData); + fixture.sendTextMessage.mockResolvedValue(expectedResponse); + messagesApi.sendTextMessage = fixture.sendTextMessage; + const response = await messagesApi.sendTextMessage(requestData); - // Then - expect(response).toEqual(expectedResponse); - expect(fixture.send).toHaveBeenCalledWith(requestData); - }); + // Then + expect(response).toEqual(expectedResponse); + expect(fixture.sendTextMessage).toHaveBeenCalledWith(requestData); + }); }); describe ('updateMessageMetadata', () => { diff --git a/packages/conversation/tests/rest/v1/mocks.ts b/packages/conversation/tests/rest/v1/mocks.ts new file mode 100644 index 00000000..9497adfc --- /dev/null +++ b/packages/conversation/tests/rest/v1/mocks.ts @@ -0,0 +1,26 @@ +import { ChannelRecipientIdentity } from '../../../src'; + +const channelIdentities: ChannelRecipientIdentity[] = [ + { + channel: 'SMS', + identity: 'phoneNumber', + }, + { + channel: 'MESSENGER', + identity: 'messengerId', + }, +]; + +export const recipientContactId = { + recipient: { + contact_id: 'contact_id', + }, +}; + +export const recipientChannelIdentities = { + recipient: { + identified_by: { + channel_identities: channelIdentities, + }, + }, +};