Here at SBO we love our food trucks. Even in the dead of winter we can be found waiting in line for our chicken and rice while enduring wind chills of 20°F and below. When we are not outside freezing our butts off, we can be found at our desks communicating with each other through HipChat, our preferred team chat software. On most days, the question of which Boston Food Truck awaits us comes up. I decided it would be fun to find a way to get HipChat to tell us each day what we want to know before we even ask.
HipChat automation basics
HipChat has a nice API available. To take advantage of it, you will need a group admin account on HipChat. The first step is to create an API Auth Token —a fairly simple process that is explained on the site. For our purposes, it will need to be of type ‘Notification.’ Its label can be what ever you like; I chose FTotD: Food Truck of the Day. (It will be useful to make an admin token as well for testing this next part, but in the end, we want the notification token.)
Now we need to test out the authentication by getting the HipChat API to give us a list of the rooms. HipChat kindly supplies some sample code for us in many languages. We write lots of Python code at SBO, so I chose to write my script in Python. Here is the code that will get us started:
import urllib2 url = "https://api.hipchat.com/v1/rooms/list?auth_token=TOKEN" request = urllib2.Request(url) response = urllib2.urlopen(request) print response.read()
If you put your admin token in the code where indicated, you should get back a list of the rooms as well as the id values for each room. (It would be useful at this point to create a room to test your code. Once you have that ready, re-run this script and take note of the room you just made.)
We want to be able to send messages to HipChat, so we will first need to change the method from rooms/list to room/message in the URL above. The rooms/message method has a few required parameters that we will need to pass along such as room_id, from, and message. There are two others that I chose to change form their default values: notify and color. Add or change the following lines in the script, add your own specific values for the all-caps text, and give it a shot:
room = "YOUR ROOM NUMBER" token = "YOUR AUTH TOKEN" sender = "BostonFoodTruck" color = "purple" notify = "1" message = "Test Message" url = "https://api.hipchat.com/v1/rooms/message?room_id="+room+"&amp;auth_token="+token+"&amp;from="+sender+"&amp;message="+message+"&amp;color="+color+"&amp;notify="+notify
If all went well, you should have gotten a response that said “sent” and a message in your newly created room.
What’s for lunch?
Now that we have mastered sending a message to a room in HipChat, we need to make it interesting. The City of Boston provides a nice online app to help you figure out which food truck will be stopping by your neighborhood on which days. Check it out! This is great for a human user, but getting a script to extract the info we need from here will not be easy. The good news is that they have a mobile version of this page here that’s marked up as a simple table. I chose to use the Python urllib and urlopen methods to grab all the info off this page:
import urllib url_file = urllib.urlopen("http://www.cityofboston.gov/business/mobile/schedule-app-min.asp") file_lines = url_file.readlines()
I added that last line to break the file up into an array of lines so that later I can search through them and reference them with simple indexing. If you look at the markup code for the table on the city of Boston webpage, you will see that each line in the table looks something like this:
<td class="map"><a href="#maps" onClick='window.location.href=getMapLink("770074664779-2952731269296",
"Roxy's Gourmet Grilled Cheese 1");'>Map</a></td>
<td class="com"><a href="http://www.roxysgrilledcheese.com">Roxy's Gourmet Grilled Cheese 1</a></td>
"Roxy's Gourmet Grilled Cheese 1"))</script>
(25) Innovation District, Seaport Blvd at Thompson</td>
Ultimately we want to get the URL out of the second line above, but we need to make sure it comes form the right part of the table. The last three lines help make that easy. All we need to do is search for a set of lines that contain my location, (25) Innovation District, Seaport Blvd at Thompson, the meal of interest (lunch), and the day of the week. But before we can do the search, we need to determine which day of the week it is. Luckily, Python will just handle this for us:
import datetime now = datetime.datetime.now() dotw = now.strftime("%A") # For example, "Thursday" meal = "Lunch" location = "(25) Innovation District, Seaport Blvd at Thompson"
Putting that right after the file_lines declaration should set us up well to extract the information we seek. The trick here is to reference the right lines as we loop though all the file lines and cut out the html code so that we are only left with the URL to the web page of the food truck we want.
i = 0 for line in file_lines: if location in line and meal in file_lines[i-1] and dotw in file_lines[i-2]: truck_url = file_lines[i-3].rsplit('href="',1).rsplit('">',1) i += 1
[Ed. For a more complicated HTML parsing problem we definitely recommend using a real XML/HTML parser like our perennial favorite lxml, but the sooner Matt could write this bot, the sooner we could get lunch. – Liza]
At this point we have the URL for the truck and we only need to add a line for the message as such:
message = truck_url
If you run your script now you should get a message in your room that tells you the URL for today’s truck at your location. But that is pretty boring, especially since HipChat expects an HTML-encoded message by default. We can send out a message that looks good and will do something if you click on it. For this I choose to use the main logo from each of the food truck’s websites that stop by our office and their menu page if they had one. Since all the webpages are written differently, there was no elegant way to code this, I simply had to copy the URLs for every page and put them directly into my code. The last block of code looks like this:
if truck_url == "http://www.roxysgrilledcheese.com": message = "<a href='http://www.roxysgrilledcheese.com/menu'> <img height='100' src='http://www.roxysgrilledcheese.com/wp-content/themes/bones/images/header.png'/></a>" elif truck_url == "http://www.bennyscrepecafe.com": message = "<a href='http://www.bennyscrepecafe.com/menu'> <img height='100' src='http://www.bennyscrepecafe.com/wp-content/uploads/2012/10/header3.png'/></a>" elif truck_url == "http://thechickenriceguys.com": message = "<a href='http://thechickenriceguys.com/'> <img height='100' src='http://thechickenriceguys.com/images/cnrg_logo.jpg'/></a>" elif truck_url == "http://www.bonmetruck.com": message = "<a href='http://blog.bonmetruck.com/?page_id=9'> <img height='100' src='http://blog.bonmetruck.com/wp-content/uploads/2012/11/Bon_Me__4colorlogo3-300x235.png'/></a>" elif truck_url == "http://www.meimeistreetkitchen.com": message = "<a href='http://meimeiboston.com/menu/'> <img height='100' src='http://meimeiboston.com/wp-content/uploads/2012/03/cropped-meimeiheader1.jpg'/></a>" else: message = truck_url
While the food trucks that show up here do not typically change from week to week, I added the last condition just in case. If I see a plain URL pop up one day I will have to add a new condition to make up for the new truck. One final line is needed to make the message safe for passing through a URL:
message = urllib.quote(message)
At this point you should be able to run this and see a message pop up in your test room with what ever info you put in your message. At this point, the Python script is complete, you will just need to edit it to put have the right notification token and room ID.
The next trick will be to get the script to run at a certain time each day and on the days that are important to you. For that we will use cron. I want my script to run Monday through Friday at noon. Log in to your favorite unix machine that is on all the time. Run the command ‘crontab -e’. If it is your first time, it will ask you which editor you use, choose your favorite. Read the info it gives you and at the end add a line like this:
00 12 * * 1-5 /path/to/your/script.py
the way that will read to cron is, run this command “/path/to/your/script.py” any month of the year, any day of the month, Monday – Friday, at the 12th hour, on the 00 minute. You will need to add:
as the first line in your Python script and make the file executable. Last thing to do is wait and enjoy the results.
Well, there you have it, a Python script that will look up food truck info and post it to HipChat five days a week.