コード例 #1
0
ファイル: library.py プロジェクト: rodrigoma/ComicStreamer
    def getComicPage(self, comic_id, page_number, max_height=None):
        (path, page_count) = self.getSession().query(Comic.path, Comic.page_count) \
            .filter(Comic.id == int(comic_id)).first()

        image_data = None
        default_img_file = AppFolders.imagePath("default.jpg")

        if path is not None:
            if int(page_number) < page_count:
                ca = self.getComicArchive(path)
                image_data = ca.getPage(int(page_number))

        if image_data is None:
            with open(default_img_file, 'rb') as fd:
                image_data = fd.read()
            return image_data

        # resize image
        if max_height is not None:
            try:
                image_data = comicstreamerlib.utils.resizeImage(
                    int(max_height), image_data)
            except Exception as e:
                logging.exception(e)
                pass
        return image_data
コード例 #2
0
ファイル: library.py プロジェクト: kounch/ComicStreamer
    def getComicPage(self, comic_id, page_number, max_height=None):
        (path, page_count) = self.getSession().query(Comic.path, Comic.page_count) \
                                 .filter(Comic.id == int(comic_id)).first()

        image_data = None
        default_img_file = AppFolders.imagePath("default.jpg")

        if path is not None:
            if int(page_number) < page_count:
                ca = self.getComicArchive(path)
                image_data = ca.getPage(int(page_number))

        if image_data is None:
            with open(default_img_file, 'rb') as fd:
                image_data = fd.read()
            return image_data

        # resize image
        if max_height is not None:
            try:
                image_data = comicstreamerlib.utils.resizeImage(
                    int(max_height), image_data)
            except:
                pass
        return image_data
コード例 #3
0
ファイル: database.py プロジェクト: docmo716/ComicStreamer
    def __init__(self):
        self.dbfile = os.path.join(AppFolders.appData(), "comicdb.sqlite")

        self.engine = create_engine('sqlite:///' + self.dbfile, echo=False)

        session_factory = sessionmaker(bind=self.engine)
        self.Session = scoped_session(session_factory)
コード例 #4
0
ファイル: database.py プロジェクト: Kalinon/ComicStreamer
    def __init__(self):
        self.dbfile = os.path.join(AppFolders.appData(), "comicdb.sqlite")

        self.engine = create_engine('sqlite:///'+ self.dbfile, echo=False)

        session_factory = sessionmaker(bind=self.engine)
        self.Session = scoped_session(session_factory)
コード例 #5
0
ファイル: server.py プロジェクト: rodrigoma/ComicStreamer
    def get(self):
        log_file = os.path.join(AppFolders.logs(), "ComicStreamer.log")

        logtxt = ""
        for line in reversed(open(log_file).readlines()):
            logtxt += line.rstrip() + '\n'

        self.render("log.html", logtxt=logtxt)
コード例 #6
0
    def __init__(self):
        super(ComicStreamerConfig, self).__init__()

        self.csfolder = AppFolders.settings()

        # make sure folder exisits
        if not os.path.exists(self.csfolder):
            os.makedirs(self.csfolder)

        # set up initial values
        self.filename = os.path.join(self.csfolder, "settings")
        self.configspec = io.StringIO(ComicStreamerConfig.configspec)
        self.encoding = "UTF8"

        # since some stuff in the configobj has to happen during object initialization,
        # use a temporary delegate,  and them merge it into self
        tmp = ConfigObj(self.filename,
                        configspec=self.configspec,
                        encoding=self.encoding)
        validator = Validator()
        tmp.validate(validator, copy=True)

        # set up the install ID
        if tmp['general']['install_id'] == '':
            tmp['general']['install_id'] = uuid.uuid4().hex

        #set up the cookie secret
        if tmp['security']['cookie_secret'] == '':
            tmp['security']['cookie_secret'] = base64.b64encode(
                uuid.uuid4().bytes + uuid.uuid4().bytes)

        # normalize the folder list
        tmp['general']['folder_list'] = [
            os.path.abspath(os.path.normpath(unicode(a)))
            for a in tmp['general']['folder_list']
        ]

        self.merge(tmp)
        if not os.path.exists(self.filename):
            self.write()

        # not sure if this belongs here:
        # if mac app, and no unrar in path, add the one from the app bundle
        if getattr(sys, 'frozen', None) and platform.system() == "Darwin":
            if which("unrar") is None:
                addtopath(AppFolders.appBase())
