mirror of https://github.com/kianby/stacosys
WIP
parent
ed2a284102
commit
0a2cdbbe8f
@ -1,3 +0,0 @@
|
|||||||
from flask import Flask
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
|
@ -1,3 +1,48 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import profig
|
||||||
|
|
||||||
|
# constants
|
||||||
|
FLASK_APP = "flask.app"
|
||||||
|
|
||||||
|
DB_URL = "main.db_url"
|
||||||
|
|
||||||
|
HTTP_HOST = "http.host"
|
||||||
|
HTTP_PORT = "http.port"
|
||||||
|
|
||||||
|
SECURITY_SALT = "security.salt"
|
||||||
|
SECURITY_SECRET = "security.secret"
|
||||||
|
|
||||||
|
MAIL_POLLING = "polling.newmail"
|
||||||
|
COMMENT_POLLING = "polling.newcomment"
|
||||||
|
|
||||||
|
# variable
|
||||||
|
params = dict()
|
||||||
|
|
||||||
|
|
||||||
|
def initialize(config_pathname, flask_app):
|
||||||
|
cfg = profig.Config(config_pathname)
|
||||||
|
cfg.sync()
|
||||||
|
params.update(cfg)
|
||||||
|
params.update({FLASK_APP: flask_app})
|
||||||
|
|
||||||
|
|
||||||
|
def get(key):
|
||||||
|
return params[key]
|
||||||
|
|
||||||
|
|
||||||
|
def getInt(key):
|
||||||
|
return int(params[key])
|
||||||
|
|
||||||
|
|
||||||
|
def _str2bool(v):
|
||||||
|
return v.lower() in ("yes", "true", "t", "1")
|
||||||
|
|
||||||
|
|
||||||
|
def getBool(key):
|
||||||
|
return _str2bool(params[key])
|
||||||
|
|
||||||
|
|
||||||
|
def flaskapp():
|
||||||
|
return params[FLASK_APP]
|
||||||
|
@ -1,115 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Created with https://app.quicktype.io
|
|
||||||
# name: stacosys
|
|
||||||
|
|
||||||
json_schema = """
|
|
||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-06/schema#",
|
|
||||||
"$ref": "#/definitions/Welcome",
|
|
||||||
"definitions": {
|
|
||||||
"Welcome": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"general": {
|
|
||||||
"$ref": "#/definitions/General"
|
|
||||||
},
|
|
||||||
"http": {
|
|
||||||
"$ref": "#/definitions/HTTP"
|
|
||||||
},
|
|
||||||
"security": {
|
|
||||||
"$ref": "#/definitions/Security"
|
|
||||||
},
|
|
||||||
"rss": {
|
|
||||||
"$ref": "#/definitions/RSS"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"general",
|
|
||||||
"http",
|
|
||||||
"rss",
|
|
||||||
"security"
|
|
||||||
],
|
|
||||||
"title": "Welcome"
|
|
||||||
},
|
|
||||||
"General": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"debug": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"lang": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"db_url": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"db_url",
|
|
||||||
"debug",
|
|
||||||
"lang"
|
|
||||||
],
|
|
||||||
"title": "General"
|
|
||||||
},
|
|
||||||
"HTTP": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"root_url": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"host": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"port": {
|
|
||||||
"type": "integer"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"host",
|
|
||||||
"port",
|
|
||||||
"root_url"
|
|
||||||
],
|
|
||||||
"title": "HTTP"
|
|
||||||
},
|
|
||||||
"RSS": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"proto": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"file": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"file",
|
|
||||||
"proto"
|
|
||||||
],
|
|
||||||
"title": "RSS"
|
|
||||||
},
|
|
||||||
"Security": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"salt": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"secret": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"salt",
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"title": "Security"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
@ -1,84 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: UTF-8 -*-
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import logging
|
|
||||||
from flask import Flask
|
|
||||||
from conf import config
|
|
||||||
from jsonschema import validate
|
|
||||||
from flask_apscheduler import APScheduler
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
|
||||||
|
|
||||||
# add current path and parent path to syspath
|
|
||||||
current_path = os.path.dirname(__file__)
|
|
||||||
parent_path = os.path.abspath(os.path.join(current_path, os.path.pardir))
|
|
||||||
paths = [current_path, parent_path]
|
|
||||||
for path in paths:
|
|
||||||
if path not in sys.path:
|
|
||||||
sys.path.insert(0, path)
|
|
||||||
|
|
||||||
# more imports
|
|
||||||
import database
|
|
||||||
import processor
|
|
||||||
from interface import api
|
|
||||||
from interface import form
|
|
||||||
|
|
||||||
# configure logging
|
|
||||||
def configure_logging(level):
|
|
||||||
root_logger = logging.getLogger()
|
|
||||||
root_logger.setLevel(level)
|
|
||||||
ch = logging.StreamHandler()
|
|
||||||
ch.setLevel(level)
|
|
||||||
# create formatter
|
|
||||||
formatter = logging.Formatter(
|
|
||||||
'[%(asctime)s] %(name)s %(levelname)s %(message)s')
|
|
||||||
# add formatter to ch
|
|
||||||
ch.setFormatter(formatter)
|
|
||||||
# add ch to logger
|
|
||||||
root_logger.addHandler(ch)
|
|
||||||
|
|
||||||
logging_level = (20, 10)[config.general['debug']]
|
|
||||||
configure_logging(logging_level)
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
class Config(object):
|
|
||||||
JOBS = [
|
|
||||||
{
|
|
||||||
'id': 'fetch_mail',
|
|
||||||
'func': 'core.cron:fetch_mail_answers',
|
|
||||||
'trigger': 'interval',
|
|
||||||
'seconds': 120
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'id': 'submit_new_comment',
|
|
||||||
'func': 'core.cron:submit_new_comment',
|
|
||||||
'trigger': 'interval',
|
|
||||||
'seconds': 60
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
# initialize database
|
|
||||||
database.setup()
|
|
||||||
|
|
||||||
# start processor
|
|
||||||
template_path = os.path.abspath(os.path.join(current_path, '../templates'))
|
|
||||||
processor.start(template_path)
|
|
||||||
|
|
||||||
# cron
|
|
||||||
app.config.from_object(Config())
|
|
||||||
scheduler = APScheduler()
|
|
||||||
scheduler.init_app(app)
|
|
||||||
scheduler.start()
|
|
||||||
|
|
||||||
# tune logging level
|
|
||||||
if not config.general['debug']:
|
|
||||||
logging.getLogger('werkzeug').level = logging.WARNING
|
|
||||||
|
|
||||||
logger.info("Start Stacosys application")
|
|
||||||
|
|
||||||
app.run(host=config.http['host'],
|
|
||||||
port=config.http['port'],
|
|
||||||
debug=config.general['debug'], use_reloader=False)
|
|
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
from jinja2 import Environment
|
||||||
|
from jinja2 import FileSystemLoader
|
||||||
|
from conf import config
|
||||||
|
|
||||||
|
current_path = os.path.dirname(__file__)
|
||||||
|
template_path = os.path.abspath(os.path.join(current_path, "../templates"))
|
||||||
|
env = Environment(loader=FileSystemLoader(template_path))
|
||||||
|
|
||||||
|
|
||||||
|
def get_template(name):
|
||||||
|
return env.get_template(config.general["lang"] + "/" + name + ".tpl")
|
@ -1,36 +1,90 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# -*- coding: UTF-8 -*-
|
# -*- coding: UTF-8 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
import logging
|
import logging
|
||||||
import json
|
|
||||||
from clize import Clize, run
|
from clize import Clize, run
|
||||||
from jsonschema import validate
|
from flask import Flask
|
||||||
from conf import config, schema
|
from flask_apscheduler import APScheduler
|
||||||
|
from conf import config
|
||||||
|
|
||||||
|
# configure logging
|
||||||
|
def configure_logging(level):
|
||||||
|
root_logger = logging.getLogger()
|
||||||
|
root_logger.setLevel(level)
|
||||||
|
ch = logging.StreamHandler()
|
||||||
|
ch.setLevel(level)
|
||||||
|
# create formatter
|
||||||
|
formatter = logging.Formatter("[%(asctime)s] %(name)s %(levelname)s %(message)s")
|
||||||
|
# add formatter to ch
|
||||||
|
ch.setFormatter(formatter)
|
||||||
|
# add ch to logger
|
||||||
|
root_logger.addHandler(ch)
|
||||||
|
|
||||||
def load_json(filename):
|
|
||||||
jsondoc = None
|
class JobConfig(object):
|
||||||
with open(filename, 'rt') as json_file:
|
|
||||||
jsondoc = json.loads(json_file.read())
|
JOBS = []
|
||||||
return jsondoc
|
|
||||||
|
def __init__(self, mail_polling_seconds, new_comment_polling_seconds):
|
||||||
|
self.JOBS = [
|
||||||
|
{
|
||||||
|
"id": "fetch_mail",
|
||||||
|
"func": "core.cron:fetch_mail_answers",
|
||||||
|
"trigger": "interval",
|
||||||
|
"seconds": mail_polling_seconds,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "submit_new_comment",
|
||||||
|
"func": "core.cron:submit_new_comment",
|
||||||
|
"trigger": "interval",
|
||||||
|
"seconds": new_comment_polling_seconds,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
@Clize
|
@Clize
|
||||||
def stacosys_server(config_pathname):
|
def stacosys_server(config_pathname):
|
||||||
|
|
||||||
# load and validate startup config
|
app = Flask(__name__)
|
||||||
conf = load_json(config_pathname)
|
config.initialize(config_pathname, app)
|
||||||
json_schema = json.loads(schema.json_schema)
|
|
||||||
validate(conf, json_schema)
|
# configure logging
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
configure_logging(logging.INFO)
|
||||||
|
logging.getLogger("werkzeug").level = logging.WARNING
|
||||||
|
|
||||||
|
# initialize database
|
||||||
|
from core import database
|
||||||
|
|
||||||
|
database.setup()
|
||||||
|
|
||||||
|
# start processor
|
||||||
|
from core import processor
|
||||||
|
|
||||||
|
# cron email fetcher
|
||||||
|
app.config.from_object(
|
||||||
|
JobConfig(
|
||||||
|
config.getInt(config.MAIL_POLLING), config.getInt(config.COMMENT_POLLING)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
scheduler = APScheduler()
|
||||||
|
scheduler.init_app(app)
|
||||||
|
scheduler.start()
|
||||||
|
|
||||||
|
logger.info("Start Stacosys application")
|
||||||
|
|
||||||
|
# start Flask
|
||||||
|
from interface import api
|
||||||
|
from interface import form
|
||||||
|
|
||||||
# set configuration
|
app.run(
|
||||||
config.general = conf['general']
|
host=config.get(config.HTTP_HOST),
|
||||||
config.http = conf['http']
|
port=config.get(config.HTTP_PORT),
|
||||||
config.security = conf['security']
|
debug=False,
|
||||||
config.rss = conf['rss']
|
use_reloader=False,
|
||||||
|
)
|
||||||
|
|
||||||
# start application
|
|
||||||
from core import app
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
run(stacosys_server)
|
run(stacosys_server)
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
; Default configuration
|
||||||
|
[main]
|
||||||
|
lang = fr
|
||||||
|
db_url = sqlite:///db.sqlite
|
||||||
|
|
||||||
|
[http]
|
||||||
|
root_url = http://localhost:8100
|
||||||
|
host = 0.0.0.0
|
||||||
|
port = 8100
|
||||||
|
|
||||||
|
[security]
|
||||||
|
salt = BRRJRqXgGpXWrgTidBPcixIThHpDuKc0
|
||||||
|
secret = Uqca5Kc8xuU6THz9
|
||||||
|
|
||||||
|
[rss]
|
||||||
|
proto = http
|
||||||
|
file = comments.xml
|
||||||
|
|
||||||
|
[polling]
|
||||||
|
newmail = 15
|
||||||
|
newcomment = 60
|
Loading…
Reference in New Issue