Skip to content

Latest commit

 

History

History
76 lines (57 loc) · 3.99 KB

CALL_TOOL_README.md

File metadata and controls

76 lines (57 loc) · 3.99 KB

Call Tool

Call Tool Plugin

The Call Tool is implemented as a Page plugin (Plugins::CallTool). Every plugin instance has the following fields:

  • targets: json array that holds the targets information (the json contents are automatically mapped to CallTool::Target instances)
  • sound_clip: paperclip attachment that holds a recorded audio file that should include a message and instructions from the campaigner about the campaign.
  • menu_sound_clip: paperclip attachment that holds a recorded audio file to be used as a menu during a call (Press 1 to connect, press 2 to hear the campaigner's message again)

Call flow

To make phone calls we use an external service provided by Twilio. In order to know how to handle a particular call, Twilio makes request to our server and expects to return a Twiml file (xml). The returned Twiml file will hold the instructions that tell Twilio how to proceed with the call.

This is a simplified overview of the flow of a call:

  • A member visits a page that has the call tool plugin. He's presented with a form that will make a POST /api/call request to the backend sending these two params: target_id and member_phone_number.

  • The backend creates an instance of Call and makes a request to Twilio to initiate a call sending the member's phone number and the Twiml callback URL with instructions on how to handle the call.

  • Twilio makes a call to the member and then immediately makes a request to twilio/calls/:id/start. The start instructions (see CallTool::TwimlGenerator::Start) tell Twilio to play the sound clip with the campaigner's message and then is redirected to twilio/calls/:id/menu.

  • When Twilio makes a request to twilio/calls/:id:/menu the menu is played, and the key presses are captured. If the member presses 1 it's redirected to twilio/calls/:id/start, and if the member presses 2 it's redirected to the next step at twilio/calls/:id/connect. See CallTool::TwimlGenerator::Menu.

  • twilio/calls/:id/connect tells twilio to make a call to the target's phone number and bridge it with the in-progress call to the member.

Call state

The status of a call is quite complex, since in the simplified flow I just described at any step something can go wrong in a couple of different ways.

The full state of a call is stored in three different places, and it's the combination of three different state machines.

  1. AR Call status: This the main status of the call, it's stored in Call#status as an enum. The possible statuses are:
  • :failed: A request was made to Twilio to initiate a call and it responded with an error message. This usually means the number is invalid.
  • :unstarted: This means that the call was made to the member but either the line was busy, never picked up or the phone was disconnected.
  • :started: This means the member picked up the phone and started hearing the campaignerer's message
  • :connected: This means the member pressed 1 and got connected to the target.
  1. Member call status: This holds the details of the actual phone call made to the member by Twilio. Twilio sends Champaign events when the status of a call changes, and they are stored in: Call#member_call_events. So in order to know the last state of a call we need to do call.member_call_events.last['CallStatus']. The possible statuses are: completed, answered, busy, no-answer, failed, canceled and unknown. To understand what each status means please check out Twilio's docs. I added an extra status unknown to describe the case when we don't receive a callback from Twilio.

  2. Target call status: This holds the details of the actual phone call made to the target by Twilio. This is sent in a callback request and stored in Call#target_call_info['DialCallStatus']. To know the possible states and their meanings please see Twilio's docs