コード例 #7
0
ファイル: config.py プロジェクト: kounch/ComicStreamer
    def __init__(self):
        super(ComicStreamerConfig, self).__init__()

        self.csfolder = AppFolders.settings()

        # make sure folder exisits
        if not os.path.exists(self.csfolder):
            os.makedirs(self.csfolder)

        # set up initial values
        self.filename = os.path.join(self.csfolder, "settings")
        self.configspec = io.StringIO(ComicStreamerConfig.configspec)
        self.encoding = "UTF8"

        # since some stuff in the configobj has to happen during object initialization,
        # use a temporary delegate,  and them merge it into self
        tmp = ConfigObj(
            self.filename, configspec=self.configspec, encoding=self.encoding)
        validator = Validator()
        tmp.validate(validator, copy=True)

        # set up the install ID
        if tmp['general']['install_id'] == '':
            tmp['general']['install_id'] = uuid.uuid4().hex

        #set up the cookie secret
        if tmp['security']['cookie_secret'] == '':
            tmp['security']['cookie_secret'] = base64.b64encode(
                uuid.uuid4().bytes + uuid.uuid4().bytes)

        # normalize the folder list
        tmp['general']['folder_list'] = [
            os.path.abspath(os.path.normpath(str(a)))
            for a in tmp['general']['folder_list']
        ]

        self.merge(tmp)
        if not os.path.exists(self.filename):
            self.write()

        # not sure if this belongs here:
        # if mac app, and no unrar in path, add the one from the app bundle
        if getattr(sys, 'frozen', None) and platform.system() == "Darwin":
            if which("unrar") is None:
                addtopath(AppFolders.appBase())
コード例 #8
0
ファイル: server.py プロジェクト: kounch/ComicStreamer
    def get(self):

        log_file = os.path.join(AppFolders.logs(), "ComicStreamer.log")

        logtxt = ""
        for line in reversed(open(log_file).readlines()):
            logtxt += line.rstrip() + '\n'

        self.render("log.html", logtxt=logtxt)
コード例 #9
0
    def __init__(self, apiServer):
        self.apiServer = apiServer

        self.app = QtGui.QApplication(sys.argv)

        pixmap = QtGui.QPixmap(AppFolders.imagePath("trout.png"))
        icon = QtGui.QIcon(pixmap.scaled(16, 16))

        self.trayIcon = SystemTrayIcon(icon, self)

        self.trayIcon.show()
コード例 #10
0
ファイル: gui_win.py プロジェクト: Amohell/ComicStreamer
 def __init__(self, apiServer):
     
     self.apiServer = apiServer
     
     self.icon = AppFolders.imagePath("trout.ico")
     self.hover_text = "ComicStreamer"
     self.on_quit = self.bye    
         
     menu_options = (
                     ('Show ComicStreamer UI', None, self.show),
                    )
     
     menu_options = menu_options + (('Quit', None, self.QUIT),)
     self._next_action_id = self.FIRST_ID
     self.menu_actions_by_id = set()
     self.menu_options = self._add_ids_to_menu_options(list(menu_options))
     self.menu_actions_by_id = dict(self.menu_actions_by_id)
     del self._next_action_id
     
     
     self.default_menu_index = 1
     self.window_class_name = "ComicStreamerTrayIcon"
     
     message_map = {win32gui.RegisterWindowMessage("TaskbarCreated"): self.restart,
                    win32con.WM_DESTROY: self.destroy,
                    win32con.WM_COMMAND: self.command,
                    win32con.WM_USER+20 : self.notify,}
     # Register the Window class.
     window_class = win32gui.WNDCLASS()
     hinst = window_class.hInstance = win32gui.GetModuleHandle(None)
     window_class.lpszClassName = self.window_class_name
     window_class.style = win32con.CS_VREDRAW | win32con.CS_HREDRAW;
     window_class.hCursor = win32gui.LoadCursor(0, win32con.IDC_ARROW)
     window_class.hbrBackground = win32con.COLOR_WINDOW
     window_class.lpfnWndProc = message_map # could also specify a wndproc.
     classAtom = win32gui.RegisterClass(window_class)
     # Create the Window.
     style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU
     self.hwnd = win32gui.CreateWindow(classAtom,
                                       self.window_class_name,
                                       style,
                                       0,
                                       0,
                                       win32con.CW_USEDEFAULT,
                                       win32con.CW_USEDEFAULT,
                                       0,
                                       0,
                                       hinst,
                                       None)
     win32gui.UpdateWindow(self.hwnd)
     self.notify_id = None
     self.refresh_icon()
