Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

395 lines (315 sloc) 12.667 kB
from flask import Flask, render_template, request, make_response, session, redirect
import urllib2
from urllib2 import URLError, HTTPError
import json
app = Flask(__name__)
app.debug = True
#If you want to be able to authenticate with github, you need to register an
#And setup (you can copy from and fill in the keys)
app.secret_key = FLASK_SECRET_KEY
base_url = "/"
#We assume a default filename of inlet.js to grab from the gist
default_filename = "inlet.js"
#Index page
def hello():
return render_template("index.html", base_url=base_url)
#return render_template("gallery.html", base_url=base_url)
def render_defaults(template, gist=None, filename=None):
#TODO: add user info
if filename is None:
return render_template(template,
loggedin=session.get("loggedin", False),
userid=session.get("userid", ""),
username=session.get("username", ""),
avatar=session.get("avatar", ""),
userurl=session.get("userurl", "")
#Live editing d3 for exploring parameter spaces
def tributary_gist(gist=None, filename=None):
return render_defaults("tributary.html", gist=gist, filename=filename)
#Live editing d3 for exploring parameter spaces
def ocean_gist(gist=None, filename=None):
return render_defaults("ocean.html", gist=gist, filename=filename)
#Live editing transitions
def delta_gist(gist=None, filename=None):
return render_defaults("delta.html", gist=gist, filename=filename)
#Live editing run loops
def hourglass_gist(gist=None, filename=None):
return render_defaults("hourglass.html", gist=gist, filename=filename)
#Live editing run loops for canvas
def cypress_gist(gist=None, filename=None):
return render_defaults("cypress.html", gist=gist, filename=filename)
#Live editing run loops for canvas
def levee_gist(gist=None, filename=None):
return render_defaults("levee.html", gist=gist, filename=filename)
#Live editing boids (and other node based things)
def bigfish_gist(gist=None, filename=None):
return render_defaults("bigfish.html", gist=gist, filename=filename)
#Live editing boids (and other node based things) in canvas
def fly_gist(gist=None, filename=None):
return render_defaults("fly.html", gist=gist, filename=filename)
#Live editing music visualization
def flow_gist(gist=None, filename=None):
return render_defaults("flow.html", gist=gist, filename=filename)
#Experimenting with tiling and patterns
def reptile_gist(gist=None, filename=None):
return render_defaults("reptile.html", gist=gist, filename=filename)
#Experimenting with three.js WebGL Library
def curiosity_gist(gist=None, filename=None):
return render_defaults("curiosity.html", gist=gist, filename=filename)
#Embedded view for Tributary
def embed_gist(gist=None, filename=None):
return render_defaults("embed.html", gist=gist, filename=filename)
#Embedded view for Delta
def shore_gist(gist=None, filename=None):
return render_defaults("shore.html", gist=gist, filename=filename)
def internal_gist(gist, filename=None):
code = ""
if filename is None:
filename = default_filename
#print gist, filename
url = "" #1569370/boid.js
url += gist + "/" + filename
#print "url", url
req = urllib2.Request(url)
obj = urllib2.urlopen(req)
code ='utf-8')
except URLError, e:
print "ERROR", e.code
return code
@app.route('/github-login/<product>', methods=["GET"])
@app.route("/github-login/<product>/<id>", methods=["GET"])
def github_login(product=None,id=None):
if (product is None):
# Default product
product = "tributary"
if(id is not None):
#take user to github for authentication
return redirect('' + GITHUB_CLIENT_ID + '&scope=gist' + '&state=/' + product + '/' + id)
return redirect('' + GITHUB_CLIENT_ID + '&scope=gist' + '&state=/' + product)
@app.route("/github-logout/<product>", methods=["GET"])
@app.route("/github-logout/<product>/<id>", methods=["GET"])
def github_logout(product=None,id=None):
session["access_token"] = None
session["loggedin"] = None
session["username"] = None
session["avatar"] = None
session["userid"] = None
session["userurl"] = None
if(product is None):
product = "tributary"
if (id is None):
return redirect('/'+product)
return redirect('/'+product+'/'+id)
def github_authenticated():
#code poached from water:
tempcode = request.args.get('code', '')
# construct data and headers to send to github
data = {'client_id': GITHUB_CLIENT_ID, 'client_secret': GITHUB_CLIENT_SECRET, 'code': tempcode }
headers = {'content-type': 'application/json', 'accept': 'application/json'}
# request an access token
req = urllib2.Request('', data=json.dumps(data), headers=headers)
resp = json.loads(urllib2.urlopen(req).read())
# save access token in session
session['access_token'] = resp['access_token']
# let client know we are logged in
session['loggedin'] = True
#get info about the user
req = urllib2.Request("" + session['access_token'])
resp = json.loads(urllib2.urlopen(req).read())
session['username'] = resp['login']
session['avatar'] = resp['avatar_url']
session['userid'] = resp['id']
session['userurl'] = resp['url']
nexturl = request.args.get('state')
#TODO: redirect back to next parameter
return redirect(nexturl)
#TODO: make fork and save button different
# make js send gist id for fork or save unless its a fresh gist
# if fresh gist disable fork button
def save(id, data, token=None):
#print "ID", id
#if id, send a patch
if(id is not None):
#TODO: check id is a valid id?
url = '' + id
#if not id create a new gist
url = ''
#code = json.loads(request.values.get("gist"))
data = data.encode('utf-8')
#print "DATA", code
#data = urllib.urlencode(code)
#print data
headers = {'content-type': 'application/json; charset=utf-8', 'accept': 'application/json', 'encoding':'UTF-8'}
if token is not None:
headers['Authorization'] = 'token ' + token
#print "LOGGED IN, using TOKEN", token
#url += "?access_token="+token
#url += "?authenticity_token="+token
url = url.encode('utf-8')
req = urllib2.Request(url, data, headers=headers)
#req = urllib2.Request(url, data)
#print "NOT LOGGED IN"
req = urllib2.Request(url, data, headers=headers)
#to save over a gist
if(id is not None):
#print "PATCH", url
req.get_method = lambda: 'PATCH'
response = urllib2.urlopen(req)
#print "RESP", response
ret =
#print "ret", ret
resp = make_response(ret, 200)
resp.headers['Content-Type'] = 'application/json'
return resp
#Save a tributary to a gist
@app.route("/tributary/save", methods=["POST"])
@app.route("/tributary/save/<id>", methods=["POST"])
def save_endpoint(id=None):
data = request.values.get("gist")
token = session.get("access_token", None)
return save(id, data, token)
#Save a tributary to a gist
@app.route("/tributary/fork", methods=["POST"])
@app.route("/tributary/fork/<id>", methods=["POST"])
def fork_endpoint(id=None):
#TODO: check id is valid
data = request.values.get("gist")
data = data.encode('utf-8')
token = session.get("access_token", None)
userid = session.get("userid", None)
gist_userid = json.loads(data).get("user", {}).get("id", None)
#print 'gist_userid=' , gist_userid
#print 'userid=' , userid
#print 'token=' , token
if(id is None or token is None):
return save(None, data, token)
#if user doesn't own this gist, just fork it
elif(userid == gist_userid):
newgist = fork(id, token)
resp = make_response(json.dumps(newgist), 200)
resp.headers['Content-Type'] = 'application/json'
return resp
#hacky shit. github won't let me fork a gist a user already owns
#first we make anon fork
anonid = fork(id)["id"]
#then we fork that with our account
newid = fork(anonid, token)["id"]
#then we save over with the original data
return save(newid, data, token)
def fork(id, token=None):
#print "FORKING", id
url = '' + id + '/fork'
#need data to make this a post request
#data = None
data = "{}"
headers = {
'content-type': 'application/json; charset=utf-8',
'accept': 'application/json',
if token is not None:
#authenticate the request
headers['Authorization'] = 'token ' + token
#data = "{authenticity_token:" + token + "}"
#data = "{access_token:" + token + "}"
#print "LOGGED IN, using TOKEN", token
#url += "?access_token="+token
#url = url.encode('utf-8')
req = urllib2.Request(url, data, headers=headers)
#req = urllib2.Request(url, data)
#print "NOT LOGGED IN"
req = urllib2.Request(url, data, headers=headers)
response = urllib2.urlopen(req)
ret =
gist = json.loads(ret)
#print "ret", gist["id"]
return gist
def latest_user(user):
return render_template("latest.html", username=user)
#svg open presentation
def svgopen2012():
return render_template("svgopen2012.html", base_url=base_url)
#return render_template("gallery.html", base_url=base_url)
#An experimental view that allowed creating screenshots from the gallery
def creator():
return render_defaults("gallery_creator.html", base_url=base_url)
#EXPIREMENTAL: these don't work with the rewrite, will need to be resurrected
def geyser_gist(gist=None, filename=None):
return render_defaults("geyser.html", gist=gist, filename=default_filename, base_url=base_url)
def fountain_gist(gist=None, filename=None):
return render_defaults("fountain.html", gist=gist, filename=default_filename, base_url=base_url)
def carbonite_gist(gist=None, filename=None):
return render_defaults("carbonite.html", gist=gist, filename=default_filename, base_url=base_url)
if __name__ == "__main__":"localhost", port=8888)
Jump to Line
Something went wrong with that request. Please try again.