Manage reader subscription

This commit is contained in:
Yax 2015-05-24 19:40:46 +02:00
parent ffab88e369
commit e19aae121b
7 changed files with 102 additions and 44 deletions

View file

@ -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
View 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
View 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()

View file

@ -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'))

View file

@ -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)

View file

@ -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):

View file

@ -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'