Example #1
0
def main():
    board = np.reshape(np.array(list(map(lambda x: int(x), request.args.get('board').split(',')[:-1]))), (6, 7))
    algorithm = request.args.get('algorithm')
    difficulty = request.args.get('difficulty')

    turn = 1 if len(np.where(np.reshape(board, (42,)) != 0)[0]) % 2 == 0 else -1
    response = {}
    if len(np.where(np.reshape(board, (42,)) != 0)[0]) < 3:
        response['action'] = 3
        return response
    if algorithm == 'mcts':
        tree = mcts(board, turn, MCTS_DIFFICULTIES[difficulty])
        actions = get_action_space(board)
        np.random.shuffle(actions)
        next_idxs = [np.where(np.all(tree[:, :-2]==flatten(simulate_move(board.copy(), action, turn)),axis=1))[0][0] for action in actions]
        values = [tree[i, -2] for i in next_idxs]
        if turn == 1:
            best_action = actions[np.argmax(values)]
        else:
            best_action = actions[np.argmin(values)]
        response['action'] = int(best_action)
    elif algorithm == 'ab':
        _, action = alpha_beta(turn, board, 1, turn * np.inf, AB_DIFFICULTIES[difficulty])
        response['action'] = int(action)

    return jsonify(response)
Example #2
0
    def on_timeline(self, tweet, prefix):
        """
        Defines actions to take on a timeline tweet.

        tweet - a tweepy.Status object. You can access the text with
        tweet.text

        prefix - the @-mentions for this reply. No need to include this in the
        reply string; it's provided so you can use it to make sure the value
        you return is within the 140 character limit with this.

        It's up to you to ensure that the prefix and tweet are less than 140
        characters.

        When calling post_tweet, you MUST include reply_to=tweet, or
        Twitter won't count it as a reply.
        """

        photos = get_photos_from_tweet(tweet)

        face_regions = core.flatten(
            [self.face_regions(photo) for photo in photos])

        recognitions = []
        for region in face_regions:
            try:
                recognitions.append(
                    self.face_recognizer.recognize_face(region))
            except cv2.error as e:
                logging.error("Error recognizing face region: " + e.message)

        likely_recognitions = filter(
            lambda (_, margin): margin < self.get_confidence(),
            recognitions)

        recognized_labels = set([label for (label, _) in likely_recognitions])

        for label in recognized_labels:
            recognized = self.store.get_friend(label)
            # it's possible someone is in the model but not in the database,
            # e.g. people that asked to be forgotten
            if recognized and recognized.get('twitter_id', None):
                twitter_friend = self.api.get_user(recognized['twitter_id'])
                self.favorite_tweet(tweet)
                self.post_tweet(
                    prefix +
                    ' ' + compliments.get_compliment() + ' ' +
                    '@' + twitter_friend.screen_name,
                    reply_to=tweet)
def _expand_as(func, predicate_string, *namespaces):
    """Pre-parse predicate string and register meta function"""

    args, varargs, kw, defaults = arginfo = inspect.getargspec(func)
    argnames = list(flatten(filter(None, [args, varargs, kw])))
    parsed = parser.expr(predicate_string).totuple(1)[1]
    builder = CriteriaBuilder(
        dict([(arg,Local(arg)) for arg in argnames]), *namespaces
    )
    bindings = {}
    for b in builder.bindings[-len(namespaces):][::-1]:
        bindings.update(b)

    # Make a function that just gets the arguments we want
    c = Code.from_function(func)
    c.return_(Call(Const(locals),fold=False))
    getargs = new.function(
        c.code(), func.func_globals, func.func_name, func.func_defaults,
        func.func_closure
    )

    def expand(builder, *args):        
        builder.push(bindings)   # globals, locals, etc.
        builder.bind(apply_meta(builder, (getargs, {}, arginfo), *args))

        # build in the newly-isolated namespace
        result = build(builder, parsed) 
        builder.pop()
        return result

    meta_functions[func] = expand

    c = Code.from_function(func)
    c.return_()
    if func.func_code.co_code == c.code().co_code:  # function body is empty
        c = Code.from_function(func)
        c.return_(build(builder, parsed))
        func.func_code = c.code()

    return func
Example #4
0
def _expand_as(func, predicate_string, *namespaces):
    """Pre-parse predicate string and register meta function"""

    args, varargs, kw, defaults = arginfo = inspect.getargspec(func)
    argnames = list(flatten(filter(None, [args, varargs, kw])))
    parsed = parser.expr(predicate_string).totuple(1)[1]
    builder = CriteriaBuilder(dict([(arg, Local(arg)) for arg in argnames]),
                              *namespaces)
    bindings = {}
    for b in builder.bindings[-len(namespaces):][::-1]:
        bindings.update(b)

    # Make a function that just gets the arguments we want
    c = Code.from_function(func)
    c.return_(Call(Const(locals), fold=False))
    getargs = new.function(c.code(), func.func_globals, func.func_name,
                           func.func_defaults, func.func_closure)

    def expand(builder, *args):
        builder.push(bindings)  # globals, locals, etc.
        builder.bind(apply_meta(builder, (getargs, {}, arginfo), *args))

        # build in the newly-isolated namespace
        result = build(builder, parsed)
        builder.pop()
        return result

    meta_functions[func] = expand
    func.__doc__  # workaround for PyPy issue #1293
    c = Code.from_function(func)
    c.return_()
    if func.func_code.co_code == c.code().co_code:  # function body is empty
        c = Code.from_function(func)
        c.return_(build(builder, parsed))
        func.func_code = c.code()

    return func
