Python module (submodule repositary), which provides content (video streams) from various online stream sources to corresponding Enigma2, Kodi, Plex plugins

playstreamproxy5.py 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. # coding: utf-8
  2. u"""
  3. GIS failu web serveris
  4. """
  5. prog = "web-server"
  6. version="%(prog)s v0.1"
  7. epilog = "(c)Ivars 2017"
  8. import sys, os, os.path, argparse
  9. import re,cgi, urllib, json
  10. import datetime,time
  11. from zope.interface import implements
  12. from twisted.internet import reactor,defer, threads, task
  13. from twisted.web import server, resource, http, error, util
  14. from twisted.python import log,logfile
  15. from twisted.web import static
  16. xset = lambda x,y: x if x else y
  17. options = []
  18. class ResponseFile(static.File):
  19. def __init__(self, path):
  20. static.File.__init__(self, path)
  21. def render_GET(self, request):
  22. #request.setHeader('Content-Disposition', ['attachment ; filename="tick_db_export.csv"'])
  23. return static.File.render_GET(self, request)
  24. def parse_arguments(argv):
  25. "Parse command line arguments"
  26. parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, description =__doc__,epilog=epilog, version=version, prog=prog)
  27. parser.add_argument("-p", "--port", type=int, help="web server port")
  28. parser.add_argument("--debug", action="store_true", dest="debug", default=False, help="print debug info")
  29. return parser.parse_args(argv), parser
  30. #import config # get parameters from ini file
  31. def main(argv):
  32. # get global parameters from command line arguments and ini file
  33. global options
  34. options,parser = parse_arguments(argv[1:])
  35. #log.startLogging(logfile.DailyLogFile.fromFullPath("logs\\gis-faili.log"))
  36. log.startLogging(sys.stdout)
  37. # root = MyFile(base) # no directory browsing
  38. #root = Root()
  39. #root = static.File("/")
  40. #root = ResponseFile(".")
  41. root = urlproxy.URLProxy()
  42. # Start web server
  43. reactor.listenTCP(8000, server.Site(root))
  44. reactor.run()
  45. class ResourceThread(resource.Resource):
  46. "Resource subclass, which renders request in thread. Redefine 'process' "
  47. def render_GET(self, request):
  48. d = threads.deferToThread(self.process,request)
  49. d.addCallback(self._cb,request)
  50. d.addErrback(self._eb,request)
  51. request.notifyFinish().addErrback(self._connection_lost, d)
  52. return server.NOT_DONE_YET
  53. def render_POST(self, request):
  54. d = threads.deferToThread(self.process,request)
  55. d.addCallback(self._cb,request)
  56. d.addErrback(self._eb,request)
  57. request.notifyFinish().addErrback(self._connection_lost, d)
  58. return server.NOT_DONE_YET
  59. def _cb(self, result, request):
  60. "Callback function"
  61. request.write(result)
  62. request.finish()
  63. def _eb(self, failure, request):
  64. "Errorback function"
  65. #err = failure.trap(defer.CancelledError)
  66. if failure == defer.CancelledError:
  67. log.msg("Connection canceled")
  68. return None
  69. else:
  70. #log.err(failure)
  71. failure.printTraceback()
  72. body = resource.ErrorPage(http.INTERNAL_SERVER_ERROR,
  73. "Internal errror, see log file for details","").render(request)
  74. request.write(body)
  75. request.finish()
  76. def _connection_lost(self,err,d):
  77. d.cancel()
  78. def process(self,request):
  79. "Process request. Shoud be redefined"
  80. return "No process method defined"
  81. def get_req(self,request,exclude=[]):
  82. "Return request parameters as Rec() object in utf8, add user. Exclude parameters listed in exclude"
  83. req = Rec()
  84. for k,v in request.args.iteritems():
  85. if k in exclude:
  86. continue
  87. req[k] = ",".join(v)
  88. req[k] = req[k].decode("utf8")
  89. req.user = request.getUser()
  90. return req
  91. ######### http commands handlers ####################
  92. class Root(ResourceThread):
  93. "Server root"
  94. isLeaf = True
  95. def process(self,request):
  96. "Apstrada pieprasijumu"
  97. req = self.get_req(request)
  98. request.responseHeaders.setRawHeaders("Content-type",['text/html; charset=utf-8'])
  99. html = u"Response text".encode("utf8")
  100. return html
  101. #self.file = static.File("./aaa.mp4")
  102. #request.uri = "/aaa.mp4"
  103. #return self.file.render_GET(request)
  104. import UserDict
  105. class Rec(UserDict.DictMixin):
  106. "Dict like class allowing a.x instead of a['x']"
  107. def __init__(self, dict=None, **kwargs):
  108. self.__dict__ = {}
  109. if dict is not None:
  110. self.update(dict)
  111. if len(kwargs):
  112. self.update(kwargs)
  113. def __setitem__(self, name, value): setattr(self, name, value)
  114. def __getitem__(self, name): return getattr(self,name,None)
  115. def __getattr__(self,key): return None
  116. def has_key(self,key): return True if self.__dict__.has_key(key) else False
  117. def keys(self): return list(self.__dict__)
  118. if __name__ == "__main__":
  119. sys.exit(main(sys.argv))