From 077d5f372bf1f2240efc64bbdc3f22e90212ebe5 Mon Sep 17 00:00:00 2001 From: Robert Myers Date: Sat, 14 Jul 2012 15:16:13 -0500 Subject: [PATCH] Hooking up the channel api to the index page --- app.yaml | 1 + july/live/models.py | 39 +++++++++++++++++++++++++++++++++++---- july/live/tasks.py | 15 --------------- july/live/views.py | 27 +++++++++++++++++++++++++-- july/urls.py | 4 +++- july/views.py | 18 ++++++++++++++++++ 6 files changed, 82 insertions(+), 22 deletions(-) delete mode 100644 july/live/tasks.py diff --git a/app.yaml b/app.yaml index 41324a2..a1eda2c 100644 --- a/app.yaml +++ b/app.yaml @@ -16,6 +16,7 @@ builtins: inbound_services: - warmup +- channel_presence libraries: - name: django diff --git a/july/live/models.py b/july/live/models.py index c4ffa38..2c55e3c 100644 --- a/july/live/models.py +++ b/july/live/models.py @@ -1,8 +1,10 @@ +import datetime +import json + from google.appengine.ext import deferred from google.appengine.ext.ndb import model - -from tasks import create_message +from google.appengine.api import channel class Message(model.Model): @@ -20,11 +22,40 @@ def __str__(self): def __unicode__(self): return self.__str__() + def to_json(self): + data = self.to_dict(exclude=['timestamp']) + return json.dumps(data) + @classmethod def create_message(cls, username, picture_url, message, **kwargs): message = cls(username=username, picture_url=picture_url, message=message) message.populate(**kwargs) message.put() - deferred.defer(create_message, message.key.urlsafe()) - return message \ No newline at end of file + deferred.defer(send_live_message, message.key.urlsafe()) + return message + +class Connection(model.Model): + """Store all the connected clients.""" + + client_id = model.StringProperty() + timestamp = model.DateTimeProperty(auto_now=True) + + +def send_live_message(key): + """Deferred task for sending messages to the open channels.""" + + message_key = model.Key(urlsafe=key) + message = message_key.get() + + if message is None: + return + + # Only notify rescent connections + timestamp = datetime.datetime.now() + oldest = timestamp - datetime.timedelta(hours=2) + + connections = Connection.query().filter(Connection.timestamp >= oldest).fetch(200, keys_only=True) + + for connection in connections: + channel.send_message(connection.id(), message.to_json()) \ No newline at end of file diff --git a/july/live/tasks.py b/july/live/tasks.py deleted file mode 100644 index adf095a..0000000 --- a/july/live/tasks.py +++ /dev/null @@ -1,15 +0,0 @@ - -import json - -from google.appengine.ext import ndb - -def create_message(key): - """Deferred task for sending messages to the open channels.""" - - message_key = ndb.Key(urlsafe=key) - message = message_key.get() - - if message is None: - return - - # TODO: for c in channels: spam channel... \ No newline at end of file diff --git a/july/live/views.py b/july/live/views.py index dcc9637..118423d 100644 --- a/july/live/views.py +++ b/july/live/views.py @@ -1,11 +1,13 @@ import json +import logging from django.shortcuts import render_to_response from django.contrib.auth.decorators import login_required from django.template.context import RequestContext from july.api import to_dict -from july.live.models import Message +from july.live.models import Message, Connection +from django import http @login_required def live(request): @@ -20,4 +22,25 @@ def live(request): return render_to_response('live/index.html', { 'token': token, 'mesages': messages}, - context_instance=RequestContext(request)) \ No newline at end of file + context_instance=RequestContext(request)) + +def connected(request): + + client_id = request.POST.get('from') + + connection = Connection.get_or_insert(client_id, client_id=client_id) + connection.put() + + return http.HttpResponse('Ok') + +def disconnected(request): + + client_id = request.POST.get('from') + + connection = Connection.get_by_id(client_id) + if connection is None: + return http.HttpResponse('Ok') + + connection.delete() + + return http.HttpResponse('Ok') \ No newline at end of file diff --git a/july/urls.py b/july/urls.py index 7b7ad8d..5874698 100644 --- a/july/urls.py +++ b/july/urls.py @@ -8,13 +8,15 @@ urlpatterns = patterns('', # This line should only be active during maintenance! #url(r'^.*', 'july.views.maintenance'), + url(r'^_ah/warmup', 'july.views.warmup'), + url(r'^_ah/channel/connected/', 'july.live.views.connected'), + url(r'^_ah/channel/disconnected/', 'july.live.views.disconnected'), url(r'^$', 'july.views.index', name='index'), url(r'^help/', 'july.views.help_view', name='help'), url(r'^signin/$', views.login, {'authentication_form': AuthenticationForm}, name="signin"), url(r'^signout/$', views.logout, {'next_page': '/'}, name="signout"), url(r'^accounts/profile', 'july.views.login_redirect'), url(r'^accounts/', include('gae_django.auth.urls')), - url(r'^_ah/warmup', 'july.views.warmup'), url(r'^', include('july.people.urls')), ) diff --git a/july/views.py b/july/views.py index a0ede42..44f05f2 100644 --- a/july/views.py +++ b/july/views.py @@ -11,6 +11,9 @@ from gae_django.auth.models import User from july.people.models import Accumulator, Location, Project, Team +from google.appengine.api import channel +from july.live.models import Message +from july.api import to_dict def index(request): @@ -28,6 +31,8 @@ def index(request): locations = [] projects = [] teams = [] + messages = [] + token = '' # this is only shown on authenticated page loads # to save on the overhead. @@ -42,6 +47,17 @@ def index(request): people = people_future.get_result() projects = project_future.get_result() teams = team_future.get_result() + + # Julython live stuffs + if not request.session.get('live_token'): + _token = channel.create_channel(request.user.username) + request.session['live_token'] = _token + + token = request.session['live_token'] + message_future = Message.query().order(-Message.timestamp).fetch_async(10) + message_models = message_future.get_result() + m_list = [to_dict(m) for m in message_models] + messages = json.dumps(m_list) ctx = Context({ 'sections': [], @@ -51,6 +67,8 @@ def index(request): 'teams': teams, 'stats': json.dumps(stats), 'total': total, + 'token': token, + 'messages': messages, 'user': request.user, 'MEDIA_URL': settings.MEDIA_URL, 'STATIC_URL': settings.STATIC_URL})