Silly Project of The Day: Find out when Bake Off is on next, via phone

I’ve recently been playing around with Plivo, which is a competitor to Twilio and lets you connect voice calls and text messages to HTTP endpoints.

I decided to put together a silly demo app that used the text-to-speech API.

First off let’s parse http://www.bbc.co.uk/programmes/b013pqnm/broadcasts/upcoming, which happens to be the page listing the next time The Great British Bake Off is on.

BBC’s HTML is pretty excellently marked up, so we’ll import BeautifulSoup and requests, then get to work.

import requests
from bs4 import BeautifulSoup
import os
import arrow

def get_next_bakeoff():
    url = "http://www.bbc.co.uk/programmes/b013pqnm/broadcasts/upcoming"

    if not os.path.isfile("bakeoff.cache"):
        print('downloading')
        bakeoff = requests.get(url).content
        open('bakeoff.cache', 'w').write(str(bakeoff))
    else:
        bakeoff = open('bakeoff.cache', 'r')
        content = BeautifulSoup(bakeoff, 'html.parser')
        elements = content.find('ol', 'highlight-box-wrapper')
        spans = elements.find_all('span')

I’ll save you some of the work here. The main program listing on that page is in an ordered-list (ol element). The interesting meta-data is in spans, so the lazy way is to just grab all of them and then filter from there.

Each program listing has a span with a position attribute so let’s use list comprehensions and magic.

positions = [span for span in spans if span.get('property') == 'position']

Now we have BeautifulSoup references for each program that has a ‘position’ in the list.

.,
Next, let’s sort the list and grab the ‘startTime’ attribute for the latest episode

        positions.sort(key=lambda x: x.text)
        start_time = [p.find('h3') for p in positions[-1].parents if
                      p.find('h3') is not None and p.find('h3').get('property') == 'startDate'][0]['content']

Now we have a start_time of something like 2015-08-26T20:00:00+01:00 which is fantastic, because it’s a standard datetime, and it’s got a timezone offset. BBC are really making this easy for us.

Next, let’s use the excellent arrow Python module to convert the datetime into our local timezone (at the moment for me that’s Canada’s Pacific time)

        next_bakeoff = arrow.get(start_time).to('local') 

2015-08-26T20:00:00+01:00 becomes 2015-08-26T12:00:00-07:00, and we know I might be able to watch Bake Off in my lunch break on Wednesday, if I’m lucky.

        next_bakeoff = arrow.get(start_time).to('local')
        current_time = arrow.now('local')
        if (next_bakeoff > current_time):
            return next_bakeoff

The text to speech part is really the easiest. Have a look at Plivo’s documentation
We could use Plivo’s XML library but at the time I didn’t know about this and I was fighting compilation issues in lxml, so again, I did this the easy way – "".format(). There’s not a lot of magic here – Plivo’s servers do the hard work. I’m setting en-GB so I get a voice with a distinctly British accent. The TTS voices are really nice, I think Plivo have shelled out the big bucks for Cepstral voices.

            xml = '''<Response>
                  <Speak language="en-GB" loop="1" voice="WOMAN">
                  The next episode of Bake Off is {0}
                  </Speak>
                  </Response>'''.format(next_bakeoff.humanize())

The call to .humanize() again comes from arrow and turns the timestamp into something nice like in 5 days
What I haven’t shown here is the Flask app that I’ve put my code in, so instead of return xml I do return Response(xml, mimetype='text/xml').

Plivo have posted a good example of a TTS application at https://github.com/plivo/phone-tts-python.

Left as an exercise to the reader is hooking up the application to a Plivo phone number. I just followed the tutorial in the Getting Started / Text to Speech on a Call section.

At 0.8 cents a call, it wouldn’t be a cheap toy to play around with in any significant amount, but it’s not going to break the bank, either.

The Great British Bake Off airs in the UK on BBC1 at 20:00 GMT.

If you’d like to support me and this blog, send bitcoins to 17RugTAi9LdxMUcgVhpWVRRvVsWg11P6V5 or check out my Support Me page.

If you’d like something completely different, try making some Chicken Avocado Alfredo from The Cinnamon Scrolls

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s