SMS Workflow Madness: Twilio to PHP to Python to Dropbox to Autohotkey to Conquer The World
Recently, I've been trying to trigger some python code using a text message. It has been a complicated little journey, so I thought I'd write it up for you. If you don't want to read through it all, the summary is - twilio to PHP to launch Python to put a file in Dropbox, autohotkey to monitor dropbox and run a python script. Away we go... First, Twilio is a great service if you want to develop anything with text messages. At first, I built a quick fix using If This Then That (which you should check out either way). However, I soon realized that the benefit of a text message is that it is nearly instant. IFTTT only checks tasks every 15 minutes and in a crunch, I would want a response back before then...
So I signed up for Twilio and created my application. The applications can be very complex, but for my purposes, I just needed a few lines of PHP to receive the text from the SMS and then use that information. Here is my test script:
<?php
header("content-type: text/xml");
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
$body = $_REQUEST['Body'];
$from = $_REQUEST['From'];
$path = "/var/www/cgi-bin/addfile.py";
$command = "python ".$path." '$body'";
$command = escapeshellcmd($command);
exec($command,$result);
echo "<Response>
<Sms>Thanks for the message:".$body." your num:".$from." </Sms>
</Response>";
?>
There's a lot going on there, but here is the gist. The first two lines format the document as XML for Twilio to understand what should be done. No surprises here.
header("content-type: text/xml");
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
The next part pulls the data from the text message into body and from and then passes these values to a python script I wrote to interact with dropbox.
$body = $_REQUEST['Body'];
$from = $_REQUEST['From'];
$path = "/var/www/cgi-bin/addfile.py";
$command = "python ".$path." '$body'";
$command = escapeshellcmd($command);
exec($command,$result);
The final part is the xml. This I pulled straight from the Twilio getting started guide
echo "<Response>
<Sms>Thanks for the message:".$body." your num:".$from." </Sms>
</Response>";
Ok so now we have a file for Twilio to interact with. Next we need to put some content in that python file. Before you try this out, you'll need to install the dropbox api libraries. I used the command
easy_install dropbox
but you might have to do that differently based on your operating system.
#!/usr/bin/python
# Include the Dropbox SDK libraries
from dropbox import client, rest, session
import sys
name = sys.argv[1]
# Get your app key and secret from the Dropbox developer website
APP_KEY = 'xxxxxxxxxxxxxxx'
APP_SECRET = 'xxxxxxxxxxxxxxx'
# Access type will be defined in your dropbox settings
ACCESS_TYPE = 'app_folder'
sess = session.DropboxSession(APP_KEY, APP_SECRET, ACCESS_TYPE)
# I removed this section after obtaining my access_token
# and access_token_secret, but you'll need to do it once.
# The return value will be a string that you can parse.
#request_token = sess.obtain_request_token()
#url = sess.build_authorize_url(request_token)
#print "url:", url
#print "Please visit this website and press the 'Allow' button.
#raw_input()
access_token = "xxxxxxxxxxxxxxx"
access_token_secret= "xxxxxxxxxxxxxxx"
sess.set_token(access_token, access_token_secret)
client = client.DropboxClient(sess)
print "linked account:", client.account_info()
#create the file if it doesn't exist
#f = open('file.txt', "w")
#f.close()
#open it for reading only...
f = open('file.txt')
# put the file to the app_folder in dropbox
response = client.put_file('/'+name+'.txt', f)
# this is the response passed back to PHP for debugging.
print "uploaded:", response
The file above is a bit of a mess but the idea is simple, take an argument as the command, authenticate with dropbox and put a file in dropbox with that name. I've tried a few different ways to do this a Dropbox PHP class or two... The python script turned out to be much easier for me - perhaps you have had better luck?
So now, with all that lovely code above, when I send a text message to my twilio account number, the php file takes the SMS message as a command and launches the python dropbox script, putting a file with that command name in my folder. The last part is an autohotkey script that I have to monitor the app_folder (it's actually sitting in the app folder for simplicity). Here is that file:
#persistent
setTimer check_file,1000
return
check_file:
IfExist, command.txt
{
filemove command.txt, %A_ScriptDir%\processed\command%A_Now%.txt
run myprogram.py command
}
This script checks my folder for a file called "command.txt" and then if it finds it, runs a script and moves the file to a processed folder with a time stamp. It's not perfect, as it requires a separate "look" for each command that you want to run, but it was perfect for my needs.
So that's my system. It's not pretty and it has a few more steps than I'd like for efficiency and safety, but it does work. Fast. In fact, a text message can trigger a program on my remote machine within 10 seconds. That is not bad...
Let me know if you've tried something similar or have suggestions on improvements. I'd love to hear it.
-ab