├── README ├── app.yaml ├── index.html └── sample.py /README: -------------------------------------------------------------------------------- 1 | A sample push API consumer for the new foursquare push API. 2 | 3 | Has a very simple endpoint for doing OAuth, and a /checkin handler that 4 | receives a POST with checkin and user JSON. The JSON is expected to have a 5 | "checkin" key with a corresponding checkin object, and a "user" key with a 6 | correspoding compact user object. Those formats are described in more depth at 7 | http://developer.foursquare.com/docs/responses/checkin.html and 8 | http://developer.foursquare.com/docs/responses/user.html, respectively. 9 | -------------------------------------------------------------------------------- /app.yaml: -------------------------------------------------------------------------------- 1 | application: 4sq-push-api-sample 2 | version: 1 3 | runtime: python 4 | api_version: 1 5 | 6 | handlers: 7 | - url: / 8 | static_files: index.html 9 | upload: index.html 10 | expiration: 0 11 | login: required 12 | - url: /checkin 13 | script: sample.py 14 | - url: /.* 15 | script: sample.py 16 | login: required 17 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | foursquare push api sample 5 | 6 | 7 |
8 |
9 |

Checkins that have been pushed to this server:

10 | 11 | 12 | 13 | 14 | 15 | 16 |
Checkin IDVenue Name (or Shout)Time
17 |
18 | 19 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /sample.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import cgi 4 | import logging 5 | import urllib2 6 | 7 | from django.utils import simplejson 8 | 9 | from google.appengine.api import users 10 | from google.appengine.ext import db 11 | from google.appengine.ext import webapp 12 | from google.appengine.ext.webapp.util import run_wsgi_app 13 | 14 | # prod 15 | config = {'server':'https://foursquare.com', 16 | 'api_server':'https://api.foursquare.com', 17 | 'redirect_uri': 'http://4sq-push-api-sample.appspot.com/oauth', 18 | 'client_id': 'YOUR ID HERE', 19 | 'client_secret': 'YOUR SECRET'} 20 | 21 | class UserToken(db.Model): 22 | """Contains the user to foursquare_id + oauth token mapping.""" 23 | user = db.UserProperty() 24 | fs_id = db.StringProperty() 25 | token = db.StringProperty() 26 | 27 | class Checkin(db.Model): 28 | """A very simple checkin object, with a denormalized userid for querying.""" 29 | fs_id = db.StringProperty() 30 | checkin_json = db.TextProperty() 31 | 32 | def fetchJson(url): 33 | """Does a GET to the specified URL and returns a dict representing its reply.""" 34 | logging.info('fetching url: ' + url) 35 | result = urllib2.urlopen(url).read() 36 | logging.info('got back: ' + result) 37 | return simplejson.loads(result) 38 | 39 | class OAuth(webapp.RequestHandler): 40 | """Handle the OAuth redirect back to the service.""" 41 | def post(self): 42 | self.get() 43 | 44 | def get(self): 45 | code = self.request.get('code') 46 | args = dict(config) 47 | args['code'] = code 48 | url = ('%(server)s/oauth2/access_token?client_id=%(client_id)s&client_secret=%(client_secret)s&grant_type=authorization_code&redirect_uri=%(redirect_uri)s&code=%(code)s' % args) 49 | 50 | json = fetchJson(url) 51 | 52 | token = UserToken() 53 | token.token = json['access_token'] 54 | token.user = users.get_current_user() 55 | 56 | self_response = fetchJson('%s/v2/users/self?oauth_token=%s' % (config['api_server'], token.token)) 57 | 58 | token.fs_id = self_response['response']['user']['id'] 59 | token.put() 60 | 61 | self.redirect("/") 62 | 63 | class ReceiveCheckin(webapp.RequestHandler): 64 | """Received a pushed checkin and store it in the datastore.""" 65 | def post(self): 66 | json = simplejson.loads(self.request.body) 67 | checkin_json = json['checkin'] 68 | user_json = json['user'] 69 | checkin = Checkin() 70 | checkin.fs_id = user_json['id'] 71 | checkin.checkin_json = simplejson.dumps(checkin_json) 72 | checkin.put() 73 | 74 | class FetchCheckins(webapp.RequestHandler): 75 | """Fetch the checkins we've received via push for the current user.""" 76 | def get(self): 77 | user = UserToken.all().filter("user = ", users.get_current_user()).get() 78 | ret = [] 79 | if user: 80 | checkins = Checkin.all().filter("fs_id = ", user.fs_id).fetch(1000) 81 | ret = [c.checkin_json for c in checkins] 82 | self.response.out.write('['+ (','.join(ret)) +']') 83 | 84 | class GetConfig(webapp.RequestHandler): 85 | """Returns the OAuth URI as JSON so the constants aren't in two places.""" 86 | def get(self): 87 | uri = '%(server)s/oauth2/authenticate?client_id=%(client_id)s&response_type=code&redirect_uri=%(redirect_uri)s' % config 88 | self.response.out.write(simplejson.dumps({'auth_uri': uri})) 89 | 90 | application = webapp.WSGIApplication([('/oauth', OAuth), 91 | ('/checkin', ReceiveCheckin), 92 | ('/fetch', FetchCheckins), 93 | ('/config', GetConfig)], 94 | debug=True) 95 | 96 | def main(): 97 | run_wsgi_app(application) 98 | 99 | if __name__ == "__main__": 100 | main() 101 | --------------------------------------------------------------------------------