├── 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 | Checkin ID |
13 | Venue Name (or Shout) |
14 | Time |
15 |
16 |
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 |
--------------------------------------------------------------------------------