Example #5
0
def process_torrent(input_directory, input_name, input_category, input_hash, input_id, client_agent):
    status = 1  # 1 = failed | 0 = success
    root = 0
    found_file = 0

    if client_agent != 'manual' and not core.DOWNLOADINFO:
        logger.debug('Adding TORRENT download info for directory {0} to database'.format(input_directory))

        my_db = main_db.DBConnection()

        input_directory1 = input_directory
        input_name1 = input_name

        try:
            encoded, input_directory1 = char_replace(input_directory)
            encoded, input_name1 = char_replace(input_name)
        except Exception:
            pass

        control_value_dict = {'input_directory': text_type(input_directory1)}
        new_value_dict = {
            'input_name': text_type(input_name1),
            'input_hash': text_type(input_hash),
            'input_id': text_type(input_id),
            'client_agent': text_type(client_agent),
            'status': 0,
            'last_update': datetime.date.today().toordinal(),
        }
        my_db.upsert('downloads', new_value_dict, control_value_dict)

    logger.debug('Received Directory: {0} | Name: {1} | Category: {2}'.format(input_directory, input_name, input_category))

    # Confirm the category by parsing directory structure
    input_directory, input_name, input_category, root = core.category_search(input_directory, input_name, input_category,
                                                                             root, core.CATEGORIES)
    if input_category == '':
        input_category = 'UNCAT'

    usercat = input_category
    try:
        input_name = input_name.encode(core.SYS_ENCODING)
    except UnicodeError:
        pass
    try:
        input_directory = input_directory.encode(core.SYS_ENCODING)
    except UnicodeError:
        pass

    logger.debug('Determined Directory: {0} | Name: {1} | Category: {2}'.format
                 (input_directory, input_name, input_category))

    # auto-detect section
    section = core.CFG.findsection(input_category).isenabled()
    if section is None:
        section = core.CFG.findsection('ALL').isenabled()
        if section is None:
            logger.error('Category:[{0}] is not defined or is not enabled. '
                         'Please rename it or ensure it is enabled for the appropriate section '
                         'in your autoProcessMedia.cfg and try again.'.format
                         (input_category))
            return [-1, '']
        else:
            usercat = 'ALL'

    if len(section) > 1:
        logger.error('Category:[{0}] is not unique, {1} are using it. '
                     'Please rename it or disable all other sections using the same category name '
                     'in your autoProcessMedia.cfg and try again.'.format
                     (usercat, section.keys()))
        return [-1, '']

    if section:
        section_name = section.keys()[0]
        logger.info('Auto-detected SECTION:{0}'.format(section_name))
    else:
        logger.error('Unable to locate a section with subsection:{0} '
                     'enabled in your autoProcessMedia.cfg, exiting!'.format
                     (input_category))
        return [-1, '']

    section = dict(section[section_name][usercat])  # Type cast to dict() to allow effective usage of .get()

    torrent_no_link = int(section.get('Torrent_NoLink', 0))
    keep_archive = int(section.get('keep_archive', 0))
    extract = int(section.get('extract', 0))
    extensions = section.get('user_script_mediaExtensions', '').lower().split(',')
    unique_path = int(section.get('unique_path', 1))

    if client_agent != 'manual':
        core.pause_torrent(client_agent, input_hash, input_id, input_name)

    # In case input is not directory, make sure to create one.
    # This way Processing is isolated.
    if not os.path.isdir(os.path.join(input_directory, input_name)):
        basename = os.path.basename(input_directory)
        basename = core.sanitize_name(input_name) \
            if input_name == basename else os.path.splitext(core.sanitize_name(input_name))[0]
        output_destination = os.path.join(core.OUTPUTDIRECTORY, input_category, basename)
    elif unique_path:
        output_destination = os.path.normpath(
            core.os.path.join(core.OUTPUTDIRECTORY, input_category, core.sanitize_name(input_name).replace(' ', '.')))
    else:
        output_destination = os.path.normpath(
            core.os.path.join(core.OUTPUTDIRECTORY, input_category))
    try:
        output_destination = output_destination.encode(core.SYS_ENCODING)
    except UnicodeError:
        pass

    if output_destination in input_directory:
        output_destination = input_directory

    logger.info('Output directory set to: {0}'.format(output_destination))

    if core.SAFE_MODE and output_destination == core.TORRENT_DEFAULTDIR:
        logger.error('The output directory:[{0}] is the Download Directory. '
                     'Edit outputDirectory in autoProcessMedia.cfg. Exiting'.format
                     (input_directory))
        return [-1, '']

    logger.debug('Scanning files in directory: {0}'.format(input_directory))

    if section_name in ['HeadPhones', 'Lidarr']:
        core.NOFLATTEN.extend(
            input_category)  # Make sure we preserve folder structure for HeadPhones.

    now = datetime.datetime.now()

    if extract == 1:
        input_files = core.list_media_files(input_directory, archives=False, other=True, otherext=extensions)
    else:
        input_files = core.list_media_files(input_directory, other=True, otherext=extensions)
    if len(input_files) == 0 and os.path.isfile(input_directory):
        input_files = [input_directory]
        logger.debug('Found 1 file to process: {0}'.format(input_directory))
    else:
        logger.debug('Found {0} files in {1}'.format(len(input_files), input_directory))
    for inputFile in input_files:
        file_path = os.path.dirname(inputFile)
        file_name, file_ext = os.path.splitext(os.path.basename(inputFile))
        full_file_name = os.path.basename(inputFile)

        target_file = core.os.path.join(output_destination, full_file_name)
        if input_category in core.NOFLATTEN:
            if not os.path.basename(file_path) in output_destination:
                target_file = core.os.path.join(
                    core.os.path.join(output_destination, os.path.basename(file_path)), full_file_name)
                logger.debug('Setting outputDestination to {0} to preserve folder structure'.format
                             (os.path.dirname(target_file)))
        try:
            target_file = target_file.encode(core.SYS_ENCODING)
        except UnicodeError:
            pass
        if root == 1:
            if not found_file:
                logger.debug('Looking for {0} in: {1}'.format(input_name, inputFile))
            if any([core.sanitize_name(input_name) in core.sanitize_name(inputFile),
                    core.sanitize_name(file_name) in core.sanitize_name(input_name)]):
                found_file = True
                logger.debug('Found file {0} that matches Torrent Name {1}'.format
                             (full_file_name, input_name))
            else:
                continue

        if root == 2:
            mtime_lapse = now - datetime.datetime.fromtimestamp(os.path.getmtime(inputFile))
            ctime_lapse = now - datetime.datetime.fromtimestamp(os.path.getctime(inputFile))

            if not found_file:
                logger.debug('Looking for files with modified/created dates less than 5 minutes old.')
            if (mtime_lapse < datetime.timedelta(minutes=5)) or (ctime_lapse < datetime.timedelta(minutes=5)):
                found_file = True
                logger.debug('Found file {0} with date modified/created less than 5 minutes ago.'.format
                             (full_file_name))
            else:
                continue  # This file has not been recently moved or created, skip it

        if torrent_no_link == 0:
            try:
                core.copy_link(inputFile, target_file, core.USELINK)
                core.remove_read_only(target_file)
            except Exception:
                logger.error('Failed to link: {0} to {1}'.format(inputFile, target_file))

    input_name, output_destination = convert_to_ascii(input_name, output_destination)

    if extract == 1:
        logger.debug('Checking for archives to extract in directory: {0}'.format(input_directory))
        core.extract_files(input_directory, output_destination, keep_archive)

    if input_category not in core.NOFLATTEN:
        # don't flatten hp in case multi cd albums, and we need to copy this back later.
        core.flatten(output_destination)

    # Now check if video files exist in destination:
    if section_name in ['SickBeard', 'NzbDrone', 'Sonarr', 'CouchPotato', 'Radarr']:
        num_videos = len(
            core.list_media_files(output_destination, media=True, audio=False, meta=False, archives=False))
        if num_videos > 0:
            logger.info('Found {0} media files in {1}'.format(num_videos, output_destination))
            status = 0
        elif extract != 1:
            logger.info('Found no media files in {0}. Sending to {1} to process'.format(output_destination, section_name))
            status = 0
        else:
            logger.warning('Found no media files in {0}'.format(output_destination))

    # Only these sections can handling failed downloads
    # so make sure everything else gets through without the check for failed
    if section_name not in ['CouchPotato', 'Radarr', 'SickBeard', 'NzbDrone', 'Sonarr']:
        status = 0

    logger.info('Calling {0}:{1} to post-process:{2}'.format(section_name, usercat, input_name))

    if core.TORRENT_CHMOD_DIRECTORY:
        core.rchmod(output_destination, core.TORRENT_CHMOD_DIRECTORY)

    result = ProcessResult(
        message='',
        status_code=0,
    )
    if section_name == 'UserScript':
        result = external_script(output_destination, input_name, input_category, section)
    elif section_name in ['CouchPotato', 'Radarr']:
        result = movies.process(section_name, output_destination, input_name, status, client_agent, input_hash, input_category)
    elif section_name in ['SickBeard', 'NzbDrone', 'Sonarr']:
        if input_hash:
            input_hash = input_hash.upper()
        result = tv.process(section_name, output_destination, input_name, status, client_agent, input_hash, input_category)
    elif section_name in ['HeadPhones', 'Lidarr']:
        result = music.process(section_name, output_destination, input_name, status, client_agent, input_category)
    elif section_name == 'Mylar':
        result = comics.process(section_name, output_destination, input_name, status, client_agent, input_category)
    elif section_name == 'Gamez':
        result = games.process(section_name, output_destination, input_name, status, client_agent, input_category)

    plex_update(input_category)

    if result.status_code != 0:
        if not core.TORRENT_RESUME_ON_FAILURE:
            logger.error('A problem was reported in the autoProcess* script. '
                         'Torrent won\'t resume seeding (settings)')
        elif client_agent != 'manual':
            logger.error('A problem was reported in the autoProcess* script. '
                         'If torrent was paused we will resume seeding')
            core.resume_torrent(client_agent, input_hash, input_id, input_name)

    else:
        if client_agent != 'manual':
            # update download status in our DB
            core.update_download_info_status(input_name, 1)

            # remove torrent
            if core.USELINK == 'move-sym' and not core.DELETE_ORIGINAL == 1:
                logger.debug('Checking for sym-links to re-direct in: {0}'.format(input_directory))
                for dirpath, dirs, files in os.walk(input_directory):
                    for file in files:
                        logger.debug('Checking symlink: {0}'.format(os.path.join(dirpath, file)))
                        replace_links(os.path.join(dirpath, file))
            core.remove_torrent(client_agent, input_hash, input_id, input_name)

        if not section_name == 'UserScript':
            # for user script, we assume this is cleaned by the script or option USER_SCRIPT_CLEAN
            # cleanup our processing folders of any misc unwanted files and empty directories
            core.clean_dir(output_destination, section_name, input_category)

    return result
