diffido.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. import os
  4. import logging
  5. from tornado.ioloop import IOLoop
  6. # from lxml.html.diff import htmldiff
  7. from apscheduler.schedulers.tornado import TornadoScheduler
  8. from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
  9. import tornado.httpserver
  10. import tornado.ioloop
  11. import tornado.options
  12. from tornado.options import define, options
  13. import tornado.web
  14. from tornado import gen, escape
  15. CONF_DIR = ''
  16. JOBS_STORE = 'sqlite:///storage/jobs.db'
  17. API_VERSION = '1.0'
  18. class DiffidoBaseException(Exception):
  19. """Base class for diffido custom exceptions.
  20. :param message: text message
  21. :type message: str
  22. :param status: numeric http status code
  23. :type status: int"""
  24. def __init__(self, message, status=400):
  25. super(DiffidoBaseException, self).__init__(message)
  26. self.message = message
  27. self.status = status
  28. class BaseHandler(tornado.web.RequestHandler):
  29. """Base class for request handlers."""
  30. # Cache currently connected users.
  31. _users_cache = {}
  32. # set of documents we're managing (a collection in MongoDB or a table in a SQL database)
  33. document = None
  34. collection = None
  35. # A property to access the first value of each argument.
  36. arguments = property(lambda self: dict([(k, v[0].decode('utf-8'))
  37. for k, v in self.request.arguments.items()]))
  38. @property
  39. def clean_body(self):
  40. """Return a clean dictionary from a JSON body, suitable for a query on MongoDB.
  41. :returns: a clean copy of the body arguments
  42. :rtype: dict"""
  43. return escape.json_decode(self.request.body or '{}')
  44. def write_error(self, status_code, **kwargs):
  45. """Default error handler."""
  46. if isinstance(kwargs.get('exc_info', (None, None))[1], DiffidoBaseException):
  47. exc = kwargs['exc_info'][1]
  48. status_code = exc.status
  49. message = exc.message
  50. else:
  51. message = 'internal error'
  52. self.build_error(message, status=status_code)
  53. def is_api(self):
  54. """Return True if the path is from an API call."""
  55. return self.request.path.startswith('/v%s' % API_VERSION)
  56. def initialize(self, **kwargs):
  57. """Add every passed (key, value) as attributes of the instance."""
  58. for key, value in kwargs.items():
  59. setattr(self, key, value)
  60. def build_error(self, message='', status=400):
  61. """Build and write an error message.
  62. :param message: textual message
  63. :type message: str
  64. :param status: HTTP status code
  65. :type status: int
  66. """
  67. self.set_status(status)
  68. self.write({'error': True, 'message': message})
  69. class TemplateHandler(BaseHandler):
  70. """Handler for the / path."""
  71. app_path = os.path.join(os.path.dirname(__file__), "dist")
  72. @gen.coroutine
  73. def get(self, *args, **kwargs):
  74. page = 'index.html'
  75. if args and args[0]:
  76. page = args[0].strip('/')
  77. arguments = self.arguments
  78. arguments['schedules'] = [{
  79. 'id': 1,
  80. 'title': 'wikipedia',
  81. 'url': 'https://it.wikipedia.org/wiki/Pagina_principale',
  82. 'scheduling': {'interval': 5, 'unit': 'minutes'},
  83. 'enabled': True
  84. }]
  85. self.render(page, **arguments)
  86. def run_scheduled(id_=None, *args, **kwargs):
  87. print('RUNNING %d' % id_)
  88. def run():
  89. print('runno!')
  90. def serve():
  91. jobstores = {'default': SQLAlchemyJobStore(url=JOBS_STORE)}
  92. scheduler = TornadoScheduler(jobstores=jobstores)
  93. scheduler.start()
  94. #scheduler.remove_job('run')
  95. #scheduler.add_job(run, 'interval', minutes=1)
  96. define("port", default=3210, help="run on the given port", type=int)
  97. define("address", default='', help="bind the server at the given address", type=str)
  98. define("ssl_cert", default=os.path.join(os.path.dirname(__file__), 'ssl', 'diffido_cert.pem'),
  99. help="specify the SSL certificate to use for secure connections")
  100. define("ssl_key", default=os.path.join(os.path.dirname(__file__), 'ssl', 'diffido_key.pem'),
  101. help="specify the SSL private key to use for secure connections")
  102. define("debug", default=False, help="run in debug mode")
  103. define("config", help="read configuration file",
  104. callback=lambda path: tornado.options.parse_config_file(path, final=False))
  105. tornado.options.parse_command_line()
  106. logger = logging.getLogger()
  107. logger.setLevel(logging.INFO)
  108. if options.debug:
  109. logger.setLevel(logging.DEBUG)
  110. ssl_options = {}
  111. if os.path.isfile(options.ssl_key) and os.path.isfile(options.ssl_cert):
  112. ssl_options = dict(certfile=options.ssl_cert, keyfile=options.ssl_key)
  113. init_params = dict(listen_port=options.port, logger=logger, ssl_options=ssl_options)
  114. # _days_path = r"/days/?(?P<day>[\d_-]+)?"
  115. application = tornado.web.Application([
  116. # (_days_path, DaysHandler, init_params),
  117. # (r'/v%s%s' % (API_VERSION, _days_path), DaysHandler, init_params),
  118. (r"/?(.*)", TemplateHandler, init_params),
  119. ],
  120. static_path=os.path.join(os.path.dirname(__file__), "dist/static"),
  121. template_path=os.path.join(os.path.dirname(__file__), 'dist/'),
  122. debug=options.debug)
  123. http_server = tornado.httpserver.HTTPServer(application, ssl_options=ssl_options or None)
  124. logger.info('Start serving on %s://%s:%d', 'https' if ssl_options else 'http',
  125. options.address if options.address else '127.0.0.1',
  126. options.port)
  127. http_server.listen(options.port, options.address)
  128. try:
  129. IOLoop.instance().start()
  130. except (KeyboardInterrupt, SystemExit):
  131. pass
  132. if __name__ == '__main__':
  133. serve()