Automate Whatsapp Messages Using Twilio and Flask

1321 VIEWS

Twilio Frontline is a programmable mobile application that enables digital relationships over messaging and voice to improve sales efficiency and outcomes. This platform enables a host of things to be automated especially within ecommerce products. Twilio services combined with Flask can allow business owners to automatically send replies to a buyer; thus, improving customer relations. In this article we will show you how to automate Whatsapp messages using Twilio and Flask.

Prerequisites

Here are the following prerequisites needed during this tutorial:

  1. The reader is required to have intermediate knowledge of Python programming
  2. Installation of the following Python dependencies:
    • Twilio
      pip install twilio
    • Flask
      pip install flask
Aim

In this article, we want to guide the reader on the following:

  • How to create an HTML form that contains an input area (text and date)
  • How to render the HTML template
  • How to send an HTTP request and create a scheduled function that executes at a particular time.

Let us begin!

Creating a Twilio Account

This section will give a step-by-step guide on creating a new Twilio account. In this account, we will get our Account SID and Auth Token. To proceed, we will follow the steps below:

  • We will start by signing into a new Twilio account.
  • Next, we will create a new project and call Automate. Then, we will go ahead and click verify.
  • After, we will need to verify our identity using our email and mobile number; then, we will fill in some prompts.
  • Now, we will need to activate our Twilio sandbox. To do this, we will send the command displayed in Twilio on our Whatsapp as a message to our provided Twilio number.
  • After, in the left-hand corner, click on one-way messages. 
  • Note: We will strictly work with one-way messages using our registered number and Twilio number.

One way messages involve a lone sender, and as we are using a trial account, we can only send messages to our designated Twilio number at the moment.

We will return to this section when we implement the project’s functionalities. Now we want to build our Flask project.

Creating a Virtual Environment

In this project, we will use Flask in a virtual environment. Thus, we will begin by creating a simple Python virtual environment using the steps below:

  1. We will start by making a new directory using the command below:
    mkdir project_1
  2. Within the newly created directory, we will create a virtual environment. To do this, we will head to the directory using the command cd project_1 and create a virtual environment using the command below:
    python -m venv <projectname>
    • Note: Replace <projectname> with the name of your choice.
  3. In a minute or two, we will have a new virtual environment. To use the environment, we will need to run the activate file that is in the Scripts folder, and we do that by typing the command below in our terminal:
    <projectname>\Scripts\activate

Voila! We have our virtual environment up and running. Now, we can run the commands specified in the prerequisite section on our terminal, and we are good to go.

Creating a Flask Server and Rendering Our HTML Template

 Flask is one of the few Python frameworks designed for the web. It allows us to utilize functions and methods within Python to access HTML properties called templates. In this section, we will create a simple Flask server returning a string (text) “HELLO WORLD!”. To do that, we will copy the code below:

from flask import Flask
app = Flask (__name__)
@app.route("/")
def index():
    return "HELLO WORLD"
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=80)

We want to add a simple HTML template containing an input box, and a submit button to our Python code. To do this, we will start by creating a folder called templates within our virtual environment.

  • Note: the folder name templates are standard practice in Flask, and we advise the name to remain like that.

Within the templates folder, we will create a simple HTML file called index.html, and we will add the elements below:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
    <title>Document</title>
    <style>
        div{
            display: flex ; 
            align-items: center; 
            justify-content: center; 
        }
    </style>
</head>
<body>
    <div>
        <form action="/sms" method="POST">
            <p>Body <input type = "text" id="Field_name" name = "Field_name" /></p>
            <p>To <input type = "text" id="Field1_name" name = "Field1_name" /></p>
            <p>Date <input type = "datetime-local" id="Field2_name" name = "Field2_name" /></p>
            <p><input type = "submit" value = "submit" onclick="text_message()"/></p>
        </form>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
    <script>
        config ={
            enableTime:true,
            dateFormat:"Y/m/d H:i"
        }
        flatpickr("input[type=datetime-local]", config);
    </script>
</body>
</html>

Concerning the codes we will implement later, the above elements are three input tags (two input fields and a date input) and the flatpickr. We will use the flatpickr library to change the default date format from the Y-m-d string to a Y/m/d datetime. That information sounds little but will be handy when implementing the schedule feature.

Now we want to render the HTML template on our Flask server, and we will do this by removing the HELLO WORLD string that we specified above and instead returning a render_template function with our HTML file as a parameter. We have an implementation of that below:

