Manage reader subscription
This commit is contained in:
parent
ffab88e369
commit
e19aae121b
7 changed files with 102 additions and 44 deletions
|
@ -14,7 +14,7 @@ def new_mail():
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
logger.info(data)
|
logger.debug(data)
|
||||||
|
|
||||||
processor.enqueue({'request': 'new_mail', 'data': data})
|
processor.enqueue({'request': 'new_mail', 'data': data})
|
||||||
|
|
||||||
|
|
29
app/controllers/reader.py
Normal file
29
app/controllers/reader.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from flask import request, abort
|
||||||
|
from app import app
|
||||||
|
from app.services import processor
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/unsubscribe", methods=['GET'])
|
||||||
|
def unsubscribe():
|
||||||
|
|
||||||
|
try:
|
||||||
|
data = {
|
||||||
|
'token': request.args.get('token', ''),
|
||||||
|
'url': request.args.get('url', ''),
|
||||||
|
'email': request.args.get('email', '')
|
||||||
|
}
|
||||||
|
logger.debug(data)
|
||||||
|
|
||||||
|
processor.enqueue({'request': 'unsubscribe', 'data': data})
|
||||||
|
|
||||||
|
except:
|
||||||
|
logger.exception("unsubscribe failure")
|
||||||
|
abort(400)
|
||||||
|
|
||||||
|
return "OK"
|
17
app/models/reader.py
Normal file
17
app/models/reader.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: UTF-8 -*-
|
||||||
|
|
||||||
|
from peewee import Model
|
||||||
|
from peewee import CharField
|
||||||
|
from peewee import ForeignKeyField
|
||||||
|
from app.services.database import get_db
|
||||||
|
from app.models.site import Site
|
||||||
|
|
||||||
|
|
||||||
|
class Reader(Model):
|
||||||
|
url = CharField()
|
||||||
|
email = CharField(default='')
|
||||||
|
site = ForeignKeyField(Site, related_name='reader_site')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
database = get_db()
|
|
@ -21,6 +21,7 @@ from app.services import database
|
||||||
from app.services import processor
|
from app.services import processor
|
||||||
from app.controllers import api
|
from app.controllers import api
|
||||||
from app.controllers import mail
|
from app.controllers import mail
|
||||||
|
from app.controllers import reader
|
||||||
from app import app
|
from app import app
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,6 +50,7 @@ database.setup()
|
||||||
# routes
|
# routes
|
||||||
logger.debug('imported: %s ' % api.__name__)
|
logger.debug('imported: %s ' % api.__name__)
|
||||||
logger.debug('imported: %s ' % mail.__name__)
|
logger.debug('imported: %s ' % mail.__name__)
|
||||||
|
logger.debug('imported: %s ' % reader.__name__)
|
||||||
|
|
||||||
# start processor
|
# start processor
|
||||||
template_path = os.path.abspath(os.path.join(current_path, 'templates'))
|
template_path = os.path.abspath(os.path.join(current_path, 'templates'))
|
||||||
|
|
|
@ -23,5 +23,6 @@ def provide_db(func):
|
||||||
def setup(db):
|
def setup(db):
|
||||||
from app.models.site import Site
|
from app.models.site import Site
|
||||||
from app.models.comment import Comment
|
from app.models.comment import Comment
|
||||||
|
from app.models.reader import Reader
|
||||||
|
|
||||||
db.create_tables([Site, Comment], safe=True)
|
db.create_tables([Site, Comment, Reader], safe=True)
|
||||||
|
|
|
@ -9,6 +9,7 @@ from queue import Queue
|
||||||
from jinja2 import Environment, FileSystemLoader
|
from jinja2 import Environment, FileSystemLoader
|
||||||
from app.models.site import Site
|
from app.models.site import Site
|
||||||
from app.models.comment import Comment
|
from app.models.comment import Comment
|
||||||
|
from app.models.reader import Reader
|
||||||
import requests
|
import requests
|
||||||
import json
|
import json
|
||||||
import config
|
import config
|
||||||
|
@ -36,8 +37,8 @@ class Processor(Thread):
|
||||||
new_comment(msg['data'])
|
new_comment(msg['data'])
|
||||||
elif msg['request'] == 'new_mail':
|
elif msg['request'] == 'new_mail':
|
||||||
reply_comment_email(msg['data'])
|
reply_comment_email(msg['data'])
|
||||||
# elif req['type'] == 'unsubscribe':
|
elif msg['request'] == 'unsubscribe':
|
||||||
# unsubscribe_reader(req['email'], req['article'])
|
unsubscribe_reader(msg['data'])
|
||||||
else:
|
else:
|
||||||
logger.info("throw unknown request " + str(msg))
|
logger.info("throw unknown request " + str(msg))
|
||||||
except:
|
except:
|
||||||
|
@ -91,16 +92,14 @@ def new_comment(data):
|
||||||
|
|
||||||
# Reader subscribes to further comments
|
# Reader subscribes to further comments
|
||||||
if subscribe and author_email:
|
if subscribe and author_email:
|
||||||
# TODO support subscription
|
subscribe_reader(author_email, token, url)
|
||||||
# subscribe_reader(email, article, url)
|
|
||||||
pass
|
|
||||||
|
|
||||||
logger.debug("new comment processed ")
|
logger.debug("new comment processed ")
|
||||||
|
|
||||||
|
|
||||||
def reply_comment_email(data):
|
def reply_comment_email(data):
|
||||||
|
|
||||||
email_address = data['from']
|
from_email = data['from']
|
||||||
subject = data['subject']
|
subject = data['subject']
|
||||||
message = ''
|
message = ''
|
||||||
for part in data['parts']:
|
for part in data['parts']:
|
||||||
|
@ -127,7 +126,7 @@ def reply_comment_email(data):
|
||||||
logger.info('discard comment: %d' % comment_id)
|
logger.info('discard comment: %d' % comment_id)
|
||||||
comment.delete_instance()
|
comment.delete_instance()
|
||||||
email_body = get_template('drop_comment').render(original=message)
|
email_body = get_template('drop_comment').render(original=message)
|
||||||
mail(email_address, 'Re: ' + subject, email_body)
|
mail(from_email, 'Re: ' + subject, email_body)
|
||||||
else:
|
else:
|
||||||
# update Comment row
|
# update Comment row
|
||||||
comment.published = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
comment.published = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
@ -137,63 +136,71 @@ def reply_comment_email(data):
|
||||||
|
|
||||||
# send approval confirmation email to admin
|
# send approval confirmation email to admin
|
||||||
email_body = get_template('approve_comment').render(original=message)
|
email_body = get_template('approve_comment').render(original=message)
|
||||||
mail(email_address, 'Re: ' + subject, email_body)
|
mail(from_email, 'Re: ' + subject, email_body)
|
||||||
|
|
||||||
# TODO manage subscriptions
|
|
||||||
# notify reader once comment is published
|
# notify reader once comment is published
|
||||||
# reader_email, article_url = get_email_metadata(message)
|
reader_email = get_email_metadata(message)
|
||||||
# if reader_email:
|
if reader_email:
|
||||||
# notify_reader(reader_email, article_url)
|
notify_reader(from_email, reader_email, comment.site.token,
|
||||||
|
comment.url)
|
||||||
|
|
||||||
# notify subscribers every time a new comment is published
|
# notify subscribers every time a new comment is published
|
||||||
# notify_subscribers(article)
|
notify_subscribed_readers(comment.site.token, comment.url)
|
||||||
|
|
||||||
|
|
||||||
def get_email_metadata(message):
|
def get_email_metadata(message):
|
||||||
# retrieve metadata reader email and URL from email body sent by admin
|
# retrieve metadata reader email from email body sent by admin
|
||||||
email = ""
|
email = ""
|
||||||
url = ""
|
|
||||||
m = re.search('email:\s(.+@.+\..+)', message)
|
m = re.search('email:\s(.+@.+\..+)', message)
|
||||||
if m:
|
if m:
|
||||||
email = m.group(1)
|
email = m.group(1)
|
||||||
|
return email
|
||||||
m = re.search('url:\s(.+)', message)
|
|
||||||
if m:
|
|
||||||
url = m.group(1)
|
|
||||||
return (email, url)
|
|
||||||
|
|
||||||
|
|
||||||
def subscribe_reader(email, article, url):
|
def subscribe_reader(email, token, url):
|
||||||
logger.info("subscribe reader %s to %s (%s)" % (email, article, url))
|
logger.info('subscribe reader %s to %s [%s]' % (email, url, token))
|
||||||
db = TinyDB(pecosys.get_config('global', 'cwd') + '/db.json')
|
recorded = Reader.select().join(Site).where(Site.token == token,
|
||||||
db.insert({'email': email, 'article': article, 'url': url})
|
Reader.email == email,
|
||||||
|
Reader.url == url).count()
|
||||||
|
if recorded:
|
||||||
|
logger.debug('reader %s is already recorded' % email)
|
||||||
|
else:
|
||||||
|
site = Site.select().where(Site.token == token).get()
|
||||||
|
reader = Reader(site=site, email=email, url=url)
|
||||||
|
reader.save()
|
||||||
|
|
||||||
|
|
||||||
def unsubscribe_reader(email, article):
|
def unsubscribe_reader(data):
|
||||||
logger.info("unsubscribe reader %s from %s" % (email, article))
|
token = data.get('token', '')
|
||||||
db = TinyDB(pecosys.get_config('global', 'cwd') + '/db.json')
|
url = data.get('url', '')
|
||||||
db.remove((where('email') == email) & (where('article') == article))
|
email = data.get('email', '')
|
||||||
|
logger.info('unsubscribe reader %s from %s (%s)' % (email, url, token))
|
||||||
|
for reader in Reader.select().join(Site).where(Site.token == token,
|
||||||
|
Reader.email == email,
|
||||||
|
Reader.url == url):
|
||||||
|
reader.delete_instance()
|
||||||
|
|
||||||
|
|
||||||
def notify_subscribers(article):
|
def notify_subscribed_readers(token, url):
|
||||||
logger.info('notify subscribers for article %s' % article)
|
logger.info('notify subscribers for %s (%s)' % (url, token))
|
||||||
db = TinyDB(pecosys.get_config('global', 'cwd') + '/db.json')
|
for reader in Reader.select().join(Site).where(Site.token == token,
|
||||||
for item in db.search(where('article') == article):
|
Reader.url == url):
|
||||||
logger.info(item)
|
to_email = reader.email
|
||||||
to_email = item['email']
|
logger.info('notify reader %s' % to_email)
|
||||||
logger.info("notify reader %s for article %s" % (to_email, article))
|
unsubscribe_url = '%s?email=%s&token=%s&url=%s' % (
|
||||||
unsubscribe_url = pecosys.get_config('subscription', 'url') + '?email=' + to_email + '&article=' + article
|
config.UNSUBSCRIBE_URL, to_email, token, reader.url)
|
||||||
email_body = get_template('notify_subscriber').render(article_url=item['url'],
|
email_body = get_template(
|
||||||
|
'notify_subscriber').render(article_url=reader.url,
|
||||||
unsubscribe_url=unsubscribe_url)
|
unsubscribe_url=unsubscribe_url)
|
||||||
subject = get_template('notify_message').render()
|
subject = get_template('notify_message').render()
|
||||||
mail(pecosys.get_config('subscription', 'from_email'), to_email, subject, email_body)
|
mail(to_email, subject, email_body)
|
||||||
|
|
||||||
|
|
||||||
def notify_reader(email, url):
|
def notify_reader(from_email, to_email, token, url):
|
||||||
logger.info('notify reader: email %s about URL %s' % (email, url))
|
logger.info('notify reader: email %s about URL %s' % (to_email, url))
|
||||||
email_body = get_template('notify_reader').render(article_url=url)
|
email_body = get_template('notify_reader').render(article_url=url)
|
||||||
subject = get_template('notify_message').render()
|
subject = get_template('notify_message').render()
|
||||||
mail(pecosys.get_config('subscription', 'from_email'), email, subject, email_body)
|
mail(to_email, subject, email_body)
|
||||||
|
|
||||||
|
|
||||||
def mail(to_email, subject, message):
|
def mail(to_email, subject, message):
|
||||||
|
|
|
@ -13,3 +13,5 @@ HTTP_ADDRESS = "0.0.0.0"
|
||||||
HTTP_PORT = 8000
|
HTTP_PORT = 8000
|
||||||
|
|
||||||
SALT = "BRRJRqXgGpXWrgTidBPcixIThHpDuKc0"
|
SALT = "BRRJRqXgGpXWrgTidBPcixIThHpDuKc0"
|
||||||
|
|
||||||
|
UNSUBSCRIBE_URL = 'http://localhost:8000/unsubscribe'
|
||||||
|
|
Loading…
Add table
Reference in a new issue