diff --git a/examples/simple-examples/.env.template b/examples/simple-examples/.env.template index c523358e..8c769e24 100644 --- a/examples/simple-examples/.env.template +++ b/examples/simple-examples/.env.template @@ -19,3 +19,11 @@ VERIFICATION_ID=verification-id to fill with the verification started with the V VERIFICATION_IDENTITY=verification-identity to fill with the identity of the user VERIFICATION_REFERENCE=verification-reference to add when starting a verification or getting its status VOICE_CALLBACK_URL=URL found in the Voice dashboard to handle webhooks +CONVERSATION_APP_ID=app_id to fill with one of the conversation app created with the Conversation API or in the Dashboard +CONVERSATION_CONTACT_ID=contact_id to fill with one off the contacts +MESSENGER_TOKEN=static token to define credentials for a Messenger application +MESSENGER_USER_ID=Id of a user using messenger (can be found on a desktop by selecting a user: the user id will be in the URL) +CONVERSATION_ID=conversation_id to fill with one of the conversation create with the Conversation API +MESSAGE_ID=message_id to fill from a sent or injected message +WEBHOOK_ID=webhook_id to fill from a webhook creation with the Conversation API or the Dashboard +WEBHOOK_TARGET=URL of the webhook diff --git a/examples/simple-examples/package.json b/examples/simple-examples/package.json index 20736d8d..1cd6283a 100644 --- a/examples/simple-examples/package.json +++ b/examples/simple-examples/package.json @@ -8,6 +8,37 @@ "build": "yarn run clean && yarn run compile", "clean": "rimraf dist tsconfig.tsbuildinfo", "compile": "tsc --build --verbose", + "conversation:app:create": "ts-node src/conversation/app/create.ts", + "conversation:app:get": "ts-node src/conversation/app/get.ts", + "conversation:app:list": "ts-node src/conversation/app/list.ts", + "conversation:app:update": "ts-node src/conversation/app/update.ts pretty", + "conversation:app:delete": "ts-node src/conversation/app/delete.ts", + "conversation:contact:create": "ts-node src/conversation/contact/create.ts", + "conversation:contact:get": "ts-node src/conversation/contact/get.ts", + "conversation:contact:list": "ts-node src/conversation/contact/list.ts", + "conversation:contact:update": "ts-node src/conversation/contact/update.ts", + "conversation:contact:merge": "ts-node src/conversation/contact/merge.ts", + "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:get": "ts-node src/conversation/messages/get.ts", + "conversation:messages:list": "ts-node src/conversation/messages/list.ts", + "conversation:messages:delete": "ts-node src/conversation/messages/delete.ts", + "conversation:conversation:create": "ts-node src/conversation/conversation/create.ts", + "conversation:conversation:get": "ts-node src/conversation/conversation/get.ts", + "conversation:conversation:list": "ts-node src/conversation/conversation/list.ts", + "conversation:conversation:injectMessage": "ts-node src/conversation/conversation/injectMessage.ts", + "conversation:conversation:update": "ts-node src/conversation/conversation/update.ts", + "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:transcoding:transcode": "ts-node src/conversation/transcoding/transcode.ts", + "conversation:capability:lookup": "ts-node src/conversation/capability/lookup.ts", + "conversation:webhooks:create": "ts-node src/conversation/webhooks/create.ts", + "conversation:webhooks:get": "ts-node src/conversation/webhooks/get.ts", + "conversation:webhooks:list": "ts-node src/conversation/webhooks/list.ts", + "conversation:webhooks:update": "ts-node src/conversation/webhooks/update.ts", + "conversation:webhooks:delete": "ts-node src/conversation/webhooks/delete.ts", "numbers:regions:list": "ts-node src/numbers/regions/list.ts", "numbers:available:list": "ts-node src/numbers/available/list.ts", "numbers:available:checkAvailability": "ts-node src/numbers/available/checkAvailability.ts", diff --git a/examples/simple-examples/src/config.ts b/examples/simple-examples/src/config.ts index 49e57d4a..012b697d 100644 --- a/examples/simple-examples/src/config.ts +++ b/examples/simple-examples/src/config.ts @@ -101,6 +101,38 @@ export const getVoiceCallBackUrl = (): string => { return readVariable('VOICE_CALLBACK_URL'); }; +export const getAppIdFromConfig = () => { + return readVariable('CONVERSATION_APP_ID'); +}; + +export const getContactIdFromConfig = () => { + return readVariable('CONVERSATION_CONTACT_ID'); +}; + +export const getMessengerTokenFormConfig = () => { + return readVariable('MESSENGER_TOKEN'); +}; + +export const getMessengerUserIdFromConfig = () => { + return readVariable('MESSENGER_USER_ID'); +}; + +export const getConversationIdFromConfig = () => { + return readVariable('CONVERSATION_ID'); +}; + +export const getMessageIdFromConfig = () => { + return readVariable('MESSAGE_ID'); +}; + +export const getWebhookIdFromConfig = () => { + return readVariable('WEBHOOK_ID'); +}; + +export const getWebhookTargetFromConfig = () => { + return readVariable('WEBHOOK_TARGET'); +}; + const readVariable = ( name: string): string => { const value = process.env[name]; if (!value) { diff --git a/examples/simple-examples/src/conversation/app/create.ts b/examples/simple-examples/src/conversation/app/create.ts new file mode 100644 index 00000000..fbf487b8 --- /dev/null +++ b/examples/simple-examples/src/conversation/app/create.ts @@ -0,0 +1,41 @@ +import { CreateAppRequestData } from '@sinch/sdk-core'; +import { getMessengerTokenFormConfig, getPrintFormat, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('*****************'); + console.log('* App_CreateApp *'); + console.log('*****************'); + + const messengerToken = getMessengerTokenFormConfig(); + + const requestData: CreateAppRequestData = { + appCreateRequestBody: { + display_name: 'New app created with the Node.js SDK', + channel_credentials: [ + { + channel: 'MESSENGER', + static_token: { + token: messengerToken, + }, + }, + ], + conversation_metadata_report_view: 'FULL', + retention_policy: { + retention_type: 'CONVERSATION_EXPIRE_POLICY', + ttl_days: 60, + }, + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.app.create(requestData); + + const printFormat = getPrintFormat(process.argv); + + if (printFormat === 'pretty') { + console.log(`New app created with the id '${response.id}'`); + } else { + printFullResponse(response); + } + console.log(`You may want to update your .env file with the following value: CONVERSATION_APP_ID=${response.id}`); +})(); diff --git a/examples/simple-examples/src/conversation/app/delete.ts b/examples/simple-examples/src/conversation/app/delete.ts new file mode 100644 index 00000000..15414354 --- /dev/null +++ b/examples/simple-examples/src/conversation/app/delete.ts @@ -0,0 +1,20 @@ +import { DeleteAppRequestData } from '@sinch/sdk-core'; +import { getAppIdFromConfig, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('*****************'); + console.log('* App_DeleteApp *'); + console.log('*****************'); + + const appId = getAppIdFromConfig(); + + const requestData: DeleteAppRequestData = { + app_id: appId, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.app.delete(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/app/get.ts b/examples/simple-examples/src/conversation/app/get.ts new file mode 100644 index 00000000..8667fe0a --- /dev/null +++ b/examples/simple-examples/src/conversation/app/get.ts @@ -0,0 +1,26 @@ +import { GetAppRequestData } from '@sinch/sdk-core'; +import { getAppIdFromConfig, getPrintFormat, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('**************'); + console.log('* App_GetApp *'); + console.log('**************'); + + const appId = getAppIdFromConfig(); + + const requestData: GetAppRequestData = { + app_id: appId, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.app.get(requestData); + + const printFormat = getPrintFormat(process.argv); + + if (printFormat === 'pretty') { + console.log(`The app with the id '${response.id}' is named '${response.display_name}'`); + } else { + printFullResponse(response); + } + +})(); diff --git a/examples/simple-examples/src/conversation/app/list.ts b/examples/simple-examples/src/conversation/app/list.ts new file mode 100644 index 00000000..c51d83a9 --- /dev/null +++ b/examples/simple-examples/src/conversation/app/list.ts @@ -0,0 +1,24 @@ +import { ListAppsRequestData } from '@sinch/sdk-core'; +import { getPrintFormat, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('****************'); + console.log('* App_ListApps *'); + console.log('****************'); + + const requestData: ListAppsRequestData= {}; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.app.list(requestData); + + const printFormat = getPrintFormat(process.argv); + + if (printFormat === 'pretty') { + console.log(response.apps + ? response.apps.map((app) => `'${app.id}': ${app.display_name}`).join('\n') + : 'No Conversation Applications were found'); + } else { + printFullResponse(response); + } + +})(); diff --git a/examples/simple-examples/src/conversation/app/update.ts b/examples/simple-examples/src/conversation/app/update.ts new file mode 100644 index 00000000..49a1d27d --- /dev/null +++ b/examples/simple-examples/src/conversation/app/update.ts @@ -0,0 +1,47 @@ +import { UpdateAppRequestData } from '@sinch/sdk-core'; +import { + getAppIdFromConfig, getMessengerTokenFormConfig, + getPrintFormat, + initClient, + printFullResponse, +} from '../../config'; + +(async () => { + console.log('*****************'); + console.log('* App_UpdateApp *'); + console.log('*****************'); + + const appId = getAppIdFromConfig(); + + const requestData: UpdateAppRequestData = { + app_id: appId, + update_mask: ['display_name', 'conversation_metadata_report_view'], + appUpdateRequestBody: { + display_name: 'Updated name by the Node.js SDK', + conversation_metadata_report_view: 'NONE', + channel_credentials: [ + { + channel: 'MESSENGER', + static_token: { + token: 'new token (invalid) - should not be updated thanks to the mask', + }, + }, + ], + + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.app.update(requestData); + + const printFormat = getPrintFormat(process.argv); + + if (printFormat === 'pretty') { + console.log(`App updated! New name: '${response.display_name}'.`); + const token = getMessengerTokenFormConfig(); + console.log(`Verifying the token (it should be unchanged):\nOLD: '${token}'\nNEW: '${response.channel_credentials?.[0].static_token?.token}'`); + } else { + printFullResponse(response); + } + +})(); diff --git a/examples/simple-examples/src/conversation/capability/lookup.ts b/examples/simple-examples/src/conversation/capability/lookup.ts new file mode 100644 index 00000000..ee1b5145 --- /dev/null +++ b/examples/simple-examples/src/conversation/capability/lookup.ts @@ -0,0 +1,27 @@ +import { LookupCapabilityRequestData } from '@sinch/sdk-core'; +import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('******************************'); + console.log('* Capability_QueryCapability *'); + console.log('******************************'); + + const appId = getAppIdFromConfig(); + const contactId = getContactIdFromConfig(); + + const requestData: LookupCapabilityRequestData = { + lookupCapabilityRequestBody: { + app_id: appId, + recipient: { + contact_id: contactId, + }, + request_id: 'myPersonalId_' + new Date().getTime(), + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.capability.lookup(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/contact/create.ts b/examples/simple-examples/src/conversation/contact/create.ts new file mode 100644 index 00000000..c54566bf --- /dev/null +++ b/examples/simple-examples/src/conversation/contact/create.ts @@ -0,0 +1,50 @@ +import { CreateContactRequestData } from '@sinch/sdk-core'; +import { + getAppIdFromConfig, + getMessengerUserIdFromConfig, + getPhoneNumberFromConfig, + getPrintFormat, + initClient, + printFullResponse, +} from '../../config'; + +(async () => { + console.log('*************************'); + console.log('* Contact_CreateContact *'); + console.log('*************************'); + + const phoneNumber = getPhoneNumberFromConfig(); + const messengerUserId = getMessengerUserIdFromConfig(); + const appId = getAppIdFromConfig(); + + const requestData: CreateContactRequestData = { + contactCreateRequestBody: { + display_name: 'New contact created with the Node.js SDK', + channel_identities: [ + { + identity: messengerUserId, + channel: 'MESSENGER', + app_id:appId, + }, + { + identity: phoneNumber, + channel: 'WHATSAPP', + }, + ], + channel_priority: ['WHATSAPP'], + language: 'EN_US', + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.contact.create(requestData); + + const printFormat = getPrintFormat(process.argv); + + if (printFormat === 'pretty') { + console.log(`New contact created with the id '${response.id}'`); + } else { + printFullResponse(response); + } + +})(); diff --git a/examples/simple-examples/src/conversation/contact/delete.ts b/examples/simple-examples/src/conversation/contact/delete.ts new file mode 100644 index 00000000..6fbad08a --- /dev/null +++ b/examples/simple-examples/src/conversation/contact/delete.ts @@ -0,0 +1,20 @@ +import { DeleteContactRequestData } from '@sinch/sdk-core'; +import { getContactIdFromConfig, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('*************************'); + console.log('* Contact_DeleteContact *'); + console.log('*************************'); + + const contactId = getContactIdFromConfig(); + + const requestData: DeleteContactRequestData = { + contact_id: contactId, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.contact.delete(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/contact/get.ts b/examples/simple-examples/src/conversation/contact/get.ts new file mode 100644 index 00000000..4978c478 --- /dev/null +++ b/examples/simple-examples/src/conversation/contact/get.ts @@ -0,0 +1,26 @@ +import { GetContactRequestData } from '@sinch/sdk-core'; +import { getContactIdFromConfig, getPrintFormat, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('**********************'); + console.log('* Contact_GetContact *'); + console.log('**********************'); + + const contactId = getContactIdFromConfig(); + + const requestData: GetContactRequestData = { + contact_id: contactId, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.contact.get(requestData); + + const printFormat = getPrintFormat(process.argv); + + if (printFormat === 'pretty') { + console.log(`The contact with the id '${response.id}' is named '${response.display_name}'`); + } else { + printFullResponse(response); + } + +})(); diff --git a/examples/simple-examples/src/conversation/contact/getChannelProfile.ts b/examples/simple-examples/src/conversation/contact/getChannelProfile.ts new file mode 100644 index 00000000..4febbca6 --- /dev/null +++ b/examples/simple-examples/src/conversation/contact/getChannelProfile.ts @@ -0,0 +1,39 @@ +import { GetChannelProfileRequestData } from '@sinch/sdk-core'; +import { + getAppIdFromConfig, + getMessengerUserIdFromConfig, + initClient, + printFullResponse, +} from '../../config'; + +(async () => { + console.log('*****************************'); + console.log('* Contact_GetChannelProfile *'); + console.log('*****************************'); + + const appId = getAppIdFromConfig(); + const messengerUserId = getMessengerUserIdFromConfig(); + + const requestData: GetChannelProfileRequestData = { + getChannelProfileRequestBody: { + app_id: appId, + channel: 'MESSENGER', + recipient: { + identified_by: { + channel_identities: [ + { + identity: messengerUserId, + channel: 'MESSENGER', + }, + ], + }, + }, + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.contact.getChannelProfile(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/contact/list.ts b/examples/simple-examples/src/conversation/contact/list.ts new file mode 100644 index 00000000..3e83a3e4 --- /dev/null +++ b/examples/simple-examples/src/conversation/contact/list.ts @@ -0,0 +1,66 @@ +import { Contact, ListContactsRequestData, PageResult } from '@sinch/sdk-core'; +import { getPrintFormat, initClient, printFullResponse } from '../../config'; + +const populateContactsList = ( + contactPage: PageResult, + contactList: Contact[], + contactDetailsList: string[], +) => { + contactPage.data?.map((contact: Contact) => { + contactList.push(contact); + contactDetailsList.push(`${contact.id} - ${contact.display_name}`); + }); +}; + +(async () => { + console.log('************************'); + console.log('* Contact_ListContacts *'); + console.log('************************'); + + const requestData: ListContactsRequestData = { + page_size: 2, + }; + + const sinchClient = initClient(); + + // ---------------------------------------------- + // Method 1: Fetch the data page by page manually + // ---------------------------------------------- + let response = await sinchClient.conversation.contact.list(requestData); + + const contactList: Contact[] = []; + const contactDetailsList: string[] = []; + + // Loop on all the pages to get all the active numbers + let reachedEndOfPages = false; + while (!reachedEndOfPages) { + populateContactsList(response, contactList, contactDetailsList); + if (response.hasNextPage) { + response = await response.nextPage(); + } else { + reachedEndOfPages = true; + } + } + + const printFormat = getPrintFormat(process.argv); + + if (printFormat === 'pretty') { + console.log(contactDetailsList.length > 0 + ? 'List of contacts:\n' + contactDetailsList.join('\n') + : 'Sorry, no contacts were found.'); + } else { + printFullResponse(contactList); + } + + // --------------------------------------------------------------------- + // Method 2: Use the iterator and fetch data on more pages automatically + // --------------------------------------------------------------------- + for await (const contact of sinchClient.conversation.contact.list(requestData)) { + if (printFormat === 'pretty') { + console.log(`${contact.id} - ${contact.display_name}`); + } else { + console.log(contact); + } + } + +})(); diff --git a/examples/simple-examples/src/conversation/contact/merge.ts b/examples/simple-examples/src/conversation/contact/merge.ts new file mode 100644 index 00000000..9035853c --- /dev/null +++ b/examples/simple-examples/src/conversation/contact/merge.ts @@ -0,0 +1,74 @@ +import { CreateContactRequestData, MergeContactRequestData } from '@sinch/sdk-core'; +import { + getPhoneNumberFromConfig, + getPrintFormat, + initClient, + printFullResponse, +} from '../../config'; + + +(async () => { + console.log('************************'); + console.log('* Contact_MergeContact *'); + console.log('************************'); + + const phoneNumber = getPhoneNumberFromConfig(); + + const sourceContactRequestData: CreateContactRequestData = { + contactCreateRequestBody: { + channel_identities: [ + { + channel: 'SMS', + identity: phoneNumber, + }, + ], + language: 'FR', + email: 'source@mail.com', + display_name: 'Source Contact', + metadata: 'Some metadata belonging to the source contact', + }, + }; + + const destinationContactRequestData: CreateContactRequestData = { + contactCreateRequestBody: { + channel_identities: [ + { + channel: 'MMS', + identity: phoneNumber, + }, + ], + language: 'EN_US', + channel_priority: ['MMS'], + display_name: 'Destination Contact', + }, + }; + + const sinchClient = initClient(); + const sourceContact = await sinchClient.conversation.contact.create(sourceContactRequestData); + const destinationContact = await sinchClient.conversation.contact.create(destinationContactRequestData); + + if (sourceContact.id && destinationContact.id) { + const requestData: MergeContactRequestData = { + destination_id: destinationContact.id, + mergeContactRequestBody: { + source_id: sourceContact.id, + strategy: 'MERGE', + }, + }; + + const response = await sinchClient.conversation.contact.mergeContact(requestData); + + const printFormat = getPrintFormat(process.argv); + if (printFormat === 'pretty') { + console.log(`The merged contact has the Id '${response.id}' (should be the same as the destination contact: '${destinationContact.id}')`); + console.log(`The merged contact should still have the same '${destinationContact.language}' language from the destination contact: ${response.language}`); + console.log(`The merged contact has now the email: ${response.email}`); + console.log(`The merged contact has ${response.channel_identities?.length} channel identities: ${response.channel_identities?.map((channelIdentity) => channelIdentity.channel).join(', ')}`); + }else { + printFullResponse(response); + } + } else { + console.log(`An error occurred when creating the contacts`); + } + +})(); diff --git a/examples/simple-examples/src/conversation/contact/update.ts b/examples/simple-examples/src/conversation/contact/update.ts new file mode 100644 index 00000000..f5c763ed --- /dev/null +++ b/examples/simple-examples/src/conversation/contact/update.ts @@ -0,0 +1,33 @@ +import { getContactIdFromConfig, getPrintFormat, initClient, printFullResponse } from '../../config'; +import { UpdateContactRequestData } from '@sinch/sdk-core'; + +(async () => { + console.log('*************************'); + console.log('* Contact_UpdateContact *'); + console.log('*************************'); + + const contactId = getContactIdFromConfig(); + + const requestData: UpdateContactRequestData = { + contact_id: contactId, + update_mask:['channel_priority'], + updateContactRequestBody: { + display_name: 'Updated name with the Node.js SDK', + language: 'FR', + channel_priority: ['MESSENGER'], + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.contact.update(requestData); + + const printFormat = getPrintFormat(process.argv); + + if (printFormat === 'pretty') { + console.log(`Contact updated! New name: '${response.display_name}`); + console.log(`Verifying the language (it should be unchanged):\nOLD: 'EN-US'\nNEW: '${response.language}'`); + } else { + printFullResponse(response); + } + +})(); diff --git a/examples/simple-examples/src/conversation/conversation/create.ts b/examples/simple-examples/src/conversation/conversation/create.ts new file mode 100644 index 00000000..4e1c993c --- /dev/null +++ b/examples/simple-examples/src/conversation/conversation/create.ts @@ -0,0 +1,45 @@ +import { CreateConversationRequestData } from '@sinch/sdk-core'; +import { + getAppIdFromConfig, + getContactIdFromConfig, + getPrintFormat, + initClient, + printFullResponse, +} from '../../config'; + +(async () => { + console.log('***********************************'); + console.log('* Conversation_CreateConversation *'); + console.log('***********************************'); + + const appId = getAppIdFromConfig(); + const contactId = getContactIdFromConfig(); + + const requestData: CreateConversationRequestData = { + createConversationRequestBody: { + app_id: appId, + contact_id: contactId, + active: true, + active_channel: 'MESSENGER', + metadata: 'somme metadata', + metadata_json: { + date: new Date(), + string: 'metadata', + number: 0, + boolean: true, + }, + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.conversation.create(requestData); + + const printFormat = getPrintFormat(process.argv); + + if (printFormat === 'pretty') { + console.log(`New contact created with the id '${response.id}'`); + } else { + printFullResponse(response); + } + +})(); diff --git a/examples/simple-examples/src/conversation/conversation/delete.ts b/examples/simple-examples/src/conversation/conversation/delete.ts new file mode 100644 index 00000000..bea76e55 --- /dev/null +++ b/examples/simple-examples/src/conversation/conversation/delete.ts @@ -0,0 +1,21 @@ +import { DeleteConversationRequestData } from '@sinch/sdk-core'; +import { getConversationIdFromConfig, initClient, printFullResponse } from '../../config'; + + +(async () => { + console.log('***********************************'); + console.log('* Conversation_DeleteConversation *'); + console.log('***********************************'); + + const conversationId = getConversationIdFromConfig(); + + const requestData: DeleteConversationRequestData = { + conversation_id: conversationId, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.conversation.delete(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/conversation/get.ts b/examples/simple-examples/src/conversation/conversation/get.ts new file mode 100644 index 00000000..7bcd5eec --- /dev/null +++ b/examples/simple-examples/src/conversation/conversation/get.ts @@ -0,0 +1,31 @@ +import { GetConversationRequestData } from '@sinch/sdk-core'; +import { + getConversationIdFromConfig, + getPrintFormat, + initClient, + printFullResponse, +} from '../../config'; + +(async () => { + console.log('********************************'); + console.log('* Conversation_GetConversation *'); + console.log('********************************'); + + const conversationId = getConversationIdFromConfig(); + + const requestData: GetConversationRequestData = { + conversation_id: conversationId, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.conversation.get(requestData); + + const printFormat = getPrintFormat(process.argv); + + if (printFormat === 'pretty') { + console.log(`The conversation with the id '${response.id}' has the last message received at '${response.last_received}'`); + } else { + printFullResponse(response); + } + +})(); diff --git a/examples/simple-examples/src/conversation/conversation/injectMessage.ts b/examples/simple-examples/src/conversation/conversation/injectMessage.ts new file mode 100644 index 00000000..6f71aea3 --- /dev/null +++ b/examples/simple-examples/src/conversation/conversation/injectMessage.ts @@ -0,0 +1,47 @@ +import { InjectMessageRequestData } from '@sinch/sdk-core'; +import { + getAppIdFromConfig, getContactIdFromConfig, + getConversationIdFromConfig, + getMessengerUserIdFromConfig, + initClient, + printFullResponse, +} from '../../config'; + + +(async () => { + console.log('***********************************'); + console.log('* Conversation_InjectMessage *'); + console.log('***********************************'); + + const conversationId = getConversationIdFromConfig(); + const messengerUserId = getMessengerUserIdFromConfig(); + const appId = getAppIdFromConfig(); + const contactId = getContactIdFromConfig(); + + const requestData: InjectMessageRequestData= { + conversation_id: conversationId, + injectMessageRequestBody: { + app_message: { + message: { + text_message: { + text: 'test', + }, + }, + }, + direction: 'TO_CONTACT', + channel_identity: { + channel: 'MESSENGER', + identity: messengerUserId, + app_id: appId, + }, + accept_time: new Date(), + contact_id: contactId, + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.conversation.injectMessage(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/conversation/list.ts b/examples/simple-examples/src/conversation/conversation/list.ts new file mode 100644 index 00000000..5aefa536 --- /dev/null +++ b/examples/simple-examples/src/conversation/conversation/list.ts @@ -0,0 +1,69 @@ +import { Conversation, ListConversationsRequestData, PageResult } from '@sinch/sdk-core'; +import { getAppIdFromConfig, getPrintFormat, initClient, printFullResponse } from '../../config'; + +const populateConversationsList = ( + conversationPage: PageResult, + conversationList: Conversation[], + conversationDetailsList: string[], +) => { + conversationPage.data.map((conversation: Conversation) => { + conversationList.push(conversation); + conversationDetailsList.push(`${conversation.id} - ${conversation.active_channel}`); + }); +}; + +(async () => { + console.log('**********************************'); + console.log('* Conversation_ListConversations *'); + console.log('**********************************'); + + const appId = getAppIdFromConfig(); + + const requestData: ListConversationsRequestData = { + only_active: false, + app_id: appId, + }; + + const sinchClient = initClient(); + + // ---------------------------------------------- + // Method 1: Fetch the data page by page manually + // ---------------------------------------------- + let response = await sinchClient.conversation.conversation.list(requestData); + + const conversationList: Conversation[] = []; + const conversationDetailsList: string[] = []; + + // Loop on all the pages to get all the active numbers + let reachedEndOfPages = false; + while (!reachedEndOfPages) { + populateConversationsList(response, conversationList, conversationDetailsList); + if (response.hasNextPage) { + response = await response.nextPage(); + } else { + reachedEndOfPages = true; + } + } + + const printFormat = getPrintFormat(process.argv); + + if (printFormat === 'pretty') { + console.log(conversationDetailsList.length > 0 + ? 'List of conversations:\n' + conversationDetailsList.join('\n') + : 'Sorry, no conversations were found.'); + } else { + printFullResponse(conversationList); + } + + // --------------------------------------------------------------------- + // Method 2: Use the iterator and fetch data on more pages automatically + // --------------------------------------------------------------------- + for await (const conversation of sinchClient.conversation.conversation.list(requestData)) { + if (printFormat === 'pretty') { + console.log(`${conversation.id} - ${conversation.active_channel}`); + } else { + console.log(conversation); + } + } + +})(); diff --git a/examples/simple-examples/src/conversation/conversation/stop.ts b/examples/simple-examples/src/conversation/conversation/stop.ts new file mode 100644 index 00000000..606c56c1 --- /dev/null +++ b/examples/simple-examples/src/conversation/conversation/stop.ts @@ -0,0 +1,21 @@ +import { StopActiveConversationRequestData } from '@sinch/sdk-core'; +import { getConversationIdFromConfig, initClient, printFullResponse } from '../../config'; + + +(async () => { + console.log('***************************************'); + console.log('* Conversation_StopActiveConversation *'); + console.log('***************************************'); + + const conversationId = getConversationIdFromConfig(); + + const requestData: StopActiveConversationRequestData = { + conversation_id: conversationId, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.conversation.stopActive(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/conversation/update.ts b/examples/simple-examples/src/conversation/conversation/update.ts new file mode 100644 index 00000000..81d12b51 --- /dev/null +++ b/examples/simple-examples/src/conversation/conversation/update.ts @@ -0,0 +1,37 @@ +import { + getConversationIdFromConfig, + getPrintFormat, + initClient, + printFullResponse, +} from '../../config'; +import { UpdateConversationRequestData } from '@sinch/sdk-core'; + +(async () => { + console.log('***********************************'); + console.log('* Conversation_UpdateConversation *'); + console.log('***********************************'); + + const conversationId = getConversationIdFromConfig(); + + const requestData: UpdateConversationRequestData = { + conversation_id: conversationId, + update_mask: ['metadata'], + updateConversationRequestBody: { + metadata: 'Updates metadata', + active_channel: 'KAKAOTALK', + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.conversation.update(requestData); + + const printFormat = getPrintFormat(process.argv); + + if (printFormat === 'pretty') { + console.log(`Conversation updated! New metadata: '${response.metadata}`); + console.log(`Verifying the active channel (it should be unchanged):\nOLD: 'MESSENGER'\nNEW: '${response.active_channel}'`); + } else { + printFullResponse(response); + } + +})(); diff --git a/examples/simple-examples/src/conversation/events/send.ts b/examples/simple-examples/src/conversation/events/send.ts new file mode 100644 index 00000000..6aed9db1 --- /dev/null +++ b/examples/simple-examples/src/conversation/events/send.ts @@ -0,0 +1,33 @@ +import { SendEventRequestData } 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: SendEventRequestData = { + 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.send(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/messages/delete.ts b/examples/simple-examples/src/conversation/messages/delete.ts new file mode 100644 index 00000000..e2f0fb8d --- /dev/null +++ b/examples/simple-examples/src/conversation/messages/delete.ts @@ -0,0 +1,21 @@ +import { DeleteMessageRequestData } from '@sinch/sdk-core'; +import { getMessageIdFromConfig, initClient, printFullResponse } from '../../config'; + + +(async () => { + console.log('**************************'); + console.log('* Messages_DeleteMessage *'); + console.log('**************************'); + + const messageId = getMessageIdFromConfig(); + + const requestData: DeleteMessageRequestData = { + message_id: messageId, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.messages.delete(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/messages/get.ts b/examples/simple-examples/src/conversation/messages/get.ts new file mode 100644 index 00000000..ddbbad18 --- /dev/null +++ b/examples/simple-examples/src/conversation/messages/get.ts @@ -0,0 +1,20 @@ +import { GetMessageRequestData } from '@sinch/sdk-core'; +import { getMessageIdFromConfig, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('***********************'); + console.log('* Messages_GetMessage *'); + console.log('***********************'); + + const messageId = getMessageIdFromConfig(); + + const requestData: GetMessageRequestData = { + message_id: messageId, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.messages.get(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/messages/list.ts b/examples/simple-examples/src/conversation/messages/list.ts new file mode 100644 index 00000000..b6faf157 --- /dev/null +++ b/examples/simple-examples/src/conversation/messages/list.ts @@ -0,0 +1,79 @@ +import { ConversationMessage, ListMessagesRequestData, PageResult } from '@sinch/sdk-core'; +import { + getAppIdFromConfig, + getContactIdFromConfig, getConversationIdFromConfig, + getPrintFormat, + initClient, + printFullResponse, +} from '../../config'; + +const populateMessagesList = ( + conversationPage: PageResult, + conversationList: ConversationMessage[], + conversationDetailsList: string[], +) => { + conversationPage.data.map((message: ConversationMessage) => { + conversationList.push(message); + conversationDetailsList.push(`${message.id} - ${message.accept_time}`); + }); +}; + +(async () => { + console.log('*************************'); + console.log('* Messages_ListMessages *'); + console.log('*************************'); + + const appId = getAppIdFromConfig(); + const contactId = getContactIdFromConfig(); + const conversationId = getConversationIdFromConfig(); + + const requestData: ListMessagesRequestData = { + app_id: appId, + contact_id: contactId, + conversation_id: conversationId, + channel: 'MESSENGER', + }; + + const sinchClient = initClient(); + + // ---------------------------------------------- + // Method 1: Fetch the data page by page manually + // ---------------------------------------------- + let response = await sinchClient.conversation.messages.list(requestData); + + const messageList: ConversationMessage[] = []; + const messagesDetailsList: string[] = []; + + // Loop on all the pages to get all the active numbers + let reachedEndOfPages = false; + while (!reachedEndOfPages) { + populateMessagesList(response, messageList, messagesDetailsList); + if (response.hasNextPage) { + response = await response.nextPage(); + } else { + reachedEndOfPages = true; + } + } + + const printFormat = getPrintFormat(process.argv); + + if (printFormat === 'pretty') { + console.log(messagesDetailsList.length > 0 + ? 'List of messages:\n' + messagesDetailsList.join('\n') + : 'Sorry, no messages were found.'); + } else { + printFullResponse(messageList); + } + + // --------------------------------------------------------------------- + // Method 2: Use the iterator and fetch data on more pages automatically + // --------------------------------------------------------------------- + for await (const message of sinchClient.conversation.messages.list(requestData)) { + if (printFormat === 'pretty') { + console.log(`${message.id} - ${message.accept_time}`); + } else { + console.log(message); + } + } + +})(); diff --git a/examples/simple-examples/src/conversation/messages/send.ts b/examples/simple-examples/src/conversation/messages/send.ts new file mode 100644 index 00000000..6f4468c9 --- /dev/null +++ b/examples/simple-examples/src/conversation/messages/send.ts @@ -0,0 +1,35 @@ +import { SendMessageRequestData } from '@sinch/sdk-core'; +import { getAppIdFromConfig, getContactIdFromConfig, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('************************'); + console.log('* Messages_SendMessage *'); + console.log('************************'); + + const appId = getAppIdFromConfig(); + const contactId = getContactIdFromConfig(); + + const requestData: SendMessageRequestData = { + sendMessageRequestBody: { + app_id: appId, + message: { + text_message: { + text: 'Text message from Sinch', + }, + }, + recipient: { + contact_id: contactId, + }, + correlation_id: 'correlator', + queue: 'HIGH_PRIORITY', + processing_strategy: 'DEFAULT', + channel_priority_order: ['MESSENGER'], + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.messages.send(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/transcoding/transcode.ts b/examples/simple-examples/src/conversation/transcoding/transcode.ts new file mode 100644 index 00000000..b2f3b477 --- /dev/null +++ b/examples/simple-examples/src/conversation/transcoding/transcode.ts @@ -0,0 +1,50 @@ +import { TranscodeMessageRequestData } from '@sinch/sdk-core'; +import { getAppIdFromConfig, getPrintFormat, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('********************************'); + console.log('* Transcoding_TranscodeMessage *'); + console.log('********************************'); + + const appId = getAppIdFromConfig(); + + const requestData: TranscodeMessageRequestData = { + transcodeMessageRequestBody: { + app_id: appId, + app_message: { + location_message: { + title: 'Phare d\'Eckmühl', + label: 'Pointe de Penmarch', + coordinates: { + latitude: 47.7981899, + longitude: -4.3727685, + }, + }, + }, + channels: [ + 'MESSENGER', + ], + from: 'from', + to: 'to', + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.transcoding.transcodeMessage(requestData); + + const printFormat = getPrintFormat(process.argv); + + if (printFormat === 'pretty') { + if (response.transcoded_message) { + console.log(`Transcoded messages:\n - ${Object.keys(response.transcoded_message) + .map((key: string) => { + const transcodedMessage = JSON.parse(response.transcoded_message![key]); + return key + ': ' + JSON.stringify(transcodedMessage.message); + })}`); + } else { + console.log('No transcoded messages returned.'); + } + } else { + printFullResponse(response); + } +})(); diff --git a/examples/simple-examples/src/conversation/webhooks/create.ts b/examples/simple-examples/src/conversation/webhooks/create.ts new file mode 100644 index 00000000..b5789d10 --- /dev/null +++ b/examples/simple-examples/src/conversation/webhooks/create.ts @@ -0,0 +1,46 @@ +import { CreateWebhookRequestData } from '@sinch/sdk-core'; +import { + getAppIdFromConfig, + getPrintFormat, getWebhookTargetFromConfig, + initClient, + printFullResponse, +} from '../../config'; + +(async () => { + console.log('**************************'); + console.log('* Webhooks_CreateWebhook *'); + console.log('**************************'); + + const appId = getAppIdFromConfig(); + const webhookTarget = getWebhookTargetFromConfig(); + + const requestData: CreateWebhookRequestData = { + webhookCreateRequestBody: { + app_id: appId, + target: webhookTarget, + target_type: 'HTTP', + triggers: [ + 'MESSAGE_DELIVERY', + 'MESSAGE_INBOUND', + 'CAPABILITY', + 'CONTACT_CREATE', + 'CONTACT_UPDATE', + 'CONTACT_DELETE', + 'CONTACT_MERGE', + ], + secret: 'A secret', + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.webhooks.create(requestData); + + const printFormat = getPrintFormat(process.argv); + + if (printFormat === 'pretty') { + console.log(`New webhook created with the id '${response.id}'`); + } else { + printFullResponse(response); + } + +})(); diff --git a/examples/simple-examples/src/conversation/webhooks/delete.ts b/examples/simple-examples/src/conversation/webhooks/delete.ts new file mode 100644 index 00000000..66b692cf --- /dev/null +++ b/examples/simple-examples/src/conversation/webhooks/delete.ts @@ -0,0 +1,21 @@ +import { DeleteWebhookRequestData } from '@sinch/sdk-core'; +import { getWebhookIdFromConfig, initClient, printFullResponse } from '../../config'; + + +(async () => { + console.log('**************************'); + console.log('* Webhooks_DeleteWebhook *'); + console.log('**************************'); + + const webhookId = getWebhookIdFromConfig(); + + const requestData: DeleteWebhookRequestData = { + webhook_id: webhookId, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.webhooks.delete(requestData); + + printFullResponse(response); + +})(); diff --git a/examples/simple-examples/src/conversation/webhooks/get.ts b/examples/simple-examples/src/conversation/webhooks/get.ts new file mode 100644 index 00000000..2ce54894 --- /dev/null +++ b/examples/simple-examples/src/conversation/webhooks/get.ts @@ -0,0 +1,31 @@ +import { GetWebhookRequestData } from '@sinch/sdk-core'; +import { + getPrintFormat, + getWebhookIdFromConfig, + initClient, + printFullResponse, +} from '../../config'; + +(async () => { + console.log('***********************'); + console.log('* Webhooks_GetWebhook *'); + console.log('***********************'); + + const webhookId = getWebhookIdFromConfig(); + + const requestData: GetWebhookRequestData = { + webhook_id: webhookId, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.webhooks.get(requestData); + + const printFormat = getPrintFormat(process.argv); + + if (printFormat === 'pretty') { + console.log(`Webhook id: ${response.id} - Triggers: ${response.triggers.join(', ')}`); + } else { + printFullResponse(response); + } + +})(); diff --git a/examples/simple-examples/src/conversation/webhooks/list.ts b/examples/simple-examples/src/conversation/webhooks/list.ts new file mode 100644 index 00000000..3df1d1ae --- /dev/null +++ b/examples/simple-examples/src/conversation/webhooks/list.ts @@ -0,0 +1,30 @@ +import { ListWebhooksRequestData } from '@sinch/sdk-core'; +import { getAppIdFromConfig, getPrintFormat, initClient, printFullResponse } from '../../config'; + +(async () => { + console.log('*************************'); + console.log('* Webhooks_ListWebhooks *'); + console.log('*************************'); + + const appId = getAppIdFromConfig(); + + const requestData: ListWebhooksRequestData = { + app_id: appId, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.webhooks.list(requestData); + + const printFormat = getPrintFormat(process.argv); + + if (printFormat === 'pretty') { + if (response.webhooks && response.webhooks.length > 0) { + console.log(`${response.webhooks.map((webhook) => `Webhook id: ${webhook.id} - Triggers: ${webhook.triggers.join(', ')}`).join('\n')}`); + } else { + console.log('Sorry, no webhooks were found.'); + } + } else { + printFullResponse(response); + } + +})(); diff --git a/examples/simple-examples/src/conversation/webhooks/update.ts b/examples/simple-examples/src/conversation/webhooks/update.ts new file mode 100644 index 00000000..be113477 --- /dev/null +++ b/examples/simple-examples/src/conversation/webhooks/update.ts @@ -0,0 +1,45 @@ +import { UpdateWebhookRequestData } from '@sinch/sdk-core'; +import { + getAppIdFromConfig, + getPrintFormat, getWebhookIdFromConfig, + initClient, + printFullResponse, +} from '../../config'; + + +(async () => { + console.log('**************************'); + console.log('* Webhooks_UpdateWebhook *'); + console.log('**************************'); + + const webhookId = getWebhookIdFromConfig(); + const appId = getAppIdFromConfig(); + + const requestData: UpdateWebhookRequestData = { + webhook_id: webhookId, + update_mask: ['triggers', 'secret'], + webhookUpdateRequestBody: { + app_id: appId, + triggers: [ + 'CONVERSATION_START', + 'CONVERSATION_STOP', + 'CONVERSATION_DELETE', + ], + target: 'http://no-update.url', + secret: 'New secret', + }, + }; + + const sinchClient = initClient(); + const response = await sinchClient.conversation.webhooks.update(requestData); + + const printFormat = getPrintFormat(process.argv); + + if (printFormat === 'pretty') { + console.log(`Webhook updated! New triggers: '${response.triggers.join(', ')}`); + console.log(`Verifying the target (it should the original URL): '${response.target}'`); + } else { + printFullResponse(response); + } + +})(); diff --git a/examples/webhooks/src/app.module.ts b/examples/webhooks/src/app.module.ts index 21df1f8b..5d6a66e4 100644 --- a/examples/webhooks/src/app.module.ts +++ b/examples/webhooks/src/app.module.ts @@ -4,11 +4,13 @@ import { NumbersService } from './services/numbers.service'; import { SmsService } from './services/sms.service'; import { VerificationService } from './services/verification.service'; import { VoiceService } from './services/voice.service'; +import { ConversationService } from './services/conversation.service'; @Module({ imports: [], controllers: [AppController], providers: [ + ConversationService, NumbersService, SmsService, VerificationService, diff --git a/examples/webhooks/src/controller/app.controller.ts b/examples/webhooks/src/controller/app.controller.ts index b7873867..17b24dc2 100644 --- a/examples/webhooks/src/controller/app.controller.ts +++ b/examples/webhooks/src/controller/app.controller.ts @@ -11,6 +11,7 @@ import { import { SmsService } from '../services/sms.service'; import { VerificationService } from '../services/verification.service'; import { VoiceService } from '../services/voice.service'; +import { ConversationService } from '../services/conversation.service'; require('dotenv').config(); const SINCH_APPLICATION_KEY = process.env.SINCH_APPLICATION_KEY || ''; @@ -20,6 +21,7 @@ const SINCH_APPLICATION_SECRET = process.env.SINCH_APPLICATION_SECRET || ''; export class AppController { constructor( + private readonly conversationService: ConversationService, private readonly numbersService: NumbersService, private readonly smsService: SmsService, private readonly verificationService: VerificationService, @@ -91,4 +93,10 @@ export class AppController { res.status(500).send(); } } + + @Post('/conversation') + public conversation(@Body() requestBody: any, @Res() res: Response) { + this.conversationService.handleEvent(JSON.stringify(requestBody)); + res.status(200).send(); + } } diff --git a/examples/webhooks/src/services/conversation.service.ts b/examples/webhooks/src/services/conversation.service.ts new file mode 100644 index 00000000..d92300ab --- /dev/null +++ b/examples/webhooks/src/services/conversation.service.ts @@ -0,0 +1,9 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class ConversationService { + + handleEvent(event: string): void { + console.log(event); + } +}