return render_template(“index.html”)

Note: For the render_template function to work, we will need to import render_template from our flask module

Creating the Schedule Function

Automation requires the handling of tasks with little to no human intervention. Thus, we will intervene by implementing a timer capability within our code that runs our message function at a specified time.

To begin, we will create a new route called /sms and specify a POST method to send data to the route. 

@app.route("/sms", methods=["POST"])

Next, we will create a function called getnew_form, and within the function, we will get our input fields using the request object in our Flask module.

def getnew_form():
    msg = request.form.get("Field_name")
    phone = request.form.get("Field1_name")
    y = request.form.get("Field2_name")
    return "Hello world"

Afterward, we will need to convert our date input data type because we will use a calculation involving our current date (a datetime class) and our input date (a string class). After, we will convert the result into seconds using our datetime module.

d = datetime.strptime(y, "%Y/%m/%d %H:%M")
x = datetime.today()
delta = d - x
secs = delta.seconds

Now, we want to send our messages, and to do that; we will head to our Twilio console in the one-way messages section and use the code particular to Python as a reference. We will also copy our Account SID and Auth Token as we will use them to access our Twilio console.

sid = 'AC74992e1923d40ae3401216f65455be8a'
authtoken = '53ea35d9d91ffa5fbf5e35f8b5b898b2'
client = Client(sid, authtoken)

Now within our function, we will create a nested function called whatsapp which we will call once our timer exceeds its specified time. Within the function, we will create a variable that will send our message to the specified contact (at the moment, Twilio).

def whatsapp():
    messages = client.messages.create(
        from_='whatsapp:+14155238886',
        body=msg,
        to=phone
    )
    return str(messages)

Finally, we will call the Timer object and specify two parameters, secs and the nested function, and we will initialize our timer by calling the start() method.

t = Timer(secs, whatsapp)
t.start()

Total Code and Result

Here is all the Python code for the tutorial and the result:

from flask import Flask, render_template, request
from datetime import datetime
from twilio.rest import Client
from threading import Timer
app = Flask (__name__)
@app.route("/")
def index():
    return render_template("index.html")
@app.route("/sms", methods=["POST"])
def getnew_form():
    msg = request.form.get("Field_name")
    phone = request.form.get("Field1_name")
    y = request.form.get("Field2_name")
    d = datetime.strptime(y, "%Y/%m/%d %H:%M")
    x = datetime.today()
    delta = d - x
    secs = delta.seconds
    sid = 'AC74992e1923d40ae3401216f65455be8a'
    authtoken = '53ea35d9d91ffa5fbf5e35f8b5b898b2'
    client = Client(sid, authtoken)
    def whatsapp():
        messages = client.messages.create(
            from_='whatsapp:+14155238886',
            body=msg,
            to=phone
        )
        return str(messages)
    t = Timer(secs, whatsapp)
    t.start()
    return "Hello world"
if __name__ == '__main__':
      app.run(host='0.0.0.0', port=80)

Automate Whatsapp messages using twilio and flask

Using Twilio and Flask, now you should be able to automate Whatsapp messages. If you encounter any errors, double check your code based on the below.

Errors Faced

  1. TypeError: The view function for 'getnew_form' did not return a valid response. The function either returned None or ended without a return statement.
    • We get this error because our functions returned None. Thus, we can eliminate it by adding a return statement with a sting or rendering an HTML file.
  2. RuntimeError: Working outside of request context.

    This typically means that you attempted to use functionality that needed an active HTTP request. Consult the documentation on testing for information about how to avoid this problem.

    • We get this error because we called our function before sending our HTTP request. To resolve this issue, we will remove the function call and end our function with a return statement.
  3. TypeError: unsupported operand type(s) for -: 'datetime.datetime' and 'datetime.date'
    • We get this error when we use different data types. So, we will advise readers always to check the input data types to prevent such errors.

Conclusion

In this article, we have shown how to automate Whatsapp messages in Twilio and Flask by scheduling our messaging function. Thanks for reading, and happy coding!

Curious about other ways to use Flask? Take a look at this article.


Muyiwa Femi-ige is a technical writer who has a knack for putting codes and coding processes into a well documented format.


Discussion

Click on a tab to select how you'd like to leave your comment

Leave a Comment

Your email address will not be published. Required fields are marked *

Menu
Skip to toolbar