Search code examples
node.jstwiliotwilio-apitwilio-twiml

Twilio: Waiting voice (Say) while the caller is waiting for a response from forwarded number (Dial)


I struggle with something that seem simple:

When I receive a call on a twilio phone number, I want to forward the call using <Dial>, and while the caller waits, play a message that can also gather user input.

I managed to forward a call OR to make the caller here the message and gather input but not both in parallel

Here is what I tried:

...
const response = new VoiceResponse()
response.dial('+33611182299')
response.enqueue({
    waitUrl: `https://myapi.com/api/repondeur/wait-msg`,
}, 'support')
...

I also tried to set Dialin waitUrl, and a lot of different combinations (like changing the order, trying to create a queue...etc) with no success.

Also tried to adapt this and this but it didn't work

Could you point me to the right direction please ?


Solution

  • After a lot of trial and headbanging, here is what I've got:

    
    const inProgressCallsCache = {}
    
    
    // MAIN WEBHOOK ROUTE
    export const answerCallSvc = {
        route: '/answer-call',
        async main(body) {
            const response = new VoiceResponse()
    
            // First we redirect caller to the waiting url
            response.enqueue({
                waitUrl: url(`/answer-call/wait-msg`),
                method: 'POST',
            }, queueName)
    
            // Then we call the respondent. When he'll answer
            // the call will be redirected to `url`
            const call = await client.calls
                .create({
                    to: telTest,
                    from: body.Caller,
                    url: url(`/answer-call/call-back`),
                    method: 'POST',
                    // time while trying to call respondent
                    // before giving up
                    timeout, 
                })
    
            // store the respondent SID in cache so we can
            // end the call if the user end the call
            // this is a HACK, it may need to be stored in DB
            inProgressCallsCache[body.CallSid] = call.sid
    
            return response.toString()
        },
    }
    
    export const answerCallCallback = {
        route: '/answer-call/call-back',
        async main() {
            // this allow the respondent to be connected to the caller 
            // once the respondent pick up the phone
            const response = new VoiceResponse()
            response.dial().queue(queueName)
            return response.toString()
        },
    }
    
    export const answerCallWaitMsgSvc = {
        route: '/answer-call/wait-msg',
        async main() {
            // wait url will be responsible for playing the message 
            // and gathering user input while the callers awaits
            const response = new VoiceResponse()
            const gather = response.gather({
                action: url(`/answer-call/record-input`),
                method: 'POST'
            })
            gather.say(`We are connecting you with someone. You can press any digit to end the call.`)
            return response.toString()
        },
    }
    
    
    
    export const answerCallRecordUserINput = {
        route: '/answer-call/record-input',
        async main(body) {
            // The user has pressed a digit so we may take further actions here
            // and end the call for both caller and respondent
            console.log(`Recorded input`, body.Digits)
    
            const callingSid = body.CallSid
    
            const response = new VoiceResponse()
            response.say(`Thank you, we will end the call now.`)
            response.hangup()
    
                const respondentSid = inProgressCallsCache[callingSid] 
                if (respondentSid) client.calls(respondentSid).update({ status: 'canceled' }).catch(err => console.error(err))
    
            return response.toString()
        },
    }
    
    

    Please let me know if you need further details or converting to express syntax.