Last active
January 1, 2016 19:59
-
-
Save armanbilge/8194402 to your computer and use it in GitHub Desktop.
Web app that automatically coordinates a Secret Snowflake Gift Exchange
This file contains hidden or 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
#!/usr/bin/env python | |
# SecretSnowflakeOrganizer.py | |
# Web app that automatically coordinates a Secret Snowflake Gift Exchange | |
COORDINATOR_PASSWORD = 'COORDINATOR_PASSWORD' | |
DB_HOST = 'DB_HOST' | |
DB_USER = 'DB_USER' | |
DB_PASSWORD = 'DB_PASSWORD' | |
DB_NAME = 'DB_NAME' | |
GMAIL_USER = 'EMAIL' | |
GMAIL_PASSWORD = 'EMAIL_PASSWORD' | |
ORGANIZATION = 'ORGANIZATION' | |
import MySQLdb | |
class DB: | |
def connect(self): | |
self.db = MySQLdb.connect(host=DB_HOST, | |
user=DB_USER, | |
passwd=DB_PASSWORD, | |
db=DB_NAME) | |
return self.db.cursor() | |
def commit(self): | |
self.db.commit() | |
def close(self): | |
self.db.close() | |
db = DB() | |
def is_open(): | |
sql = db.connect() | |
sql.execute("""SELECT open FROM status WHERE 1 LIMIT 1""") | |
for status in sql.fetchall(): | |
db.close() | |
return bool(int(status[0])) | |
# email stuff | |
import smtplib | |
from email.MIMEMultipart import MIMEMultipart | |
from email.MIMEText import MIMEText | |
def mail(to, subject, text): | |
msg = MIMEMultipart() | |
msg['From'] = GMAIL_USER | |
msg['To'] = to | |
msg['Subject'] = subject | |
msg.attach(MIMEText(text)) | |
mailServer = smtplib.SMTP("smtp.gmail.com", 587) | |
mailServer.ehlo() | |
mailServer.starttls() | |
mailServer.ehlo() | |
mailServer.login(GMAIL_USER, GMAIL_PASSWORD) | |
mailServer.sendmail(GMAIL_USER, to, msg.as_string()) | |
mailServer.close() | |
import web | |
urls = ( | |
'/', 'index', | |
'/signup', 'signup', | |
'/assign', 'assign', | |
'/open', 'open' | |
) | |
class index: | |
def signup(self,open): | |
if open: | |
return """<div style="color:white;line-height:200%"> | |
<form action="signup" method="post"> | |
Name: <input type="text" name="name"><br/> | |
Email: <input type="text" name="email"><br/> | |
Additional Info (interests/favorites/allergies/etc.):<br/> | |
<textarea name="info" columns=64 rows=4></textarea><br/> | |
<label><input type="checkbox" name="promise"> I promise to make my Secret Snowflake's day!</label><br/> | |
<input type="submit" value="Sign Up"/> | |
</form> | |
</div> | |
<div style="color:white;line-height:200%"> | |
<form action="assign" method="post"> | |
<b>Coordinator Only</b><br/> | |
Password: <input type="password" name="password"><br/> | |
<input type="submit" value="Assign Snowflakes"/> | |
</form> | |
</div> | |
""" | |
else: | |
return """<h3 style="color:white">Sign-up is currently closed.</h3> | |
<div style="color:white;line-height:200%"> | |
<form action="open" method="post"> | |
<b>Coordinator Only</b><br/> | |
Password: <input type="password" name="password"><br/> | |
<input type="submit" value="Open Sign-Up"/> | |
</form> | |
</div> | |
""" | |
def GET(self): | |
web.header('Content-Type','text/html; charset=utf-8', unique=True) | |
try: | |
message = self.signup(is_open()) | |
except: | |
message = '<div style="color:white;line-height:200%">Currently experiencing problems, but hoping to be back up shortly. Sorry!</div>' | |
return """<html> | |
<head> | |
<title>{0} | Secret Snowflake | Sign-Up</title> | |
<script type="text/javascript"> | |
</script> | |
</head> | |
<body style="background-image:url(static/snowflake.png);font-family:Georgia;padding:5% 20%"> | |
<center> | |
<h1 style="color:white">{0}'s Secret Snowflake Sign-Up</h1> | |
</center>""".format(ORGANIZATION) \ | |
+ message + \ | |
"""</html>""" | |
class signup: | |
def POST(self): | |
import re | |
data = web.input() | |
message = '' | |
if data.name == '': message += 'Please enter your name.<br/>' | |
if not re.match(r"[a-z0-9!#$%&'*+/=?^_{|}~-]+(?:.[a-z0-9!#$%&'*+/=?^_{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[A-Za-z]{2}|com|org|net|edu|info)\b", data['email']): message += 'Please enter your email.<br/>' | |
if not hasattr(data, 'promise'): message += 'Please make the promise.<br/>' | |
if message == '': | |
message += '<b>You have signed up! Please look for a email confirming your participation in the gift exchange.</b>' | |
sql = db.connect() | |
sql.execute("""INSERT INTO snowflakes VALUES (%s, %s, %s)""", (data.name, data.email, data.info)) | |
db.commit() | |
db.close() | |
mail(data.email, '{} Secret Snowflake'.format(ORGANIZATION), 'Hi {},\n\nJust an email confirmation that you have succesfully signed up for {}\'s Secret Snowflake gift exchange! Expect\n\nHappy Holidays!\nYour Secret Snowflake Coordinator'.format(data.name.split()[0], ORGANIZATION)) | |
else: | |
message += '<b><a href="javascript:history.back()">Back to sign-up.</a></b>' | |
web.header('Content-Type','text/html; charset=utf-8', unique=True) | |
return """<html> | |
<head> | |
<title>{0} | Secret Snowflake | Sign-Up</title> | |
<style type="text/css"> | |
a:link {color:#FFFFFF;} | |
a:visited {color:#FFFFFF;} | |
a:hover {color:#FFFFFF;text-decoration:none;} | |
a:active {color:#FFFFFF;} | |
</style> | |
</head> | |
<body style="background-image:url(static/snowflake.png);font-family:Georgia;padding:5% 20%"> | |
<center> | |
<h1 style="color:white">{0}'s Secret Snowflake Sign-Up</h1> | |
</center> | |
<div style="color:white;line-height:200%">""".format(ORGANIZATION) \ | |
+ message + \ | |
"""</div> | |
</html>""" | |
class Snowflake: | |
def __init__(self,name,email,info): | |
self.name = name | |
self.email = email | |
self.info = info | |
class assign: | |
def POST(self): | |
data = web.input() | |
if not is_open(): | |
message = 'You can only assign Secret Snowflakes once!' | |
elif data.password == PASSWORD: | |
message = 'Secret Snowflake assignments have been emailed successfully!' | |
sql = db.connect() | |
sql.execute("""UPDATE status SET open=0 WHERE 1 LIMIT 1""") | |
sql.execute("""SELECT name, email, info FROM snowflakes WHERE 1""") | |
db.commit() | |
from collections import deque | |
from random import shuffle | |
snowflakes = deque([]) | |
for sf in sql.fetchall(): | |
snowflakes.append(Snowflake(sf[0], sf[1], sf[2])) | |
db.close() | |
shuffle(snowflakes) | |
shuffle(snowflakes) | |
shuffle(snowflakes) | |
snowflakes2 = deque(snowflakes) | |
snowflakes2.rotate(1) | |
for i in xrange(len(snowflakes)): | |
a = snowflakes[i] | |
b = snowflakes2[i] | |
mail(a.email, 'Your {} Snowflake'.format(ORGANIZATION), 'Hi {},\n\nThanks for participating in {}\'s Secret Snowflake gift exchange! Your Secret Snowflake is {}. They would like you to know the following about themselves:\n{}\n\nHappy Holidays!\nYour Secret Snowflake Coordinator'.format(a.name.split()[0], ORGANIZATION, b.name, b.info if b.info else '[Nothing]')) | |
else: | |
message = 'Incorrect password.<br/><b><a href="javascript:history.back()">Back.</a></b>' | |
web.header('Content-Type','text/html; charset=utf-8', unique=True) | |
return """<html> | |
<head> | |
<title>{0} | Secret Snowflake | Sign-Up</title> | |
<style type="text/css"> | |
a:link {color:#FFFFFF;} | |
a:visited {color:#FFFFFF;} | |
a:hover {color:#FFFFFF;text-decoration:none;} | |
a:active {color:#FFFFFF;} | |
</style> | |
</head> | |
<body style="background-image:url(static/snowflake.png);font-family:Georgia;padding:5% 20%"> | |
<center> | |
<h1 style="color:white">{0}'s Secret Snowflake Sign-Up</h1> | |
</center> | |
<div style="color:white;line-height:200%">""".format(ORGANIZATION) + message + """</div> | |
</html>""" | |
class open: | |
def POST(self): | |
data = web.input() | |
if data.password == PASSWORD: | |
message = 'Sign-up is now open!<br/><b><a href="/">Go to sign-up.</a></b>' | |
sql = db.connect() | |
sql.execute("""UPDATE status SET open=1 WHERE 1 LIMIT 1""") | |
sql.execute("""DELETE FROM snowflakes WHERE 1""") | |
db.commit() | |
db.close() | |
else: | |
message = 'Incorrect password.<br/><b><a href="javascript:history.back()">Back.</a></b>' | |
web.header('Content-Type','text/html; charset=utf-8', unique=True) | |
return """<html> | |
<head> | |
<title>{0} | Secret Snowflake | Sign-Up</title> | |
<style type="text/css"> | |
a:link {color:#FFFFFF;} | |
a:visited {color:#FFFFFF;} | |
a:hover {color:#FFFFFF;text-decoration:none;} | |
a:active {color:#FFFFFF;} | |
</style> | |
</head> | |
<body style="background-image:url(static/snowflake.png);font-family:Georgia;padding:5% 20%"> | |
<center> | |
<h1 style="color:white">{0}'s Secret Snowflake Sign-Up</h1> | |
</center> | |
<div style="color:white;line-height:200%">""".format(ORGANIZATION) + message + """</div> | |
</html>""" | |
app = web.application(urls, globals()) | |
application = app.wsgifunc() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment