Implement opt-out for email notifications
This commit is contained in:
parent
bc4bc55025
commit
c9045f5b1f
@ -81,6 +81,15 @@ class Comments:
|
||||
' mode=1',
|
||||
'WHERE id=? AND mode=2'], (id, ))
|
||||
|
||||
def unsubscribe(self, id):
|
||||
"""
|
||||
Turn off email notifications for replies to this comment.
|
||||
"""
|
||||
self.db.execute([
|
||||
'UPDATE comments SET',
|
||||
' notification=0',
|
||||
'WHERE id=?'], (id, ))
|
||||
|
||||
def update(self, id, data):
|
||||
"""
|
||||
Update comment :param:`id` with values from :param:`data` and return
|
||||
|
@ -93,7 +93,7 @@ class SMTP(object):
|
||||
def __iter__(self):
|
||||
yield "comments.new:after-save", self.notify
|
||||
|
||||
def format(self, thread, comment, admin=False):
|
||||
def format(self, thread, comment, comment_parent, admin=False):
|
||||
|
||||
rv = io.StringIO()
|
||||
|
||||
@ -115,17 +115,23 @@ class SMTP(object):
|
||||
rv.write("Link to comment: %s\n" %
|
||||
(local("origin") + thread["uri"] + "#isso-%i" % comment["id"]))
|
||||
rv.write("\n")
|
||||
rv.write("---\n")
|
||||
|
||||
if admin:
|
||||
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))
|
||||
|
||||
if comment["mode"] == 2:
|
||||
rv.write("Activate comment: %s\n" % (uri + "/activate/" + key))
|
||||
|
||||
else:
|
||||
uri = local("host") + "/id/%i" % comment_parent["id"]
|
||||
key = self.isso.sign(('unsubscribe', comment_parent["id"]))
|
||||
|
||||
rv.write("Unsubscribe from this conversation: %s\n" % (uri + "/unsubscribe/" + key))
|
||||
|
||||
rv.seek(0)
|
||||
return rv.read()
|
||||
|
||||
@ -134,11 +140,11 @@ class SMTP(object):
|
||||
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)
|
||||
body = self.format(thread, comment, comment_parent, 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, admin=True)
|
||||
body = self.format(thread, comment, None, admin=True)
|
||||
self.sendmail(thread["title"], body, thread, comment)
|
||||
|
||||
def sendmail(self, subject, body, thread, comment, to=None):
|
||||
|
@ -87,21 +87,22 @@ class API(object):
|
||||
ACCEPT = set(['text', 'author', 'website', 'email', 'parent', 'title', 'notification'])
|
||||
|
||||
VIEWS = [
|
||||
('fetch', ('GET', '/')),
|
||||
('new', ('POST', '/new')),
|
||||
('count', ('GET', '/count')),
|
||||
('counts', ('POST', '/count')),
|
||||
('view', ('GET', '/id/<int:id>')),
|
||||
('edit', ('PUT', '/id/<int:id>')),
|
||||
('delete', ('DELETE', '/id/<int:id>')),
|
||||
('moderate', ('GET', '/id/<int:id>/<any(edit,activate,delete):action>/<string:key>')),
|
||||
('moderate', ('POST', '/id/<int:id>/<any(edit,activate,delete):action>/<string:key>')),
|
||||
('like', ('POST', '/id/<int:id>/like')),
|
||||
('dislike', ('POST', '/id/<int:id>/dislike')),
|
||||
('demo', ('GET', '/demo')),
|
||||
('preview', ('POST', '/preview')),
|
||||
('login', ('POST', '/login')),
|
||||
('admin', ('GET', '/admin'))
|
||||
('fetch', ('GET', '/')),
|
||||
('new', ('POST', '/new')),
|
||||
('count', ('GET', '/count')),
|
||||
('counts', ('POST', '/count')),
|
||||
('view', ('GET', '/id/<int:id>')),
|
||||
('edit', ('PUT', '/id/<int:id>')),
|
||||
('delete', ('DELETE', '/id/<int:id>')),
|
||||
('unsubscribe', ('GET', '/id/<int:id>/unsubscribe/<string:key>')),
|
||||
('moderate', ('GET', '/id/<int:id>/<any(edit,activate,delete):action>/<string:key>')),
|
||||
('moderate', ('POST', '/id/<int:id>/<any(edit,activate,delete):action>/<string:key>')),
|
||||
('like', ('POST', '/id/<int:id>/like')),
|
||||
('dislike', ('POST', '/id/<int:id>/dislike')),
|
||||
('demo', ('GET', '/demo')),
|
||||
('preview', ('POST', '/preview')),
|
||||
('login', ('POST', '/login')),
|
||||
('admin', ('GET', '/admin'))
|
||||
]
|
||||
|
||||
def __init__(self, isso, hasher):
|
||||
@ -477,6 +478,66 @@ class API(object):
|
||||
resp.headers.add("X-Set-Cookie", cookie("isso-%i" % id))
|
||||
return resp
|
||||
|
||||
"""
|
||||
@api {get} /id/:id/key unsubscribe
|
||||
@apiGroup Comment
|
||||
@apiDescription
|
||||
Opt out from getting any further email notifications about replies to a particular comment. In order to use this endpoint, the requestor needs a `key` that is usually obtained from an email sent out by isso.
|
||||
|
||||
@apiParam {number} id
|
||||
The id of the comment to unsubscribe from replies to.
|
||||
@apiParam {string} key
|
||||
The key to authenticate the subscriber.
|
||||
|
||||
@apiExample {curl} Unsubscribe from replies to comment with id 13:
|
||||
curl -X GET 'https://comments.example.com/id/13/unsubscribe/TODO-COMPUTE-HASH'
|
||||
|
||||
@apiSuccessExample {html} Using GET:
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
if (confirm('Delete: Are you sure?')) {
|
||||
xhr = new XMLHttpRequest;
|
||||
xhr.open('POST', window.location.href);
|
||||
xhr.send(null);
|
||||
}
|
||||
</script>
|
||||
|
||||
@apiSuccessExample Using POST:
|
||||
Yo
|
||||
"""
|
||||
|
||||
def unsubscribe(self, environ, request, id, key):
|
||||
try:
|
||||
rv = self.isso.unsign(key, max_age=2**32)
|
||||
except (BadSignature, SignatureExpired):
|
||||
raise Forbidden
|
||||
|
||||
if rv[0] != 'unsubscribe' or rv[1] != id:
|
||||
raise Forbidden
|
||||
|
||||
item = self.comments.get(id)
|
||||
|
||||
if item is None:
|
||||
raise NotFound
|
||||
|
||||
with self.isso.lock:
|
||||
self.comments.unsubscribe(id)
|
||||
|
||||
modal = (
|
||||
"<!DOCTYPE html>"
|
||||
"<html>"
|
||||
"<head>"
|
||||
" <title>Successfully unsubscribed</title>"
|
||||
"</head>"
|
||||
"<body>"
|
||||
" <p>You have been unsubscribed from replies in the given conversation.</p>"
|
||||
"</body>"
|
||||
"</html>")
|
||||
|
||||
return Response(modal, 200, content_type="text/html")
|
||||
|
||||
"""
|
||||
@api {post} /id/:id/:action/key moderate
|
||||
@apiGroup Comment
|
||||
|
Loading…
Reference in New Issue
Block a user