# Comments plugin for Vellum

import vellum.hooks,vellum.Entry,vellum.functions,vellum.config
import audience
import bsddb,os
try:
    import cPickle as pickle
except:
    import pickle

# Create the Comment object and make it available from an Entry

class Comment(audience.Audience):
    pass

def get_comments(entry):
    "Gets all comments for the passed entry"
    return audience.get_audience(entry) #,"comment")

vellum.Entry.Entry.comments = get_comments

# Comment form

def commentForm(form):
    if not form.has_key("eid"): raise "No entry id was specified."
    e = vellum.Entry.get(form.getvalue("eid"))
    if not e: raise "The specified entry doesn't exist."
    print """
    <form action="vellum.cgi?a=postComment" method="POST" class="comment">
    <h3>Commenting on %s</h3>
    <p>Everything is optional.
    <h3>Name</h3>
    <input type="text" name="name">
    <h3>Email address</h3>
    <input type="text" name="email">
    <h3>URL</h3>
    <input type="text" name="url">
    </p>
    <p>
    <textarea name="text" rows="7" cols="40"></textarea>
    </p>
    <p>
    <input type="checkbox" name="private">Private comment?
    <input type="hidden" name="eid" value="%s">
    </p>
    <p>
    <input type="submit" name="save" value="Post comment">
    </p>
    </form>
    """ % (e.title,e.id)

vellum.functions.commentForm = commentForm
vellum.functions.commentForm.noAuth = 1

# Post the comment form to here

def postComment(form):
    if not form.has_key("eid"): raise "No entry id was specified."
    e = vellum.Entry.get(form.getvalue("eid"))
    if not e: raise "The specified entry doesn't exist."
    url = form.getvalue("url") or ''
    email = form.getvalue("email") or ''
    name = form.getvalue("name") or 'Anonymous'
    text = form.getvalue("text") or ''
    allowPrivateComments = vellum.config.get("AllowPrivateComments")
    private = None
    if str(allowPrivateComments).lower() in ['y','yes','1','true']:
        private = form.getvalue("private") or None
        if private == '0': private = None
    suppressEmails = vellum.config.get("SuppressEmails")
    if str(suppressEmails).lower() in ['n','no','0','false']:
        suppressEmails = None
    if text:
        if not private:
            c = Comment()
            if url:
                c.ref = '<a href="%s">%s</a>' % (url,name)
            else:
                c.ref = name
            c.entryid = e.id
            c.text = text
            c.type = "comment"
            c.save()
        if private or (not private and not suppressEmails):
            #try:
                # Get author email address
                dbdir = vellum.config.get("DatabaseDir")
                if not dbdir:
                    raise "There is no DatabaseDir listed in the config file"

                adb = bsddb.hashopen(os.path.join(dbdir,"authors"),"c")
                authordict = pickle.loads(adb[e.author])
                aemail = authordict["email"]
                mailServer = vellum.config.get("MailServer")
                if mailServer:
                    import smtplib
                    if email:
                        fromemail = email
                    else:
                        fromemail = aemail
                    msg = "Subject: Post to %s\n" % e.blog().title
                    msg += "To: %s\n\n" % aemail
                    msg += "A comment has been posted to your weblog %s\n" % e.blog().title
                    msg += "Comment by '%s' (%s) at '%s'\n" % (name,email,url)
                    msg += wrap(text,72)
                    smtp = smtplib.SMTP(mailServer)
                    smtp.sendmail(fromemail,aemail,msg)
                    smtp.quit()
            #except:
            #    pass
        e.rebuild()
    return e.permalink

vellum.functions.postComment = postComment
vellum.functions.postComment.noAuth = 1

def wrap(text, width):
    """
    A word-wrap function that preserves existing line breaks
    and most spaces in the text. Expects that existing line
    breaks are posix newlines (\n).
    http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/148061
    """
    return reduce(lambda line, word, width=width: '%s%s%s' %
                  (line,
                   ' \n'[(len(line[line.rfind('\n')+1:])
                         + len(word.split('\n',1)[0]
                              ) >= width)],
                   word),
                  text.split(' ')
                 )

# Print an entry's comment count in the entry list
def printListComments(entry):
    print '<td>'
    if hasattr(entry,"comments"):
        print "(%s)" % len(entry.comments())
    print '</td>'

vellum.hooks.register_hook("entry-listdisplay-print",printListComments)

__pluginname__ = "Comments"
__description__ = "Allow readers to add comments to your posts."