Skip to content

Commit

Permalink
Implement user page and working digest email and reminder email.
Browse files Browse the repository at this point in the history
  • Loading branch information
kushal committed Jan 9, 2011
1 parent b669d90 commit c470f2b
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 80 deletions.
45 changes: 45 additions & 0 deletions dateutil.py
@@ -0,0 +1,45 @@
import datetime

class Eastern_tzinfo(datetime.tzinfo):
"""Implementation of the Eastern timezone.
Adapted from http://code.google.com/appengine/docs/python/datastore/typesandpropertyclasses.html
"""
def utcoffset(self, dt):
return datetime.timedelta(hours=-5) + self.dst(dt)

def _FirstSunday(self, dt):
"""First Sunday on or after dt."""
return dt + datetime.timedelta(days=(6-dt.weekday()))

def dst(self, dt):
# 2 am on the second Sunday in March
dst_start = self._FirstSunday(datetime.datetime(dt.year, 3, 8, 2))
# 1 am on the first Sunday in November
dst_end = self._FirstSunday(datetime.datetime(dt.year, 11, 1, 1))

if dst_start <= dt.replace(tzinfo=None) < dst_end:
return datetime.timedelta(hours=1)
else:
return datetime.timedelta(hours=0)

def tzname(self, dt):
if self.dst(dt) == datetime.timedelta(hours=0):
return "EST"
else:
return "EDT"


def date_for_new_snippet():
"""Return next Monday, unless it is Monday (0) or Tuesday (1)"""
today = datetime.datetime.now(Eastern_tzinfo()).date()
if (today.weekday() < 2):
aligned = today - datetime.timedelta(days=today.weekday())
else:
aligned = today + datetime.timedelta(days=(7 - today.weekday()))
return aligned

def date_for_retrieval():
"""Always return the most recent Monday."""
today = datetime.datetime.now(Eastern_tzinfo()).date()
return today - datetime.timedelta(days=today.weekday())
65 changes: 38 additions & 27 deletions emails.py
@@ -1,37 +1,48 @@
import logging

from google.appengine.api import mail
from google.appengine.api import taskqueue
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util

class ReminderEmail(webapp.RequestHandler):
def get(self):
pass
taskqueue.add(url='/onereminder', params={'user': key})

class DigestEmail(webapp.RequestHandler):
def get(self):
# Find all users and add to queue
taskqueue.add(url='/onedigest', params={'user': key})
from dateutil import *
from model import *

class OneReminder(webapp.RequestHandler):
def post(self):
key = self.request.get('user')
mail.send_mail(sender="Example.com Support <support@example.com>",
to="Albert Johnson <Albert.Johnson@example.com>",
subject="Your account has been approved",
body="""
Dear Albert:
REMINDER = """
Hey nerd,
Your example.com account has been approved. You can now visit
http://www.example.com/ and sign in using your Google Account to
access new features.
The kids want to know what you're up to. Don't leave 'em hanging.
"""

Please let us know if you have any questions.
The example.com Team
""")
class ReminderEmail(webapp.RequestHandler):
def __send_mail(self, recipient):
mail.send_mail(sender="snippets <snippets@fssnippets.appspotmail.com>",
to=recipient,
subject="Snippet time!",
body=REMINDER)

class OneDigest(webapp.RequestHandler):
def post(self):
key = self.request.get('user')
def get(self):
all_users = User.all().filter("enabled =", True).fetch(500)
for user in all_users:
# TODO: Check if one has already been submitted for this period.
self.__send_mail(user.user.email())

class DigestEmail(webapp.RequestHandler):
def __send_mail(self, recipient, body):
mail.send_mail(sender="snippets <snippets@fssnippets.appspotmail.com>",
to=recipient,
subject="Snippet delivery!",
body=body)

def __snippet_to_text(self, snippet):
divider = '-' * 30
return '%s\n%s\n%s' % (snippet.user.user.email(), divider, snippet.text)

def get(self):
all_users = User.all().filter("enabled =", True).fetch(500)
d = date_for_retrieval()
all_snippets = Snippet.all().filter("date =", d).fetch(500)
# TODO: Build custom emails
body = '\n\n\n'.join([self.__snippet_to_text(s) for s in all_snippets])
for user in all_users:
self.__send_mail(user.user.email(), body)
18 changes: 15 additions & 3 deletions main.py
Expand Up @@ -57,13 +57,15 @@ class UserHandler(BaseHandler):
"""Show a given user's snippets."""

def authed_get(self, user):
desired_user = user_from_email(self.request.get('user'))
snippets = user.snippets_set
desired_user = user_from_email(self.request.get('email'))
snippets = user.snippet_set
snippets = sorted(snippets, key=lambda s: s.date, reverse=True)

self.response.headers['Content-Type'] = 'text/html'
template_values = {
'current_user' : user,
'user': desired_user
'user': desired_user,
'snippets': snippets
}

path = os.path.join(os.path.dirname(__file__), 'templates/user.html')
Expand All @@ -81,6 +83,16 @@ class MainHandler(BaseHandler):
"""Show list of all users and acting user's settings."""