Example #6
0
def processTorrent(inputDirectory, inputName, inputCategory, inputHash, inputID, clientAgent):
    status = 1  # 1 = failed | 0 = success
    root = 0
    foundFile = 0
    uniquePath = 1

    if clientAgent != 'manual' and not core.DOWNLOADINFO:
        logger.debug('Adding TORRENT download info for directory %s to database' % (inputDirectory))

        myDB = nzbToMediaDB.DBConnection()

        encoded, inputDirectory1 = CharReplace(inputDirectory)
        encoded, inputName1 = CharReplace(inputName)

        controlValueDict = {"input_directory": unicode(inputDirectory1)}
        newValueDict = {"input_name": unicode(inputName1),
                        "input_hash": unicode(inputHash),
                        "input_id": unicode(inputID),
                        "client_agent": unicode(clientAgent),
                        "status": 0,
                        "last_update": datetime.date.today().toordinal()
        }
        myDB.upsert("downloads", newValueDict, controlValueDict)

    logger.debug("Received Directory: %s | Name: %s | Category: %s" % (inputDirectory, inputName, inputCategory))

    inputDirectory, inputName, inputCategory, root = core.category_search(inputDirectory, inputName,
                                                                                        inputCategory, root,
                                                                                        core.CATEGORIES)  # Confirm the category by parsing directory structure 
    if inputCategory == "":
        inputCategory = "UNCAT"

    usercat = inputCategory
    try:
        inputName = inputName.encode(core.SYS_ENCODING)
    except: pass
    try:
        inputDirectory = inputDirectory.encode(core.SYS_ENCODING)
    except: pass

    logger.debug("Determined Directory: %s | Name: %s | Category: %s" % (inputDirectory, inputName, inputCategory))

    # auto-detect section
    section = core.CFG.findsection(inputCategory).isenabled()
    if section is None:
        section = core.CFG.findsection("ALL").isenabled()
        if section is None:
            logger.error(
                'Category:[%s] is not defined or is not enabled. Please rename it or ensure it is enabled for the appropriate section in your autoProcessMedia.cfg and try again.' % (
                    inputCategory))
            return [-1, ""]
        else:
            usercat = "ALL"

    if len(section) > 1:
        logger.error(
            'Category:[%s] is not unique, %s are using it. Please rename it or disable all other sections using the same category name in your autoProcessMedia.cfg and try again.' % (
                usercat, section.keys()))
        return [-1, ""]

    if section:
        sectionName = section.keys()[0]
        logger.info('Auto-detected SECTION:%s' % (sectionName))
    else:
        logger.error("Unable to locate a section with subsection:%s enabled in your autoProcessMedia.cfg, exiting!" % (
            inputCategory))
        return [-1, ""]

    try:
        Torrent_NoLink = int(section[usercat]["Torrent_NoLink"])
    except:
        Torrent_NoLink = 0

    try:
        extract = int(section[usercat]['extract'])
    except:
        extract = 0

    try:
        uniquePath = int(section[usercat]["unique_path"])
    except:
        uniquePath = 1

    if clientAgent != 'manual':
        core.pause_torrent(clientAgent, inputHash, inputID, inputName)

    # Incase input is not directory, make sure to create one.
    # This way Processing is isolated.
    if not os.path.isdir(os.path.join(inputDirectory, inputName)):
        basename = os.path.splitext(core.sanitizeName(inputName))[0]
        outputDestination = os.path.join(core.OUTPUTDIRECTORY, inputCategory, basename)
    elif uniquePath:
        outputDestination = os.path.normpath(
            core.os.path.join(core.OUTPUTDIRECTORY, inputCategory, core.sanitizeName(inputName)))
    else:
        outputDestination = os.path.normpath(
            core.os.path.join(core.OUTPUTDIRECTORY, inputCategory))
    try:
        outputDestination = outputDestination.encode(core.SYS_ENCODING)
    except: pass

    logger.info("Output directory set to: %s" % (outputDestination))

    if core.SAFE_MODE and outputDestination == core.TORRENT_DEFAULTDIR:
        logger.error(
            'The output directory:[%s] is the Download Directory. Edit outputDirectory in autoProcessMedia.cfg. Exiting' % (
            inputDirectory))
        return [-1, ""]

    logger.debug("Scanning files in directory: %s" % (inputDirectory))

    if sectionName == 'HeadPhones':
        core.NOFLATTEN.extend(
            inputCategory)  # Make sure we preserve folder structure for HeadPhones.

    now = datetime.datetime.now()

    inputFiles = core.listMediaFiles(inputDirectory)
    logger.debug("Found %s files in %s" % (str(len(inputFiles)), inputDirectory))
    for inputFile in inputFiles:
        filePath = os.path.dirname(inputFile)
        fileName, fileExt = os.path.splitext(os.path.basename(inputFile))
        fullFileName = os.path.basename(inputFile)

        targetFile = core.os.path.join(outputDestination, fullFileName)
        if inputCategory in core.NOFLATTEN:
            if not os.path.basename(filePath) in outputDestination:
                targetFile = core.os.path.join(
                    core.os.path.join(outputDestination, os.path.basename(filePath)), fullFileName)
                logger.debug(
                    "Setting outputDestination to %s to preserve folder structure" % (os.path.dirname(targetFile)))
        try:
            targetFile = targetFile.encode(core.SYS_ENCODING)
        except: pass
        if root == 1:
            if not foundFile:
                logger.debug("Looking for %s in: %s" % (inputName, inputFile))
            if (core.sanitizeName(inputName) in core.sanitizeName(inputFile)) or (
                        core.sanitizeName(fileName) in core.sanitizeName(inputName)):
                foundFile = True
                logger.debug("Found file %s that matches Torrent Name %s" % (fullFileName, inputName))
            else:
                continue

        if root == 2:
            mtime_lapse = now - datetime.datetime.fromtimestamp(os.path.getmtime(inputFile))
            ctime_lapse = now - datetime.datetime.fromtimestamp(os.path.getctime(inputFile))

            if not foundFile:
                logger.debug("Looking for files with modified/created dates less than 5 minutes old.")
            if (mtime_lapse < datetime.timedelta(minutes=5)) or (ctime_lapse < datetime.timedelta(minutes=5)):
                foundFile = True
                logger.debug("Found file %s with date modifed/created less than 5 minutes ago." % (fullFileName))
            else:
                continue  # This file has not been recently moved or created, skip it

        if Torrent_NoLink == 0:
            try:
                core.copy_link(inputFile, targetFile, core.USELINK)
                core.rmReadOnly(targetFile)
            except:
                logger.error("Failed to link: %s to %s" % (inputFile, targetFile))

    inputName, outputDestination = convert_to_ascii(inputName, outputDestination)

    if extract == 1:
        logger.debug('Checking for archives to extract in directory: %s' % (outputDestination))
        core.extractFiles(outputDestination)

    if not inputCategory in core.NOFLATTEN:  #don't flatten hp in case multi cd albums, and we need to copy this back later.
        core.flatten(outputDestination)

    # Now check if video files exist in destination:
    if sectionName in ["SickBeard", "NzbDrone", "CouchPotato"]:
        numVideos = len(
            core.listMediaFiles(outputDestination, media=True, audio=False, meta=False, archives=False))
        if numVideos > 0:
            logger.info("Found %s media files in %s" % (numVideos, outputDestination))
            status = 0
        elif extract != 1:
            logger.info("Found no media files in %s. Sending to %s to process" % (outputDestination, sectionName))
            status = 0
        else:
            logger.warning("Found no media files in %s" % outputDestination)

    # Only these sections can handling failed downloads so make sure everything else gets through without the check for failed
    if not sectionName in ['CouchPotato', 'SickBeard', 'NzbDrone']:
        status = 0

    logger.info("Calling %s:%s to post-process:%s" % (sectionName, usercat, inputName))

    if core.TORRENT_CHMOD_DIRECTORY:
        core.rchmod(outputDestination, core.TORRENT_CHMOD_DIRECTORY)

    result = [ 0, "" ]
    if sectionName == 'UserScript':
        result = external_script(outputDestination, inputName, inputCategory, section[usercat])

    elif sectionName == 'CouchPotato':
        result = core.autoProcessMovie().process(sectionName,outputDestination, inputName, status, clientAgent, inputHash,
                                                       inputCategory)
    elif sectionName in ['SickBeard','NzbDrone']:
        if inputHash:
            inputHash = inputHash.upper()
        result = core.autoProcessTV().processEpisode(sectionName,outputDestination, inputName, status, clientAgent,
                                                           inputHash, inputCategory)
    elif sectionName == 'HeadPhones':
        result = core.autoProcessMusic().process(sectionName,outputDestination, inputName, status, clientAgent, inputCategory)
    elif sectionName == 'Mylar':
        result = core.autoProcessComics().processEpisode(sectionName,outputDestination, inputName, status, clientAgent,
                                                               inputCategory)
    elif sectionName == 'Gamez':
        result = core.autoProcessGames().process(sectionName,outputDestination, inputName, status, clientAgent, inputCategory)

    plex_update(inputCategory)

    if result[0] != 0:
        if not core.TORRENT_RESUME_ON_FAILURE:
            logger.error("A problem was reported in the autoProcess* script. torrent won't resume seeding (settings)")
        elif clientAgent != 'manual':
            logger.error(
                "A problem was reported in the autoProcess* script. If torrent was paused we will resume seeding")
            core.resume_torrent(clientAgent, inputHash, inputID, inputName)

    else:
        if clientAgent != 'manual':
            # update download status in our DB
            core.update_downloadInfoStatus(inputName, 1)

            # remove torrent
            core.remove_torrent(clientAgent, inputHash, inputID, inputName)

        if not sectionName == 'UserScript':  # for user script, we assume this is cleaned by the script or option USER_SCRIPT_CLEAN
            # cleanup our processing folders of any misc unwanted files and empty directories
            core.cleanDir(outputDestination, sectionName, inputCategory)

    return result
