changeset 10:c28a4840e1a8

server: microblog resource
author Goffi <goffi@goffi.org>
date Fri, 25 Mar 2011 00:32:58 +0100
parents c80b75bf2e91
children 331c093e4eb3
files libervia.tac server_css/blog.css server_side/__init__.py server_side/blog.py
diffstat 3 files changed, 151 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/libervia.tac	Fri Mar 25 00:31:27 2011 +0100
+++ b/libervia.tac	Fri Mar 25 00:32:58 2011 +0100
@@ -28,10 +28,13 @@
 from twisted.web import error as weberror
 from twisted.web.static import File
 from twisted.web.resource import Resource
+from twisted.words.protocols.jabber.jid import JID
 from txjsonrpc.web import jsonrpc
 from txjsonrpc import jsonrpclib
 from sat_frontends.bridge.DBus import DBusBridgeFrontend,BridgeExceptionNoService
 
+from server_side.blog import MicroBlog
+
 TIMEOUT = 120 #Session's time out, after that the user will be disconnected
 
 
@@ -237,17 +240,14 @@
         self.request = request
         return jsonrpc.JSONRPC.render(self, request)
 
+
 class Libervia(service.Service):
    
     def __init__(self):
         root = File("output/") 
         self.signal_handler = SignalHandler(self)
-        root.putChild('json_signal_api', self.signal_handler)
         _register = Register(self)
         self.signal_handler.plugRegister(_register)
-        root.putChild('json_api', MethodHandler(self))
-        root.putChild('register_api', _register)
-        self.site = server.Site(root)
         self.sessions = {} #key = session value = user
         ## bridge ##
         try:
@@ -260,6 +260,12 @@
         self.bridge.register("connectionError", self.signal_handler.connectionError)
         for signal_name in ['presenceUpdate', 'personalEvent']:
             self.bridge.register(signal_name, self.signal_handler.getGenericCb(signal_name))
+        root.putChild('json_signal_api', self.signal_handler)
+        root.putChild('json_api', MethodHandler(self))
+        root.putChild('register_api', _register)
+        root.putChild('blog', MicroBlog(self))
+        root.putChild('css', File("server_css/"))
+        self.site = server.Site(root)
 
     def startService(self):
         reactor.listenTCP(8080, self.site)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server_css/blog.css	Fri Mar 25 00:32:58 2011 +0100
@@ -0,0 +1,53 @@
+/*
+Libervia: a Salut à Toi frontend
+Copyright (C) 2011  Jérôme Poisson (goffi@goffi.org)
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+.mblog_title {
+    text-align: center;
+    font-size: x-large;
+    font-weight: bold;
+    margin-bottom: 40px;
+}
+
+.mblog_content {
+    width: 60%;
+    text-align:center;
+    
+    border: 1px solid LightGray;
+
+    border-bottom-width: 1px;
+    margin-left: auto;
+    margin-right: auto;
+    margin-bottom: 20px;
+    margin-top: 5px;
+    padding-left: 10px;
+    padding-right: 10px;
+    padding-top: 5px;
+    padding-bottom: 5px;
+
+    -moz-border-radius: 15px;
+    -webkit-border-radius: 15px;
+    border-radius: 15px;
+}
+
+.mblog_timestamp {
+    display: block;
+    font-size: small;
+    border-bottom: 1px dashed LightGrey;
+    color: gray;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server_side/blog.py	Fri Mar 25 00:32:58 2011 +0100
@@ -0,0 +1,88 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""
+Libervia: a Salut à Toi frontend
+Copyright (C) 2011  Jérôme Poisson (goffi@goffi.org)
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+
+from server_side.html_tools import sanitizeHtml
+from twisted.internet import reactor, defer
+from twisted.web import server
+from twisted.web.resource import Resource
+from twisted.words.protocols.jabber.jid import JID
+from datetime import datetime
+
+class MicroBlog(Resource):
+    isLeaf = True
+
+    ERROR_TEMPLATE = """
+                <html>
+                <head>
+                    <title>MICROBLOG ERROR</title>
+                </head>
+                <body>
+                    <h1 style='text-align: center; color: red;'>%s</h1>
+                </body>
+                </html>
+                """
+
+    def __init__(self,host):
+        self.host = host
+        Resource.__init__(self)
+        if not host.bridge.isConnected("libervia"): #FIXME: hard coded value for test
+            host.bridge.connect("libervia")
+
+    def render_GET(self, request):
+        if not request.postpath:
+            return MicroBlog.ERROR_TEMPLATE % "You must indicate a nickname"
+        else:
+            prof_requested = request.postpath[0]
+            #TODO: char check: only use alphanumerical chars + some extra(_,-,...) here
+            prof_found = self.host.bridge.getProfileName(prof_requested)
+            if not prof_found or prof_found=='libervia':
+                return MicroBlog.ERROR_TEMPLATE % "Invalid nickname"
+            else:
+                pub_jid=JID(self.host.bridge.getParamA('JabberID','Connection','value',prof_found))
+                d = defer.Deferred()
+                d.addCallbacks(self.render_html_blog, self.render_error_blog, [request, prof_found], None, [request, prof_found], None)
+                self.host.bridge.getLastMicroblogs(pub_jid.userhost(), 10, 'libervia', d.callback, d.errback)
+
+                return server.NOT_DONE_YET
+
+    def render_html_blog(self, mblog_data, request, profile):
+        user = sanitizeHtml(profile).encode('utf-8')
+        request.write("""
+            <html>
+            <head>
+                <link rel="stylesheet" type="text/css" href="../css/blog.css" />
+                <title>%(user)s's microblog</title>
+            </head>
+            <body>
+                <div class='mblog_title'>%(user)s</div>
+            """ % {'user':user})
+        for entry in mblog_data:
+            timestamp = float(entry.get('timestamp',0))
+            _datetime = datetime.fromtimestamp(timestamp)
+            request.write("<div class='mblog_content'><span class='mblog_timestamp'>%(date)s</span>%(content)s</div>" % {
+                          'date':_datetime,
+                          'content':sanitizeHtml(entry['content']).encode('utf-8')})
+        request.write('</body></html>')
+        request.finish()
+        
+    def render_error_blog(self, error, request):
+        request.write(MicroBlog.ERROR_TEMPLATE % "Can't access requested data")
+        request.finish()