My affinity towards programming grows stronger with each hackathon I attend. Personally, being on a time restraint serves as a big motivation to hack and code without interruption, optimizing productivity and absorbance… and when I have a deadline, I want to perfectly finish a task from start to end—bug-free. With this trait in mind, this weekend’s Hack for Change really made me realize the flexibility and magical qualities of programming on the back-end. Our project this weekend (Blastee) is an application that helps anyone in danger alert and get help from pre-selected contacts with the touch of a big red HELP button. I offered to handle the Twilio component (SMS+Call) of our app:
- Once a Victim presses the big red button, a Machine will call all of Victim’s emergency contacts at the same time.
- When a Contact picks up, Machine will report to Contact the Victim’s location, and that he needs assistance.
- Machine will ask if Contact wants to help. If yes, press one.
- Contact then receives an SMS detailing Victim’s location.
- Machine connects Victim to Contact so they can talk.
Aaaaand that’s where I began my road to happiness, exuberance, and passion-building. The snippets of code here will all add up to be my whole code.
Initially, I tried to run the Twilio code via Sinatra on a localhost, but soon realized Twilio can’t access my localhost domain, so that’s why I couldn’t call. Well, the other reason was because I didn’t upgrade my trial account, so I couldn’t call no matter what I did.
Thus, I set up a heroku server for Blastee and began testing out each function. Here’s the set-up.
require 'rubygems'
require 'twilio-ruby'
require 'sinatra'
ACCOUNT_SID = 'AC2b5c36b6e2b9969be7596d7e8f2e0f7c'
AUTH_TOKEN = '6ab5b4dc96ff7bd3cfc97cdcade057b2'
CLIENT = Twilio::REST::Client.new(ACCOUNT_SID, AUTH_TOKEN)
#+13109826618 is the machine's number
Twilio’s REST API lets you call several numbers at once, so here’s step 2.
get '/call' do
@account = CLIENT.account
@contacts = ['3108455437', '3109755545', '3105555555'] #emergency contacts
@contacts.each do |contact|
@account.calls.create(
:from => '+13109826618',
:to => contact,
:method => "GET",
:url => "http://tblastee.herokuapp.com/call-handler?contact=#{contact}")
end
erb:call
end
Once we integrate this into our application, @contacts will import the whole emergency contact list so Twilio calls each on of them, all at the same time.
Step 3 below further uses the “contact” stored in the url to send an SMS to the Contact (twiML).
get '/call-handler' do
params = Rack::Utils.parse_nested_query(request.query_string)
contact = params["contact"]
response = Twilio::TwiML::Response.new do |r|
r.Gather :timeout => "20", :numDigits => "1", :finishOnKey => "1",
:action => "/direct", :method => "GET" do |g|
g.Say "DRUNKARD needs a ride. He is at ADDRESS. If you can help, press 1.",
:voice => "woman", :loop => "2"
end
puts contact
r.Sms "I am at ADDRESS", :from =>'+13109826618', :to => contact,
:method => "GET"
r.Dial do |d|
d.Number "3109755545" #VICTIM
d.Conference "Help", :waitMethod => "GET", :beep => "false"
end
end
response.text
end
Since “contact” is stored in the url, params[“contact”] extracts the number so we can use that in sending SMS to Contact once Contact presses 1. As the SMS is sent, Twilio then calls the Victim, and connects them together. YIPEE! Help has arrived! =D
Additional feature: In each call, the machine states who the Victim is, and where the Victim is.
The concept of XML never really unclouded itself in my head, so twiML was hard to understand—I could not figure out how to use it. How will my code understand commands like “Record”, “Response”, and “Say”? WELL. Twilio intern Oscar Sanchez gave me a couple lines of example code, and BOOM! Revelation.
response = Twilio::TwiML::Response.new do |r|
That line ^ is what I had to include to finally have the commands make sense and logic.
Well, to get this code to where it is now, there was undoubtedly ugly, ugly code. Twilio’s documentation for twiML confused me a little in that it didn’t differentiate between the Dial and Conference command. With that said, here’s the difference I discovered through trial and error. Dial can connect person1 with person2, just like Conference does, but Dial hangs up on person1 then calls them back after person2 picks up, while Conference just keeps person1 on the line, regardless of whatever person2 decides to do. Oh, and switching to Conference command from Dial for this particular project took off ~20 lines of code.
This brings me to how my passion for programming grew. After I cleaned up my code and shortnened it drastically form what it was before, a feeling of pure satisfaction came over me and I felt myself lifted to a thoroughly clean and refreshed state of mind, partnered with an immense amount of relief and pride. Though perfectly implementing a simple API like Twilio’s may not seem like an achievement at all for experienced programmers, I am not afraid to still say that I am happy, and I am proud of what I accomplished. Experiences like these account for most of my passion-intensifying because I get a type of satisfaction not attainable anywhere else. I hope that as I continue with my code adventure, other women and teenagers can experiment more with programming and experience the bitter-sweet moments that helped me run forward on the path I am now.