Example #7
0
def process_torrent(input_directory, input_name, input_category, input_hash, input_id, client_agent):
    status = 1  # 1 = failed | 0 = success
    root = 0
    found_file = 0

    if client_agent != 'manual' and not core.DOWNLOADINFO:
        logger.debug('Adding TORRENT download info for directory {0} to database'.format(input_directory))

        my_db = main_db.DBConnection()

        input_directory1 = input_directory
        input_name1 = input_name

        try:
            encoded, input_directory1 = char_replace(input_directory)
            encoded, input_name1 = char_replace(input_name)
        except Exception:
            pass

        control_value_dict = {'input_directory': text_type(input_directory1)}
        new_value_dict = {
            'input_name': text_type(input_name1),
            'input_hash': text_type(input_hash),
            'input_id': text_type(input_id),
            'client_agent': text_type(client_agent),
            'status': 0,
            'last_update': datetime.date.today().toordinal(),
        }
        my_db.upsert('downloads', new_value_dict, control_value_dict)

    logger.debug('Received Directory: {0} | Name: {1} | Category: {2}'.format(input_directory, input_name, input_category))

    # Confirm the category by parsing directory structure
    input_directory, input_name, input_category, root = core.category_search(input_directory, input_name, input_category,
                                                                             root, core.CATEGORIES)
    if input_category == '':
        input_category = 'UNCAT'

    usercat = input_category
    try:
        input_name = input_name.encode(core.SYS_ENCODING)
    except UnicodeError:
        pass
    try:
        input_directory = input_directory.encode(core.SYS_ENCODING)
    except UnicodeError:
        pass

    logger.debug('Determined Directory: {0} | Name: {1} | Category: {2}'.format
                 (input_directory, input_name, input_category))

    # auto-detect section
    section = core.CFG.findsection(input_category).isenabled()
    if section is None:
        section = core.CFG.findsection('ALL').isenabled()
        if section is None:
            logger.error('Category:[{0}] is not defined or is not enabled. '
                         'Please rename it or ensure it is enabled for the appropriate section '
                         'in your autoProcessMedia.cfg and try again.'.format
                         (input_category))
            return [-1, '']
        else:
            usercat = 'ALL'

    if len(section) > 1:
        logger.error('Category:[{0}] is not unique, {1} are using it. '
                     'Please rename it or disable all other sections using the same category name '
                     'in your autoProcessMedia.cfg and try again.'.format
                     (usercat, section.keys()))
        return [-1, '']

    if section:
        section_name = section.keys()[0]
        logger.info('Auto-detected SECTION:{0}'.format(section_name))
    else:
        logger.error('Unable to locate a section with subsection:{0} '
                     'enabled in your autoProcessMedia.cfg, exiting!'.format
                     (input_category))
        return [-1, '']

    section = dict(section[section_name][usercat])  # Type cast to dict() to allow effective usage of .get()

    torrent_no_link = int(section.get('Torrent_NoLink', 0))
    keep_archive = int(section.get('keep_archive', 0))
    extract = int(section.get('extract', 0))
    extensions = section.get('user_script_mediaExtensions', '').lower().split(',')
    unique_path = int(section.get('unique_path', 1))

    if client_agent != 'manual':
        core.pause_torrent(client_agent, input_hash, input_id, input_name)

    # In case input is not directory, make sure to create one.
    # This way Processing is isolated.
    if not os.path.isdir(os.path.join(input_directory, input_name)):
        basename = os.path.basename(input_directory)
        basename = core.sanitize_name(input_name) \
            if input_name == basename else os.path.splitext(core.sanitize_name(input_name))[0]
        output_destination = os.path.join(core.OUTPUTDIRECTORY, input_category, basename)
    elif unique_path:
        output_destination = os.path.normpath(
            core.os.path.join(core.OUTPUTDIRECTORY, input_category, core.sanitize_name(input_name).replace(' ', '.')))
    else:
        output_destination = os.path.normpath(
            core.os.path.join(core.OUTPUTDIRECTORY, input_category))
    try:
        output_destination = output_destination.encode(core.SYS_ENCODING)
    except UnicodeError:
        pass

    if output_destination in input_directory:
        output_destination = input_directory

    logger.info('Output directory set to: {0}'.format(output_destination))

    if core.SAFE_MODE and output_destination == core.TORRENT_DEFAULTDIR:
        logger.error('The output directory:[{0}] is the Download Directory. '
                     'Edit outputDirectory in autoProcessMedia.cfg. Exiting'.format
                     (input_directory))
        return [-1, '']

    logger.debug('Scanning files in directory: {0}'.format(input_directory))

    if section_name in ['HeadPhones', 'Lidarr']:
        core.NOFLATTEN.extend(
            input_category)  # Make sure we preserve folder structure for HeadPhones.

    now = datetime.datetime.now()

    if extract == 1:
        input_files = core.list_media_files(input_directory, archives=False, other=True, otherext=extensions)
    else:
        input_files = core.list_media_files(input_directory, other=True, otherext=extensions)
    if len(input_files) == 0 and os.path.isfile(input_directory):
        input_files = [input_directory]
        logger.debug('Found 1 file to process: {0}'.format(input_directory))
    else:
        logger.debug('Found {0} files in {1}'.format(len(input_files), input_directory))
    for inputFile in input_files:
        file_path = os.path.dirname(inputFile)
        file_name, file_ext = os.path.splitext(os.path.basename(inputFile))
        full_file_name = os.path.basename(inputFile)

        target_file = core.os.path.join(output_destination, full_file_name)
        if input_category in core.NOFLATTEN:
            if not os.path.basename(file_path) in output_destination:
                target_file = core.os.path.join(
                    core.os.path.join(output_destination, os.path.basename(file_path)), full_file_name)
                logger.debug('Setting outputDestination to {0} to preserve folder structure'.format
                             (os.path.dirname(target_file)))
        try:
            target_file = target_file.encode(core.SYS_ENCODING)
        except UnicodeError:
            pass
        if root == 1:
            if not found_file:
                logger.debug('Looking for {0} in: {1}'.format(input_name, inputFile))
            if any([core.sanitize_name(input_name) in core.sanitize_name(inputFile),
                    core.sanitize_name(file_name) in core.sanitize_name(input_name)]):
                found_file = True
                logger.debug('Found file {0} that matches Torrent Name {1}'.format
                             (full_file_name, input_name))
            else:
                continue

        if root == 2:
            mtime_lapse = now - datetime.datetime.fromtimestamp(os.path.getmtime(inputFile))
            ctime_lapse = now - datetime.datetime.fromtimestamp(os.path.getctime(inputFile))

            if not found_file:
                logger.debug('Looking for files with modified/created dates less than 5 minutes old.')
            if (mtime_lapse < datetime.timedelta(minutes=5)) or (ctime_lapse < datetime.timedelta(minutes=5)):
                found_file = True
                logger.debug('Found file {0} with date modified/created less than 5 minutes ago.'.format
                             (full_file_name))
            else:
                continue  # This file has not been recently moved or created, skip it

        if torrent_no_link == 0:
            try:
                core.copy_link(inputFile, target_file, core.USELINK)
                core.remove_read_only(target_file)
            except Exception:
                logger.error('Failed to link: {0} to {1}'.format(inputFile, target_file))

    input_name, output_destination = convert_to_ascii(input_name, output_destination)

    if extract == 1:
        logger.debug('Checking for archives to extract in directory: {0}'.format(input_directory))
        core.extract_files(input_directory, output_destination, keep_archive)

    if input_category not in core.NOFLATTEN:
        # don't flatten hp in case multi cd albums, and we need to copy this back later.
        core.flatten(output_destination)

    # Now check if video files exist in destination:
    if section_name in ['SickBeard', 'NzbDrone', 'Sonarr', 'CouchPotato', 'Radarr']:
        num_videos = len(
            core.list_media_files(output_destination, media=True, audio=False, meta=False, archives=False))
        if num_videos > 0:
            logger.info('Found {0} media files in {1}'.format(num_videos, output_destination))
            status = 0
        elif extract != 1:
            logger.info('Found no media files in {0}. Sending to {1} to process'.format(output_destination, section_name))
            status = 0
        else:
            logger.warning('Found no media files in {0}'.format(output_destination))

    # Only these sections can handling failed downloads
    # so make sure everything else gets through without the check for failed
    if section_name not in ['CouchPotato', 'Radarr', 'SickBeard', 'NzbDrone', 'Sonarr']:
        status = 0

    logger.info('Calling {0}:{1} to post-process:{2}'.format(section_name, usercat, input_name))

    if core.TORRENT_CHMOD_DIRECTORY:
        core.rchmod(output_destination, core.TORRENT_CHMOD_DIRECTORY)

    result = ProcessResult(
        message='',
        status_code=0,
    )
    if section_name == 'UserScript':
        result = external_script(output_destination, input_name, input_category, section)
    elif section_name in ['CouchPotato', 'Radarr']:
        result = movies.process(section_name, output_destination, input_name, status, client_agent, input_hash, input_category)
    elif section_name in ['SickBeard', 'NzbDrone', 'Sonarr']:
        if input_hash:
            input_hash = input_hash.upper()
        result = tv.process(section_name, output_destination, input_name, status, client_agent, input_hash, input_category)
    elif section_name in ['HeadPhones', 'Lidarr']:
        result = music.process(section_name, output_destination, input_name, status, client_agent, input_category)
    elif section_name == 'Mylar':
        result = comics.process(section_name, output_destination, input_name, status, client_agent, input_category)
    elif section_name == 'Gamez':
        result = games.process(section_name, output_destination, input_name, status, client_agent, input_category)

    plex_update(input_category)

    if result.status_code != 0:
        if not core.TORRENT_RESUME_ON_FAILURE:
            logger.error('A problem was reported in the autoProcess* script. '
                         'Torrent won\'t resume seeding (settings)')
        elif client_agent != 'manual':
            logger.error('A problem was reported in the autoProcess* script. '
                         'If torrent was paused we will resume seeding')
            core.resume_torrent(client_agent, input_hash, input_id, input_name)

    else:
        if client_agent != 'manual':
            # update download status in our DB
            core.update_download_info_status(input_name, 1)

            # remove torrent
            if core.USELINK == 'move-sym' and not core.DELETE_ORIGINAL == 1:
                logger.debug('Checking for sym-links to re-direct in: {0}'.format(input_directory))
                for dirpath, dirs, files in os.walk(input_directory):
                    for file in files:
                        logger.debug('Checking symlink: {0}'.format(os.path.join(dirpath, file)))
                        replace_links(os.path.join(dirpath, file))
            core.remove_torrent(client_agent, input_hash, input_id, input_name)

        if not section_name == 'UserScript':
            # for user script, we assume this is cleaned by the script or option USER_SCRIPT_CLEAN
            # cleanup our processing folders of any misc unwanted files and empty directories
            core.clean_dir(output_destination, section_name, input_category)

    return result
