move DB operations to DAO
This commit is contained in:
parent
3eb1b86246
commit
c175b4a120
8 changed files with 94 additions and 238 deletions
|
|
@ -5,12 +5,13 @@ import logging
|
|||
import os
|
||||
import re
|
||||
|
||||
from stacosys.core.templater import Templater, Template
|
||||
from stacosys.model.comment import Comment
|
||||
from stacosys.model.email import Email
|
||||
from stacosys.core.rss import Rss
|
||||
from stacosys.core.mailer import Mailer
|
||||
from stacosys.core.rss import Rss
|
||||
from stacosys.core.templater import Templater, Template
|
||||
from stacosys.db import dao
|
||||
from stacosys.model.email import Email
|
||||
|
||||
REGEX_EMAIL_SUBJECT = r".*STACOSYS.*\[(\d+)\:(\w+)\]"
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -21,41 +22,42 @@ templater = Templater(template_path)
|
|||
|
||||
def fetch_mail_answers(lang, mailer: Mailer, rss: Rss, site_token):
|
||||
for msg in mailer.fetch():
|
||||
if re.search(r".*STACOSYS.*\[(\d+)\:(\w+)\]", msg.subject, re.DOTALL):
|
||||
if _reply_comment_email(lang, mailer, rss, msg, site_token):
|
||||
mailer.delete(msg.id)
|
||||
# filter stacosys e-mails
|
||||
m = re.search(REGEX_EMAIL_SUBJECT, msg.subject, re.DOTALL)
|
||||
if not m:
|
||||
continue
|
||||
|
||||
comment_id = int(m.group(1))
|
||||
submitted_token = m.group(2)
|
||||
|
||||
# validate token
|
||||
if submitted_token != site_token:
|
||||
logger.warning("ignore corrupted email. Unknown token %d" % comment_id)
|
||||
continue
|
||||
|
||||
if not msg.plain_text_content:
|
||||
logger.warning("ignore empty email")
|
||||
continue
|
||||
|
||||
_reply_comment_email(lang, mailer, rss, msg, comment_id)
|
||||
mailer.delete(msg.id)
|
||||
|
||||
|
||||
def _reply_comment_email(lang, mailer: Mailer, rss: Rss, email: Email, site_token):
|
||||
|
||||
m = re.search(r"\[(\d+)\:(\w+)\]", email.subject)
|
||||
if not m:
|
||||
logger.warning("ignore corrupted email. No token %s" % email.subject)
|
||||
return
|
||||
comment_id = int(m.group(1))
|
||||
token = m.group(2)
|
||||
if token != site_token:
|
||||
logger.warning("ignore corrupted email. Unknown token %d" % comment_id)
|
||||
return
|
||||
|
||||
# retrieve site and comment rows
|
||||
comment = Comment
|
||||
def _reply_comment_email(lang, mailer: Mailer, rss: Rss, email: Email, comment_id):
|
||||
# retrieve comment
|
||||
comment = dao.find_comment_by_id(comment_id)
|
||||
if not comment:
|
||||
logger.warning("unknown comment %d" % comment_id)
|
||||
return True
|
||||
return
|
||||
|
||||
if comment.published:
|
||||
logger.warning("ignore already published email. token %d" % comment_id)
|
||||
return
|
||||
|
||||
if not email.plain_text_content:
|
||||
logger.warning("ignore empty email")
|
||||
return
|
||||
|
||||
# safe logic: no answer or unknown answer is a go for publishing
|
||||
if email.plain_text_content[:2].upper() == "NO":
|
||||
logger.info("discard comment: %d" % comment_id)
|
||||
comment.delete_instance()
|
||||
dao.delete_comment(comment)
|
||||
new_email_body = templater.get_template(lang, Template.DROP_COMMENT).render(
|
||||
original=email.plain_text_content
|
||||
)
|
||||
|
|
@ -63,7 +65,7 @@ def _reply_comment_email(lang, mailer: Mailer, rss: Rss, email: Email, site_toke
|
|||
logger.warning("minor failure. cannot send rejection mail " + email.subject)
|
||||
else:
|
||||
# save publishing datetime
|
||||
dao.publish(comment)
|
||||
dao.publish_comment(comment)
|
||||
logger.info("commit comment: %d" % comment_id)
|
||||
|
||||
# rebuild RSS
|
||||
|
|
@ -76,11 +78,9 @@ def _reply_comment_email(lang, mailer: Mailer, rss: Rss, email: Email, site_toke
|
|||
if not mailer.send(email.from_addr, "Re: " + email.subject, new_email_body):
|
||||
logger.warning("minor failure. cannot send approval email " + email.subject)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def submit_new_comment(lang, site_name, site_token, site_admin_email, mailer):
|
||||
for comment in Comment.select().where(Comment.notified.is_null()):
|
||||
for comment in dao.find_not_notified_comments():
|
||||
comment_list = (
|
||||
"author: %s" % comment.author_name,
|
||||
"site: %s" % comment.author_site,
|
||||
|
|
@ -95,12 +95,12 @@ def submit_new_comment(lang, site_name, site_token, site_admin_email, mailer):
|
|||
url=comment.url, comment=comment_text
|
||||
)
|
||||
|
||||
# send email
|
||||
# send email to notify admin
|
||||
subject = "STACOSYS %s: [%d:%s]" % (site_name, comment.id, site_token)
|
||||
if mailer.send(site_admin_email, subject, email_body):
|
||||
logger.debug("new comment processed ")
|
||||
|
||||
# notify site admin and save notification datetime
|
||||
dao.notify_site_admin(comment)
|
||||
# save notification datetime
|
||||
dao.notify_comment(comment)
|
||||
else:
|
||||
logger.warning("rescheduled. send mail failure " + subject)
|
||||
|
|
|
|||
|
|
@ -5,14 +5,49 @@ from datetime import datetime
|
|||
from stacosys.model.comment import Comment
|
||||
|
||||
|
||||
def notify_site_admin(comment: Comment):
|
||||
def find_comment_by_id(id):
|
||||
return Comment.get_by_id(id)
|
||||
|
||||
|
||||
def notify_comment(comment: Comment):
|
||||
comment.notified = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
comment.save()
|
||||
|
||||
|
||||
def publish(comment: Comment):
|
||||
def publish_comment(comment: Comment):
|
||||
comment.published = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
comment.save()
|
||||
|
||||
|
||||
def delete_comment(comment: Comment):
|
||||
comment.delete_instance()
|
||||
|
||||
|
||||
def find_not_notified_comments():
|
||||
return Comment.select().where(Comment.notified.is_null())
|
||||
|
||||
|
||||
def find_published_comments_by_url(url):
|
||||
return Comment.select(Comment).where((Comment.url == url) & (Comment.published.is_null(False))).order_by(
|
||||
+Comment.published)
|
||||
|
||||
|
||||
def count_published_comments(url):
|
||||
return Comment.select(Comment).where(
|
||||
(Comment.url == url) & (Comment.published.is_null(False))).count() if url else Comment.select(Comment).where(
|
||||
Comment.publishd.is_null(False)).count()
|
||||
|
||||
|
||||
def create_comment(url, author_name, author_site, author_gravatar, message):
|
||||
created = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
comment = Comment(
|
||||
url=url,
|
||||
author_name=author_name,
|
||||
author_site=author_site,
|
||||
author_gravatar=author_gravatar,
|
||||
content=message,
|
||||
created=created,
|
||||
notified=None,
|
||||
published=None,
|
||||
)
|
||||
comment.save()
|
||||
|
|
|
|||
|
|
@ -1,11 +1,8 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
import json
|
||||
from peewee import Model
|
||||
from playhouse.db_url import SqliteDatabase
|
||||
from playhouse.shortcuts import model_to_dict
|
||||
from tinydb import TinyDB
|
||||
|
||||
db = SqliteDatabase(None)
|
||||
|
||||
|
|
@ -20,29 +17,8 @@ class Database:
|
|||
return db
|
||||
|
||||
def setup(self, db_url):
|
||||
|
||||
db.init(db_url)
|
||||
db.connect()
|
||||
|
||||
from stacosys.model.comment import Comment
|
||||
db.create_tables([Comment], safe=True)
|
||||
|
||||
|
||||
# if config.exists(config.DB_BACKUP_JSON_FILE):
|
||||
# _backup_db(config.DB_BACKUP_JSON_FILE, Comment)
|
||||
|
||||
|
||||
def _tojson_model(comment):
|
||||
dcomment = model_to_dict(comment)
|
||||
# del dcomment["site"]
|
||||
tcomment = json.dumps(dcomment, indent=4, sort_keys=True, default=str)
|
||||
return json.loads(tcomment)
|
||||
|
||||
|
||||
def _backup_db(db_file, Comment):
|
||||
db = TinyDB(db_file, sort_keys=True, indent=4, separators=(",", ": "))
|
||||
db.drop_tables()
|
||||
table = db.table("comments")
|
||||
for comment in Comment.select():
|
||||
cc = _tojson_model(comment)
|
||||
table.insert(cc)
|
||||
|
|
|
|||
|
|
@ -2,14 +2,15 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import logging
|
||||
|
||||
from flask import abort, jsonify, request
|
||||
|
||||
from stacosys.db import dao
|
||||
from stacosys.interface import app
|
||||
from stacosys.model.comment import Comment
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
@app.route("/ping", methods=["GET"])
|
||||
def ping():
|
||||
return "OK"
|
||||
|
|
@ -23,12 +24,8 @@ def query_comments():
|
|||
abort(401)
|
||||
url = request.args.get("url", "")
|
||||
|
||||
logger.info("retrieve comments for url %s" % (url))
|
||||
for comment in (
|
||||
Comment.select(Comment)
|
||||
.where((Comment.url == url) & (Comment.published.is_null(False)))
|
||||
.order_by(+Comment.published)
|
||||
):
|
||||
logger.info("retrieve comments for url %s" % url)
|
||||
for comment in dao.find_published_comments_by_url(url):
|
||||
d = {
|
||||
"author": comment.author_name,
|
||||
"content": comment.content,
|
||||
|
|
@ -48,12 +45,4 @@ def get_comments_count():
|
|||
if token != app.config.get("SITE_TOKEN"):
|
||||
abort(401)
|
||||
url = request.args.get("url", "")
|
||||
if url:
|
||||
count = (
|
||||
Comment.select(Comment)
|
||||
.where((Comment.url == url) & (Comment.published.is_null(False)))
|
||||
.count()
|
||||
)
|
||||
else:
|
||||
count = Comment.select(Comment).where(Comment.publishd.is_null(False)).count()
|
||||
return jsonify({"count": count})
|
||||
return jsonify({"count": dao.count_published_comments(url)})
|
||||
|
|
|
|||
|
|
@ -2,18 +2,17 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
from flask import abort, redirect, request
|
||||
|
||||
from stacosys.db import dao
|
||||
from stacosys.interface import app
|
||||
from stacosys.model.comment import Comment
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@app.route("/newcomment", methods=["POST"])
|
||||
def new_form_comment():
|
||||
|
||||
try:
|
||||
data = request.form
|
||||
logger.info("form data " + str(data))
|
||||
|
|
@ -26,7 +25,7 @@ def new_form_comment():
|
|||
# honeypot for spammers
|
||||
captcha = data.get("remarque", "")
|
||||
if captcha:
|
||||
logger.warn("discard spam: data %s" % data)
|
||||
logger.warning("discard spam: data %s" % data)
|
||||
abort(400)
|
||||
|
||||
url = data.get("url", "")
|
||||
|
|
@ -39,23 +38,14 @@ def new_form_comment():
|
|||
|
||||
# anti-spam again
|
||||
if not url or not author_name or not message:
|
||||
logger.warn("empty field: data %s" % data)
|
||||
logger.warning("empty field: data %s" % data)
|
||||
abort(400)
|
||||
if not check_form_data(data.to_dict()):
|
||||
logger.warning("additional field: data %s" % data)
|
||||
abort(400)
|
||||
check_form_data(data)
|
||||
|
||||
# add a row to Comment table
|
||||
created = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
comment = Comment(
|
||||
url=url,
|
||||
author_name=author_name,
|
||||
author_site=author_site,
|
||||
author_gravatar=author_gravatar,
|
||||
content=message,
|
||||
created=created,
|
||||
notified=None,
|
||||
published=None,
|
||||
)
|
||||
comment.save()
|
||||
dao.create_comment(url, author_name, author_site, author_gravatar, message)
|
||||
|
||||
except Exception:
|
||||
logger.exception("new comment failure")
|
||||
|
|
@ -64,12 +54,13 @@ def new_form_comment():
|
|||
return redirect("/redirect/", code=302)
|
||||
|
||||
|
||||
def check_form_data(data):
|
||||
def check_form_data(d):
|
||||
fields = ["url", "message", "site", "remarque", "author", "token", "email"]
|
||||
d = data.to_dict()
|
||||
for field in fields:
|
||||
if field in d:
|
||||
del d[field]
|
||||
if d:
|
||||
logger.warn("additional field: data %s" % data)
|
||||
abort(400)
|
||||
|
||||
# filtered = dict(filter(lambda x: x[0] not in fields, data.to_dict().items()))
|
||||
return not d
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
# -*- coding: UTF-8 -*-
|
||||
|
||||
from peewee import CharField
|
||||
from peewee import TextField
|
||||
from peewee import DateTimeField
|
||||
from datetime import datetime
|
||||
from peewee import TextField
|
||||
|
||||
from stacosys.db.database import BaseModel
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue