Merge remote-tracking branch 'tsileo/reply_notification' into reply_notification
Conflicts: isso/css/isso.scss isso/db/comments.py isso/ext/notifications.py isso/js/app/i18n/fr.js isso/js/app/isso.js isso/js/app/text/postbox.html isso/views/comments.py
This commit is contained in:
commit
c30873e8a2
@ -209,6 +209,10 @@
|
||||
.isso-postbox > .form-wrapper > .auth-section .post-action > input:active {
|
||||
background-color: #BBB;
|
||||
}
|
||||
.isso-postbox > .form-wrapper > .notification-section {
|
||||
display: none;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
@media screen and (max-width:600px) {
|
||||
.isso-postbox > .form-wrapper > .auth-section .input-wrapper {
|
||||
display: block;
|
||||
|
@ -23,7 +23,7 @@ class Comments:
|
||||
'mode', # status of the comment 1 = valid, 2 = pending,
|
||||
# 4 = soft-deleted (cannot hard delete because of replies)
|
||||
'remote_addr', 'text', 'author', 'email', 'website',
|
||||
'likes', 'dislikes', 'voters']
|
||||
'likes', 'dislikes', 'voters', 'notification']
|
||||
|
||||
def __init__(self, db):
|
||||
|
||||
@ -33,7 +33,8 @@ class Comments:
|
||||
' tid REFERENCES threads(id), id INTEGER PRIMARY KEY, parent INTEGER,',
|
||||
' created FLOAT NOT NULL, modified FLOAT, mode INTEGER, remote_addr VARCHAR,',
|
||||
' text VARCHAR, author VARCHAR, email VARCHAR, website VARCHAR,',
|
||||
' likes INTEGER DEFAULT 0, dislikes INTEGER DEFAULT 0, voters BLOB NOT NULL);'])
|
||||
' likes INTEGER DEFAULT 0, dislikes INTEGER DEFAULT 0, voters BLOB NOT NULL,',
|
||||
' notification INTEGER NOT NULL DEFAULT 0);'])
|
||||
|
||||
def add(self, uri, c):
|
||||
"""
|
||||
@ -50,16 +51,16 @@ class Comments:
|
||||
'INSERT INTO comments (',
|
||||
' tid, parent,'
|
||||
' created, modified, mode, remote_addr,',
|
||||
' text, author, email, website, voters )',
|
||||
' text, author, email, website, voters, notification)',
|
||||
'SELECT',
|
||||
' threads.id, ?,',
|
||||
' ?, ?, ?, ?,',
|
||||
' ?, ?, ?, ?, ?',
|
||||
' ?, ?, ?, ?, ?, ?',
|
||||
'FROM threads WHERE threads.uri = ?;'], (
|
||||
c.get('parent'),
|
||||
c.get('created') or time.time(), None, c["mode"], c['remote_addr'],
|
||||
c['text'], c.get('author'), c.get('email'), c.get('website'), buffer(
|
||||
Bloomfilter(iterable=[c['remote_addr']]).array),
|
||||
Bloomfilter(iterable=[c['remote_addr']]).array), c.get('notification'),
|
||||
uri)
|
||||
)
|
||||
|
||||
|
@ -88,7 +88,7 @@ class SMTP(object):
|
||||
def __iter__(self):
|
||||
yield "comments.new:after-save", self.notify
|
||||
|
||||
def format(self, thread, comment):
|
||||
def format(self, thread, comment, admin=False):
|
||||
|
||||
rv = io.StringIO()
|
||||
|
||||
@ -101,40 +101,51 @@ class SMTP(object):
|
||||
rv.write(comment["text"] + "\n")
|
||||
rv.write("\n")
|
||||
|
||||
if comment["website"]:
|
||||
rv.write("User's URL: %s\n" % comment["website"])
|
||||
if admin:
|
||||
if comment["website"]:
|
||||
rv.write("User's URL: %s\n" % comment["website"])
|
||||
|
||||
rv.write("IP address: %s\n" % comment["remote_addr"])
|
||||
rv.write("Link to comment: %s\n" %
|
||||
(local("origin") + thread["uri"] + "#isso-%i" % comment["id"]))
|
||||
rv.write("\n")
|
||||
rv.write("IP address: %s\n" % comment["remote_addr"])
|
||||
rv.write("Link to comment: %s\n" %
|
||||
(local("origin") + thread["uri"] + "#isso-%i" % comment["id"]))
|
||||
rv.write("\n")
|
||||
|
||||
uri = local("host") + "/id/%i" % comment["id"]
|
||||
key = self.isso.sign(comment["id"])
|
||||
uri = local("host") + "/id/%i" % comment["id"]
|
||||
key = self.isso.sign(comment["id"])
|
||||
|
||||
rv.write("---\n")
|
||||
rv.write("Delete comment: %s\n" % (uri + "/delete/" + key))
|
||||
rv.write("---\n")
|
||||
rv.write("Delete comment: %s\n" % (uri + "/delete/" + key))
|
||||
|
||||
if comment["mode"] == 2:
|
||||
rv.write("Activate comment: %s\n" % (uri + "/activate/" + key))
|
||||
if comment["mode"] == 2:
|
||||
rv.write("Activate comment: %s\n" % (uri + "/activate/" + key))
|
||||
|
||||
rv.seek(0)
|
||||
return rv.read()
|
||||
|
||||
def notify(self, thread, comment):
|
||||
if "parent" in comment:
|
||||
comment_parent = self.isso.db.comments.get(comment["parent"])
|
||||
# Notify the author that a new comment is posted if requested
|
||||
if comment_parent and "email" in comment_parent and comment_parent["notification"]:
|
||||
body = self.format(thread, comment, admin=False)
|
||||
subject = "Re: New comment posted on %s" % thread["title"]
|
||||
self.sendmail(subject, body, thread, comment, to=comment_parent["email"])
|
||||
|
||||
body = self.format(thread, comment)
|
||||
body = self.format(thread, comment, admin=True)
|
||||
self.sendmail(thread["title"], body, thread, comment)
|
||||
|
||||
def sendmail(self, subject, body, thread, comment, to=None):
|
||||
if uwsgi:
|
||||
uwsgi.spool({b"subject": thread["title"].encode("utf-8"),
|
||||
b"body": body.encode("utf-8")})
|
||||
uwsgi.spool({b"subject": subject.encode("utf-8"),
|
||||
b"body": body.encode("utf-8"),
|
||||
b"to": to})
|
||||
else:
|
||||
start_new_thread(self._retry, (thread["title"], body))
|
||||
start_new_thread(self._retry, (subject, body, to))
|
||||
|
||||
def _sendmail(self, subject, body):
|
||||
def _sendmail(self, subject, body, to=None):
|
||||
|
||||
from_addr = self.conf.get("from")
|
||||
to_addr = self.conf.get("to")
|
||||
to_addr = to or self.conf.get("to")
|
||||
|
||||
msg = MIMEText(body, 'plain', 'utf-8')
|
||||
msg['From'] = from_addr
|
||||
@ -145,10 +156,10 @@ class SMTP(object):
|
||||
with self as con:
|
||||
con.sendmail(from_addr, to_addr, msg.as_string())
|
||||
|
||||
def _retry(self, subject, body):
|
||||
def _retry(self, subject, body, to):
|
||||
for x in range(5):
|
||||
try:
|
||||
self._sendmail(subject, body)
|
||||
self._sendmail(subject, body, to)
|
||||
except smtplib.SMTPConnectError:
|
||||
time.sleep(60)
|
||||
else:
|
||||
|
@ -90,6 +90,8 @@ define(function() {
|
||||
this.focus = function() { node.focus() };
|
||||
this.scrollIntoView = function(args) { node.scrollIntoView(args) };
|
||||
|
||||
this.checked = function() { return node.checked; };
|
||||
|
||||
this.setAttribute = function(key, value) { node.setAttribute(key, value) };
|
||||
this.getAttribute = function(key) { return node.getAttribute(key) };
|
||||
|
||||
|
@ -4,6 +4,7 @@ define({
|
||||
"postbox-email": "E-mail (optional)",
|
||||
"postbox-website": "Website (optional)",
|
||||
"postbox-submit": "Submit",
|
||||
"postbox-notification": "Subscribe to email notification of replies",
|
||||
|
||||
"num-comments": "One Comment\n{{ n }} Comments",
|
||||
"no-comments": "No Comments Yet",
|
||||
|
@ -4,6 +4,7 @@ define({
|
||||
"postbox-email": "Courriel (optionnel)",
|
||||
"postbox-website": "Site web (optionnel)",
|
||||
"postbox-submit": "Soumettre",
|
||||
"postbox-notification": "S'abonner aux notifications de réponses",
|
||||
"num-comments": "{{ n }} commentaire\n{{ n }} commentaires",
|
||||
"no-comments": "Aucun commentaire pour l'instant",
|
||||
"comment-reply": "Répondre",
|
||||
|
@ -39,6 +39,17 @@ define(["app/dom", "app/utils", "app/config", "app/api", "app/jade", "app/i18n",
|
||||
return true;
|
||||
};
|
||||
|
||||
// only display notification checkbox if email is filled in
|
||||
var email_edit = function() {
|
||||
if ($("[name='email']", el).value.length > 0) {
|
||||
$(".notification-section", el).show();
|
||||
} else {
|
||||
$(".notification-section", el).hide();
|
||||
}
|
||||
};
|
||||
$("[name='email']", el).on("input", email_edit);
|
||||
email_edit();
|
||||
|
||||
// email is not optional if this config parameter is set
|
||||
if (config["require-email"]) {
|
||||
$("[name='email']", el).setAttribute("placeholder",
|
||||
@ -70,7 +81,8 @@ define(["app/dom", "app/utils", "app/config", "app/api", "app/jade", "app/i18n",
|
||||
author: author, email: email, website: website,
|
||||
text: utils.text($(".textarea", el).innerHTML),
|
||||
parent: parent || null,
|
||||
title: $("#isso-thread").getAttribute("data-title") || null
|
||||
title: $("#isso-thread").getAttribute("data-title") || null,
|
||||
notification: $("[name=notification]", el).checked() ? 1 : 0,
|
||||
}).then(function(comment) {
|
||||
$(".textarea", el).innerHTML = "";
|
||||
$(".textarea", el).blur();
|
||||
|
@ -15,3 +15,7 @@ div(class='isso-postbox')
|
||||
value=website != null ? '#{website}' : '')
|
||||
p(class='post-action')
|
||||
input(type='submit' value=i18n('postbox-submit'))
|
||||
section(class='notification-section')
|
||||
label
|
||||
input(type='checkbox' name='notification')
|
||||
= i18n('postbox-notification')
|
||||
|
@ -81,10 +81,10 @@ def xhr(func):
|
||||
class API(object):
|
||||
|
||||
FIELDS = set(['id', 'parent', 'text', 'author', 'website',
|
||||
'mode', 'created', 'modified', 'likes', 'dislikes', 'hash'])
|
||||
'mode', 'created', 'modified', 'likes', 'dislikes', 'hash', 'notification'])
|
||||
|
||||
# comment fields, that can be submitted
|
||||
ACCEPT = set(['text', 'author', 'website', 'email', 'parent', 'title'])
|
||||
ACCEPT = set(['text', 'author', 'website', 'email', 'parent', 'title', 'notification'])
|
||||
|
||||
VIEWS = [
|
||||
('fetch', ('GET', '/')),
|
||||
|
Loading…
Reference in New Issue
Block a user