improve encapsulation
This commit is contained in:
parent
962e0d2e41
commit
5fea1e358a
7 changed files with 240 additions and 196 deletions
83
run.py
83
run.py
|
@ -1,19 +1,21 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# -*- coding: UTF-8 -*-
|
# -*- coding: UTF-8 -*-
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
from flask_apscheduler import APScheduler
|
|
||||||
|
|
||||||
import stacosys.conf.config as config
|
import stacosys.conf.config as config
|
||||||
from stacosys.core import database
|
from stacosys.core import database
|
||||||
from stacosys.core import rss
|
from stacosys.core.rss import Rss
|
||||||
#from stacosys.interface import api
|
from stacosys.core.mailer import Mailer
|
||||||
#from stacosys.interface import form
|
from stacosys.interface import app
|
||||||
|
from stacosys.interface import api
|
||||||
|
from stacosys.interface import form
|
||||||
|
from stacosys.interface import scheduler
|
||||||
|
|
||||||
|
|
||||||
# configure logging
|
# configure logging
|
||||||
def configure_logging(level):
|
def configure_logging(level):
|
||||||
|
@ -29,33 +31,8 @@ def configure_logging(level):
|
||||||
root_logger.addHandler(ch)
|
root_logger.addHandler(ch)
|
||||||
|
|
||||||
|
|
||||||
class JobConfig(object):
|
|
||||||
|
|
||||||
JOBS = []
|
|
||||||
|
|
||||||
SCHEDULER_EXECUTORS = {"default": {"type": "threadpool", "max_workers": 4}}
|
|
||||||
|
|
||||||
def __init__(self, imap_polling_seconds, new_comment_polling_seconds):
|
|
||||||
self.JOBS = [
|
|
||||||
{
|
|
||||||
"id": "fetch_mail",
|
|
||||||
"func": "stacosys.core.cron:fetch_mail_answers",
|
|
||||||
"trigger": "interval",
|
|
||||||
"seconds": imap_polling_seconds,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "submit_new_comment",
|
|
||||||
"func": "stacosys.core.cron:submit_new_comment",
|
|
||||||
"trigger": "interval",
|
|
||||||
"seconds": new_comment_polling_seconds,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def stacosys_server(config_pathname):
|
def stacosys_server(config_pathname):
|
||||||
|
|
||||||
app = Flask(__name__)
|
|
||||||
|
|
||||||
conf = config.Config.load(config_pathname)
|
conf = config.Config.load(config_pathname)
|
||||||
|
|
||||||
# configure logging
|
# configure logging
|
||||||
|
@ -68,26 +45,38 @@ def stacosys_server(config_pathname):
|
||||||
db = database.Database()
|
db = database.Database()
|
||||||
db.setup(conf.get(config.DB_URL))
|
db.setup(conf.get(config.DB_URL))
|
||||||
|
|
||||||
# cron email fetcher
|
|
||||||
app.config.from_object(
|
|
||||||
JobConfig(
|
|
||||||
conf.get_int(config.IMAP_POLLING), conf.get_int(config.COMMENT_POLLING)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
scheduler = APScheduler()
|
|
||||||
scheduler.init_app(app)
|
|
||||||
scheduler.start()
|
|
||||||
|
|
||||||
logger.info("Start Stacosys application")
|
logger.info("Start Stacosys application")
|
||||||
|
|
||||||
# generate RSS for all sites
|
# generate RSS for all sites
|
||||||
rss_manager = rss.Rss(conf.get(config.LANG), conf.get(config.RSS_FILE), conf.get(config.RSS_PROTO))
|
rss = Rss(
|
||||||
rss_manager.generate_all()
|
conf.get(config.LANG), conf.get(config.RSS_FILE), conf.get(config.RSS_PROTO)
|
||||||
|
)
|
||||||
|
rss.generate_all()
|
||||||
|
|
||||||
|
# configure mailer
|
||||||
|
mailer = Mailer(
|
||||||
|
conf.get(config.IMAP_HOST),
|
||||||
|
conf.get_int(config.IMAP_PORT),
|
||||||
|
conf.get_bool(config.IMAP_SSL),
|
||||||
|
conf.get(config.IMAP_LOGIN),
|
||||||
|
conf.get(config.IMAP_PASSWORD),
|
||||||
|
conf.get(config.SMTP_HOST),
|
||||||
|
conf.get_int(config.SMTP_PORT),
|
||||||
|
conf.get_bool(config.SMTP_STARTTLS),
|
||||||
|
conf.get(config.SMTP_LOGIN),
|
||||||
|
conf.get(config.SMTP_PASSWORD),
|
||||||
|
)
|
||||||
|
|
||||||
|
# configure scheduler
|
||||||
|
scheduler.configure(
|
||||||
|
conf.get_int(config.IMAP_POLLING),
|
||||||
|
conf.get_int(config.COMMENT_POLLING),
|
||||||
|
conf.get(config.LANG),
|
||||||
|
mailer,
|
||||||
|
rss,
|
||||||
|
)
|
||||||
|
|
||||||
# start Flask
|
# start Flask
|
||||||
#logger.info("Load interface %s" % api)
|
|
||||||
#logger.info("Load interface %s" % form)
|
|
||||||
|
|
||||||
app.run(
|
app.run(
|
||||||
host=conf.get(config.HTTP_HOST),
|
host=conf.get(config.HTTP_HOST),
|
||||||
port=conf.get(config.HTTP_PORT),
|
port=conf.get(config.HTTP_PORT),
|
||||||
|
|
|
@ -6,7 +6,7 @@ import re
|
||||||
import time
|
import time
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from stacosys.core import mailer, rss
|
from stacosys.core import rss
|
||||||
from stacosys.core.templater import get_template
|
from stacosys.core.templater import get_template
|
||||||
from stacosys.model.comment import Comment, Site
|
from stacosys.model.comment import Comment, Site
|
||||||
from stacosys.model.email import Email
|
from stacosys.model.email import Email
|
||||||
|
@ -14,59 +14,18 @@ from stacosys.model.email import Email
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def cron(func):
|
def fetch_mail_answers(lang, mailer, rss):
|
||||||
def wrapper():
|
|
||||||
logger.debug('execute CRON ' + func.__name__)
|
|
||||||
func()
|
|
||||||
|
|
||||||
return wrapper
|
|
||||||
|
|
||||||
|
|
||||||
@cron
|
|
||||||
def fetch_mail_answers():
|
|
||||||
|
|
||||||
for msg in mailer.fetch():
|
for msg in mailer.fetch():
|
||||||
if re.search(r'.*STACOSYS.*\[(\d+)\:(\w+)\]', msg.subject, re.DOTALL):
|
if re.search(r".*STACOSYS.*\[(\d+)\:(\w+)\]", msg.subject, re.DOTALL):
|
||||||
if _reply_comment_email(msg):
|
if _reply_comment_email(lang, mailer, rss, msg):
|
||||||
mailer.delete(msg.id)
|
mailer.delete(msg.id)
|
||||||
|
|
||||||
|
|
||||||
@cron
|
def _reply_comment_email(lang, mailer, rss, email: Email):
|
||||||
def submit_new_comment():
|
|
||||||
|
|
||||||
for comment in Comment.select().where(Comment.notified.is_null()):
|
m = re.search(r"\[(\d+)\:(\w+)\]", email.subject)
|
||||||
|
|
||||||
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)
|
|
||||||
if mailer.send(site.admin_email, subject, email_body):
|
|
||||||
logger.debug('new comment processed ')
|
|
||||||
|
|
||||||
# notify site admin and save notification datetime
|
|
||||||
comment.notify_site_admin()
|
|
||||||
else:
|
|
||||||
logger.warn('rescheduled. send mail failure ' + subject)
|
|
||||||
|
|
||||||
|
|
||||||
def _reply_comment_email(email : Email):
|
|
||||||
|
|
||||||
m = re.search(r'\[(\d+)\:(\w+)\]', email.subject)
|
|
||||||
if not m:
|
if not m:
|
||||||
logger.warn('ignore corrupted email. No token %s' % email.subject)
|
logger.warn("ignore corrupted email. No token %s" % email.subject)
|
||||||
return
|
return
|
||||||
comment_id = int(m.group(1))
|
comment_id = int(m.group(1))
|
||||||
token = m.group(2)
|
token = m.group(2)
|
||||||
|
@ -75,39 +34,75 @@ def _reply_comment_email(email : Email):
|
||||||
try:
|
try:
|
||||||
comment = Comment.select().where(Comment.id == comment_id).get()
|
comment = Comment.select().where(Comment.id == comment_id).get()
|
||||||
except:
|
except:
|
||||||
logger.warn('unknown comment %d' % comment_id)
|
logger.warn("unknown comment %d" % comment_id)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if comment.published:
|
if comment.published:
|
||||||
logger.warn('ignore already published email. token %d' % comment_id)
|
logger.warn("ignore already published email. token %d" % comment_id)
|
||||||
return
|
return
|
||||||
|
|
||||||
if comment.site.token != token:
|
if comment.site.token != token:
|
||||||
logger.warn('ignore corrupted email. Unknown token %d' % comment_id)
|
logger.warn("ignore corrupted email. Unknown token %d" % comment_id)
|
||||||
return
|
return
|
||||||
|
|
||||||
if not email.plain_text_content:
|
if not email.plain_text_content:
|
||||||
logger.warn('ignore empty email')
|
logger.warn("ignore empty email")
|
||||||
return
|
return
|
||||||
|
|
||||||
# safe logic: no answer or unknown answer is a go for publishing
|
# safe logic: no answer or unknown answer is a go for publishing
|
||||||
if email.plain_text_content[:2].upper() in ('NO'):
|
if email.plain_text_content[:2].upper() in ("NO"):
|
||||||
logger.info('discard comment: %d' % comment_id)
|
logger.info("discard comment: %d" % comment_id)
|
||||||
comment.delete_instance()
|
comment.delete_instance()
|
||||||
new_email_body = get_template('drop_comment').render(original=email.plain_text_content)
|
new_email_body = get_template(lang, "drop_comment").render(
|
||||||
if not mailer.send(email.from_addr, 'Re: ' + email.subject, new_email_body):
|
original=email.plain_text_content
|
||||||
logger.warn('minor failure. cannot send rejection mail ' + email.subject)
|
)
|
||||||
|
if not mailer.send(email.from_addr, "Re: " + email.subject, new_email_body):
|
||||||
|
logger.warn("minor failure. cannot send rejection mail " + email.subject)
|
||||||
else:
|
else:
|
||||||
# save publishing datetime
|
# save publishing datetime
|
||||||
comment.publish()
|
comment.publish()
|
||||||
logger.info('commit comment: %d' % comment_id)
|
logger.info("commit comment: %d" % comment_id)
|
||||||
|
|
||||||
# rebuild RSS
|
# rebuild RSS
|
||||||
rss.generate_site(token)
|
rss.generate_site(token)
|
||||||
|
|
||||||
# send approval confirmation email to admin
|
# send approval confirmation email to admin
|
||||||
new_email_body = get_template('approve_comment').render(original=email.plain_text_content)
|
new_email_body = get_template(lang, "approve_comment").render(
|
||||||
if not mailer.send(email.from_addr, 'Re: ' + email.subject, new_email_body):
|
original=email.plain_text_content
|
||||||
logger.warn('minor failure. cannot send approval email ' + email.subject)
|
)
|
||||||
|
if not mailer.send(email.from_addr, "Re: " + email.subject, new_email_body):
|
||||||
|
logger.warn("minor failure. cannot send approval email " + email.subject)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def submit_new_comment(lang, mailer):
|
||||||
|
|
||||||
|
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)
|
||||||
|
# TODO use constants for template names
|
||||||
|
email_body = get_template(lang, "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)
|
||||||
|
if mailer.send(site.admin_email, subject, email_body):
|
||||||
|
logger.debug("new comment processed ")
|
||||||
|
|
||||||
|
# notify site admin and save notification datetime
|
||||||
|
comment.notify_site_admin()
|
||||||
|
else:
|
||||||
|
logger.warn("rescheduled. send mail failure " + subject)
|
||||||
|
|
||||||
|
|
|
@ -15,20 +15,44 @@ from stacosys.model.email import Email
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def _open_mailbox():
|
class Mailer:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
imap_host,
|
||||||
|
imap_port,
|
||||||
|
imap_ssl,
|
||||||
|
imap_login,
|
||||||
|
imap_password,
|
||||||
|
smtp_host,
|
||||||
|
smtp_port,
|
||||||
|
smtp_starttls,
|
||||||
|
smtp_login,
|
||||||
|
smtp_password,
|
||||||
|
):
|
||||||
|
self._imap_host = imap_host
|
||||||
|
self._imap_port = imap_port
|
||||||
|
self._imap_ssl = imap_ssl
|
||||||
|
self._imap_login = imap_login
|
||||||
|
self._imap_password = imap_password
|
||||||
|
self._smtp_host = smtp_host
|
||||||
|
self._smtp_port = smtp_port
|
||||||
|
self._smtp_starttls = smtp_starttls
|
||||||
|
self._smtp_login = smtp_login
|
||||||
|
self._smtp_password = smtp_password
|
||||||
|
|
||||||
|
def _open_mailbox(self):
|
||||||
return imap.Mailbox(
|
return imap.Mailbox(
|
||||||
config.get(config.IMAP_HOST),
|
self._imap_host,
|
||||||
config.get_int(config.IMAP_PORT),
|
self._imap_port,
|
||||||
config.get_bool(config.IMAP_SSL),
|
self._imap_ssl,
|
||||||
config.get(config.IMAP_LOGIN),
|
self._imap_login,
|
||||||
config.get(config.IMAP_PASSWORD),
|
self._imap_password,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def fetch(self):
|
||||||
def fetch():
|
|
||||||
msgs = []
|
msgs = []
|
||||||
try:
|
try:
|
||||||
with _open_mailbox() as mbox:
|
with self._open_mailbox() as mbox:
|
||||||
count = mbox.get_count()
|
count = mbox.get_count()
|
||||||
for num in range(count):
|
for num in range(count):
|
||||||
msgs.append(mbox.fetch_message(num + 1))
|
msgs.append(mbox.fetch_message(num + 1))
|
||||||
|
@ -36,21 +60,20 @@ def fetch():
|
||||||
logger.exception("fetch mail exception")
|
logger.exception("fetch mail exception")
|
||||||
return msgs
|
return msgs
|
||||||
|
|
||||||
|
def send(self, to_email, subject, message):
|
||||||
def send(to_email, subject, message):
|
|
||||||
|
|
||||||
# Create the container (outer) email message.
|
# Create the container (outer) email message.
|
||||||
msg = MIMEText(message)
|
msg = MIMEText(message)
|
||||||
msg["Subject"] = subject
|
msg["Subject"] = subject
|
||||||
msg["To"] = to_email
|
msg["To"] = to_email
|
||||||
msg["From"] = config.get(config.SMTP_LOGIN)
|
msg["From"] = self._smtp_login
|
||||||
|
|
||||||
success = True
|
success = True
|
||||||
try:
|
try:
|
||||||
s = smtplib.SMTP(config.get(config.SMTP_HOST), config.get_int(config.SMTP_PORT))
|
s = smtplib.SMTP(self._smtp_host, self._smtp_port)
|
||||||
if config.get_bool(config.SMTP_STARTTLS):
|
if self._smtp_starttls:
|
||||||
s.starttls()
|
s.starttls()
|
||||||
s.login(config.get(config.SMTP_LOGIN), config.get(config.SMTP_PASSWORD))
|
s.login(self._smtp_login, self._smtp_password)
|
||||||
s.send_message(msg)
|
s.send_message(msg)
|
||||||
s.quit()
|
s.quit()
|
||||||
except:
|
except:
|
||||||
|
@ -58,10 +81,9 @@ def send(to_email, subject, message):
|
||||||
success = False
|
success = False
|
||||||
return success
|
return success
|
||||||
|
|
||||||
|
def delete(self, id):
|
||||||
def delete(id):
|
|
||||||
try:
|
try:
|
||||||
with _open_mailbox() as mbox:
|
with self._open_mailbox() as mbox:
|
||||||
mbox.delete_message(id)
|
mbox.delete_message(id)
|
||||||
except:
|
except:
|
||||||
logger.exception("delete mail exception")
|
logger.exception("delete mail exception")
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from flask import Flask
|
||||||
|
app = Flask(__name__)
|
|
@ -2,31 +2,29 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from flask import abort, jsonify, request
|
from flask import abort, jsonify, request
|
||||||
|
|
||||||
from stacosys.conf import config
|
from stacosys.interface import app
|
||||||
from stacosys.model.comment import Comment
|
from stacosys.model.comment import Comment
|
||||||
from stacosys.model.site import Site
|
from stacosys.model.site import Site
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
app = config.flaskapp()
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/ping', methods=['GET'])
|
@app.route("/ping", methods=["GET"])
|
||||||
def ping():
|
def ping():
|
||||||
return 'OK'
|
return "OK"
|
||||||
|
|
||||||
|
|
||||||
@app.route('/comments', methods=['GET'])
|
@app.route("/comments", methods=["GET"])
|
||||||
def query_comments():
|
def query_comments():
|
||||||
|
|
||||||
comments = []
|
comments = []
|
||||||
try:
|
try:
|
||||||
token = request.args.get('token', '')
|
token = request.args.get("token", "")
|
||||||
url = request.args.get('url', '')
|
url = request.args.get("url", "")
|
||||||
|
|
||||||
logger.info('retrieve comments for url %s' % (url))
|
logger.info("retrieve comments for url %s" % (url))
|
||||||
for comment in (
|
for comment in (
|
||||||
Comment.select(Comment)
|
Comment.select(Comment)
|
||||||
.join(Site)
|
.join(Site)
|
||||||
|
@ -38,29 +36,29 @@ def query_comments():
|
||||||
.order_by(+Comment.published)
|
.order_by(+Comment.published)
|
||||||
):
|
):
|
||||||
d = {
|
d = {
|
||||||
'author': comment.author_name,
|
"author": comment.author_name,
|
||||||
'content': comment.content,
|
"content": comment.content,
|
||||||
'avatar': comment.author_gravatar,
|
"avatar": comment.author_gravatar,
|
||||||
'date': comment.published.strftime('%Y-%m-%d %H:%M:%S')
|
"date": comment.published.strftime("%Y-%m-%d %H:%M:%S"),
|
||||||
}
|
}
|
||||||
if comment.author_site:
|
if comment.author_site:
|
||||||
d['site'] = comment.author_site
|
d["site"] = comment.author_site
|
||||||
logger.debug(d)
|
logger.debug(d)
|
||||||
comments.append(d)
|
comments.append(d)
|
||||||
r = jsonify({'data': comments})
|
r = jsonify({"data": comments})
|
||||||
r.status_code = 200
|
r.status_code = 200
|
||||||
except:
|
except:
|
||||||
logger.warn('bad request')
|
logger.warn("bad request")
|
||||||
r = jsonify({'data': []})
|
r = jsonify({"data": []})
|
||||||
r.status_code = 400
|
r.status_code = 400
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
@app.route('/comments/count', methods=['GET'])
|
@app.route("/comments/count", methods=["GET"])
|
||||||
def get_comments_count():
|
def get_comments_count():
|
||||||
try:
|
try:
|
||||||
token = request.args.get('token', '')
|
token = request.args.get("token", "")
|
||||||
url = request.args.get('url', '')
|
url = request.args.get("url", "")
|
||||||
count = (
|
count = (
|
||||||
Comment.select(Comment)
|
Comment.select(Comment)
|
||||||
.join(Site)
|
.join(Site)
|
||||||
|
@ -71,9 +69,9 @@ def get_comments_count():
|
||||||
)
|
)
|
||||||
.count()
|
.count()
|
||||||
)
|
)
|
||||||
r = jsonify({'count': count})
|
r = jsonify({"count": count})
|
||||||
r.status_code = 200
|
r.status_code = 200
|
||||||
except:
|
except:
|
||||||
r = jsonify({'count': 0})
|
r = jsonify({"count": 0})
|
||||||
r.status_code = 200
|
r.status_code = 200
|
||||||
return r
|
return r
|
||||||
|
|
|
@ -3,53 +3,51 @@
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from flask import abort, redirect, request
|
from flask import abort, redirect, request
|
||||||
|
|
||||||
from stacosys.conf import config
|
from stacosys.interface import app
|
||||||
from stacosys.model.comment import Comment
|
from stacosys.model.comment import Comment
|
||||||
from stacosys.model.site import Site
|
from stacosys.model.site import Site
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
app = config.flaskapp()
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/newcomment', methods=['POST'])
|
@app.route("/newcomment", methods=["POST"])
|
||||||
def new_form_comment():
|
def new_form_comment():
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = request.form
|
data = request.form
|
||||||
logger.info('form data ' + str(data))
|
logger.info("form data " + str(data))
|
||||||
|
|
||||||
# validate token: retrieve site entity
|
# validate token: retrieve site entity
|
||||||
token = data.get('token', '')
|
token = data.get("token", "")
|
||||||
site = Site.select().where(Site.token == token).get()
|
site = Site.select().where(Site.token == token).get()
|
||||||
if site is None:
|
if site is None:
|
||||||
logger.warn('Unknown site %s' % token)
|
logger.warn("Unknown site %s" % token)
|
||||||
abort(400)
|
abort(400)
|
||||||
|
|
||||||
# honeypot for spammers
|
# honeypot for spammers
|
||||||
captcha = data.get('remarque', '')
|
captcha = data.get("remarque", "")
|
||||||
if captcha:
|
if captcha:
|
||||||
logger.warn('discard spam: data %s' % data)
|
logger.warn("discard spam: data %s" % data)
|
||||||
abort(400)
|
abort(400)
|
||||||
|
|
||||||
url = data.get('url', '')
|
url = data.get("url", "")
|
||||||
author_name = data.get('author', '').strip()
|
author_name = data.get("author", "").strip()
|
||||||
author_gravatar = data.get('email', '').strip()
|
author_gravatar = data.get("email", "").strip()
|
||||||
author_site = data.get('site', '').lower().strip()
|
author_site = data.get("site", "").lower().strip()
|
||||||
if author_site and author_site[:4] != 'http':
|
if author_site and author_site[:4] != "http":
|
||||||
author_site = 'http://' + author_site
|
author_site = "http://" + author_site
|
||||||
message = data.get('message', '')
|
message = data.get("message", "")
|
||||||
|
|
||||||
# anti-spam again
|
# anti-spam again
|
||||||
if not url or not author_name or not message:
|
if not url or not author_name or not message:
|
||||||
logger.warn('empty field: data %s' % data)
|
logger.warn("empty field: data %s" % data)
|
||||||
abort(400)
|
abort(400)
|
||||||
check_form_data(data)
|
check_form_data(data)
|
||||||
|
|
||||||
# add a row to Comment table
|
# add a row to Comment table
|
||||||
created = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
created = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
comment = Comment(
|
comment = Comment(
|
||||||
site=site,
|
site=site,
|
||||||
url=url,
|
url=url,
|
||||||
|
@ -64,18 +62,18 @@ def new_form_comment():
|
||||||
comment.save()
|
comment.save()
|
||||||
|
|
||||||
except:
|
except:
|
||||||
logger.exception('new comment failure')
|
logger.exception("new comment failure")
|
||||||
abort(400)
|
abort(400)
|
||||||
|
|
||||||
return redirect('/redirect/', code=302)
|
return redirect("/redirect/", code=302)
|
||||||
|
|
||||||
|
|
||||||
def check_form_data(data):
|
def check_form_data(data):
|
||||||
fields = ['url', 'message', 'site', 'remarque', 'author', 'token', 'email']
|
fields = ["url", "message", "site", "remarque", "author", "token", "email"]
|
||||||
d = data.to_dict()
|
d = data.to_dict()
|
||||||
for field in fields:
|
for field in fields:
|
||||||
if field in d:
|
if field in d:
|
||||||
del d[field]
|
del d[field]
|
||||||
if d:
|
if d:
|
||||||
logger.warn('additional field: data %s' % data)
|
logger.warn("additional field: data %s" % data)
|
||||||
abort(400)
|
abort(400)
|
||||||
|
|
37
stacosys/interface/scheduler.py
Normal file
37
stacosys/interface/scheduler.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from flask_apscheduler import APScheduler
|
||||||
|
from stacosys.interface import app
|
||||||
|
|
||||||
|
|
||||||
|
class JobConfig(object):
|
||||||
|
|
||||||
|
JOBS = []
|
||||||
|
|
||||||
|
SCHEDULER_EXECUTORS = {"default": {"type": "threadpool", "max_workers": 4}}
|
||||||
|
|
||||||
|
def __init__(self, imap_polling_seconds, new_comment_polling_seconds, lang, mailer, rss):
|
||||||
|
self.JOBS = [
|
||||||
|
{
|
||||||
|
"id": "fetch_mail",
|
||||||
|
"func": "stacosys.core.cron:fetch_mail_answers",
|
||||||
|
"args": [lang, mailer, rss],
|
||||||
|
"trigger": "interval",
|
||||||
|
"seconds": imap_polling_seconds,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "submit_new_comment",
|
||||||
|
"func": "stacosys.core.cron:submit_new_comment",
|
||||||
|
"args": [lang, mailer],
|
||||||
|
"trigger": "interval",
|
||||||
|
"seconds": new_comment_polling_seconds,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def configure(imap_polling, comment_polling, lang, mailer, rss):
|
||||||
|
app.config.from_object(JobConfig(imap_polling, comment_polling, lang, mailer, rss))
|
||||||
|
scheduler = APScheduler()
|
||||||
|
scheduler.init_app(app)
|
||||||
|
scheduler.start()
|
Loading…
Add table
Reference in a new issue