コード例 #11
0
ファイル: gui_mac.py プロジェクト: Amohell/ComicStreamer
 def __init__(self, apiServer):
     super(MacGui, self).__init__("ComicStreamer", icon=AppFolders.imagePath("trout.png"))
     self.apiServer =  apiServer
     
     self.menu = [
         #rumps.MenuItem('About'), 
         'Show ComicStreamer UI',
         #None,  # None functions as a separator in your menu
         #{'Arbitrary':
         #    {"Depth": ["Menus", "It's pretty easy"],
         #     "And doesn't": ["Even look like Objective C", rumps.MenuItem("One bit", callback=self.onebitcallback)]}},
         None
     ]         
コード例 #12
0
ファイル: server.py プロジェクト: Kalinon/ComicStreamer
    def get(self, comic_id):
        self.validateAPIKey()
        thumbnail = self.library.getComicThumbnail(comic_id)

        if thumbnail != None:
            self.setContentType('image/jpg')
            self.write(thumbnail)
        else:
            default_img_file = AppFolders.imagePath("default.jpg")
            with open(default_img_file, 'rb') as fd:
                image_data = fd.read()
            self.setContentType('image/jpg')
            self.write(image_data)
コード例 #13
0
    def get(self, comic_id):
        self.validateAPIKey()
        thumbnail = self.library.getComicThumbnail(comic_id)

        if thumbnail != None:
            self.setContentType('image/jpg')
            self.write(thumbnail)
        else:
            default_img_file = AppFolders.imagePath("default.jpg")
            with open(default_img_file, 'rb') as fd:
                image_data = fd.read()
            self.setContentType('image/jpg')
            self.write(image_data)
コード例 #14
0
ファイル: gui_mac.py プロジェクト: rodrigoma/ComicStreamer
    def __init__(self, apiServer):
        super(MacGui, self).__init__("ComicStreamer",
                                     icon=AppFolders.imagePath("trout.png"))
        self.apiServer = apiServer

        self.menu = [
            # rumps.MenuItem('About'),
            'Show ComicStreamer UI',
            # None,  # None functions as a separator in your menu
            # {'Arbitrary':
            #    {"Depth": ["Menus", "It's pretty easy"],
            #     "And doesn't": ["Even look like Objective C", rumps.MenuItem("One bit", callback=self.onebitcallback)]}},
            None
        ]
コード例 #15
0
ファイル: library.py プロジェクト: kounch/ComicStreamer
 def getComicArchive(self, path):
     # should also look at modified time of file
     for ca in self.comicArchiveList:
         if ca.path == path:
             # remove from list and put at end
             self.comicArchiveList.remove(ca)
             self.comicArchiveList.append(ca)
             return ca
     else:
         ca = ComicArchive(
             path, default_image_path=AppFolders.imagePath("default.jpg"))
         self.comicArchiveList.append(ca)
         if len(self.comicArchiveList) > 10:
             self.comicArchiveList.pop(0)
         return ca
コード例 #16
0
ファイル: library.py プロジェクト: rodrigoma/ComicStreamer
 def getComicArchive(self, path):
     # should also look at modified time of file
     for ca in self.comicArchiveList:
         if ca.path == path:
             # remove from list and put at end
             self.comicArchiveList.remove(ca)
             self.comicArchiveList.append(ca)
             return ca
     else:
         ca = ComicArchive(
             path, default_image_path=AppFolders.imagePath("default.jpg"))
         self.comicArchiveList.append(ca)
         if len(self.comicArchiveList) > 10:
             self.comicArchiveList.pop(0)
         return ca
コード例 #17
0
ファイル: utils.py プロジェクト: rodrigoma/ComicStreamer
def resizeImage(max, image_data):
    # disable WebP for now, due a memory leak in python library
    imtype = imghdr.what(StringIO(image_data))
    if imtype == "webp":
        with open(AppFolders.imagePath("default.jpg"), 'rb') as fd:
            image_data = fd.read()

    im = Image.open(StringIO(image_data)).convert('RGB')
    w, h = im.size
    if max < h:
        im.thumbnail((w, max), Image.ANTIALIAS)
        output = StringIO()
        im.save(output, format="JPEG")
        return output.getvalue()
    else:
        return image_data
コード例 #18
0
ファイル: utils.py プロジェクト: Kalinon/ComicStreamer
def resizeImage(max, image_data):
    # disable WebP for now, due a memory leak in python library
    imtype = imghdr.what(StringIO.StringIO(image_data))
    if imtype == "webp":
        with open(AppFolders.imagePath("default.jpg"), 'rb') as fd:
            image_data = fd.read()

    im = Image.open(StringIO.StringIO(image_data)).convert('RGB')
    w,h = im.size
    if max < h:
        im.thumbnail((w,max), Image.ANTIALIAS)
        output = StringIO.StringIO()
        im.save(output, format="JPEG")
        return output.getvalue()
    else:
        return image_data
コード例 #19
0
def resize(img, box, out, fit=False):
    '''Downsample the image.
    @param img: Image -  an Image-object
    @param box: tuple(x, y) - the bounding box of the result image
    @param fix: boolean - crop the image to fill the box
    @param out: file-like-object - save the image into the output stream
    '''

    if type(img) != Image and type(img) == str:
        try:
            img = Image.open(StringIO.StringIO(img))
        except:
            img = Image.open(
                StringIO(open(AppFolders.imagePath("default.jpg")).read()))

    #preresize image with factor 2, 4, 8 and fast algorithm
    factor = 1
    while img.size[0] / factor > 2 * box[0] and img.size[
            1] * 2 / factor > 2 * box[1]:
        factor *= 2
    if factor > 1:
        img.thumbnail((img.size[0] / factor, img.size[1] / factor),
                      Image.NEAREST)

    #calculate the cropping box and get the cropped part
    if fit:
        x1 = y1 = 0
        x2, y2 = img.size
        wRatio = 1.0 * x2 / box[0]
        hRatio = 1.0 * y2 / box[1]
        if hRatio > wRatio:
            y1 = int(y2 / 2 - box[1] * wRatio / 2)
            y2 = int(y2 / 2 + box[1] * wRatio / 2)
        else:
            x1 = int(x2 / 2 - box[0] * hRatio / 2)
            x2 = int(x2 / 2 + box[0] * hRatio / 2)
        img = img.crop((x1, y1, x2, y2))

    #Resize the image with best quality algorithm ANTI-ALIAS
    img.thumbnail(box, Image.ANTIALIAS)

    img = img.convert('RGB')

    #save it into a file-like object
    img.save(out, "JPEG", quality=65)
コード例 #20
0
ファイル: gui_win.py プロジェクト: rodrigoma/ComicStreamer
    def __init__(self, apiServer):

        self.apiServer = apiServer

        self.icon = AppFolders.imagePath("trout.ico")
        self.hover_text = "ComicStreamer"
        self.on_quit = self.bye

        menu_options = (('Show ComicStreamer UI', None, self.show), )

        menu_options = menu_options + (('Quit', None, self.QUIT), )
        self._next_action_id = self.FIRST_ID
        self.menu_actions_by_id = set()
        self.menu_options = self._add_ids_to_menu_options(list(menu_options))
        self.menu_actions_by_id = dict(self.menu_actions_by_id)
        del self._next_action_id

        self.default_menu_index = 1
        self.window_class_name = "ComicStreamerTrayIcon"

        message_map = {
            win32gui.RegisterWindowMessage("TaskbarCreated"): self.restart,
            win32con.WM_DESTROY: self.destroy,
            win32con.WM_COMMAND: self.command,
            win32con.WM_USER + 20: self.notify,
        }
        # Register the Window class.
        window_class = win32gui.WNDCLASS()
        hinst = window_class.hInstance = win32gui.GetModuleHandle(None)
        window_class.lpszClassName = self.window_class_name
        window_class.style = win32con.CS_VREDRAW | win32con.CS_HREDRAW
        window_class.hCursor = win32gui.LoadCursor(0, win32con.IDC_ARROW)
        window_class.hbrBackground = win32con.COLOR_WINDOW
        window_class.lpfnWndProc = message_map  # could also specify a wndproc.
        classAtom = win32gui.RegisterClass(window_class)
        # Create the Window.
        style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU
        self.hwnd = win32gui.CreateWindow(classAtom, self.window_class_name,
                                          style, 0, 0, win32con.CW_USEDEFAULT,
                                          win32con.CW_USEDEFAULT, 0, 0, hinst,
                                          None)
        win32gui.UpdateWindow(self.hwnd)
        self.notify_id = None
        self.refresh_icon()
コード例 #21
0
ファイル: server.py プロジェクト: Kalinon/ComicStreamer
    def __init__(self, config, opts):
        utils.fix_output_encoding()   
        
        self.config = config
        self.opts = opts
        
        self.port = self.config['general']['port']
        self.webroot = self.config['general']['webroot']
        
        self.comicArchiveList = []
        
        #if len(self.config['general']['folder_list']) == 0:
        #    logging.error("No folders on either command-line or config file.  Quitting.")
        #    sys.exit(-1)
        
        self.dm = DataManager()
        self.library = Library(self.dm.Session)
        
        if opts.reset or opts.reset_and_run:
            logging.info( "Deleting any existing database!")
            self.dm.delete()
            
        # quit on a standard reset
        if opts.reset:
            sys.exit(0)
            
        try:
            self.dm.create()
        except SchemaVersionException as e:
            msg = "Couldn't open database.  Probably the schema has changed."
            logging.error(msg)
            utils.alert("Schema change", msg)
            sys.exit(-1)
            
        
        try:
            self.listen(self.port, no_keep_alive = True)
        except Exception as e:
            logging.error(e)
            msg = "Couldn't open socket on port {0}.  (Maybe ComicStreamer is already running?)  Quitting.".format(self.port)
            logging.error(msg)
            utils.alert("Port not available", msg)
            sys.exit(-1)

        logging.info( "Stream server running on port {0}...".format(self.port))
        
        #http_server = tornado.httpserver.HTTPServer(self, no_keep_alive = True, ssl_options={
        #    "certfile": "server.crt",
        #    "keyfile": "server.key",
        #})
        #http_server.listen(port+1)        
         
        self.version = csversion.version

        handlers = [
            # Web Pages
            (self.webroot + r"/", MainHandler),
            (self.webroot + r"/(.*)\.html", GenericPageHandler),
            (self.webroot + r"/about", AboutPageHandler),
            (self.webroot + r"/control", ControlPageHandler),
            (self.webroot + r"/configure", ConfigPageHandler),
            (self.webroot + r"/log", LogPageHandler),
            (self.webroot + r"/comiclist/browse", ComicListBrowserHandler),
            (self.webroot + r"/folders/browse(/.*)*", FoldersBrowserHandler),
            (self.webroot + r"/entities/browse(/.*)*", EntitiesBrowserHandler),
            (self.webroot + r"/comic/([0-9]+)/reader", ReaderHandler),
            (self.webroot + r"/login", LoginHandler),
            # Data
            (self.webroot + r"/dbinfo", DBInfoAPIHandler),
            (self.webroot + r"/version", VersionAPIHandler),
            (self.webroot + r"/deleted", DeletedAPIHandler),
            (self.webroot + r"/comic/([0-9]+)", ComicAPIHandler),
            (self.webroot + r"/comiclist", ComicListAPIHandler),
            (self.webroot + r"/comic/([0-9]+)/page/([0-9]+|clear)/bookmark", ComicBookmarkAPIHandler ),
            (self.webroot + r"/comic/([0-9]+)/page/([0-9]+)", ComicPageAPIHandler ),
            (self.webroot + r"/comic/([0-9]+)/thumbnail", ThumbnailAPIHandler),
            (self.webroot + r"/comic/([0-9]+)/file", FileAPIHandler),
            (self.webroot + r"/entities(/.*)*", EntityAPIHandler),
            (self.webroot + r"/folders(/.*)*", FolderAPIHandler),
            (self.webroot + r"/command", CommandAPIHandler),
            (self.webroot + r"/scanstatus", ScanStatusAPIHandler),
            #(r'/favicon.ico', tornado.web.StaticFileHandler, {'path': os.path.join(AppFolders.appBase(), "static","images")}),
            (self.webroot + r'/.*', UnknownHandler),
            
        ]

        settings = dict(
            template_path=os.path.join(AppFolders.appBase(), "templates"),
            static_path=os.path.join(AppFolders.appBase(), "static"),
            static_url_prefix=self.webroot + "/static/",
            debug=True,
            #autoreload=False,
            login_url=self.webroot + "/login",
            cookie_secret=self.config['security']['cookie_secret'],
            xsrf_cookies=True,
        )

        tornado.web.Application.__init__(self, handlers, **settings)

        if not opts.no_monitor:     
            logging.debug("Going to scan the following folders:")
            for l in self.config['general']['folder_list']:
                logging.debug(u"   {0}".format(repr(l)))

            self.monitor = Monitor(self.dm, self.config['general']['folder_list'])
            self.monitor.start()
            self.monitor.scan()
            
        self.bookmarker = Bookmarker(self.dm)
        self.bookmarker.start()

        if opts.launch_browser and self.config['general']['launch_browser']:
            if ((platform.system() == "Linux" and os.environ.has_key('DISPLAY')) or
                    (platform.system() == "Darwin" and not os.environ.has_key('SSH_TTY')) or
                    platform.system() == "Windows"):
                webbrowser.open("http://localhost:{0}".format(self.port), new=0)
コード例 #22
0
ファイル: main.py プロジェクト: Amohell/ComicStreamer
 def go(self):
     utils.fix_output_encoding()
     self.apiServer = None
     
     #Configure logging
     # root level        
     logger = logging.getLogger()    
     logger.setLevel(logging.DEBUG)
     formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
     
     log_file = os.path.join(AppFolders.logs(), "ComicStreamer.log")
     if not os.path.exists(os.path.dirname(log_file)):
         os.makedirs(os.path.dirname(log_file))
     fh = logging.handlers.RotatingFileHandler(log_file, maxBytes=1048576, backupCount=4, encoding="UTF8")
     fh.setLevel(logging.DEBUG)
     fh.setFormatter(formatter)
     logger.addHandler(fh)
     
     # By default only do info level to console
     sh = logging.StreamHandler(sys.stdout)
     sh.setLevel(logging.INFO)
     sh.setFormatter(formatter)
     logger.addHandler(sh)
 
     config = ComicStreamerConfig()
     opts = Options()
     opts.parseCmdLineArgs()
 
     # set file logging according to config file
     #fh.setLevel(config['general']['loglevel'])
         
     # turn up the log level, if requested
     if opts.debug:
         sh.setLevel(logging.DEBUG)
     elif opts.quiet:
         sh.setLevel(logging.CRITICAL)
 
     config.applyOptions(opts)
     
     self.apiServer = APIServer(config, opts)
 
     self.apiServer.logFileHandler = fh
     self.apiServer.logConsoleHandler = sh
     
     signal.signal(signal.SIGINT, self.signal_handler)
 
 
     bonjour = BonjourThread(self.apiServer.port)
     bonjour.start()
 
     if getattr(sys, 'frozen', None):
         # A frozen app will run a GUI
         self.apiServer.runInThread()
    
         logging.info("starting GUI loop")    
         if platform.system() == "Darwin":
             from gui_mac import MacGui
             MacGui(self.apiServer).run()
     
         elif platform.system() == "Windows":
             from gui_win import WinGui
             WinGui(self.apiServer).run()
             self.apiServer.shutdown()
     else:
         #from gui_qt import QtBasedGui
         #self.apiServer.runInThread()
         #QtBasedGui(self.apiServer).run()			
         #self.apiServer.shutdown()
         self.apiServer.run()
         
     logging.info("gui shoudld be done now")
コード例 #23
0
    def __init__(self, config, opts):
        utils.fix_output_encoding()

        self.config = config
        self.opts = opts

        self.port = self.config['general']['port']
        self.webroot = self.config['general']['webroot']

        self.comicArchiveList = []

        #if len(self.config['general']['folder_list']) == 0:
        #    logging.error("No folders on either command-line or config file.  Quitting.")
        #    sys.exit(-1)

        self.dm = DataManager()
        self.library = Library(self.dm.Session)

        if opts.reset or opts.reset_and_run:
            logging.info("Deleting any existing database!")
            self.dm.delete()

        # quit on a standard reset
        if opts.reset:
            sys.exit(0)

        try:
            self.dm.create()
        except SchemaVersionException as e:
            msg = "Couldn't open database.  Probably the schema has changed."
            logging.error(msg)
            utils.alert("Schema change", msg)
            sys.exit(-1)

        try:
            self.listen(self.port, no_keep_alive=True)
        except Exception as e:
            logging.error(e)
            msg = "Couldn't open socket on port {0}.  (Maybe ComicStreamer is already running?)  Quitting.".format(
                self.port)
            logging.error(msg)
            utils.alert("Port not available", msg)
            sys.exit(-1)

        logging.info("Stream server running on port {0}...".format(self.port))

        #http_server = tornado.httpserver.HTTPServer(self, no_keep_alive = True, ssl_options={
        #    "certfile": "server.crt",
        #    "keyfile": "server.key",
        #})
        #http_server.listen(port+1)

        self.version = csversion.version

        handlers = [
            # Web Pages
            (self.webroot + r"/", MainHandler),
            (self.webroot + r"/(.*)\.html", GenericPageHandler),
            (self.webroot + r"/about", AboutPageHandler),
            (self.webroot + r"/control", ControlPageHandler),
            (self.webroot + r"/configure", ConfigPageHandler),
            (self.webroot + r"/log", LogPageHandler),
            (self.webroot + r"/comiclist/browse", ComicListBrowserHandler),
            (self.webroot + r"/folders/browse(/.*)*", FoldersBrowserHandler),
            (self.webroot + r"/entities/browse(/.*)*", EntitiesBrowserHandler),
            (self.webroot + r"/comic/([0-9]+)/reader", ReaderHandler),
            (self.webroot + r"/login", LoginHandler),
            # Data
            (self.webroot + r"/dbinfo", DBInfoAPIHandler),
            (self.webroot + r"/version", VersionAPIHandler),
            (self.webroot + r"/deleted", DeletedAPIHandler),
            (self.webroot + r"/comic/([0-9]+)", ComicAPIHandler),
            (self.webroot + r"/comiclist", ComicListAPIHandler),
            (self.webroot + r"/comic/([0-9]+)/page/([0-9]+|clear)/bookmark",
             ComicBookmarkAPIHandler),
            (self.webroot + r"/comic/([0-9]+)/page/([0-9]+)",
             ComicPageAPIHandler),
            (self.webroot + r"/comic/([0-9]+)/thumbnail", ThumbnailAPIHandler),
            (self.webroot + r"/comic/([0-9]+)/file", FileAPIHandler),
            (self.webroot + r"/entities(/.*)*", EntityAPIHandler),
            (self.webroot + r"/folders(/.*)*", FolderAPIHandler),
            (self.webroot + r"/command", CommandAPIHandler),
            (self.webroot + r"/scanstatus", ScanStatusAPIHandler),
            #(r'/favicon.ico', tornado.web.StaticFileHandler, {'path': os.path.join(AppFolders.appBase(), "static","images")}),
            (self.webroot + r'/.*', UnknownHandler),
        ]

        settings = dict(
            template_path=os.path.join(AppFolders.appBase(), "templates"),
            static_path=os.path.join(AppFolders.appBase(), "static"),
            static_url_prefix=self.webroot + "/static/",
            debug=True,
            #autoreload=False,
            login_url=self.webroot + "/login",
            cookie_secret=self.config['security']['cookie_secret'],
            xsrf_cookies=True,
        )

        tornado.web.Application.__init__(self, handlers, **settings)

        if not opts.no_monitor:
            logging.debug("Going to scan the following folders:")
            for l in self.config['general']['folder_list']:
                logging.debug(u"   {0}".format(repr(l)))

            self.monitor = Monitor(self.dm,
                                   self.config['general']['folder_list'])
            self.monitor.start()
            self.monitor.scan()

        self.bookmarker = Bookmarker(self.dm)
        self.bookmarker.start()

        if opts.launch_browser and self.config['general']['launch_browser']:
            if ((platform.system() == "Linux"
                 and os.environ.has_key('DISPLAY'))
                    or (platform.system() == "Darwin"
                        and not os.environ.has_key('SSH_TTY'))
                    or platform.system() == "Windows"):
                webbrowser.open("http://localhost:{0}".format(self.port),
                                new=0)
