Calling Twilio Voice API to deliver custom voice calls to the subscriber

Hello Guys!

It’s time to share another installment of fun & exciting posts from the world of Python-verse.

Today, We’ll be leveraging the Twilio voice API to send custom messages through phone calls directly. This service is beneficial on many occasions, including alerting the customer of potential payment reminders to pending product delivery calls to warehouse managers.


Dependent Packages:

Let us explore what packages we need for this –

Dependent Package Installation

The commands for your reference –

pip install twilio
pip install pandas

Also, you need to subscribe/register in Twilio. I’ve already shown you what to do about that. You can refer to my old post to know more about it. However, you need to reserve one phone number from which you will be calling your customers.

Buying phone numbers

As you can see, I’ve reserved one phone number to demonstrate this use case.


Let us explore the key codebase –

  1. clsVoiceAPI.py (Main class invoking the voice API)


##############################################
#### Written By: SATYAKI DE ####
#### Written On: 30-Mar-2021 ####
#### Modified On 30-Mar-2021 ####
#### ####
#### Objective: Calling Twilio Voice API ####
##############################################
import json
from clsConfig import clsConfig as cf
import logging
import os
from twilio.rest import Client
class clsVoiceAPI:
def __init__(self):
self.account_sid = cf.conf['TWILIO_ACCOUNT_SID']
self.auth_token = cf.conf['TWILIO_AUTH_TOKEN']
self.from_phone = cf.conf['FROM_PHONE']
self.to_phone = cf.conf['TO_PHONE']
def sendCall(self, msg):
try:
account_sid = self.account_sid
auth_token = self.auth_token
from_phone = self.from_phone
to_phone = self.to_phone
client = Client(account_sid, auth_token)
call = client.calls.create(
twiml='<Response><Say>' + str(msg) + '</Say></Response>',
to=str(from_phone),
from_=str(to_phone)
)
resTokenOutput = call.sid
print('Final Respone: ' + str(resTokenOutput))
resToken = 0
return resToken
except Exception as e:
x = str(e)
resToken = 1
print(x)
logging.info(x)
return resToken

view raw

clsVoiceAPI.py

hosted with ❤ by GitHub

Key snippets from the above codebase –

call = client.calls.create(
                            twiml='<Response><Say>' + str(msg) + '</Say></Response>',
                            to='+18048048844',
                            from_='+19999990396'
                        )

We’re invoking the Twilio API in the above block by giving both the calling & Callee numbers. And, we’re receiving the desired messages from our primary calling program, which the IVR will spell while calling to the customers.

2. callTwilioVoice.py (Main calling script)


#########################################################
#### Written By: SATYAKI DE ####
#### Written On: 06-Mar-2021 ####
#### Modified On 07-Mar-2021 ####
#### ####
#### Objective: Main calling scripts – ####
#### This Python script will consume an ####
#### source API data from Azure-Cloud & publish the ####
#### data into an Oracle Streaming platform, ####
#### which is compatible with Kafka. Later, another ####
#### consumer app will read the data from the stream.####
#########################################################
from clsConfig import clsConfig as cf
import clsL as cl
import logging
import datetime
import clsVoiceAPI as ca
# Disbling Warning
def warn(*args, **kwargs):
pass
import warnings
warnings.warn = warn
# Lookup functions from
# Azure cloud SQL DB
var = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
def main():
try:
# Declared Variable
ret_1 = 0
debug_ind = 'Y'
res_2 = ''
# Defining Generic Log File
general_log_path = str(cf.conf['LOG_PATH'])
# Enabling Logging Info
logging.basicConfig(filename=general_log_path + 'TwillioAPICall.log', level=logging.INFO)
# Initiating Log Class
l = cl.clsL()
# Moving previous day log files to archive directory
log_dir = cf.conf['LOG_PATH']
tmpR0 = "*" * 157
logging.info(tmpR0)
tmpR9 = 'Start Time: ' + str(var)
logging.info(tmpR9)
logging.info(tmpR0)
print()
print("Log Directory::", log_dir)
tmpR1 = 'Log Directory::' + log_dir
logging.info(tmpR1)
print('Welcome to the Twilio Voice Calling Program: ')
print('*' * 160)
print()
# Provide a short input text for calls
voiceCallText = 'Voice From Satyaki, Welcome to the Python World!'
# Create the instance of the Twilio Voice API Class
x1 = ca.clsVoiceAPI()
# Let's pass this to our map section
resSID = x1.sendCall(voiceCallText)
if resSID == 0:
print('Successfully send Audio Message!')
else:
print('Failed to send Audio Message!')
print()
print('Finished Sending Automated Calls..')
print("*" * 160)
logging.info('FFinished Sending Automated Calls..')
logging.info(tmpR0)
tmpR10 = 'End Time: ' + str(var)
logging.info(tmpR10)
logging.info(tmpR0)
except ValueError as e:
print(str(e))
print("Invalid option!")
logging.info("Invalid option!")
except Exception as e:
print("Top level Error: args:{0}, message{1}".format(e.args, e.message))
if __name__ == "__main__":
main()

Key snippets from the above codebase –

        # Create the instance of the Twilio Voice API Class
        x1 = ca.clsVoiceAPI()

        # Let's pass this to our map section
        resSID = x1.sendCall(voiceCallText)

As you can see, we’re first instantiating the class & then calling the method from it by providing the appropriate messages that will eventually deliver to our customer. You can configure dynamic content & pass it to this class.


Let us explore the directory structure –

Directory Structures

Let us see how it runs –

Running Applications

You need to make sure that you are checking your balance of your Twilio account diligently.

Checking Balance

And, here is the sneak peak of how it looks like in an video –

Actual execution

For more information on IVR, please check the following link.


Please find the git details in this link.

So, finally, we have done it.

I’ll bring some more exciting topic in the coming days from the Python verse.

Till then, Happy Avenging! 😀

Note: All the data & scenario posted here are representational data & scenarios & available over the internet & for educational purpose only.