Example #8
0
def processTorrent(inputDirectory, inputName, inputCategory, inputHash, inputID, clientAgent):
    status = 1  # 1 = failed | 0 = success
    root = 0
    foundFile = 0
    uniquePath = 1

    if clientAgent != 'manual' and not core.DOWNLOADINFO:
        logger.debug('Adding TORRENT download info for directory %s to database' % (inputDirectory))

        myDB = nzbToMediaDB.DBConnection()

        encoded = False
        inputDirectory1 = inputDirectory
        inputName1 = inputName

        try:
            encoded, inputDirectory1 = CharReplace(inputDirectory)
            encoded, inputName1 = CharReplace(inputName)
        except:
            pass

        controlValueDict = {"input_directory": unicode(inputDirectory1)}
        newValueDict = {"input_name": unicode(inputName1),
                        "input_hash": unicode(inputHash),
                        "input_id": unicode(inputID),
                        "client_agent": unicode(clientAgent),
                        "status": 0,
                        "last_update": datetime.date.today().toordinal()
        }
        myDB.upsert("downloads", newValueDict, controlValueDict)

    logger.debug("Received Directory: %s | Name: %s | Category: %s" % (inputDirectory, inputName, inputCategory))

    inputDirectory, inputName, inputCategory, root = core.category_search(inputDirectory, inputName,
                                                                                        inputCategory, root,
                                                                                        core.CATEGORIES)  # Confirm the category by parsing directory structure 
    if inputCategory == "":
        inputCategory = "UNCAT"

    usercat = inputCategory
    try:
        inputName = inputName.encode(core.SYS_ENCODING)
    except: pass
    try:
        inputDirectory = inputDirectory.encode(core.SYS_ENCODING)
    except: pass

    logger.debug("Determined Directory: %s | Name: %s | Category: %s" % (inputDirectory, inputName, inputCategory))

    # auto-detect section
    section = core.CFG.findsection(inputCategory).isenabled()
    if section is None:
        section = core.CFG.findsection("ALL").isenabled()
        if section is None:
            logger.error(
                'Category:[%s] is not defined or is not enabled. Please rename it or ensure it is enabled for the appropriate section in your autoProcessMedia.cfg and try again.' % (
                    inputCategory))
            return [-1, ""]
        else:
            usercat = "ALL"

    if len(section) > 1:
        logger.error(
            'Category:[%s] is not unique, %s are using it. Please rename it or disable all other sections using the same category name in your autoProcessMedia.cfg and try again.' % (
                usercat, section.keys()))
        return [-1, ""]

    if section:
        sectionName = section.keys()[0]
        logger.info('Auto-detected SECTION:%s' % (sectionName))
    else:
        logger.error("Unable to locate a section with subsection:%s enabled in your autoProcessMedia.cfg, exiting!" % (
            inputCategory))
        return [-1, ""]

    try:
        Torrent_NoLink = int(section[usercat]["Torrent_NoLink"])
    except:
        Torrent_NoLink = 0

    try:
        keep_archive = int(section[usercat]["keep_archive"])
    except:
        keep_archive = 0

    try:
        extract = int(section[usercat]['extract'])
    except:
        extract = 0

    try:
        uniquePath = int(section[usercat]["unique_path"])
    except:
        uniquePath = 1

    if clientAgent != 'manual':
        core.pause_torrent(clientAgent, inputHash, inputID, inputName)

    # Incase input is not directory, make sure to create one.
    # This way Processing is isolated.
    if not os.path.isdir(os.path.join(inputDirectory, inputName)):
        basename = os.path.basename(inputDirectory)
        basename = core.sanitizeName(inputName) \
            if inputName == basename else os.path.splitext(core.sanitizeName(inputName)[0])
        outputDestination = os.path.join(core.OUTPUTDIRECTORY, inputCategory, basename)
    elif uniquePath:
        outputDestination = os.path.normpath(
            core.os.path.join(core.OUTPUTDIRECTORY, inputCategory, core.sanitizeName(inputName)))
    else:
        outputDestination = os.path.normpath(
            core.os.path.join(core.OUTPUTDIRECTORY, inputCategory))
    try:
        outputDestination = outputDestination.encode(core.SYS_ENCODING)
    except: pass

    if outputDestination in inputDirectory:
        outputDestination = inputDirectory

    logger.info("Output directory set to: %s" % (outputDestination))

    if core.SAFE_MODE and outputDestination == core.TORRENT_DEFAULTDIR:
        logger.error(
            'The output directory:[%s] is the Download Directory. Edit outputDirectory in autoProcessMedia.cfg. Exiting' % (
            inputDirectory))
        return [-1, ""]

    logger.debug("Scanning files in directory: %s" % (inputDirectory))

    if sectionName == 'HeadPhones':
        core.NOFLATTEN.extend(
            inputCategory)  # Make sure we preserve folder structure for HeadPhones.

    now = datetime.datetime.now()

    if extract == 1:
        inputFiles = core.listMediaFiles(inputDirectory, archives=False)
    else:
        inputFiles = core.listMediaFiles(inputDirectory)
    logger.debug("Found %s files in %s" % (str(len(inputFiles)), inputDirectory))
    for inputFile in inputFiles:
        filePath = os.path.dirname(inputFile)
        fileName, fileExt = os.path.splitext(os.path.basename(inputFile))
        fullFileName = os.path.basename(inputFile)

        targetFile = core.os.path.join(outputDestination, fullFileName)
        if inputCategory in core.NOFLATTEN:
            if not os.path.basename(filePath) in outputDestination:
                targetFile = core.os.path.join(
                    core.os.path.join(outputDestination, os.path.basename(filePath)), fullFileName)
                logger.debug(
                    "Setting outputDestination to %s to preserve folder structure" % (os.path.dirname(targetFile)))
        try:
            targetFile = targetFile.encode(core.SYS_ENCODING)
        except: pass
        if root == 1:
            if not foundFile:
                logger.debug("Looking for %s in: %s" % (inputName, inputFile))
            if (core.sanitizeName(inputName) in core.sanitizeName(inputFile)) or (
                        core.sanitizeName(fileName) in core.sanitizeName(inputName)):
                foundFile = True
                logger.debug("Found file %s that matches Torrent Name %s" % (fullFileName, inputName))
            else:
                continue

        if root == 2:
            mtime_lapse = now - datetime.datetime.fromtimestamp(os.path.getmtime(inputFile))
            ctime_lapse = now - datetime.datetime.fromtimestamp(os.path.getctime(inputFile))

            if not foundFile:
                logger.debug("Looking for files with modified/created dates less than 5 minutes old.")
            if (mtime_lapse < datetime.timedelta(minutes=5)) or (ctime_lapse < datetime.timedelta(minutes=5)):
                foundFile = True
                logger.debug("Found file %s with date modifed/created less than 5 minutes ago." % (fullFileName))
            else:
                continue  # This file has not been recently moved or created, skip it

        if Torrent_NoLink == 0:
            try:
                core.copy_link(inputFile, targetFile, core.USELINK)
                core.rmReadOnly(targetFile)
            except:
                logger.error("Failed to link: %s to %s" % (inputFile, targetFile))

    inputName, outputDestination = convert_to_ascii(inputName, outputDestination)

    if extract == 1:
        logger.debug('Checking for archives to extract in directory: %s' % (inputDirectory))
        core.extractFiles(inputDirectory, outputDestination, keep_archive)

    if not inputCategory in core.NOFLATTEN:  #don't flatten hp in case multi cd albums, and we need to copy this back later.
        core.flatten(outputDestination)

    # Now check if video files exist in destination:
    if sectionName in ["SickBeard", "NzbDrone", "CouchPotato"]:
        numVideos = len(
            core.listMediaFiles(outputDestination, media=True, audio=False, meta=False, archives=False))
        if numVideos > 0:
            logger.info("Found %s media files in %s" % (numVideos, outputDestination))
            status = 0
        elif extract != 1:
            logger.info("Found no media files in %s. Sending to %s to process" % (outputDestination, sectionName))
            status = 0
        else:
            logger.warning("Found no media files in %s" % outputDestination)

    # Only these sections can handling failed downloads so make sure everything else gets through without the check for failed
    if not sectionName in ['CouchPotato', 'SickBeard', 'NzbDrone']:
        status = 0

    logger.info("Calling %s:%s to post-process:%s" % (sectionName, usercat, inputName))

    if core.TORRENT_CHMOD_DIRECTORY:
        core.rchmod(outputDestination, core.TORRENT_CHMOD_DIRECTORY)

    result = [ 0, "" ]
    if sectionName == 'UserScript':
        result = external_script(outputDestination, inputName, inputCategory, section[usercat])

    elif sectionName == 'CouchPotato':
        result = core.autoProcessMovie().process(sectionName,outputDestination, inputName, status, clientAgent, inputHash,
                                                       inputCategory)
    elif sectionName in ['SickBeard','NzbDrone']:
        if inputHash:
            inputHash = inputHash.upper()
        result = core.autoProcessTV().processEpisode(sectionName,outputDestination, inputName, status, clientAgent,
                                                           inputHash, inputCategory)
    elif sectionName == 'HeadPhones':
        result = core.autoProcessMusic().process(sectionName,outputDestination, inputName, status, clientAgent, inputCategory)
    elif sectionName == 'Mylar':
        result = core.autoProcessComics().processEpisode(sectionName,outputDestination, inputName, status, clientAgent,
                                                               inputCategory)
    elif sectionName == 'Gamez':
        result = core.autoProcessGames().process(sectionName,outputDestination, inputName, status, clientAgent, inputCategory)

    plex_update(inputCategory)

    if result[0] != 0:
        if not core.TORRENT_RESUME_ON_FAILURE:
            logger.error("A problem was reported in the autoProcess* script. torrent won't resume seeding (settings)")
        elif clientAgent != 'manual':
            logger.error(
                "A problem was reported in the autoProcess* script. If torrent was paused we will resume seeding")
            core.resume_torrent(clientAgent, inputHash, inputID, inputName)

    else:
        if clientAgent != 'manual':
            # update download status in our DB
            core.update_downloadInfoStatus(inputName, 1)

            # remove torrent
            if core.USELINK == 'move-sym' and not core.DELETE_ORIGINAL == 1:
                logger.debug('Checking for sym-links to re-direct in: %s' % (inputDirectory))
                for dirpath, dirs, files in os.walk(inputDirectory):
                    for file in files:
                        logger.debug('Checking symlink: %s' % (os.path.join(dirpath,file)))
                        core.replace_links(os.path.join(dirpath,file))
            core.remove_torrent(clientAgent, inputHash, inputID, inputName)

        if not sectionName == 'UserScript':  # for user script, we assume this is cleaned by the script or option USER_SCRIPT_CLEAN
            # cleanup our processing folders of any misc unwanted files and empty directories
            core.cleanDir(outputDestination, sectionName, inputCategory)

    return result
