constance

Scripts for generating (an earlier obsolete version of) my personal web site
git clone https://code.djc.id.au/git/constance/
commit 9cb2251380baf1a13955869592e4bd6c6f769d82
parent 9e1e44b77d83e99f457c75f503038b48a6c4f026
Author: Dan Callaghan <djc@djc.id.au>
Date:   Tue, 16 Sep 2008 02:10:05 +1000

comment submission, requires prettification

Diffstat:
MTODO | 2+-
Mapp.py | 26++++++++++++++++++++++++--
Mblog.py | 15++++++++++++++-
Mtemplates/_entry.xml | 11++++++++++-
4 files changed, 49 insertions(+), 5 deletions(-)
diff --git a/TODO b/TODO
@@ -1,7 +1,7 @@
 - ignore pages in export_wp.py
 - feeds everywhere else
 - monthly archives
-- comment submission
+- make comment submission form prettier
 - more styles: blockquote, pre, code, ...?
 - <!-- more -->
 - customisation:
diff --git a/app.py b/app.py
@@ -6,7 +6,7 @@ from itertools import chain
 import wsgiref.util
 from genshi.template import TemplateLoader
 from colubrid import RegexApplication, HttpResponse
-from colubrid.exceptions import PageNotFound, HttpFound
+from colubrid.exceptions import PageNotFound, AccessDenied, HttpFound
 from colubrid.server import StaticExports
 
 import config
@@ -23,7 +23,8 @@ class Constance(RegexApplication):
             (r'^feed$', 'feed'), 
             (r'^\+tags/(.+)$', 'tag'), 
             (r'^\+reading/?$', 'reading'), 
-            (r'^([^+/][^/]*)/?$', 'post')]
+            (r'^([^+/][^/]*)/?$', 'post'), 
+            (r'^([^+/][^/]*)/comments/\+new$', 'add_post_comment')]
     charset = 'utf-8'
 
     def __init__(self, *args, **kwargs):
@@ -76,6 +77,27 @@ class Constance(RegexApplication):
             return HttpResponse(rendered, [('Content-Type', 'text/html')], 200)
         except blog.EntryNotFoundError:
             raise PageNotFound()
+    
+    def add_post_comment(self, id):
+        id = id.decode(self.charset) # shouldn't Colubrid do this?
+        try:
+            entry = self.blog_entries[id]
+            form_data = self.request.form.as_dict()
+            metadata = {}
+            metadata['From'] = form_data['from'] or 'Anonymous'
+            if form_data['author-url']:
+                metadata['Author-URL'] = form_data['author-url']
+            if form_data['author-email']:
+                metadata['Author-Email'] = form_data['author-email']
+            if self.request.environ['HTTP_USER_AGENT']:
+                metadata['User-Agent'] = self.request.environ['HTTP_USER_AGENT']
+            if self.request.environ['REMOTE_ADDR']:
+                metadata['Received'] = 'from %s' % self.request.environ['REMOTE_ADDR']
+            entry.add_comment(metadata, form_data['comment'])
+            raise HttpFound('%s/%s/' % (self.request.environ.get('SCRIPT_NAME', ''), 
+                    id.encode(self.charset)))
+        except blog.CommentingForbiddenError:
+            raise AccessDenied()
 
     def tag(self, tag):
         tag = tag.decode(self.charset)
diff --git a/blog.py b/blog.py
@@ -1,4 +1,4 @@
-import os, re
+import os, re, uuid
 from datetime import datetime
 import markdown
 import genshi
@@ -33,6 +33,8 @@ class EntryNotFoundError(ValueError): pass
 
 class EntryForbiddenError(ValueError): pass
 
+class CommentingForbiddenError(ValueError): pass # XXX why all the different types?
+
 class CommentNotFoundError(ValueError): pass
 
 class CommentForbiddenError(ValueError): pass
@@ -113,6 +115,17 @@ class BlogEntry(object):
         return os.path.isdir(self.comments_dir) and \
                 os.access(self.comments_dir, os.R_OK)
 
+    def add_comment(self, metadata, content):
+        if not os.access(self.comments_dir, os.W_OK):
+            raise CommentingForbiddenError()
+        # XXX write to temp file
+        guid = uuid.uuid4().get_hex()
+        f = open(os.path.join(self.comments_dir, guid), 'w')
+        for k, v in metadata.iteritems():
+            f.write('%s: %s\n' % (k, v))
+        f.write('\n')
+        f.write(content)
+
 
 class BlogEntrySet(DirectoryEntrySet):
 
diff --git a/templates/_entry.xml b/templates/_entry.xml
@@ -41,14 +41,23 @@ from viewutils import mini_markdown, tag_list
             <py:otherwise>${len(entry.comments())} comments</py:otherwise>
         </h4>
         <div py:for="n, comment in enumerate(comments)" id="comment-${comment.id}">
-            <py:if test="n > 0">${block_sep()}</py:if>
             ${comment.body}
             <p class="commentmeta">
                 ― <a py:strip="not comment.author_url" href="${comment.author_url}">${comment.author_name()}</a>
                 <span class="commentdatetime">${comment.date.strftime(str('%-1d %b %Y %H:%M'))}</span>
                 <a href="#comment-${comment.id}" class="permalink" title="permalink">#</a>
             </p>
+            ${block_sep()}
         </div>
+        <div><form method="post" action="${environ.get('SCRIPT_NAME', '')}/${entry.id}/comments/+new">
+            <p>
+                <label for="commentform-from">Name:</label> <input type="text" id="commentform-from" name="from" /><br />
+                <label for="commentform-author-url">URL:</label> <input type="text" id="commentform-author-url" name="author-url" /><br />
+                <label for="commentform-author-email">E-mail address:</label> <input type="text" id="commentform-author-email" name="author-email" /> (not published)<br />
+            </p>
+            <p><textarea name="comment"></textarea></p>
+            <p><input type="submit" value="Submit" /></p>
+        </form></div>
     </div>
 
 </div>