eliecerthoms1

inbound-call-start.js

Oct 20th, 2023
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import { getBaseUrl } from '../../../shared/utils';
  2. import { validateTwilioSignature } from '../../../shared/twilio';
  3. import { parsePhoneNumber } from '../../phone-numbers/phone-numbers-utils';
  4. import {
  5.   createInboundPhoneCall,
  6.   getCallDropResponse,
  7.   fetchInboundCallInfo,
  8. } from '../phone-call-actions';
  9. import { twiml } from 'twilio';
  10. import * as qs from 'querystring';
  11.  
  12. /**
  13.  * Inbound calls webhook handler.
  14.  *
  15.  * @param {object} event - 8base event.
  16.  * @param {object} ctx - 8base context.
  17.  *
  18.  * @returns {Promise} The webhook result.
  19.  */
  20. export default async function(event, ctx) {
  21.   console.log('call: Beginning inbound-call-start');
  22.  
  23.   console.log('call: inbound-call-start Running Inbound Calls Webhook...');
  24.   const { agency } = event.pathParameters;
  25.   const body = qs.parse(event.body);
  26.   const signature = event.headers['X-Twilio-Signature'];
  27.   const url = `${getBaseUrl(ctx)}/webhook/calls/inbound/${agency}`;
  28.   const headers = { 'Content-Type': 'text/xml' };
  29.   const options = { checkPermissions: false };
  30.   const response = new twiml.VoiceResponse();
  31.  
  32.   if (validateTwilioSignature(signature, url, body) === false) {
  33.     console.log('call: inbound-call-start Invalid twilio signature [' + signature + ']');
  34.  
  35.     return {
  36.       statusCode: 401,
  37.       body: JSON.stringify({
  38.         message: 'Unauthorized request',
  39.       }),
  40.     };
  41.   }
  42.  
  43.   const from = parsePhoneNumber(body.From);
  44.   const to = parsePhoneNumber(body.To);
  45.   let responses = [];
  46.   let call = null;
  47.  
  48.   try {
  49.     /*responses = await Promise.all([
  50.       fetchLeadPhoneFromNumber(from.number, agency, ctx, options),
  51.       fetchAgencyPhoneFromNumber(to.number, agency, ctx, options),
  52.       fetchActiveUsers(ctx, options, agency),
  53.     ]);*/
  54.  
  55.     responses = await fetchInboundCallInfo(from.number, to.number, agency, ctx, options);
  56.     console.log('call: inbound-call-start RESPONSES: After', JSON.stringify(responses));
  57.   } catch (e) {
  58.     console.log('call: inbound-call-start Could not fetch all resources:', e.message);
  59.     const response = new twiml.VoiceResponse();
  60.     response.say(`Could not fetch agency phone number: ${e.message}`);
  61.  
  62.     return {
  63.       statusCode: 200,
  64.       body: response.toString(),
  65.     };
  66.   }
  67.  
  68.   console.log('call: inbound-call-start After Promise.all', new Date().toLocaleString());
  69.  
  70.   const [leadPhone, agencyPhone, activeUsers] = responses;
  71.   console.log('call: inbound-call-start agencyPhone', agencyPhone);
  72.   const record = agencyPhone?.agency?.phoneCallSettings?.recordCalls ? true : false;
  73.   const allowVoicemail = Boolean(agencyPhone?.agency?.phoneCallSettings?.voicemail);
  74.   const voicemailUrl = agencyPhone?.agency?.voicemailUrl;
  75.   if (!agencyPhone) {
  76.     console.log('call: inbound-call-start Unassigned phone number:', body.To);
  77.  
  78.     response.say('This phone number is no longer available', {
  79.       voice: 'woman',
  80.     });
  81.  
  82.     return {
  83.       headers,
  84.       statusCode: 200,
  85.       body: response.toString(),
  86.     };
  87.   }
  88.  
  89.   const avialable = activeUsers.count > 0;
  90.  
  91.   console.log('call: inbound-call-start Available Users', avialable);
  92.  
  93.   try {
  94.     call = await createInboundPhoneCall(
  95.       {
  96.         from: body.From,
  97.         to: agencyPhone.id,
  98.         agency: agency,
  99.         callSid: body.CallSid,
  100.         lead: leadPhone ? leadPhone.lead.id : undefined,
  101.         status: avialable ? undefined : 'no-answer',
  102.       },
  103.       ctx,
  104.       options,
  105.     );
  106.     console.log('call: inbound-call-start created inbound phone call', JSON.stringify(call));
  107.   } catch (e) {
  108.     console.log('call: inbound-call-start Could not create call object:', e.message);
  109.     const response = new twiml.VoiceResponse();
  110.     response.say(`Could not create call object: ${e.message}`);
  111.     return {
  112.       statusCode: 200,
  113.       body: response.toString(),
  114.     };
  115.   }
  116.  
  117.   if (!avialable) {
  118.     console.log('call: inbound-call-start No users available');
  119.  
  120.     return {
  121.       headers,
  122.       statusCode: 200,
  123.       body: getCallDropResponse(ctx, call.id, allowVoicemail, voicemailUrl),
  124.     };
  125.   }
  126.  
  127.   response
  128.     .dial({
  129.       action: `${getBaseUrl(ctx)}/webhook/inbound-call/${call.id}/finished`,
  130.       answerOnBridge: true,
  131.       record: record,
  132.       trim: true,
  133.     })
  134.     .conference(
  135.       {
  136.         beep: true,
  137.         startConferenceOnEnter: false,
  138.         endConferenceOnExit: true,
  139.         waitUrl: `${getBaseUrl(ctx)}/webhook/inbound-wait-conference-action/${call.id}`,
  140.         waitMethod: 'POST',
  141.         statusCallbackMethod: 'POST',
  142.         statusCallback: `${getBaseUrl(ctx)}/webhook/inbound-call/${body.CallSid}/conference/event`,
  143.         statusCallbackEvent: 'start end join leave',
  144.       },
  145.       body.CallSid,
  146.     );
  147.  
  148.   console.log('call: inbound-call-start twiml:', response.toString());
  149.  
  150.   return {
  151.     headers,
  152.     statusCode: 200,
  153.     body: response.toString(),
  154.   };
  155. }
  156.  
Advertisement
Add Comment
Please, Sign In to add comment