Learning To Code

Join me as I take the plunge!

How I Made Curb Your Flombaum

I’ve been at the flatiron school for about 3 weeks now. I’ve been learning so much - it’s really incredible how much progress I’ve been able to make in such a short period of time. This is in no small part due to the ability of Avi and Bob to both engage is in lectures and help us one-on-one when we get stuck. Part of being engaging in lectures though, has lead to some rather interesting things being said. Last semester the class started a blog to keep track of such utterances. I’m proud to say our semester has not only kept up this tradition, but in just three weeks already surpassed the last class in terms of the number of blog posts!

When I was asked to present to NYC on Rails, I knew that I was limited in my knowledge of programming, and had limited time to prepare since I was spending all day in class and all night studying and doing homework. I was supposed to find a topic, research it, and make a presentation. However I was determined to build something, no matter how small. On the first day of class, Avi ripped up his prepared lecture notes and said ‘we push code from day one’ and had us make a commit to github.Curb. I came here to build things, and so build something I did.

Curb Your Flombaum takes a random quote from the blog the class keeps about Avi, calls up my phone, and speaks it back to me. Here is how I did it.

1. Use feedzirra to parse XML and grab a random quote

There are lots of XML parsers out there, but I choose to use feedzirra because it seemed simple and had decent documentation. First, I had to require the Feedzira, Twilio, and Amazon S3 gems

1
2
3
require "feedzirra"
require 'twilio-ruby'
require 'aws/s3'

Then to actually get the quote I had to set the entire XML feed into a variable

1
feed = Feedzirra::Feed.fetch_and_parse('http://shitavisays.tumblr.com/rss')

From there I could just select a random entry be calling .sample and get just the title element (omitting any comments made beyond just Avi’s quote). The code will look like this

1
feed.entries.sample.title.to_s

2. Convert the random quote to an xml file

I now have the code that will give me back a string of a random Avi quote, but I need to put it in an actual XML file. To do that I’m first setting a variable xml to a string. This string is in the TwiML format, which I learned about using twillo’s excellent documentation. Twilio will automatically play an mp3 file if you wrap the url for the file in a command. Similarly Twilio will turn any text you wrap in a command into speech. Notice that I’ve put a \ before the quotes inside this string. I’m doing this to escape the characters so that ruby doesn’t prematurely end my string.

1
2
3
4
5
6
7
8
xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<Response>
  <Play>https://s3.amazonaws.com/NYConRails/intro.mp3</Play>
  <Pause length=\"0.5\"/>
  <Say voice=\"woman\">#{feed.entries.sample.title.to_s}</Say>
  <Pause length=\"0.5\"/>
  <Play>https://s3.amazonaws.com/NYConRails/exit.mp3</Play>
</Response>"

3. Save the file to my computer

Now that I have a dynamic variable for what an XML file would contain, I need to save it to my computer. Ruby’s official documentation made this task relatively easy.

1
2
3
File.open('call.xml', 'w+') { |f|
  f.puts xml
}

4. Upload the file to Amazon S3

Each time I run the program, I now have a new file called ‘call.xml’ that is saved to my computer. Each time it will include a new random Avi quote. I now need to host this file on the internet in order for Twilio to be able to work. I tried a lot of different solutions, but ultimately Amazon S3 was what I went with. I made an account, created a ‘bucket’ to store my files, and then was able to write more code. First I had to put in my credentials

1
2
3
4
AWS::S3::Base.establish_connection!(
  :access_key_id     => 'SDF7FS7DFS202S2LKSDS', # <-- put in your own, this is a fake one
  :secret_access_key => 'ASFDHSADF23HSDFASDFJSSX722iaf28#sdfsdf2' # <-- put in your own, this is a fake one
)

Then I had to actually upload the file to S3

1
2
file = 'call.xml'
  AWS::S3::S3Object.store(file, open(file), 'NYConRails', :access => :public_read)

Amazon’s official documentation left out the ‘AWS::S3’ prefix, which I had to figure out on my own. I also just made a guess on how to make the file public (it’s private by default), so they could improve that part of the documentation as well.

5. Use Twilio to convert the text into speech and call my phone

Now that I have an XML file with a random Avi quote hosted on the internet, I need to configure Twilio to do it’s magic. First I set my my credentials

1
2
account_sid = 'JH96987LKJLKJLKJsadfasdf3323423sfasd' # <-- put in your own, this is a fake one
auth_token = '98273234sdf2342309sd0f9s8fd980s3' # <-- put in your own, this is a fake one

Then I set up a client to talk to the Twilio REST API

1
@client = Twilio::REST::Client.new account_sid, auth_token

Finally I give twilio instructions on what I want it to do. I want it to call my phone (the to:) using the phone number i have associated with the account (the from:) using the instructions in TwiML format I have hosted on S3 (the url:). At first this did not work, but I asked Twilio for help and they got back to me saying I needed to specify that this was a GET request (the method:).

1
2
3
4
5
6
@call = @client.account.calls.create(
  :from => '+12129983322', # <-- put in your own (must be the one linked to your twilio account), this is a fake one
  :to => '+12123340076', # <-- put in whatever phone number you want to call, this is a fake one
  :url => 'https://s3.amazonaws.com/NYConRails/call.xml', # <-- put in your own, if you use S3 it will just be https://s3.amazonaws.com/YOUR_BUCKET_NAME/call.xml
  :method => 'GET'
)

In conclusion

So there is how I made Curb Your Flombaum. I have open sourced the project at github, and would love anyone to take this code and run with it. I have a lot of ideas for improving this app - maybe making the ability to sign up to get Avi quotes sent to your phone as they come in. However this was an MVP for a demo, and I’m proud to have done this after learning how to code for just three weeks.