Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Jeff Lindsay
authored and
Jeff Lindsay
committed
Nov 26, 2009
1 parent
d218fc8
commit 755caf8
Showing
7 changed files
with
247 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,5 +4,7 @@ runtime: python | |
api_version: 1 | ||
|
||
handlers: | ||
- url: /static | ||
static_dir: static | ||
- url: .* | ||
script: main.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
cron: | ||
- description: refresh wiki token | ||
url: /refreshtoken | ||
schedule: every 5 minutes |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,40 +1,102 @@ | ||
#!/usr/bin/env python | ||
# | ||
# Copyright 2007 Google Inc. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
# | ||
|
||
|
||
|
||
import wsgiref.handlers | ||
|
||
from google.appengine.api.labs import taskqueue | ||
from google.appengine.ext import webapp | ||
from google.appengine.api import users | ||
from google.appengine.ext.webapp import template | ||
from google.appengine.ext import db | ||
from google.appengine.api import urlfetch | ||
from google.appengine.api import mail | ||
from google.appengine.ext.webapp.util import login_required | ||
from datetime import datetime | ||
import urllib, hashlib, time | ||
from django.utils import simplejson | ||
|
||
PBWORKS_TOKEN = None | ||
def get_token(refresh=False): | ||
global PBWORKS_TOKEN | ||
if refresh or not PBWORKS_TOKEN: | ||
response = urlfetch.fetch('http://dojo.pbworks.com/api_v2/op/Login/email/appenginebot%40hackerdojo.com/password/botbotbot/_type/jsontext').content | ||
PBWORKS_TOKEN = parse_json(response)['token'] | ||
return PBWORKS_TOKEN | ||
|
||
import wsgiref.handlers | ||
def parse_json(data): | ||
return simplejson.loads(data.replace('/*-secure-','').replace('*/', '')) | ||
|
||
def broadcast(**message): | ||
urlfetch.fetch('http://live.readyinrealtime.com/hackerdojo-signin', method='POST', payload=urllib.urlencode(message)) | ||
|
||
from google.appengine.ext import webapp | ||
class Signin(db.Model): | ||
email = db.StringProperty(required=True) | ||
hash = db.StringProperty() | ||
name = db.StringProperty() | ||
image_url = db.StringProperty() | ||
type = db.StringProperty(required=True) | ||
created = db.DateTimeProperty(auto_now_add=True) | ||
active = db.BooleanProperty(default=True) | ||
|
||
@classmethod | ||
def get_active_staff(cls): | ||
return cls.all().filter('type IN', ['StaffKey', 'StaffNoKey']).filter('active =', True).order('-created') | ||
|
||
@classmethod | ||
def deactivate_staffer(cls, email): | ||
staffer = cls.get_active_staff().filter('email =', email).get() | ||
staffer.active = False | ||
staffer.put() | ||
|
||
def name_or_nick(self): | ||
return self.name or self.email.split('@')[0] | ||
|
||
class MainHandler(webapp.RequestHandler): | ||
def get(self): | ||
self.response.out.write(template.render('templates/main.html', locals())) | ||
|
||
def post(self): | ||
email = self.request.get('email') | ||
if not '@' in email: | ||
email = '%s@hackerdojo.com' % email | ||
if email: | ||
hash=hashlib.md5(email).hexdigest() | ||
response = urlfetch.fetch('https://dojo.pbworks.com/api_v2/op/GetUserInfo/_type/jsontext/email/%s/token/%s' % (urllib.quote(email), get_token())).content | ||
if not 'appenginebot' in response: | ||
response = parse_json(response) | ||
image = response['image'] | ||
name = response['name'] | ||
else: | ||
image = 'http://0.gravatar.com/avatar/%s' % hash | ||
name = None | ||
s = Signin(email=email, type=self.request.get('type'), image_url=image, name=name) | ||
s.put() | ||
broadcast(cmd='say', text='Welcome back, %s' % name.split(' ')[0]) | ||
self.redirect('/') | ||
|
||
def get(self): | ||
self.response.out.write('Hello world!') | ||
class StaffHandler(webapp.RequestHandler): | ||
def get(self): | ||
staff = Signin.get_active_staff() | ||
self.response.out.write(template.render('templates/staff.html', locals())) | ||
|
||
def post(self): | ||
email = self.request.get('email') | ||
if email: | ||
Signin.deactivate_staffer(email) | ||
self.redirect('/staff') | ||
|
||
class TokenHandler(webapp.RequestHandler): | ||
def get(self): | ||
get_token(True) | ||
self.response.out.write("ok") | ||
|
||
def main(): | ||
application = webapp.WSGIApplication([('/', MainHandler)], | ||
debug=True) | ||
wsgiref.handlers.CGIHandler().run(application) | ||
|
||
|
||
application = webapp.WSGIApplication([ | ||
('/', MainHandler), | ||
('/staff', StaffHandler), | ||
('/refreshtoken', TokenHandler), | ||
], debug=True) | ||
wsgiref.handlers.CGIHandler().run(application) | ||
|
||
if __name__ == '__main__': | ||
main() | ||
main() | ||
|
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | ||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | ||
<head> | ||
<script type="text/javascript"> | ||
|
||
function stopRKey(evt) { | ||
var evt = (evt) ? evt : ((event) ? event : null); | ||
var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null); | ||
if ((evt.keyCode == 13) && (node.type=="text")) {return false;} | ||
if (evt.keyCode==45 || evt.keyCode==18) { | ||
showStaffButtons(); | ||
} | ||
} | ||
|
||
function showStaffButtons() { | ||
document.getElementById("staffbuttons").style.display="block"; | ||
setTimeout("document.getElementById('staffbuttons').style.display='none';",30*1000); | ||
} | ||
|
||
document.onkeydown = stopRKey; | ||
document.onkeypress = stopRKey; | ||
|
||
</script> | ||
<style> | ||
html,body {margin:0; padding:0; height:100%; width:100%} | ||
body {font-family:sans-serif; font-size:180%;} | ||
input {font-size:130%; margin:.5em } | ||
|
||
</style> | ||
</head> | ||
<body> | ||
<form id=f method=post> | ||
|
||
<div id=tos style="display:none; position:absolute; z-index:2; top:10%; left:10%; width:80%; height:80%; border:2px solid black; background:white "> | ||
<iframe style="border:none" border=0 width=100% src="http://hackerdojo.pbworks.com/api_v2/op/GetPage/page/Policies/_type/html" height=80%> | ||
</iframe> | ||
<center><input style="margin:1em" type=button onclick="ok();" value="I agree to the terms above"></center> | ||
|
||
</div> | ||
|
||
<div id=thanks style="padding:3em; display:none; position:absolute; z-index:2; top:35%; left:35%; width:20%; border:2px solid black; background:#baffbc "> | ||
<center>Thank You</center> | ||
</div> | ||
|
||
<div id=privacy style="padding:1em; display:none; position:absolute; z-index:2; top:25%; left:25%; width:40%; border:2px solid black; background:#baffbc; font-size:80% "> | ||
<h2>E-mail Privacy</h2> | ||
|
||
<p>The Dojo will not sell, rent, or give out your e-mail address to ANYONE.</p> | ||
|
||
<p>The Dojo may send you a "welcome e-mail" telling you about membership, and we may contact you in the future about interesting events and other happenings (which of course, you can opt-out of).</p> | ||
|
||
<p>We hate spam & we're not evil ;)</p> | ||
|
||
<p><a href="#" onclick="document.getElementById('privacy').style.display='none';">Close</a></p> | ||
|
||
</div> | ||
|
||
|
||
<center> | ||
<img style="margin:1.5em" src="/static/logo.png" width=690 height=244 > | ||
|
||
<h2>Please Sign In</h2> | ||
|
||
E-mail: <input id=em type=text name=email> | ||
<a style="color:green; font-size:9px" href="#" onclick="document.getElementById('privacy').style.display='block';">E-mail Privacy</a> | ||
<br> | ||
|
||
|
||
<input type=button value=Member onclick="go('Member')"/> | ||
<input type=button value=Guest onclick="go('Guest')"/> | ||
<input type=button value="Event Attendee" onclick="go('Event')"/> | ||
|
||
<div id="staffbuttons" style="display:none"> | ||
<input type=button value="Staff (keyholder)" onclick="go('StaffKey')"/> | ||
<input type=button value="Staff (nokey)" onclick="go('StaffNoKey')"/> | ||
</div> | ||
|
||
<input id=ttt type=hidden name=type value=""/> | ||
<script> | ||
function go(x) { | ||
if (isEmail(document.getElementById("em").value)) { | ||
document.getElementById("ttt").value = x; | ||
document.getElementById("tos").style.display = 'block'; | ||
} else { | ||
alert("Please enter a valid e-mail address"); | ||
} | ||
|
||
} | ||
function ok() { | ||
document.getElementById("tos").style.display = 'none'; | ||
document.getElementById("thanks").style.display = 'block'; | ||
setTimeout('document.getElementById("f").submit();',1000); | ||
} | ||
var isEmail_re = /^\s*[\w\-\+_]+(\.[\w\-\+_]+)*\@[\w\-\+_]+\.[\w\-\+_]+(\.[\w\-\+_]+)*\s*$/; | ||
function isEmail (s) { | ||
return String(s).search (isEmail_re) != -1; | ||
} | ||
</script> | ||
|
||
</form> | ||
</center> | ||
|
||
|
||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<html> | ||
<head> | ||
<link rel="stylesheet" type="text/css" src="http://dustball.com/dojo/kiosk.css" /> | ||
<script type="text/javascript"> | ||
function signout(t) { | ||
var name = t.getElementsByClassName("name")[0].innerHTML; | ||
var email = t.getElementsByClassName("email")[0].innerHTML; | ||
if (confirm("Are you sure you want to sign out "+name+"?")) { | ||
var f = document.getElementById("actionform"); | ||
f.elements['action'].value = "signout"; | ||
f.elements['email'].value = email; | ||
f.submit(); | ||
} | ||
} | ||
</script> | ||
</head> | ||
<body> | ||
<form method="POST" style="display:none" id="actionform"> | ||
<input type="hidden" name="action" value=""> | ||
<input type="hidden" name="email" value=""> | ||
</form> | ||
|
||
{% for staffer in staff %} | ||
<div class="staffline" onclick="signout(this);"> | ||
<div class="picbox"> | ||
<img class="pic" src="{{ staffer.image_url }}" /> | ||
</div> | ||
<div class="name">{{ staffer.name_or_nick }}</div> | ||
<div class="email">{{ staffer.email }}</div> | ||
<div class="ago">{{ staffer.created|timesince }} ago</div> | ||
</div> | ||
|
||
{% endfor %} | ||
</body> | ||
</html> |