Python Madlibs

The sample below is a simple Mad Libs game using news and connection from the daylife API.

The code is in python and it needs mod_python module to be accessible on a apache web server.

Sometimes the results are a bit on the funky side, but, hey, it's an example.

Play it here.

from mod_python import apache
from mod_python import util
import urllib
import random
import cjson
import md5

# Base URLs and authentication information
ACCESSKEY = '8befa1cf0a7c0291613242235638a662'
SHARED_SECRET = '2e548ef751397c653752057adcff0c9f'
SEARCH_RELATED_TOPICS = 'http://freeapi.daylife.com/jsonrest/publicapi/4.1/search_getRelatedTopics?limit=10&signature=%s&accesskey=%s&offset=0&query=%s&include_topic_type=%s'
SEARCH_RELATED_ARTICLES = 'http://freeapi.daylife.com/jsonrest/publicapi/4.1/search_getRelatedArticles?limit=25&signature=%s&accesskey=%s&offset=0&query=%s'
ARTICLES_GET_TOPICS = 'http://freeapi.daylife.com/jsonrest/publicapi/4.1/article_getTopics?limit=10&signature=%s&accesskey=%s&offset=0&article_id=%s&include_topic_type=person'
ARTICLES_GET_QUOTES = 'http://freeapi.daylife.com/jsonrest/publicapi/4.1/article_getQuotes?limit=7&signature=%s&accesskey=%s&offset=0&article_id=%s'


def index(req):
	request_data = util.FieldStorage(req)
	query = request_data.get('query', None)
	page_data = get_response(query)    
	req.content_type = 'text/html'
	req.send_http_header()
	req.write(str(page_data))
  
 
# Creates the appropriate page  
def get_response(query):
	if query is None: return BAD_QUERY_PAGE
	words = load_words(query)
	if words is None: return NO_DATA_PAGE % (query.upper(), query)
	words['query'] = query
	return PAGE_DATA % words
	   

# Gets the daylife results from the url.            
def retrieve_daylife_results(url, result_type):
	opener = urllib.urlopen(url)
	data = opener.read()
	results = cjson.decode(str(data))
	
	# If there was an error returning results, ignore it.
	if results['response']['code'] < 0: return []
	
	# All daylife results are nested in a 'payload' object, which is 
	#   nested in a 'response' object.
	return results['response']['payload'][result_type]
	  

# For a given query, get the signature from the authentication
#   information       
def calc_signature(accesskey, sharedsecret, query):
	m = md5.new()
	m.update(accesskey)
	m.update(sharedsecret)
	m.update(query)
	return m.hexdigest()

# Use the DayPi to generate the random words.
def load_words(query):
	signature = calc_signature(ACCESSKEY, SHARED_SECRET, query)
	words = {}
	
	people = retrieve_daylife_results(SEARCH_RELATED_TOPICS % (signature, ACCESSKEY, urllib.quote(query), 'person'), 'topic')
	if len(people) < 2: return None
	words['person1'] = people.pop(random.randint(0,len(people)-1))['name']
	words['person2'] = people.pop(random.randint(0,len(people)-1))['name']    
	
	place = retrieve_daylife_results(SEARCH_RELATED_TOPICS % (signature, ACCESSKEY, urllib.quote(query), 'place'), 'topic')    
	if len(place) < 1: return None
	words['place'] = place.pop(random.randint(0,len(place)-1))['name']

	organization = retrieve_daylife_results(SEARCH_RELATED_TOPICS % (signature, ACCESSKEY, urllib.quote(query), 'organization'), 'topic')    
	if len(organization) < 1: return None
	words['organization'] = organization.pop(random.randint(0,len(organization)-1))['name']    

	article_results = retrieve_daylife_results(SEARCH_RELATED_ARTICLES % (signature, ACCESSKEY, urllib.quote(query)), 'article')    
	if len(organization) < 1: return None

	for article in article_results:
		signature = calc_signature(ACCESSKEY, SHARED_SECRET, article['article_id'])
		article_quotes = retrieve_daylife_results(ARTICLES_GET_QUOTES % (signature, ACCESSKEY, urllib.quote(article['article_id'])),'quote')    
		
		if len(article_quotes) < 1: continue 
		article_topics = retrieve_daylife_results(ARTICLES_GET_TOPICS % (signature, ACCESSKEY, urllib.quote(article['article_id'])),'topic') 
		if len(article_topics) < 1: continue

		words['timestamp'] = article['timestamp']
		words['headline'] = article['headline']
		words['source'] = article['source']['name']
		words['url'] = article['url']
		words['quote'] = article_quotes.pop(random.randint(0,len(article_quotes)-1))['quote_text'].upper()
		words['person3'] = article_topics.pop(random.randint(0,len(article_topics)-1))['name']
		break

	if len(words.keys()) != 10: return None
	return words


BAD_QUERY_PAGE = """<html><head><title>Bad query! BAD!!</title><head>
				  <body>...WHAT are you looking for?!?</body></html>"""

NO_DATA_PAGE = """<html><head><title>%s??? Really??</title><head>
				  <body>As much as you love %s, it's not really something I want to talk about. Maybe we could talk about something more, er, normal...</body></html>"""

PAGE_DATA ="""<html><head><title>There's something about %(query)s</title></head><body>
<p>That's so funny that you were just talking about %(query)s! 
I remember something like that happening back around %(timestamp)s.
You see, it all started when I was walking down the street and then
%(person1)s and %(person2)s walked by. 

<p>Now, I'm not normally nosy, but these two looked like they were 
up to no good. I stopped them and asked them where they were going.
"%(place)s." is what they barked back. I could tell they were lying.

<p> Being the ever viligant citizen that I am, I followed the two.
Wouldn't you know, they weren't going to %(place)s at all, but instead
stopped by %(organization)s. I peeked in the window and wouldn't you 
know, they were meeting %(person3)s! Things looked like they were a
little heated and then %(person3)s jumped up and yelled "%(quote)s".

<p>I don't know about you, but after that remark, I didn't feel like
sticking around. Surely enough, the next day, I bought a copy of %(source)s
and there, the headline, right there in black and white, 
proclaimed <a href="%(url)s">%(headline)s</a>!

<p>How strange!
</body></html>
"""