We live in a time where it is no longer enough to build a good web app that is self contained. Applications are expected to be open, not only for accessing and migrating data, but also for extensibility. Developers provide APIs, from passive polling-based JSON formats to pushing data through mechanisms like pubsubhubbub. App Engine turns out to be a great medium to build and host these extensions, be it just for one personally or as a generally available service.
When I started this blog, I defined its purpose to being "dedicated to the Google App Engine and ways of putting it to use". Over the course of the last 17 months, I wrote about building commercial and personal applications, using Python or Java, with the datastore, memcache, urlfetch, and other services. I have posted about tricks for unit testing, and how an App Engine can be extended through low-level features, such as hooks or monkeypatches. Today, I'd like to write about another use: extending other non-Appengine web services, App Engine style. Not the so fashionable mashup kind of extension; just an everyday hack to make life easier.
This particular post is going to focus on the Meetup API. Meetup is a great service for coordinating events for groups of people, like for example the SF Bay Area Google App Engine Developers group. A meetup organizer can create new events, manage capacity constraints (how many people may join), and collect feedback on how the particular event was. One of the meetups I am personally hooked on is a boardgame group in my area. It is a ton of fun and I really enjoy it, but "getting in" can sometimes be tricky. Unfortunately, many other people have also discovered the same group, and space for the events is quite limited. New events may pop up at any time, and whoever sees it first on the callender and RSVPs gets to go.
Since I am not very good at watching out for these kind of things, I would like somebody else to do the job for me. The following script checks all my meetup groups for new events and notifies me by email when they come up (note: it would be just as easy to "snipe" the events by automatically RSVPing, but let's give the others a fair chance, too ;-):
# Assumed this runs in App Engine:
# Make this a "text request, so that all output
# appears in the browser windor
print 'Content-Type: text/plain'
print ''
# Do the necessary imports
import meetup_api_client as api
import datetime
from google.appengine.api import mail
import logging
from google.appengine.ext import db
# Some data for the meetup API (anonymized, of course ;-)
MAIL_ADDRESS = 'my-email@example.com'
API_KEY = 'get-this-from-meetup.com'
MEMBER_ID = 42 # get this from meetup.com
def pr(s):
"""Print both to console and log."""
logging.info(s)
print s
class Event(db.Model):
"""Represent an event we already sent out."""
name = db.StringProperty()
time = db.StringProperty()
# Create a new meetup api instance
mu = api.Meetup(API_KEY)
# Go through all groups of this user
for group in mu.get_groups(member_id=MEMBER_ID).results:
group_id = group.id
# Get all future events
for event in mu.get_events(
group_id=group_id,
after=datetime.datetime.now().strftime(
'%m%d%Y')).results:
# Ignore any event we have already RSVPed
if event.myrsvp == 'none':
key_name = ':%s' % event.id
# Avoid sending duplicate mail
entity = Event.get_by_key_name(key_name)
if not entity:
# Send out email
mail.send_mail(
MAIL_ADDRESS,
MAIL_ADDRESS,
'New event for %s' % group.name,
'Consider RSVPing for %s at %s' % (
event.name, event.time))
Event(key_name=key_name,
name=event.name, time=event.time).put()
pr('Sent out mail for %s at %s' % (
event.name, event.time))
else:
pr('Ignoring event %s at %s' % (
event.name, event.time))
This simple script will send me one, and only one, email for every new event that gets added to any group I am a member of. I can combine this with an App Engine cron job like the following, which fires the script every minute:
cron:
- description: Find new meetup events
url: /findEvents
schedule: every 1 minutes
This way, within a minute after its creation, I get notified about any event that may be out there. Since i get incoming emails directly onto my phone, I can quickly make up my mind whether to attend or not. Thanks to the meetup service being extendible via an API, I can customize the sites behavior, which will in return make me use the service more -- and happy users hopefully mean more revenue to a site in the long run.
While the listing above looks like an oversimplified example, it happens to be what I actually use for my meetups. A lot of the complexity is hidden by the meetup client library, and of course by the fact that python eliminates a lot of the overhead that other languages might bring to the table. It turns out that App Engine is a pretty nice host for these kind of personal hacks and scripts -- it certainly beats me having a linux box up and running all the time. Like mentioned before, I would do a terrible job of a system administrator, and thus probably miss a lot of game nights ;-)