/WhatsappReminders

Sending reminder messages through Whatsapp amb Functions in IBM Cloud

Primary LanguagePython

WhatsappReminders

Sending reminder messages through Whatsapp using Twilio and Functions in IBM Cloud

These are the instructions to create, starting from scratch, a simple application to send periodic reminder messages through whatsapp using Twilio and Functions in the IBM Cloud. Twilio makes it very easy to send whatsapp messages and Functions (OpenWhisk-based) makes it very easy to create an app without worrying on server configurations and execute the app based on many types of triggers. The cost for this use case is 0. If the number of messages you send grows both Twilio/WhatsApp and Functions may require some investment.

There are limitations when using the Twilio Whatsapp Sandbox. One of them is that if the end user (whoever receives the messages) doesn't answer something in 24h, the sending of messages is disabled (to avoid spam, obviously).

NOTE: This is not meant for serious production environments. If that's the case you'd probably need to work with Twilio/WhatsApp Business (although the code would be basically the same)

(I'll use the convention of preceding all commands with a $ and put them in italics)

Prepare the tools you need

I'm going to assume you have a laptop where you'll do your coding. I have a Mac so my examples will be based on that platform but you can find Linux/Windows equivalents easily.

You need an editor to code (just a little bit)

I use VSCode (https://code.visualstudio.com/) but this application is very simple so any text editor will do. I like Atom for example, which is simpler than VSCode and also for free: https://atom.io/ (If you want to use Atom, it's very handy to install "Shell Commands" so that you can open atom from terminal command line: just open the atom application, in the Menu go to Atom-> Install Shell Commands. Now you can write atom from any terminal)

You need a Twilio account and a Twilio WhatsApp Console

Just register here: https://www.twilio.com/try-twilio

Twilio has a nice WhatsaApp SandBox console, very easy to use, and for what we want is more than enough. Once you have registered, go to the Whatsapp Twilio console and follow the instructions:

https://www.twilio.com/console/sms/whatsapp/learn

Then go to the console Dashboard and make sure you take note of:

Be sure to take note of:

  • Account SSID (that's just a way to identify your account)
  • Auth Token (that's just a "password" to access your account)

and also (from the previous step):

  • Telephone that sends the Whatsapp (will be a +1... number)
  • Telephone that receives the Whatsapp (your phone, for example)

(The full tutorial is here in case you want to learn more, but not necessary: https://www.twilio.com/docs/whatsapp/quickstart/python)

Prepare the runtimes so that your application works on your laptop

You need the python and twilio libraries in your laptop to run and test the application. You just need to install them.

(you may want to install Anaconda if you plan to have multiple development environments but it's really not necessary)

Install Homebrew (if you don't have it). It's a Mac package manager that will save you a lot of time and make installation of most runtimes really easy. (https://brew.sh/)

Just open a Terminal and execute:
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
(remember to also execute this so that the Homebrew directory is accessible: $ export PATH="/usr/local/opt/python/libexec/bin:$PATH")

Once you have Homebrew in place, install python as easy as this: $ brew install python

Now install Twilio, very easy also once you've done the previous: $ pip install twilio

Now you can start coding your application.

Code your application and test it locally before uploading to the cloud

The application has the following parts, all them in this GitHub:

  • Missatge.py: This has the logic of the application
  • SampleParms.json: This has the information (telephones, account,...) that we don't want to put directly in the application code.
  • Dockerfile: This is the Docker file that will contain the Twilio (and a couple more) runtimes. You don't need it for the local testing but you need it to upload the app into Cloud.

Create a directory in your laptop for this project and copy these files to your environment (for example click the "Clone or download" button in the GitHub repo, donwload as a zip and put the files in the newly created directory)

Rename SampleParms.json to parmsPackage.json, open the file, fill it with your values.

Test you application using a terminal and the following command (you must be in the project directory):

$ python -c 'import Missatge; Missatge.main(0)' (you should receive a message through Whatsapp)

You can go to the Twilio Console and see what happens to your messages (beware that you can only send messages to phones that have "joined" your account, in the Console it explains how): https://www.twilio.com/console/sms/logs

Once you are happy with the basic sending of messages, we'll put the application in the Cloud and define when we want to trigger it but before we need to prepare a Docker image with the runtimes we need.

Prepare a Docker image with the runtimes that the application uses so that we can move them to the Cloud

If you don't have it, install Docker: https://docs.docker.com/docker-for-mac/install/

Create a DockerHub Account (this is where the image will be made available so that we can get it from Cloud): https://hub.docker.com/
In DockerHub, create a public repository, for example, whatsappruntime (must be lowercase)

From the terminal and in your project directory create the Docker image:
$ docker build -t <your_dockerhub_user>/whatsappruntime:inicial . (don't forget the "." at the end of the command!)

This will use Dockerfile to create the image. The image will be stored in Docker local repository, don't expect to see it in the directory

Now send the Docker image with your runtimes to DockerHub so that it can be retrieved from the Cloud (you may have to $ docker login first): $ docker push <your_dockerhub_user>/whatsappruntime:inicial

Get an IBM Cloud free account

Just register here: https://cloud.ibm.com The Service that you'll be using is called "Functions": https://cloud.ibm.com/functions/

You can take a look to all this through the IBM Cloud Console but I'd recommend to use commands from you terminal to manage it

Uploading the application to the Cloud

All the documentation to use Functions is here: https://cloud.ibm.com/docs/openwhisk?topic=cloud-functions-getting-started And all CLI commands are here: https://cloud.ibm.com/docs/openwhisk?topic=cloud-functions-cli-plugin-functions-cli

The basic things you need to know are:

  • Your Application will be an Action, that is, a piece of code that will be executed depending on a Trigger
  • A Trigger: is an event that can trigger the execution of an Action (for example, in our case, certain times)
  • A Rule is what ties a Trigger with an Action
  • A Package is a way to wrap a group of Actions so that they can be managed all together (we won't use it since we only have one Action but can be useful for more complex scenarios)
  • A Namespace is just a "space" in your Cloud where all the Functions resources live
  • A Resource Group is just an administrative concept in the Cloud to manage your resources (Functions or any other thing)

The only concepts that you really need to have clear are Action, Trigger and Rule

Install the IBM Cloud CLI and plug-in in your laptop, this will allow you to send commands to the Cloud from your laptop: https://cloud.ibm.com/docs/openwhisk?topic=cloud-functions-cli_install

After you install the CLI remember to install the plugin:

  • Login to IBM Cloud if you have not done so before: $ ibmcloud login
  • Select a Region if you have not been asked, for example, US South: $ ibmcloud target -r us-south (this means your app will be executed in Dallas)
  • Select a Resource Group if you have not been asked (this is just some administration requirement):
    • $ ibmcloud resource groups will list your resource groups, pick one
    • $ ibmcloud target -g default (I chose default)
  • $ ibmcloud plugin install cloud-functions (install the plugin)

Check if you have any IAM-based namespace: $ ibmcloud fn namespace list
If you don't, create one, for example WhatsName: $ ibmcloud fn namespace create WhatsName
Select the Namespace where you'll deploy the app and create the triggers:
$ ibmcloud fn property set --namespace WhatName

Create the Action based on your app: $ ibmcloud fn action create EnviarMissatge --docker <your_dockerhub_user>/whatsappruntime:inicial Missatge.py

(If you change your application and want to update it just use the command:

$ ibmcloud fn action update EnviarMissatge --docker <your_dockerhub_user>/whatsappruntime:inicial Missatge.py)

Create the trigger that will eventually invoke the action (the trigger will be called periodic):

$ ibmcloud fn trigger create periodic --feed /whisk.system/alarms/alarm --param cron "0 9,13,22 * * *" --param timezone "Europe/Berlin"

(this will create an event at 9 o'clock, 13 and 22 hours. The syntax is that of cron: https://en.wikipedia.org/wiki/Cron)

(you can update the trigger schedule with: $ ibmcloud fn trigger update periodic --feed-param cron "0 9,13,21 * * *")

Create a rule that links your Action with your _Trigger:
$ ibmcloud fn rule create Rule_Periodic_EnviarMissatge periodic EnviarMissatge
(If you used the console to create the Action and the Trigger, a Rule is created automatically)

Check that the Rule is active with the following command: $ ibmcloud fn rule list

If it's not active, just activate it using: $ ibmcloud fn rule enable Rule_Periodic_EnviarMissatge

Just one final step and we are there. We have created an Action with our application, a Trigger to awake the action and now we need to pass the parameters to the Action (without writing them on the application). To do that, we just update the action and specify that our application parameters are in a file called paramsPackage.json:

$ ibmcloud fn action update EnviarMissatge --docker <your_dockerhub_user>/whatsappruntime:inicial --param-file parmsPackage.json Missatge.py

(yes... we could have done that at the very beginning when creating the Action for the first time)

You can check the properties of your Action with this command (you should see all the parameters):
$ ibmcloud fn action get EnviarMissatge

And finally: try to force invoking the Action directly to see if it works from the Cloud:
$ ibmcloud fn action invoke EnviarMissatge --result

And this should make it work. You can monitor the invocations of the action from the Cloud console in the Functions section: https://cloud.ibm.com/functions/dashboard