Screen Calls Based on a Block List - Python

Overview

This guide implements a call screening system based on the concept of a blocklist containing offending numbers. When a call comes in, the From number will be cross-checked with the block list to see if it is one of the blocked numbers. If so, the call will hang up. If the number is not in the block list, the call flow moves on to the next segment.

In this case, I have redirected to an XML Bin. However, depending on your needs, this can point at an XML bin, another webhook, or another part of the code within the same document. As you can see below, it is very simple to implement such a call flow with SignalWire and SignalWire Compatible XML.

What do I need to run this code?

Check out the code on Github here!

You will need the Python SDK and Flask framework to run this code.

You will need a SignalWire phone number as well as your API Credentials (API Token, Space URL, and Project ID) which can all be found in an easily copyable format within the API tab of your SignalWire portal.

Running the application

To install prerequisites, run pip install -r requirements.txt. Using a virtualenv is recommended.

To run the application, execute export FLASK_APP=python_call_screening.py then run flask run.

You may need to use an SSH tunnel for testing this code – we recommend ngrok. After starting the tunnel, you can use the URL you receive from ngrok in your webhook configuration for your phone number.

Step by step code walkthrough

This Github repo has three files:

  • README.md
  • python_call_screening.py
  • requirements.txt

We can skip the README.md file and save the requirements.txt file for when we are running the app. We will discuss python_call_screening.py below.

We start with the necessary imports and instantiate a Flask app:

from flask import Flask, request
from signalwire.voice_response import VoiceResponse
import os

app = Flask(__name__)

We then define a quick method to fetch the blocked list (this could be a database query or something more involved in a production app):

def get_blocklist():
    # there is a default here you can change if you don't want to use the environment variable
    return os.getenv('BLOCKLIST', '+1555778899').split(',')

To set the block list, you can set the BLOCKLIST environment variable to a value of a comma-separated list of numbers. For example:

export BLOCKLIST=+15554433222,+15559988777

If you prefer not to use environment variables, you can set an additional number or demo URL as displayed in the code below with the number +15557778899 or the redirect path https://example.signalwire.com/laml-bins/55ab7685-e9c3-4449-b1f0-07ff083d041e which points at an example XML bin that calls a naval clock.

return os.getenv('BLOCK_LIST', '+1555778899').split(',')
response.redirect(os.environ.get('REDIRECT_PATH', 'https://some_redirect_url'))

The only route this application has is where we do the block list check and return the necessary SignalWire Compatible XML either to redirect or hang up:

@app.route('/check', methods=['POST'])
def check_number():
    response = VoiceResponse()
    from_number = request.form.get('From')
    
    if from_number not in get_blocklist():
        response.redirect(os.environ.get('REDIRECT_PATH', 'https://example.signalwire.com/laml-bins/55ab7685-e9c3-4449-b1f0-07ff083d041e'))

    else:
        response.hangup()

    return response.to_xml()

Finally, we run the application:

if __name__ == "__main__":
    app.run()

This is an example of what the Python code returns to make the redirect happen.

<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Redirect>https://example.signalwire.com/laml-bins/55ab7685-e9c3-4449-b1f0-07ff083d041e</Redirect>
</Response>

Wrap Up

In the current ecosystem of voice calling, business owners run the risk of facing incoming spam calls, robocalls, or people who are generally trying to take advantage of resources. Implementing a blocklist (or database) to maintain numbers that should be "blacklisted" is a very effective way of reducing the cost impact caused by these spammers and this guide shows an easy way to do that!

Required Resources:

Sign Up Here

If you would like to test this example out, you can create a SignalWire account and space here.

Please feel free to reach out to us on our Community Slack or create a Support ticket if you need guidance!


Did this page help you?