def authed_get(self, user):
# Update enabled state if requested
set_enabled = self.request.get('setenabled')
if set_enabled == '1':
user.enabled = True
user.put()
elif set_enabled == '0':
user.enabled = False
user.put()

# Fetch user list and display
all_users = User.all().fetch(500)
self.response.headers['Content-Type'] = 'text/html'
template_values = {
Expand Down
3 changes: 1 addition & 2 deletions model.py
Expand Up @@ -6,15 +6,14 @@
class User(db.Model):
user = db.UserProperty()
following = db.ListProperty(db.Key)
enabled = db.BooleanProperty()
enabled = db.BooleanProperty(default=True)

class Snippet(db.Model):
user = db.ReferenceProperty(User)
text = db.TextProperty()
date = db.DateProperty()

def user_from_email(email):
logging.info(email)
return User.all().filter("user =", users.User(email)).fetch(1)[0]

def create_or_replace_snippet(user, text, date):
Expand Down
42 changes: 2 additions & 40 deletions receive_email.py
Expand Up @@ -6,54 +6,16 @@
from google.appengine.ext.webapp.mail_handlers import InboundMailHandler
from google.appengine.ext.webapp import util

from dateutil import date_for_new_snippet
from model import user_from_email, create_or_replace_snippet


class Eastern_tzinfo(datetime.tzinfo):
"""Implementation of the Eastern timezone.
Adapted from http://code.google.com/appengine/docs/python/datastore/typesandpropertyclasses.html
"""
def utcoffset(self, dt):
return datetime.timedelta(hours=-5) + self.dst(dt)

def _FirstSunday(self, dt):
"""First Sunday on or after dt."""
return dt + datetime.timedelta(days=(6-dt.weekday()))

def dst(self, dt):
# 2 am on the second Sunday in March
dst_start = self._FirstSunday(datetime.datetime(dt.year, 3, 8, 2))
# 1 am on the first Sunday in November
dst_end = self._FirstSunday(datetime.datetime(dt.year, 11, 1, 1))

if dst_start <= dt.replace(tzinfo=None) < dst_end:
return datetime.timedelta(hours=1)
else:
return datetime.timedelta(hours=0)

def tzname(self, dt):
if self.dst(dt) == datetime.timedelta(hours=0):
return "EST"
else:
return "EDT"


class ReceiveEmail(InboundMailHandler):
"""Receive a snippet email and create or replace snippet for this week."""

def receive(self, message):
user = user_from_email(message.sender)
for content_type, body in message.bodies('text/plain'):
today = datetime.datetime.now(Eastern_tzinfo()).date()

# For now, just align to next Monday, unless it is Monday (0), Tuesday (1)
if (today.weekday() < 2):
aligned = today - datetime.timedelta(days=today.weekday())
else:
aligned = today + datetime.timedelta(days=(7 - today.weekday()))

create_or_replace_snippet(user, body.decode(), aligned)
create_or_replace_snippet(user, body.decode(), date_for_new_snippet())


def main():
Expand Down
8 changes: 5 additions & 3 deletions templates/base.html
Expand Up @@ -2,13 +2,15 @@
<html>
<head>
<style>
body { font-family: Helvetica, sans-serif; font-size: 83% }
body { font-family: Courier New, monospaced; font-size: 83% }
a.title { color: #CCC; text-decoration: none }
a.title:hover { text-decoration: underline }
</style>
<title>{% block title %}Snippets{% endblock %}</title>
<title>{% block title %}snippets{% endblock %}</title>
</head>

<body>
<h2>Snippets</h2>
<h1><a class="title" href="/">snippets</a></h2>
{% block body %}
{% endblock %}
</body>
Expand Down
14 changes: 9 additions & 5 deletions templates/index.html
@@ -1,13 +1,17 @@
{% extends "base.html" %}

{% block body %}
<b><a href="/user?email={{ current_user.user.email }}">{{ current_user.user.email }}</a></b>
<br/>
Currently {{ current_user.enabled }}

<h2><a href="/user?email={{ current_user.user.email }}">{{ current_user.user.email }}</a></h2>
currently
{% if current_user.enabled %}
<b>enabled</b> <a href="?setenabled=0">disable</a>
{% else %}
<b>disabled</b> <a href="?setenabled=1">enable</a>
{% endif %}

<h3>Users</h3>
{% for user in all_users %}
<a href="/user?email={{ user.email }}">{{ user.email }}</a>
<a href="/user?email={{ user.user.email }}">{{ user.user.email }}</a>
<br/>
{% endfor %}

Expand Down
12 changes: 12 additions & 0 deletions templates/user.html
@@ -0,0 +1,12 @@
{% extends "base.html" %}

{% block body %}
<h2>{{ user.user.email }}</h2>

{% for snippet in snippets %}
<b>{{ snippet.date }}</b><br/>
{{ snippet.text }}
<br/></br>
{% endfor %}

{% endblock %}

0 comments on commit c470f2b

Please sign in to comment.