You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
stacosys/app/core/cron.py

130 lines
3.7 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import logging
from datetime import datetime
import time
import re
from core import mailer
from core.templater import get_template
from core import rss
from model.comment import Comment
from model.comment import Site
logger = logging.getLogger(__name__)
def cron(func):
def wrapper():
logger.debug("execute CRON " + func.__name__)
func()
return wrapper
@cron
def fetch_mail_answers():
for msg in mailer.fetch():
if re.search(r".*STACOSYS.*\[(\d+)\:(\w+)\]", msg["subject"], re.DOTALL):
full_msg = mailer.get(msg["id"])
if full_msg and reply_comment_email(full_msg['email']):
mailer.delete(msg["id"])
@cron
def submit_new_comment():
for comment in Comment.select().where(Comment.notified.is_null()):
comment_list = (
"author: %s" % comment.author_name,
"site: %s" % comment.author_site,
"date: %s" % comment.created,
"url: %s" % comment.url,
"",
"%s" % comment.content,
"",
)
comment_text = "\n".join(comment_list)
email_body = get_template("new_comment").render(
url=comment.url, comment=comment_text
)
# send email
site = Site.get(Site.id == comment.site)
subject = "STACOSYS %s: [%d:%s]" % (site.name, comment.id, site.token)
mailer.send(site.admin_email, subject, email_body)
logger.debug("new comment processed ")
# update comment
comment.notified = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
comment.save()
def reply_comment_email(data):
from_email = data["from"]
subject = data["subject"]
message = ""
for part in data["parts"]:
if part["content-type"] == "text/plain":
message = part["content"]
break
m = re.search(r"\[(\d+)\:(\w+)\]", subject)
if not m:
logger.warn("ignore corrupted email. No token %s" % subject)
return
comment_id = int(m.group(1))
token = m.group(2)
# retrieve site and comment rows
try:
comment = Comment.select().where(Comment.id == comment_id).get()
except:
logger.warn("unknown comment %d" % comment_id)
return True
if comment.published:
logger.warn("ignore already published email. token %d" % comment_id)
return
if comment.site.token != token:
logger.warn("ignore corrupted email. Unknown token %d" % comment_id)
return
if not message:
logger.warn("ignore empty email")
return
# safe logic: no answer or unknown answer is a go for publishing
if message[:2].upper() in ("NO", "SP"):
# put a log to help fail2ban
if message[:2].upper() == "SP": # SPAM
if comment.ip:
logger.info(
"SPAM comment from %s: %d" % (comment.ip, comment_id)
)
else:
logger.info("cannot identify SPAM source: %d" % comment_id)
logger.info("discard comment: %d" % comment_id)
comment.delete_instance()
email_body = get_template("drop_comment").render(original=message)
mailer.send(from_email, "Re: " + subject, email_body)
else:
# update Comment row
comment.published = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
comment.ip = None
comment.save()
logger.info("commit comment: %d" % comment_id)
# rebuild RSS
rss.generate_site(token)
# send approval confirmation email to admin
email_body = get_template("approve_comment").render(original=message)
mailer.send(from_email, "Re: " + subject, email_body)
return True