Python Forum
robocall on the fly (and send texts) with Twilio
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
robocall on the fly (and send texts) with Twilio
#1
Here is the repository with better directions.

EDIT: Re-pasting the code as a --record option was added...

First you have to get your Twilio credentials and number and set some environment variables:
TWILIO_NUMBER=18885551234
TWILIO_ACCOUNT_SID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
TWILIO_AUTH_TOKEN=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

#!/usr/bin/env python3
# rootVIII
# robocall101 - Robovoice/SMS command-line tool
# pycodestyle/pep8 validated
from argparse import ArgumentParser
from json import loads
from os import environ, getcwd
from sys import exit, argv
from time import sleep
from urllib.request import Request, urlopen, urlretrieve
from urllib.error import URLError
try:
    from twilio.rest import Client
except ImportError:
    print('Unable to import Twilio module, exiting.')
    exit(1)


class TwilComm(object):
    def __init__(self):
        self.my_twilio = environ['TWILIO_NUMBER']
        self.client = Client(
            environ['TWILIO_ACCOUNT_SID'], environ['TWILIO_AUTH_TOKEN'])
        self.url = 'https://www.restwords.com/api/post_markup'
        self.message = ''

    @staticmethod
    def exit_on_error(e):
        print(type(e).__name__ + ': ' + str(e))
        exit(1)

    def post(self):
        request = Request(self.url)
        request.add_header('Content-type', 'text/xml; charset="utf-8"')
        rbody = '<?xml version=\"1.0\" encoding=\"utf-8\"?><Response>'
        rbody += '<Pause/><Say>' + self.message + '</Say></Response>'
        request.data = rbody.encode()
        try:
            result = urlopen(request)
        except URLError as e:
            self.exit_on_error(e)
        else:
            self.url = loads(result.read().decode())['url']


class Call(TwilComm):
    def __init__(self, outgoing, message, rec_call):
        TwilComm.__init__(self)
        self.outgoing = outgoing
        self.message = message
        self.rec_call = rec_call
        self.sid = ''

    def make_call(self):
        self.sid = self.client.calls.create(
            to=self.outgoing, from_=self.my_twilio,
            record=self.rec_call, url=self.url).sid

    def poll_call(self):
        print('retrieving recording... please wait for call to complete')
        # poll until Rec. SID has been created:
        rsid = [r.sid for r in self.client.recordings.list(call_sid=self.sid)]
        print('polling....')
        while not rsid:
            sleep(1)
            rsid = [r.sid for r in
                    self.client.recordings.list(call_sid=self.sid)]
        print('recording SID found...')
        # poll until call has finished:
        status = [r.status for r in
                  self.client.recordings.list(call_sid=self.sid)]
        while status != ['completed']:
            sleep(1)
            status = [r.status for r in
                      self.client.recordings.list(call_sid=self.sid)]
        print('call completed... fetching your recording')
        url = 'https://api.twilio.com/2010-04-01/Accounts/'
        url += environ['TWILIO_ACCOUNT_SID']
        url += '/Recordings/' + rsid[0] + '.mp3'
        try:
            urlretrieve(url, '%s/%s.mp3' % (getcwd(), rsid[0]))
        except URLError as url_err:
            self.exit_on_error(url_err)
        print(rsid[0] + '.mp3 downloaded to the current working directory')
        print('deleting recording from Twilio logs...')
        [r.delete() for r in self.client.recordings.list(call_sid=self.sid)]
        print('FINISHED')


class Text(TwilComm):
    def __init__(self, outgoing, message):
        TwilComm.__init__(self)
        self.outgoing = outgoing
        self.message = message

    def send_text(self):
        self.client.messages.create(
            to=self.outgoing, from_=self.my_twilio, body=self.message)


class ArnoldsHavingABadDay(Call):
    def __init__(self, outgoing, rec_call):
        Call.__init__(self, outgoing=outgoing, message=None, rec_call=rec_call)
        self.url = 'https://blue-platypus-3554.'
        self.url += 'twil.io/assets/arnold.mp3'
        self.outgoing = outgoing
        self.rec_call = rec_call


class Arguments:
    def __init__(self):
        description = 'Robocall and Robotext via the command line.\n'
        self.parser = ArgumentParser(description=description)
        self.parser.add_argument(
            '-n', '--number', required=True, help='Outgoing phone number')
        self.parser.add_argument(
            '-c', '--call', help='Robocall - enter text to be spoken')
        self.parser.add_argument(
            '-t', '--text', help='Text - enter text to send as SMS')
        self.parser.add_argument(
            '-a', '--arnold', action='store_true', help='ArnoldsHavingABadDay')
        self.parser.add_argument(
            '-r', '--record', action='store_true', help='Record Call')

    @classmethod
    def help_menu(cls):
        return """
            Obtain your Twilio Credentials and Twilio Number.
            Set the following environment variables:
            TWILIO_NUMBER=18885551234
            TWILIO_ACCOUNT_SID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
            TWILIO_AUTH_TOKEN=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
            REQUIRED:
            -n <outgoing number>             -| Target phone number
            PICK ONE:
            -c/--call <text/string here>     -| Robocall on thy fly
            -t/--text <text/string here>     -| Send an SMS
            -a/--arnold                      -| Call with Arnold recording
            ADDITIONAL OPTION:
            -r/--record                      -| Record Call/Save to .mp3 in CWD
        """

    def get_args(self):
        return self.parser.parse_args()


def main():
    # Print better help menu if no args
    if len(argv) < 2:
        print(Arguments.help_menu())
        exit(1)
    args = Arguments().get_args()
    if not args.number.isnumeric():
        print(Arguments.help_menu())
        exit(1)
    if args.call:
        call = Call(args.number, args.call, args.record)
        call.post()
        call.make_call()
        if args.record:
            call.poll_call()
    elif args.text:
        text = Text(args.number, args.text)
        text.send_text()
    elif args.arnold:
        arnold = ArnoldsHavingABadDay(args.number, args.record)
        arnold.make_call()
        if args.record:
            arnold.poll_call()
    else:
        print(Arguments.help_menu())


if __name__ == '__main__':
    main()
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  A Python daemon that sends Twilio SMS Alerts when top metrics exceed thresholds rootVIII 0 2,369 Mar-25-2019, 03:46 AM
Last Post: rootVIII

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020