SMS Swimming Lap Counter in bash with Twilio

Kate’s participating in a semester long 100 mile swim challenge at CSUF through the Student Rec Center (SRC).  They’ve got a small pool you can swim laps in, and there’s a prize if you swim a certain number of miles.  To help with tracking and motivation, I wrote a super simple set of scripts for her to keep track of her miles and send her daily stats reminders.

The application is just written in bash, because bash is easy, and can be enabled for CGI in apache.  Let’s get to it!  I wanted this to be text message based, so I started with Twilio.  I purchased a new number for $1/month and set it up to handle incoming text messages with a Webhook:

So incoming messages will hit laps.sh with a query string FULL of information.  I only care about the incoming number and the message.  Let’s take a look at laps.sh:

#!/bin/bash

echo "Content-type: text/html"
echo ""

MESSAGE=$(echo $QUERY_STRING | tr '&' '\n' | egrep '^From=|^Body=' | tr '=' ' ' | awk '{ print $4 $2 }')
MSGARRAY=($MESSAGE)

## make sure it's kate
[ ${MSGARRAY[1]} == "%2B1626xxxxxxx" ] || exit 1

## make sure it's a number greater than zero
[ ${MSGARRAY[0]} -ge 1 ] || exit 1

## record value
echo -n ${MSGARRAY[0]} >> records.csv
echo -n " " >> records.csv
date +%Y-%m-%dT%H:%M:%SZ >> records.csv

## get number of days left
NOW=$(date +%s)
END="1576886400"
DAYS=$((($END-$NOW)/86400))

## get total laps swam
SWAM=$(awk '{ sum += $1 } END { print sum }' records.csv)

## lap math
TOTALLAPS="7000"
LAPSLEFT=$(($TOTALLAPS-$SWAM))
if [ $DAYS -ge 1 ]
then
  LAPSDAY=$(($LAPSLEFT/$DAYS))
else
  LAPSDAY=$LAPSLEFT
fi

RESPONSE="Added ${MSGARRAY[0]} laps to the counter!%0aThat is $LAPSLEFT laps to go!%0a$DAYS days until the end...%0aThat is $LAPSDAY laps per day if you swam every day!"

KATE="+1626xxxxxxx"
curl --silent -XPOST -d "Body=$RESPONSE" -d "From=+1657yyyyyyy" -d "To=$KATE" "https://api.twilio.com/2010-04-01/Accounts/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/Messages" -u "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"

The script is pretty self explanatory, for the most part.  The content type stuff is required or else apache gives out 500’s.  The MESSAGE variable is just breaking apart the query string into multiple lines, grepping for the two lines I actually care about, and the following line puts them into a string array.

The “From” field needs to match Kate’s phone number, or else I just exit.  The first word of the body needs to actually be a number greater than zero, or else we exit.  Once that’s validated we store the number of laps and the date in a local csv file.

There’s 70 laps in a mile in this pool.  The ending date is in unix time (Dec 21 2019 in this case).  The rest is just a little math to build a message, and then a curl call to send a response message.

I also call a dailyreminder.sh file from a cron job.  It’s pretty much the same thing but without the query string handling and a slightly different message.  I hope she makes it to 100 miles!

Leave a Reply

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