Using a Serverless framework like Fission.io is a quick, and portable way to create an application layer between highly-programmable services like Twilio and Slack — common, but not always easily automated and integrated, services for developers to program communication services like SMS, voice, and chat services. Fission addresses this by allowing you to run lightweight programs that can consume and operate on request data, and in our scenario, act as an orchestrator or router for these communication tools.
What we’re going to create is two Fission tasks, small Python (in our case) programs, to receive a number and a message to go out through Slack to Twilio to the intended recipient, and when your Twilio SMS number receives a message, it is delivered to Slack.
You’ll need from Slack an incoming webhook (to post messages to a channel) and a Slash Command (to have Fission trigger your function via POST requests from Slack on this webhook):
Make a note of the hooks.slack URL for your Fission task in a moment. Then, create your Slack app for a Slash Command, something like /twilio :
From Twilio, you’ll just need your Account SID, API token, and an SMS-capable Twilio number:
you will also, once the tasks are deployed (because you’ll need the Fission URL you end up creating), create a Twilio Webhook for any one of your numbers:
Creating our Functions
In send.py we’re going to create the script that runs when your Slash Command is run (a POST request from Slack to Fission):
import json import requests import urllib from flask import request, redirect from twilio.rest import Client CHANNEL\_NAME="twilio" SLACK\_TOKEN="" TWILIO\_SENDER="" #Number with Country code LIMIT\_TO\_CC="" #i.e. +1
In this section, replace SLACK_TOKEN with your Slack App token, define the CHANNEL you want the response form the Slack API into (ideally the same one where the command will be run), and then optionally add the country code to limit SMS messages to (so you can have users provide a 10-digit phone number), and your Twilio number in TWILIO_SENDER .
In our main() function (Fission’s default entrypoint for Python tasks), we’ll need to do some setup so it can pick apart the body from Slack when a slash command like /twilio send:8325551900 hello, how are you hits your Fission task:
_def_ main(): params = urllib.parse.parse\_qs(_str_(request.get\_data())) incoming\_token = params["b'token"] channel\_name = params['channel\_name'] response\_url = params['response\_url'] message = params['text']
There’s a couple of new pieces here, the incoming_token which we’ll revisit in a moment to ensure it matches the desired token for the Slack app, and response_url which will give us a URL to POST a response back to with the status of the request.
We’ll, next, add some Help text, and then start slicing up the message:
so we’re separating out the number from the message text, and then handing it to our twilio_conn function (which I’ll cover in a second) and send that response back to the Slack response URL so you can see if your message was sent properly or not in slack_callback :
At this point, we can create this function:
fission function create --name twilio\_send --env python3 --route /twilio\_send --method POST --code send.py
and give the URL http://$FISSION_ROUTER/twilio_send to your Slack app’s Slash Command to POST to.
Our next step will be to create an endpoint for Twilio to send requests to, so we’ll do similar setup on our recv.py script. For this, you’ll just need your Incoming Webhook URL from Slack:
Before we go any further, let’s take a look at the sort of data Twilio sends over this webhook. In our example, we’ll get GET requests from Twilio that look like this:
"GET /twil?ToCountry=US&ToState=CO&SmsMessageSid=&NumMedia=0&ToCity=&FromZip=&SmsSid=&FromState=TX&SmsStatus=received&FromCity=&Body=Dhdhdhdhsh&FromCountry=US&To=%&ToZip=&NumSegments=1&MessageSid=&AccountSid=&From=%&ApiVersion=2010-04-01 HTTP/1.1"
and we’re mostly concerned with the From , To , and Body fields in the payload from Twilio, so in our recv.py entrypoint, we’ll want to handle these, and pass them to a slack_callout function like we did in send.py in a much simpler workflow:
We’re grabbing these fields from the request.args object containing the above formatted payload, and converting the values to strings, and passing it to a similar Slack callout function that just POSTs directly to the webhook URL to dump the message, and its sender, into the channel.
Once you create your task:
fission function create --name twilio\_recv --env python3 --route /twilio\_recv --method GET --code recv.py
go back over to the Twilio Console, and in the SMS field for your number, you’ll specify that you’d like a Webhook, and that the data be sent as a GET request to that endpoint, your http://$FISSION_ROUTER/twilio_recv URL:
You can take a look at the completed scripts here: