Esempio n. 1
0
        mylar.SAFESTART = False

    if args.noweekly:
        mylar.NOWEEKLY = True
    else:
        mylar.NOWEEKLY = False

    # Put the database in the DATA_DIR
    mylar.DB_FILE = os.path.join(mylar.DATA_DIR, 'mylar.db')

    # Read config and start logging
    if mylar.MAINTENANCE is False:
        print('Initializing startup sequence....')

    #try:
    mylar.initialize(mylar.CONFIG_FILE)
    #except Exception as e:
    #    print e
    #    raise SystemExit('FATAL ERROR')

    if mylar.MAINTENANCE is False:
        filechecker.validateAndCreateDirectory(mylar.DATA_DIR, True)

        # Make sure the DATA_DIR is writeable
        if not os.access(mylar.DATA_DIR, os.W_OK):
            raise SystemExit('Cannot write to the data directory: ' +
                             mylar.DATA_DIR + '. Exiting...')

    # backup the db and configs before they load.
    if args.backup:
        print '[AUTO-BACKUP] Backing up .db and config.ini files for safety.'
Esempio n. 2
0
                shutil.copy(ogfile, back)

            except OSError as exception:
                if exception.errno != errno.EXIST:
                    raise

            i += 1

    from configobj import ConfigObj
    mylar.CFG = ConfigObj(mylar.CONFIG_FILE, encoding='utf-8')

    # Rename the main thread
    threading.currentThread().name = "MAIN"

    # Read config & start logging
    mylar.initialize()

    if mylar.DAEMON:
        mylar.daemonize()

    # Force the http port if neccessary
    if args.port:
        http_port = args.port
        logger.info('Starting Mylar on foced port: %i' % http_port)
    else:
        http_port = int(mylar.HTTP_PORT)

    # Check if pyOpenSSL is installed. It is required for certificate generation
    # and for CherryPy.
    if mylar.ENABLE_HTTPS:
        try:
Esempio n. 3
0
def main():

    # Fixed paths to mylar
    if hasattr(sys, 'frozen'):
        mylar.FULL_PATH = os.path.abspath(sys.executable)
    else:
        mylar.FULL_PATH = os.path.abspath(__file__)
    
    mylar.PROG_DIR = os.path.dirname(mylar.FULL_PATH)
    mylar.ARGS = sys.argv[1:]
    
    # From sickbeard
    mylar.SYS_ENCODING = None

    try:
        locale.setlocale(locale.LC_ALL, "")
        mylar.SYS_ENCODING = locale.getpreferredencoding()
    except (locale.Error, IOError):
        pass

    # for OSes that are poorly configured I'll just force UTF-8
    if not mylar.SYS_ENCODING or mylar.SYS_ENCODING in ('ANSI_X3.4-1968', 'US-ASCII', 'ASCII'):
        mylar.SYS_ENCODING = 'UTF-8'
    
    # Set up and gather command line arguments
    parser = argparse.ArgumentParser(description='Comic Book add-on for SABnzbd+')

    parser.add_argument('-v', '--verbose', action='store_true', help='Increase console logging verbosity')
    parser.add_argument('-q', '--quiet', action='store_true', help='Turn off console logging')
    parser.add_argument('-d', '--daemon', action='store_true', help='Run as a daemon')
    parser.add_argument('-p', '--port', type=int, help='Force mylar to run on a specified port')
    parser.add_argument('--datadir', help='Specify a directory where to store your data files')
    parser.add_argument('--config', help='Specify a config file to use')
    parser.add_argument('--nolaunch', action='store_true', help='Prevent browser from launching on startup')
    parser.add_argument('--pidfile', help='Create a pid file (only relevant when running as a daemon)')
    
    args = parser.parse_args()

    if args.verbose:
        mylar.VERBOSE = 2
    elif args.quiet:
        mylar.VERBOSE = 0
    
    if args.daemon:
        mylar.DAEMON=True
        mylar.VERBOSE = 0
        if args.pidfile :
            mylar.PIDFILE = args.pidfile

    if args.datadir:
        mylar.DATA_DIR = args.datadir
    else:
        mylar.DATA_DIR = mylar.PROG_DIR
            
    if args.config:
        mylar.CONFIG_FILE = args.config
    else:
        mylar.CONFIG_FILE = os.path.join(mylar.DATA_DIR, 'config.ini')
        
    # Try to create the DATA_DIR if it doesn't exist
    #if not os.path.exists(mylar.DATA_DIR):
    #    try:
    #        os.makedirs(mylar.DATA_DIR)
    #    except OSError:
    #        raise SystemExit('Could not create data directory: ' + mylar.DATA_DIR + '. Exiting....')

    filechecker.validateAndCreateDirectory(mylar.DATA_DIR, True)
    
    # Make sure the DATA_DIR is writeable
    if not os.access(mylar.DATA_DIR, os.W_OK):
        raise SystemExit('Cannot write to the data directory: ' + mylar.DATA_DIR + '. Exiting...')
    
    # Put the database in the DATA_DIR
    mylar.DB_FILE = os.path.join(mylar.DATA_DIR, 'mylar.db')
    
    mylar.CFG = ConfigObj(mylar.CONFIG_FILE, encoding='utf-8')
    
    # Read config & start logging
    mylar.initialize()
        
    if mylar.DAEMON:
        mylar.daemonize()

    # Force the http port if neccessary
    if args.port:
        http_port = args.port
        logger.info('Starting Mylar on foced port: %i' % http_port)
    else:
        http_port = int(mylar.HTTP_PORT)
        
    # Try to start the server. 
    webstart.initialize({
                    'http_port':        http_port,
                    'http_host':        mylar.HTTP_HOST,
                    'http_root':        mylar.HTTP_ROOT,
                    'http_username':    mylar.HTTP_USERNAME,
                    'http_password':    mylar.HTTP_PASSWORD,
            })
    
    logger.info('Starting Mylar on port: %i' % http_port)
    
    if mylar.LAUNCH_BROWSER and not args.nolaunch:
        mylar.launch_browser(mylar.HTTP_HOST, http_port, mylar.HTTP_ROOT)
        
    # Start the background threads
    mylar.start()
    
    while True:
        if not mylar.SIGNAL:
            time.sleep(1)
        else:
            logger.info('Received signal: ' + mylar.SIGNAL)
            if mylar.SIGNAL == 'shutdown':
                mylar.shutdown()
            elif mylar.SIGNAL == 'restart':
                mylar.shutdown(restart=True)
            else:
                mylar.shutdown(restart=True, update=True)
            
            mylar.SIGNAL = None
            
    return
Esempio n. 4
0
File: Mylar.py Progetto: 2mny/mylar
                print '[AUTO-BACKUP] Now copying db file to ' + back
                shutil.copy(ogfile, back)

            except OSError as exception:
                if exception.errno != errno.EXIST:
                    raise

            i += 1

    #from configobj import ConfigObj
    #mylar.CFG = ConfigObj(mylar.CONFIG_FILE, encoding='utf-8')

    # Read config and start logging
    try:
        logger.info('Initializing startup sequence....')
        mylar.initialize(mylar.CONFIG_FILE)
    except Exception as e:
        print e
        raise SystemExit('FATAL ERROR')

    # Rename the main thread
    threading.currentThread().name = "MAIN"

    if mylar.DAEMON:
        mylar.daemonize()

    # Force the http port if neccessary
    if args.port:
        http_port = args.port
        logger.info('Starting Mylar on forced port: %i' % http_port)
    else:
Esempio n. 5
0
def main():

    # Fixed paths to mylar
    if hasattr(sys, 'frozen'):
        mylar.FULL_PATH = os.path.abspath(sys.executable)
    else:
        mylar.FULL_PATH = os.path.abspath(__file__)

    mylar.PROG_DIR = os.path.dirname(mylar.FULL_PATH)
    mylar.ARGS = sys.argv[1:]

    # From sickbeard
    mylar.SYS_ENCODING = None

    try:
        locale.setlocale(locale.LC_ALL, "")
        mylar.SYS_ENCODING = locale.getpreferredencoding()
    except (locale.Error, IOError):
        pass

    # for OSes that are poorly configured I'll just force UTF-8
    if not mylar.SYS_ENCODING or mylar.SYS_ENCODING in ('ANSI_X3.4-1968',
                                                        'US-ASCII', 'ASCII'):
        mylar.SYS_ENCODING = 'UTF-8'

    # Set up and gather command line arguments
    parser = argparse.ArgumentParser(
        description='Comic Book add-on for SABnzbd+')

    parser.add_argument('-v',
                        '--verbose',
                        action='store_true',
                        help='Increase console logging verbosity')
    parser.add_argument('-q',
                        '--quiet',
                        action='store_true',
                        help='Turn off console logging')
    parser.add_argument('-d',
                        '--daemon',
                        action='store_true',
                        help='Run as a daemon')
    parser.add_argument('-p',
                        '--port',
                        type=int,
                        help='Force mylar to run on a specified port')
    parser.add_argument(
        '--datadir', help='Specify a directory where to store your data files')
    parser.add_argument('--config', help='Specify a config file to use')
    parser.add_argument('--nolaunch',
                        action='store_true',
                        help='Prevent browser from launching on startup')
    parser.add_argument(
        '--pidfile',
        help='Create a pid file (only relevant when running as a daemon)')

    args = parser.parse_args()

    if args.verbose:
        mylar.VERBOSE = 2
    elif args.quiet:
        mylar.VERBOSE = 0

    if args.daemon:
        mylar.DAEMON = True
        mylar.VERBOSE = 0
        if args.pidfile:
            mylar.PIDFILE = args.pidfile

    if args.datadir:
        mylar.DATA_DIR = args.datadir
    else:
        mylar.DATA_DIR = mylar.PROG_DIR

    if args.config:
        mylar.CONFIG_FILE = args.config
    else:
        mylar.CONFIG_FILE = os.path.join(mylar.DATA_DIR, 'config.ini')

    # Try to create the DATA_DIR if it doesn't exist
    #if not os.path.exists(mylar.DATA_DIR):
    #    try:
    #        os.makedirs(mylar.DATA_DIR)
    #    except OSError:
    #        raise SystemExit('Could not create data directory: ' + mylar.DATA_DIR + '. Exiting....')

    filechecker.validateAndCreateDirectory(mylar.DATA_DIR, True)

    # Make sure the DATA_DIR is writeable
    if not os.access(mylar.DATA_DIR, os.W_OK):
        raise SystemExit('Cannot write to the data directory: ' +
                         mylar.DATA_DIR + '. Exiting...')

    # Put the database in the DATA_DIR
    mylar.DB_FILE = os.path.join(mylar.DATA_DIR, 'mylar.db')

    mylar.CFG = ConfigObj(mylar.CONFIG_FILE, encoding='utf-8')

    # Read config & start logging
    mylar.initialize()

    if mylar.DAEMON:
        mylar.daemonize()

    # Force the http port if neccessary
    if args.port:
        http_port = args.port
        logger.info('Starting Mylar on foced port: %i' % http_port)
    else:
        http_port = int(mylar.HTTP_PORT)

    # Try to start the server.
    webstart.initialize({
        'http_port': http_port,
        'http_host': mylar.HTTP_HOST,
        'http_root': mylar.HTTP_ROOT,
        'http_username': mylar.HTTP_USERNAME,
        'http_password': mylar.HTTP_PASSWORD,
    })

    logger.info('Starting Mylar on port: %i' % http_port)

    if mylar.LAUNCH_BROWSER and not args.nolaunch:
        mylar.launch_browser(mylar.HTTP_HOST, http_port, mylar.HTTP_ROOT)

    # Start the background threads
    mylar.start()

    while True:
        if not mylar.SIGNAL:
            time.sleep(1)
        else:
            logger.info('Received signal: ' + mylar.SIGNAL)
            if mylar.SIGNAL == 'shutdown':
                mylar.shutdown()
            elif mylar.SIGNAL == 'restart':
                mylar.shutdown(restart=True)
            else:
                mylar.shutdown(restart=True, update=True)

            mylar.SIGNAL = None

    return
Esempio n. 6
0
    filechecker.validateAndCreateDirectory(mylar.DATA_DIR, True)
    
    # Make sure the DATA_DIR is writeable
    if not os.access(mylar.DATA_DIR, os.W_OK):
        raise SystemExit('Cannot write to the data directory: ' + mylar.DATA_DIR + '. Exiting...')
    
    # Put the database in the DATA_DIR
    mylar.DB_FILE = os.path.join(mylar.DATA_DIR, 'mylar.db')
    
    mylar.CFG = ConfigObj(mylar.CONFIG_FILE, encoding='utf-8')

    # Rename the main thread
    threading.currentThread().name = "MAIN"
    
    # Read config & start logging
    mylar.initialize()
        
    if mylar.DAEMON:
        mylar.daemonize()

    # Force the http port if neccessary
    if args.port:
        http_port = args.port
        logger.info('Starting Mylar on foced port: %i' % http_port)
    else:
        http_port = int(mylar.HTTP_PORT)
        
    # Try to start the server. 
    webstart.initialize({
                    'http_port':        http_port,
                    'http_host':        mylar.HTTP_HOST,
Esempio n. 7
0
def main():

    # Fixed paths to mylar
    if hasattr(sys, 'frozen'):
        mylar.FULL_PATH = os.path.abspath(sys.executable)
    else:
        mylar.FULL_PATH = os.path.abspath(__file__)

    mylar.PROG_DIR = os.path.dirname(mylar.FULL_PATH)
    mylar.ARGS = sys.argv[1:]

    # From sickbeard
    mylar.SYS_ENCODING = None

    try:
        locale.setlocale(locale.LC_ALL, "")
        mylar.SYS_ENCODING = locale.getpreferredencoding()
    except (locale.Error, IOError):
        pass

    # for OSes that are poorly configured I'll just force UTF-8
    if not mylar.SYS_ENCODING or mylar.SYS_ENCODING in ('ANSI_X3.4-1968',
                                                        'US-ASCII', 'ASCII'):
        mylar.SYS_ENCODING = 'UTF-8'

    if not logger.LOG_LANG.startswith('en'):
        print(
            'language detected as non-English (%s). Forcing specific logging module - errors WILL NOT be captured in the logs'
            % logger.LOG_LANG)
    else:
        print('log language set to %s' % logger.LOG_LANG)

    # Set up and gather command line arguments
    parser = argparse.ArgumentParser(
        description='Automated Comic Book Downloader')
    subparsers = parser.add_subparsers(title='Subcommands', dest='maintenance')
    parser_maintenance = subparsers.add_parser(
        'maintenance',
        help=
        'Enter maintenance mode (no GUI). Additional commands are available (maintenance --help)'
    )

    #main parser
    parser.add_argument('-v',
                        '--verbose',
                        action='store_true',
                        help='Increase console logging verbosity')
    parser.add_argument('-q',
                        '--quiet',
                        action='store_true',
                        help='Turn off console logging')
    parser.add_argument('-d',
                        '--daemon',
                        action='store_true',
                        help='Run as a daemon')
    parser.add_argument('-p',
                        '--port',
                        type=int,
                        help='Force mylar to run on a specified port')
    parser.add_argument(
        '-b',
        '--backup',
        action='store_true',
        help=
        'Will automatically backup & keep the last 2 copies of the .db & ini files prior to startup'
    )
    parser.add_argument(
        '-w',
        '--noweekly',
        action='store_true',
        help=
        'Turn off weekly pull list check on startup (quicker boot sequence)')
    parser.add_argument(
        '--datadir', help='Specify a directory where to store your data files')
    parser.add_argument('--config', help='Specify a config file to use')
    parser.add_argument('--nolaunch',
                        action='store_true',
                        help='Prevent browser from launching on startup')
    parser.add_argument(
        '--pidfile',
        help='Create a pid file (only relevant when running as a daemon)')
    parser.add_argument(
        '--safe',
        action='store_true',
        help=
        'redirect the startup page to point to the Manage Comics screen on startup'
    )
    parser_maintenance.add_argument(
        '-xj',
        '--exportjson',
        action='store',
        help='Export existing mylar.db to json file')
    parser_maintenance.add_argument('-id',
                                    '--importdatabase',
                                    action='store',
                                    help='Import a mylar.db into current db')
    parser_maintenance.add_argument(
        '-ij',
        '--importjson',
        action='store',
        help=
        'Import a specified json file containing just {"ComicID": "XXXXX"} into current db'
    )
    parser_maintenance.add_argument('-st',
                                    '--importstatus',
                                    action='store_true',
                                    help='Provide current maintenance status')
    parser_maintenance.add_argument(
        '-u',
        '--update',
        action='store_true',
        help='force mylar to perform an update as if in GUI')
    parser_maintenance.add_argument(
        '-fs',
        '--fixslashes',
        action='store_true',
        help='remove double-slashes from within paths in db')
    #parser_maintenance.add_argument('-it', '--importtext', action='store', help='Import a specified text file into current db')

    args = parser.parse_args()

    if args.maintenance:
        if all([
                args.exportjson is None, args.importdatabase is None,
                args.importjson is None, args.importstatus is False,
                args.update is False, args.fixslashes is False
        ]):
            print(
                'Expecting subcommand with the maintenance positional argumeent'
            )
            sys.exit()
        mylar.MAINTENANCE = True
    else:
        mylar.MAINTENANCE = False

    if args.verbose:
        print('Verbose/Debugging mode enabled...')
        mylar.LOG_LEVEL = 2
    elif args.quiet:
        mylar.QUIET = True
        print('Quiet logging mode enabled...')
        mylar.LOG_LEVEL = 0
    else:
        mylar.LOG_LEVEL = 1

    if args.daemon:
        if sys.platform == 'win32':
            print("Daemonize not supported under Windows, starting normally")
        else:
            mylar.DAEMON = True

    if args.pidfile:
        mylar.PIDFILE = str(args.pidfile)

        # If the pidfile already exists, mylar may still be running, so exit
        if os.path.exists(mylar.PIDFILE):
            sys.exit("PID file '" + mylar.PIDFILE +
                     "' already exists. Exiting.")

        # The pidfile is only useful in daemon mode, make sure we can write the file properly
        if mylar.DAEMON:
            mylar.CREATEPID = True
            try:
                open(mylar.PIDFILE, 'w').write("pid\n")
            except IOError as e:
                raise SystemExit("Unable to write PID file: %s [%d]" %
                                 (e.strerror, e.errno))
        else:
            print("Not running in daemon mode. PID file creation disabled.")

    if args.datadir:
        mylar.DATA_DIR = args.datadir
    else:
        mylar.DATA_DIR = mylar.PROG_DIR

    if args.config:
        mylar.CONFIG_FILE = args.config
    else:
        mylar.CONFIG_FILE = os.path.join(mylar.DATA_DIR, 'config.ini')

    if args.safe:
        mylar.SAFESTART = True
    else:
        mylar.SAFESTART = False

    if args.noweekly:
        mylar.NOWEEKLY = True
    else:
        mylar.NOWEEKLY = False

    # Put the database in the DATA_DIR
    mylar.DB_FILE = os.path.join(mylar.DATA_DIR, 'mylar.db')

    # Read config and start logging
    if mylar.MAINTENANCE is False:
        print('Initializing startup sequence....')

    #try:
    mylar.initialize(mylar.CONFIG_FILE)
    #except Exception as e:
    #    print e
    #    raise SystemExit('FATAL ERROR')

    if mylar.MAINTENANCE is False:
        filechecker.validateAndCreateDirectory(mylar.DATA_DIR, True)

        # Make sure the DATA_DIR is writeable
        if not os.access(mylar.DATA_DIR, os.W_OK):
            raise SystemExit('Cannot write to the data directory: ' +
                             mylar.DATA_DIR + '. Exiting...')

    # backup the db and configs before they load.
    if args.backup:
        print('[AUTO-BACKUP] Backing up .db and config.ini files for safety.')
        backupdir = os.path.join(mylar.DATA_DIR, 'backup')

        try:
            os.makedirs(backupdir)
            print(
                '[AUTO-BACKUP] Directory does not exist for backup - creating : '
                + backupdir)
        except OSError as exception:
            if exception.errno != errno.EEXIST:
                print('[AUTO-BACKUP] Directory already exists.')
                raise

        i = 0
        while (i < 2):
            if i == 0:
                ogfile = mylar.DB_FILE
                back = os.path.join(backupdir, 'mylar.db')
                back_1 = os.path.join(backupdir, 'mylar.db.1')
            else:
                ogfile = mylar.CONFIG_FILE
                back = os.path.join(backupdir, 'config.ini')
                back_1 = os.path.join(backupdir, 'config.ini.1')

            try:
                print('[AUTO-BACKUP] Now Backing up mylar.db file')
                if os.path.isfile(back_1):
                    print('[AUTO-BACKUP] ' + back_1 +
                          ' exists. Deleting and keeping new.')
                    os.remove(back_1)
                if os.path.isfile(back):
                    print('[AUTO-BACKUP] Now renaming ' + back + ' to ' +
                          back_1)
                    shutil.move(back, back_1)
                print('[AUTO-BACKUP] Now copying db file to ' + back)
                shutil.copy(ogfile, back)

            except OSError as exception:
                if exception.errno != errno.EXIST:
                    raise

            i += 1

    # Rename the main thread
    threading.currentThread().name = "MAIN"

    if mylar.DAEMON:
        mylar.daemonize()

    if mylar.MAINTENANCE is True and any([
            args.exportjson, args.importjson, args.update is True,
            args.importstatus is True, args.fixslashes is True
    ]):
        loggermode = '[MAINTENANCE-MODE]'
        if args.importstatus:  #mylar.MAINTENANCE is True:
            cs = maintenance.Maintenance('status')
            cstat = cs.check_status()
        else:
            logger.info('%s Initializing maintenance mode' % loggermode)

            if args.update is True:
                logger.info(
                    '%s Attempting to update Mylar so things can work again...'
                    % loggermode)
                try:
                    mylar.shutdown(restart=True, update=True, maintenance=True)
                except Exception as e:
                    sys.exit('%s Mylar failed to update: %s' % (loggermode, e))

            elif args.importdatabase:
                #for attempted db import.
                maintenance_path = args.importdatabase
                logger.info('%s db path accepted as %s' %
                            (loggermode, maintenance_path))
                di = maintenance.Maintenance('database-import',
                                             file=maintenance_path)
                d = di.database_import()
            elif args.importjson:
                #for attempted file re-import (json format)
                maintenance_path = args.importjson
                logger.info(
                    '%s file indicated as being in json format - path accepted as %s'
                    % (loggermode, maintenance_path))
                ij = maintenance.Maintenance('json-import',
                                             file=maintenance_path)
                j = ij.json_import()
            #elif args.importtext:
            #    #for attempted file re-import (list format)
            #    maintenance_path = args.importtext
            #    logger.info('%s file indicated as being in list format - path accepted as %s' % (loggermode, maintenance_path))
            #    it = maintenance.Maintenance('list-import', file=maintenance_path)
            #    t = it.list_import()
            elif args.exportjson:
                #for export of db comicid's in json format
                maintenance_path = args.exportjson
                logger.info(
                    '%s file indicated as being written to json format - destination accepted as %s'
                    % (loggermode, maintenance_path))
                ej = maintenance.Maintenance('json-export',
                                             output=maintenance_path)
                j = ej.json_export()
            elif args.fixslashes:
                #for running the fix slashes on the db manually
                logger.info('%s method indicated as fix slashes' % loggermode)
                fs = maintenance.Maintenance('fixslashes')
                j = fs.fix_slashes()
            else:
                logger.info('%s Not a valid command: %s' %
                            (loggermode, maintenance_info))
                sys.exit()
            logger.info('%s Exiting Maintenance mode' % (loggermode))

        #possible option to restart automatically after maintenance has completed...
        sys.exit()

    # Force the http port if neccessary
    if args.port:
        http_port = args.port
        logger.info('Starting Mylar on forced port: %i' % http_port)
    else:
        http_port = int(mylar.CONFIG.HTTP_PORT)

    # Check if pyOpenSSL is installed. It is required for certificate generation
    # and for cherrypy.
    if mylar.CONFIG.ENABLE_HTTPS:
        try:
            import OpenSSL
        except ImportError:
            logger.warn("The pyOpenSSL module is missing. Install this " \
                "module to enable HTTPS. HTTPS will be disabled.")
            mylar.CONFIG.ENABLE_HTTPS = False

    # Try to start the server. Will exit here is address is already in use.
    web_config = {
        'http_port': http_port,
        'http_host': mylar.CONFIG.HTTP_HOST,
        'http_root': mylar.CONFIG.HTTP_ROOT,
        'enable_https': mylar.CONFIG.ENABLE_HTTPS,
        'https_cert': mylar.CONFIG.HTTPS_CERT,
        'https_key': mylar.CONFIG.HTTPS_KEY,
        'https_chain': mylar.CONFIG.HTTPS_CHAIN,
        'http_username': mylar.CONFIG.HTTP_USERNAME,
        'http_password': mylar.CONFIG.HTTP_PASSWORD,
        'authentication': mylar.CONFIG.AUTHENTICATION,
        'login_timeout': mylar.CONFIG.LOGIN_TIMEOUT,
        'opds_enable': mylar.CONFIG.OPDS_ENABLE,
        'opds_authentication': mylar.CONFIG.OPDS_AUTHENTICATION,
        'opds_username': mylar.CONFIG.OPDS_USERNAME,
        'opds_password': mylar.CONFIG.OPDS_PASSWORD,
        'opds_pagesize': mylar.CONFIG.OPDS_PAGESIZE,
    }

    # Try to start the server.
    webstart.initialize(web_config)

    #check for version here after web server initialized so it doesn't try to repeatidly hit github
    #for version info if it's already running
    versioncheck.versionload()

    if mylar.CONFIG.LAUNCH_BROWSER and not args.nolaunch:
        mylar.launch_browser(mylar.CONFIG.HTTP_HOST, http_port,
                             mylar.CONFIG.HTTP_ROOT)

    # Start the background threads
    mylar.start()

    signal.signal(signal.SIGTERM, handler_sigterm)

    while True:
        if not mylar.SIGNAL:
            try:
                time.sleep(1)
            except KeyboardInterrupt:
                mylar.SIGNAL = 'shutdown'
        else:
            logger.info('Received signal: ' + mylar.SIGNAL)
            if mylar.SIGNAL == 'shutdown':
                mylar.shutdown()
            elif mylar.SIGNAL == 'restart':
                mylar.shutdown(restart=True)
            else:
                mylar.shutdown(restart=True, update=True)

            mylar.SIGNAL = None

    return
Esempio n. 8
0
def main():

    # Fixed paths to mylar
    if hasattr(sys, 'frozen'):
        mylar.FULL_PATH = os.path.abspath(sys.executable)
    else:
        mylar.FULL_PATH = os.path.abspath(__file__)

    mylar.PROG_DIR = os.path.dirname(mylar.FULL_PATH)
    mylar.ARGS = sys.argv[1:]

    # From sickbeard
    mylar.SYS_ENCODING = None

    try:
        locale.setlocale(locale.LC_ALL, "")
        mylar.SYS_ENCODING = locale.getpreferredencoding()
    except (locale.Error, IOError):
        pass

    # for OSes that are poorly configured I'll just force UTF-8
    if not mylar.SYS_ENCODING or mylar.SYS_ENCODING in ('ANSI_X3.4-1968',
                                                        'US-ASCII', 'ASCII'):
        mylar.SYS_ENCODING = 'UTF-8'

    if not logger.LOG_LANG.startswith('en'):
        print(
            'language detected as non-English (%s). Forcing specific logging module - errors WILL NOT be captured in the logs'
            % logger.LOG_LANG)
    else:
        print('log language set to %s' % logger.LOG_LANG)

    # Set up and gather command line arguments
    parser = argparse.ArgumentParser(
        description='Automated Comic Book Downloader')
    subparsers = parser.add_subparsers(title='Subcommands', dest='maintenance')

    #main parser
    parser.add_argument('-v',
                        '--verbose',
                        action='store_true',
                        default=False,
                        help='Increase console logging verbosity')
    parser.add_argument('-q',
                        '--quiet',
                        action='store_true',
                        default=False,
                        help='Turn off console logging')
    parser.add_argument('-d',
                        '--daemon',
                        action='store_true',
                        default=False,
                        help='Run as a daemon')
    parser.add_argument('-p',
                        '--port',
                        type=int,
                        default=0,
                        help='Force mylar to run on a specified port')
    parser.add_argument(
        '-b',
        '--backup',
        nargs='?',
        const='both',
        help='Will automatically backup & keep the last 4 rolling copies.')
    parser.add_argument(
        '-w',
        '--noweekly',
        action='store_true',
        default=False,
        help=
        'Turn off weekly pull list check on startup (quicker boot sequence)')
    parser.add_argument(
        '-iu',
        '--ignoreupdate',
        action='store_true',
        default=False,
        help='Do not update db if required (for problem bypass)')
    parser.add_argument(
        '--datadir',
        default=None,
        help='Specify a directory where to store your data files')
    parser.add_argument('--config',
                        default=None,
                        help='Specify a config file to use')
    parser.add_argument('--nolaunch',
                        action='store_true',
                        default=False,
                        help='Prevent browser from launching on startup')
    parser.add_argument(
        '--pidfile',
        default=None,
        help='Create a pid file (only relevant when running as a daemon)')
    parser.add_argument(
        '--safe',
        action='store_true',
        default=False,
        help=
        'redirect the startup page to point to the Manage Comics screen on startup'
    )

    parser_maintenance = subparsers.add_parser(
        'maintenance',
        help=
        'Enter maintenance mode (no GUI). Additional commands are available (maintenance --help)'
    )
    parser_maintenance.add_argument(
        '-xj',
        '--exportjson',
        default=None,
        action='store',
        help='Export existing mylar.db to json file'
    )  #, default=argparse.SUPPRESS)
    parser_maintenance.add_argument('-id',
                                    '--importdatabase',
                                    default=None,
                                    action='store',
                                    help='Import a mylar.db into current db'
                                    )  # , default=argparse.SUPPRESS)
    parser_maintenance.add_argument(
        '-ij',
        '--importjson',
        default=None,
        action='store',
        help=
        'Import a specified json file containing just {"ComicID": "XXXXX"} into current db'
    )  #, default=argparse.SUPPRESS)
    parser_maintenance.add_argument('-st',
                                    '--importstatus',
                                    default=False,
                                    action='store_true',
                                    help='Provide current maintenance status'
                                    )  #, default=argparse.SUPPRESS)
    parser_maintenance.add_argument(
        '-u',
        '--update',
        default=False,
        action='store_true',
        help='force mylar to perform an update as if in GUI'
    )  #, default=argparse.SUPPRESS)
    parser_maintenance.add_argument(
        '-fs',
        '--fixslashes',
        default=False,
        action='store_true',
        help='remove double-slashes from within paths in db'
    )  #, default=argparse.SUPPRESS)
    parser_maintenance.add_argument(
        '-cp',
        '--clearprovidertable',
        default=False,
        action='store_true',
        help='clear out the provider_searches table in db'
    )  #, default=argparse.SUPPRESS)
    #parser_maintenance.add_argument('-it', '--importtext', action='store', help='Import a specified text file into current db')

    args = vars(parser.parse_args())

    #these need to be set for things to register
    args_exportjson = args.get('exportjson')
    args_importdatabase = args.get('importdatabase')
    args_importjson = args.get('importjson')
    args_importstatus = args.get('importstatus')
    args_update = args.get('update')
    args_fixslashes = args.get('fixslashes')
    args_clearprovidertable = args.get('clearprovidertable')
    args_maintenance = args.get('maintenance')
    args_verbose = args.get('verbose')
    args_quiet = args.get('quiet')
    args_ignoreupdate = args.get('ignoreupdate')
    args_daemon = args.get('daemon')
    args_pidfile = args.get('pidfile')
    args_datadir = args.get('datadir')
    args_config = args.get('config')
    args_safe = args.get('safe')
    args_noweekly = args.get('noweekly')
    args_port = args.get('port')
    args_nolaunch = args.get('nolaunch')
    args_backup = args.get('backup')
    if not any(
        [args_backup == 'ini', args_backup == 'db', args_backup == 'both']):
        args_backup = False

    if args_maintenance:
        if all([
                args_exportjson is None, args_importdatabase is None,
                args_importjson is None, args_importstatus is False,
                args_update is False, args_fixslashes is False,
                args_clearprovidertable is False
        ]):
            print(
                'Expecting subcommand with the maintenance positional argumeent'
            )
            sys.exit()
        mylar.MAINTENANCE = True
    else:
        mylar.MAINTENANCE = False

    if args_verbose:
        print('Verbose/Debugging mode enabled...')
        mylar.LOG_LEVEL = 2
    elif args_quiet:
        mylar.QUIET = True
        print('Quiet logging mode enabled...')
        mylar.LOG_LEVEL = 0
    else:
        mylar.LOG_LEVEL = None

    if args_ignoreupdate:
        mylar.MAINTENANCE = False

    if args_daemon:
        if sys.platform == 'win32':
            print("Daemonize not supported under Windows, starting normally")
        else:
            mylar.DAEMON = True

    if args_pidfile:
        mylar.PIDFILE = str(args_pidfile)

        # If the pidfile already exists, mylar may still be running, so exit
        if os.path.exists(mylar.PIDFILE):
            if check_stale_pidfile(mylar.PIDFILE):
                os.unlink(mylar.PIDFILE)
            else:
                sys.exit("PID file '" + mylar.PIDFILE +
                         "' already exists. Exiting.")

        # The pidfile is only useful in daemon mode, make sure we can write the file properly
        if mylar.DAEMON:
            mylar.CREATEPID = True
            curpid = os.getpid()
            try:
                open(mylar.PIDFILE, 'w').write(f"{curpid}\n")
            except IOError as e:
                raise SystemExit("Unable to write PID file: %s [%d]" %
                                 (e.strerror, e.errno))
        else:
            print("Not running in daemon mode. PID file creation disabled.")

    if args_datadir:
        mylar.DATA_DIR = args_datadir
    else:
        mylar.DATA_DIR = mylar.PROG_DIR

    if args_config:
        mylar.CONFIG_FILE = args_config
    else:
        mylar.CONFIG_FILE = os.path.join(mylar.DATA_DIR, 'config.ini')

    if args_safe:
        mylar.SAFESTART = True
    else:
        mylar.SAFESTART = False

    if args_noweekly:
        mylar.NOWEEKLY = True
    else:
        mylar.NOWEEKLY = False

    try:
        backup = False
        backup_db = False
        backup_cfg = False
        if args_backup:
            backup = True
            if args_backup == 'ini':
                backup_cfg = True
            elif args_backup == 'db':
                backup_db = True
            elif args_backup == 'both':
                backup_cfg = True
                backup_db = True
            else:
                backup = False
    except Exception as e:
        backup = False

    # Put the database in the DATA_DIR
    mylar.DB_FILE = os.path.join(mylar.DATA_DIR, 'mylar.db')

    # Read config and start logging
    if mylar.MAINTENANCE is False:
        print('Initializing startup sequence....')

    #try:
    mylar.initialize(mylar.CONFIG_FILE)
    #except Exception as e:
    #    print e
    #    raise SystemExit('FATAL ERROR')

    # check for clearprovidertable value after ini load
    if mylar.CONFIG.CLEAR_PROVIDER_TABLE is True:
        logger.info(
            '[CLEAR_PROVIDER_TABLE] forcing over-ride value from config.ini')
        args_clearprovidertable = True
        mylar.MAINTENANCE = True

    if mylar.MAINTENANCE is False:
        filechecker.validateAndCreateDirectory(mylar.DATA_DIR,
                                               True,
                                               dmode='DATA')

        # Make sure the DATA_DIR is writeable
        if not os.access(mylar.DATA_DIR, os.W_OK):
            raise SystemExit('Cannot write to the data directory: ' +
                             mylar.DATA_DIR + '. Exiting...')

    # backup the db and configs before they load.
    if (backup is True and any([backup_cfg is True, backup_db is True
                                ])) or mylar.CONFIG.BACKUP_ON_START:
        if mylar.CONFIG.BACKUP_ON_START:
            backup_cfg = True
            backup_db = True
        if mylar.CONFIG.BACKUP_ON_START or all(
            [backup_cfg is True, backup_db is True]):
            logger.info(
                '[AUTO-BACKUP] Backing up mylar.db & config.ini files for safety.'
            )
        elif backup_cfg is True:
            logger.info('[AUTO-BACKUP] Backing up config.ini file for safety.')
        elif backup_db is True:
            logger.info('[AUTO-BACKUP] Backing up mylar.db file for safety.')

        mm = maintenance.Maintenance('backup')
        back_check = mm.backup_files(cfg=backup_cfg, dbs=backup_db)
        failures = [
            re.sub('mylar database', 'mylar.db', x['file']) for x in back_check
            if x['status'] == 'failure'
        ]
        successes = [
            re.sub('mylar database', 'mylar.db', x['file']) for x in back_check
            if x['status'] == 'success'
        ]
        if failures:
            logger.warn('[AUTO-BACKUP] Failure backing up %s files [%s]' %
                        (len(failures), failures))
        if successes:
            logger.info('[AUTO-BACKUP] Successful backup of %s files [%s]' %
                        (len(successes), successes))

    # Rename the main thread
    threading.current_thread().name = "MAIN"

    if mylar.DAEMON:
        mylar.daemonize()

    #print('mylar.MAINTENANCE: %s'%  mylar.MAINTENANCE)
    #print('mylar.MAINTENANCE_TOTAL: %s'%  mylar.MAINTENANCE_DB_TOTAL)
    if mylar.MAINTENANCE is True and (mylar.MAINTENANCE_UPDATE or any([
            args_exportjson, args_importjson, args_update is True,
            args_importstatus is True, args_fixslashes is True,
            args_clearprovidertable is True
    ])):
        # Start up a temporary maintenance server for GUI display only.
        maint_config = {
            'http_port': int(mylar.CONFIG.HTTP_PORT),
            'http_host': mylar.CONFIG.HTTP_HOST,
            'http_root': mylar.CONFIG.HTTP_ROOT,
            'enable_https': mylar.CONFIG.ENABLE_HTTPS,
            'https_cert': mylar.CONFIG.HTTPS_CERT,
            'https_key': mylar.CONFIG.HTTPS_KEY,
            'https_chain': mylar.CONFIG.HTTPS_CHAIN,
            'http_username': mylar.CONFIG.HTTP_USERNAME,
            'http_password': mylar.CONFIG.HTTP_PASSWORD,
            'authentication': mylar.CONFIG.AUTHENTICATION,
            'login_timeout': mylar.CONFIG.LOGIN_TIMEOUT
        }

        # Try to start the server.
        maintenance_webstart.initialize(maint_config)
        versioncheck.versionload()
        print("started")
        loggermode = '[MAINTENANCE-MODE]'

        restart_method = True  #True will restart, False will shutdown.

        if mylar.MAINTENANCE_UPDATE:
            ur = maintenance.Maintenance('db update')
            restart_method = ur.update_db()
            if restart_method is None:
                restart_method = True

        elif args_importstatus:
            cs = maintenance.Maintenance('status')
            cstat = cs.check_status()
        else:
            logger.info('%s Initializing maintenance mode' % loggermode)

            if args_update is True:
                logger.info(
                    '%s Attempting to update Mylar so things can work again...'
                    % loggermode)
                try:
                    mylar.shutdown(restart=True, update=True, maintenance=True)
                except Exception as e:
                    sys.exit('%s Mylar failed to update: %s' % (loggermode, e))

            elif args_importdatabase:
                #for attempted db import.
                maintenance_path = args_importdatabase
                logger.info('%s db path accepted as %s' %
                            (loggermode, maintenance_path))
                di = maintenance.Maintenance('database-import',
                                             file=maintenance_path)
                d = di.database_import()
            elif args_importjson:
                #for attempted file re-import (json format)
                maintenance_path = args_importjson
                logger.info(
                    '%s file indicated as being in json format - path accepted as %s'
                    % (loggermode, maintenance_path))
                ij = maintenance.Maintenance('json-import',
                                             file=maintenance_path)
                j = ij.json_import()
            #elif args_importtext:
            #    #for attempted file re-import (list format)
            #    maintenance_path = args_importtext
            #    logger.info('%s file indicated as being in list format - path accepted as %s' % (loggermode, maintenance_path))
            #    it = maintenance.Maintenance('list-import', file=maintenance_path)
            #    t = it.list_import()
            elif args_exportjson:
                #for export of db comicid's in json format
                maintenance_path = args_exportjson
                logger.info(
                    '%s file indicated as being written to json format - destination accepted as %s'
                    % (loggermode, maintenance_path))
                ej = maintenance.Maintenance('json-export',
                                             output=maintenance_path)
                j = ej.json_export()
            elif args_fixslashes:
                #for running the fix slashes on the db manually
                logger.info('%s method indicated as fix slashes' % loggermode)
                fs = maintenance.Maintenance('fixslashes')
                j = fs.fix_slashes()
            elif args_clearprovidertable:
                #for running the clearprovidertable on the db manually
                logger.info('%s method indicated as fix clearprovidertable' %
                            loggermode)
                fs = maintenance.Maintenance('clearprovidertable')
                j = fs.clear_provider_table()
            else:
                logger.info('%s Not a valid command: %s' %
                            (loggermode, args_maintenance))
                sys.exit()
            logger.info('%s Exiting Maintenance mode' % (loggermode))

        #restart automatically after maintenance has completed...

        maintenance_webstart.shutdown()
        logger.info('%s Maintenance webserver has been shut down.' %
                    (loggermode))
        mylar.shutdown(restart=restart_method, maintenance=True)

    # Force the http port if neccessary
    if args_port > 0:
        http_port = args_port
        logger.info('Starting Mylar on forced port: %i' % http_port)
    else:
        http_port = int(mylar.CONFIG.HTTP_PORT)

    # Check if pyOpenSSL is installed. It is required for certificate generation
    # and for cherrypy.
    if mylar.CONFIG.ENABLE_HTTPS:
        try:
            import OpenSSL
        except ImportError:
            logger.warn("The pyOpenSSL module is missing. Install this " \
                "module to enable HTTPS. HTTPS will be disabled.")
            mylar.CONFIG.ENABLE_HTTPS = False

    # Try to start the server. Will exit here is address is already in use.
    web_config = {
        'http_port': http_port,
        'http_host': mylar.CONFIG.HTTP_HOST,
        'http_root': mylar.CONFIG.HTTP_ROOT,
        'enable_https': mylar.CONFIG.ENABLE_HTTPS,
        'https_cert': mylar.CONFIG.HTTPS_CERT,
        'https_key': mylar.CONFIG.HTTPS_KEY,
        'https_chain': mylar.CONFIG.HTTPS_CHAIN,
        'http_username': mylar.CONFIG.HTTP_USERNAME,
        'http_password': mylar.CONFIG.HTTP_PASSWORD,
        'authentication': mylar.CONFIG.AUTHENTICATION,
        'login_timeout': mylar.CONFIG.LOGIN_TIMEOUT,
        'cherrypy_logging': mylar.CONFIG.CHERRYPY_LOGGING,
        'opds_enable': mylar.CONFIG.OPDS_ENABLE,
        'opds_authentication': mylar.CONFIG.OPDS_AUTHENTICATION,
        'opds_username': mylar.CONFIG.OPDS_USERNAME,
        'opds_password': mylar.CONFIG.OPDS_PASSWORD,
        'opds_pagesize': mylar.CONFIG.OPDS_PAGESIZE,
    }

    # Try to start the server.
    webstart.initialize(web_config)

    #check for version here after web server initialized so it doesn't try to repeatidly hit github
    #for version info if it's already running
    versioncheck.versionload()

    if mylar.CONFIG.LAUNCH_BROWSER and not args_nolaunch:
        mylar.launch_browser(mylar.CONFIG.HTTP_HOST, http_port,
                             mylar.CONFIG.HTTP_ROOT)

    # Start the background threads
    mylar.start()

    signal.signal(signal.SIGTERM, handler_sigterm)

    while True:
        if not mylar.SIGNAL:
            try:
                time.sleep(1)
            except KeyboardInterrupt:
                mylar.GLOBAL_MESSAGES = {
                    'status': 'success',
                    'event': 'shutdown',
                    'message': 'Now shutting down system.'
                }
                time.sleep(1)
                mylar.SIGNAL = 'shutdown'
        else:
            logger.info('Received signal: ' + mylar.SIGNAL)
            if mylar.SIGNAL == 'shutdown':
                mylar.GLOBAL_MESSAGES = {
                    'status': 'success',
                    'event': 'shutdown',
                    'message': 'Now shutting down system.'
                }
                time.sleep(2)
                mylar.shutdown()
            elif mylar.SIGNAL == 'restart':
                mylar.shutdown(restart=True)
            else:
                mylar.shutdown(restart=True, update=True)

            mylar.SIGNAL = None

    return