コード例 #24
0
ファイル: database.py プロジェクト: veiraz/ComicStreamer
 def __init__(self):
     self.dbfile = os.path.join(AppFolders.appData(), "comicdb.sqlite")
コード例 #25
0
ファイル: main.py プロジェクト: frameset/ComicStreamer
    def go(self):
        utils.fix_output_encoding()
        self.apiServer = None

        opts = Options()
        opts.parseCmdLineArgs()

        #Configure logging
        # root level
        logger = logging.getLogger()
        logger.setLevel(logging.DEBUG)
        formatter = logging.Formatter(
            '%(asctime)s - %(levelname)s - %(message)s')

        log_file = os.path.join(AppFolders.logs(), "ComicStreamer.log")
        if not os.path.exists(os.path.dirname(log_file)):
            os.makedirs(os.path.dirname(log_file))
        fh = logging.handlers.RotatingFileHandler(log_file,
                                                  maxBytes=1048576,
                                                  backupCount=4,
                                                  encoding="UTF8")
        fh.setLevel(logging.DEBUG)
        fh.setFormatter(formatter)
        logger.addHandler(fh)

        # By default only do info level to console
        sh = logging.StreamHandler(sys.stdout)
        sh.setLevel(logging.INFO)
        sh.setFormatter(formatter)
        logger.addHandler(sh)

        # set file logging according to config file
        #fh.setLevel(config['general']['loglevel'])

        # turn up the log level, if requested
        if opts.debug:
            sh.setLevel(logging.DEBUG)
        elif opts.quiet:
            sh.setLevel(logging.CRITICAL)
        config = ComicStreamerConfig()
        config.applyOptions(opts)

        self.apiServer = APIServer(config, opts)

        self.apiServer.logFileHandler = fh
        self.apiServer.logConsoleHandler = sh

        signal.signal(signal.SIGINT, self.signal_handler)

        if getattr(sys, 'frozen', None):
            # A frozen app will run a GUI
            self.apiServer.runInThread()

            logging.debug("UI: Started")
            if platform.system() == "Darwin":
                from gui_mac import MacGui
                MacGui(self.apiServer).run()

            elif platform.system() == "Windows":
                from gui_win import WinGui
                WinGui(self.apiServer).run()
                self.apiServer.shutdown()
        else:
            #from gui_qt import QtBasedGui
            #self.apiServer.runInThread()
            #QtBasedGui(self.apiServer).run()
            #self.apiServer.shutdown()
            self.apiServer.run()

        logging.info("UI: Stopped")