Example #9
0
def main():
    global log
    options, args = build_parser()

    # update the opts dictionary with new values
    opts.update(eval(options.__str__()))

    # convert the formats in the args to valid formats for lame and oggenc
    opts['oggencopts'] = ' --' + ' --'.join(opts['oggencopts'].split(':'))
    opts['opusencopts'] = ' --' + ' --'.join(opts['opusencopts'].split(':'))

    # lame is not consistent, sometimes using long opts,sometimes not
    # so we need to specify on command line with dashes whether it is a long op or
    # short
    opts['lameopts'] = ' -' + ' -'.join(opts['lameopts'].split(':'))

    # ffmpeg uses colons as delimiters, just like flac2all (of course), so we had to
    # switch to commas for this one
    opts['ffmpegopts'] = opts['ffmpegopts'].split(',')
    opts['ffmpegopts'] = list(
        flatten([x.split(' ') for x in opts['ffmpegopts']]))

    try:
        opts['mode'] = args[0]

    except (IndexError):  # if no arguments specified
        print("No mode specified! Run with '-h' for help")
        sys.exit(1)  # quit the program with non-zero status

    try:
        opts['dirpath'] = os.path.abspath(args[1])

    except (IndexError):
        print("No directory specified! Run with '-h' for help")
        sys.exit(2)  # quit the program with non-zero status

    # end command line checking

    # Commence main logic
    if options.curses is True:
        log = cconsole()  # switch to cconsole, if specified as option
    else:
        log = console(stderr=True)

    # Check if we have the special mode "all", which really brings flac2all into
    # perspective. We convert to every single format supported. This is mainly added for
    # testing reasons.
    if opts['mode'] == "all":
        opts['mode'] = ','.join(
            [x[0] for x in modetable if not x[0].startswith("_")])

    # In this version, we can convert multiple format at once, so for e.g.
    # mode = mp3,vorbis will create both in parallel
    for mode in opts['mode'].split(','):
        if mode != "":
            # When copying, we don't want a _copy dir, but one representing
            # the mode being copied to, so we check and update mode here
            if "copymode" in opts:
                mode = opts['copymode']
                # As the copy folder is created in the shell module, we
                # do not have to do anything else here
                continue
            try:
                os.mkdir(os.path.join(opts['outdir'], mode))
            except OSError as e:
                if e.errno == 17:
                    log.info("Folder %s already exists, reusing..." % mode)
                elif e.errno == 2:
                    log.info("Parent path %s does not exist! quitting..." %
                             (opts['outdir']))
                else:
                    # everything else, raise error
                    raise e

    # Magic goes here :)
    if opts['master_enable']:
        clustered_encode()
    else:
        clustered_encode(localworkers=True)

    if options.curses is True:
        log.__del__(
        )  # If we are using the curses interface, clean up properly at the end.