def _list_subtitles():
            # list subtitles
            with AsyncProviderPool(
                    providers=self.config.providers,
                    provider_configs=self.config.provider_configs) as pool:
                subtitles = pool.list_subtitles(video, self.config.languages)

            # fill the subtitle liststore
            subtitle_liststore = builder.get_object('subtitle_liststore')
            for s in subtitles:
                scaled_score = compute_score(s, video)
                scores = get_scores(video)
                if s.hearing_impaired == self.config.hearing_impaired:
                    scaled_score -= scores['hearing_impaired']
                scaled_score *= 100 / scores['hash']
                subtitle_liststore.append([
                    s.id,
                    nice_language(s.language), scaled_score,
                    s.provider_name.capitalize(), s.hearing_impaired,
                    s.page_link, False
                ])
            subtitle_liststore.set_sort_column_id(2, Gtk.SortType.DESCENDING)

            # stop the spinner
            spinner.stop()

            # connect signals
            builder.connect_signals(
                ChooseHandler(self.config, video, subtitles, spinner))
示例#2
0
    def search(self, path, languages):
        languages = {language_converter.from_english(l): l for l in languages}
        xbmc.log('Languages: %s' % languages, level=xbmc.LOGDEBUG)
        video = self.get_video(path)

        providers = self.get_providers()
        provider_configs = self.get_provider_configs()
        max_workers = self.get_max_workers()
        xbmc.log('Providers: %s' % providers, level=xbmc.LOGDEBUG)
        xbmc.log('Provider Configs: %s' % provider_configs, level=xbmc.LOGDEBUG)
        with AsyncProviderPool(max_workers=max_workers, providers=providers, provider_configs=provider_configs) as p:
            subtitles = p.list_subtitles(video, languages=set(languages.keys()))
            max_score = episode_scores['hash'] if isinstance(video, Episode) else movie_scores['hash']

            scored_subtitles = sorted([(s, compute_score(s, video))
                                       for s in subtitles], key=operator.itemgetter(1), reverse=True)
            for subtitle, score in scored_subtitles:
                option = SubtitleOption(subtitle)
                option.get_subtitle(subtitle.id)
                l = languages[subtitle.language]
                release_name = '[%s] %s' % (subtitle.provider_name, self.get_release_name(subtitle))
                rating = int(round(float(5 * (score+2)/max_score)))
                sync = score + 2 >= max_score
                option.add_directory_item(self.base_url, self.handle, release_name, l, rating, sync)
            xbmc.log('%s' % subtitles, level=xbmc.LOGDEBUG)

        return True
        def _download_subtitle():
            # download the subtitle
            with AsyncProviderPool(
                    providers=self.config.providers,
                    provider_configs=self.config.provider_configs) as pool:
                pool.download_subtitle(subtitle)

            # save the subtitle
            save_subtitles(self.video, [subtitle], single=self.config.single)

            # mark the subtitle as downloaded
            model.set_value(iter, 6, True)

            # stop the spinner
            self.spinner.stop()
    def run(self,
            scan_path,
            scan_age,
            languages,
            encoding,
            min_score,
            providers,
            provider_configs,
            max_workers,
            plex_url=None,
            plex_token=None,
            *args,
            **kwargs):
        if not os.path.isdir(scan_path):
            raise IOError('Path \'%s\' doesn\'t exist!' % scan_path)
        if not scan_age >= 1:
            raise ValueError('\'scan_age\' must by at least 1!')
        if not len(languages) >= 1:
            raise ValueError('\'languages\' list can\'t be empty!')
        if not providers:
            raise ValueError('\'providers\' argument can\'t be empty!')
        if not max_workers >= 1:
            raise ValueError('\'max_workers\' must be at least 1!')

        if not provider_configs:
            provider_configs = {}

        __tree_dict = lambda: defaultdict(__tree_dict)
        result = __tree_dict()

        encoding = codecs.lookup(encoding).name
        age = timedelta(weeks=scan_age)
        languages = set([Language(l) for l in languages])

        plex = None
        if plex_url and plex_token:
            plex = PlexServer(plex_url, plex_token)

        scan_start = datetime.now()

        videos = []
        ignored_videos = []

        if not region.is_configured:
            region.configure('dogpile.cache.dbm',
                             expiration_time=timedelta(days=30),
                             arguments={
                                 'filename': 'subliminal.dbm',
                                 'lock_factory': MutexLock
                             })

        # scan videos
        scanned_videos = scan_videos(scan_path, age=age)

        for video in scanned_videos:
            video.subtitle_languages |= set(
                search_external_subtitles(video.name).values())
            if check_video(video,
                           languages=languages,
                           age=age,
                           undefined=False):
                refine(video)
                if languages - video.subtitle_languages:
                    videos.append(video)
                else:
                    ignored_videos.append(video)
            else:
                ignored_videos.append(video)

        if videos:
            result['videos']['collected'] = [
                os.path.split(v.name)[1] for v in videos
            ]
        if ignored_videos:
            result['videos']['ignored'] = len(ignored_videos)

        if videos:
            # download best subtitles
            downloaded_subtitles = defaultdict(list)
            with AsyncProviderPool(max_workers=max_workers,
                                   providers=providers,
                                   provider_configs=provider_configs) as p:
                for video in videos:
                    scores = get_scores(video)
                    subtitles_to_download = p.list_subtitles(
                        video, languages - video.subtitle_languages)
                    downloaded_subtitles[video] = p.download_best_subtitles(
                        subtitles_to_download,
                        video,
                        languages,
                        min_score=scores['hash'] * min_score / 100)

                if p.discarded_providers:
                    result['providers']['discarded'] = list(
                        p.discarded_providers)

            # filter subtitles
            with TinyDB('subtitle_db.json') as db:
                table = db.table('downloaded')
                query = Query()
                for video, subtitles in downloaded_subtitles.items():
                    discarded_subtitles = list()
                    discarded_subtitles_info = list()

                    for s in subtitles:
                        subtitle_hash = hashlib.sha256(s.content).hexdigest()
                        subtitle_file = get_subtitle_path(
                            os.path.split(video.name)[1], s.language)
                        dbo = {'hash': subtitle_hash, 'file': subtitle_file}
                        if table.search((query.hash == subtitle_hash)
                                        & (query.file == subtitle_file)):
                            discarded_subtitles.append(s)
                            discarded_subtitles_info.append(dbo)
                        else:
                            table.insert(dbo)

                    downloaded_subtitles[video] = [
                        x for x in subtitles if x not in discarded_subtitles
                    ]
                    if discarded_subtitles_info:
                        result['subtitles'][
                            'discarded'] = result['subtitles'].get(
                                'discarded', []) + discarded_subtitles_info

            downloaded_subtitles = {
                k: v
                for k, v in downloaded_subtitles.items() if v
            }

            # save subtitles
            saved_subtitles = {}
            for video, subtitles in downloaded_subtitles.items():
                saved_subtitles[video] = save_subtitles(video,
                                                        subtitles,
                                                        directory=None,
                                                        encoding=encoding)

                for key, group in groupby(saved_subtitles[video],
                                          lambda x: x.provider_name):
                    subtitle_filenames = [
                        get_subtitle_path(
                            os.path.split(video.name)[1], s.language)
                        for s in list(group)
                    ]
                    result['subtitles'][key] = result['subtitles'].get(
                        key, []) + subtitle_filenames
            result['subtitles']['total'] = sum(
                len(v) for v in saved_subtitles.values())

            # refresh plex
            for video, subtitles in saved_subtitles.items():
                if plex and subtitles:
                    item_found = False
                    for section in plex.library.sections():
                        try:
                            if isinstance(section,
                                          MovieSection) and isinstance(
                                              video, Movie):
                                results = section.search(title=video.title,
                                                         year=video.year,
                                                         libtype='movie',
                                                         sort='addedAt:desc',
                                                         maxresults=1)

                                if not results:
                                    raise NotFound

                                plex_item = results[0]
                            elif isinstance(section,
                                            ShowSection) and isinstance(
                                                video, Episode):
                                results = section.search(title=video.series,
                                                         year=video.year,
                                                         libtype='show',
                                                         sort='addedAt:desc',
                                                         maxresults=1)

                                if not results:
                                    raise NotFound

                                plex_item = results[0].episode(
                                    season=video.season, episode=video.episode)
                            else:
                                continue
                        except NotFound:
                            continue
                        except BadRequest:
                            continue

                        if plex_item:
                            plex_item.refresh()
                            result['plex']['refreshed'] = result['plex'].get(
                                'refreshed', []) + [
                                    '%s%s' %
                                    (repr(plex_item.section()), repr(video))
                                ]
                            item_found = True

                    if not item_found:
                        result['plex']['failed'] = result['plex'].get(
                            'failed', []) + [repr(video)]

            # convert subtitles
            for video, subtitles in saved_subtitles.items():
                target_format = aeidon.formats.SUBRIP
                for s in subtitles:
                    subtitle_path = get_subtitle_path(video.name, s.language)
                    source_format = aeidon.util.detect_format(
                        subtitle_path, encoding)
                    source_file = aeidon.files.new(
                        source_format, subtitle_path,
                        aeidon.encodings.detect_bom(subtitle_path) or encoding)

                    if source_format != target_format:
                        format_info = {
                            'file':
                            get_subtitle_path(
                                os.path.split(video.name)[1], s.language),
                            'from':
                            source_format.label,
                            'to':
                            target_format.label
                        }
                        result['subtitles'][
                            'converted'] = result['subtitles'].get(
                                'converted', []) + [format_info]

                    aeidon_subtitles = source_file.read()
                    for f in [
                            aeidon.formats.SUBRIP, aeidon.formats.MICRODVD,
                            aeidon.formats.MPL2
                    ]:
                        markup = aeidon.markups.new(f)
                        for s in aeidon_subtitles:
                            s.main_text = markup.decode(s.main_text)

                    markup = aeidon.markups.new(target_format)
                    for s in aeidon_subtitles:
                        s.main_text = markup.encode(s.main_text)

                    target_file = aeidon.files.new(target_format,
                                                   subtitle_path, encoding)
                    target_file.write(aeidon_subtitles, aeidon.documents.MAIN)

        scan_end = datetime.now()
        result['meta']['start'] = scan_start.isoformat()
        result['meta']['end'] = scan_end.isoformat()
        result['meta']['duration'] = str(scan_end - scan_start)
        return result
示例#5
0
def download(obj, provider, refiner, language, age, directory, encoding,
             single, force, hearing_impaired, min_score, max_workers, archives,
             verbose, path):
    """Download best subtitles.

    PATH can be an directory containing videos, a video file path or a video file name. It can be used multiple times.

    If an existing subtitle is detected (external or embedded) in the correct language, the download is skipped for
    the associated video.

    """
    # process parameters
    language = set(language)

    # scan videos
    videos = []
    ignored_videos = []
    errored_paths = []
    with click.progressbar(path,
                           label='Collecting videos',
                           item_show_func=lambda p: p or '') as bar:
        for p in bar:
            logger.debug('Collecting path %s', p)

            # non-existing
            if not os.path.exists(p):
                try:
                    video = Video.fromname(p)
                except:
                    logger.exception(
                        'Unexpected error while collecting non-existing path %s',
                        p)
                    errored_paths.append(p)
                    continue
                if not force:
                    video.subtitle_languages |= set(
                        search_external_subtitles(
                            video.name, directory=directory).values())
                refine(video,
                       episode_refiners=refiner,
                       movie_refiners=refiner,
                       embedded_subtitles=not force)
                videos.append(video)
                continue

            # directories
            if os.path.isdir(p):
                try:
                    scanned_videos = scan_videos(p, age=age, archives=archives)
                except:
                    logger.exception(
                        'Unexpected error while collecting directory path %s',
                        p)
                    errored_paths.append(p)
                    continue
                for video in scanned_videos:
                    if check_video(video,
                                   languages=language,
                                   age=age,
                                   undefined=single):
                        if not force:
                            video.subtitle_languages |= set(
                                search_external_subtitles(
                                    video.name, directory=directory).values())
                        refine(video,
                               episode_refiners=refiner,
                               movie_refiners=refiner,
                               embedded_subtitles=not force)
                        videos.append(video)
                    else:
                        ignored_videos.append(video)
                continue

            # other inputs
            try:
                video = scan_video(p)
            except:
                logger.exception('Unexpected error while collecting path %s',
                                 p)
                errored_paths.append(p)
                continue
            if check_video(video,
                           languages=language,
                           age=age,
                           undefined=single):
                if not force:
                    video.subtitle_languages |= set(
                        search_external_subtitles(
                            video.name, directory=directory).values())
                refine(video,
                       episode_refiners=refiner,
                       movie_refiners=refiner,
                       embedded_subtitles=not force)
                videos.append(video)
            else:
                ignored_videos.append(video)

    # output errored paths
    if verbose > 0:
        for p in errored_paths:
            click.secho('%s errored' % p, fg='red')

    # output ignored videos
    if verbose > 1:
        for video in ignored_videos:
            click.secho(
                '%s ignored - subtitles: %s / age: %d day%s' %
                (os.path.split(video.name)[1],
                 ', '.join(str(s) for s in video.subtitle_languages)
                 or 'none', video.age.days, 's' if video.age.days > 1 else ''),
                fg='yellow')

    # report collected videos
    click.echo('%s video%s collected / %s video%s ignored / %s error%s' % (
        click.style(
            str(len(videos)), bold=True, fg='green' if videos else None),
        's' if len(videos) > 1 else '',
        click.style(str(len(ignored_videos)),
                    bold=True,
                    fg='yellow' if ignored_videos else None),
        's' if len(ignored_videos) > 1 else '',
        click.style(str(len(errored_paths)),
                    bold=True,
                    fg='red' if errored_paths else None),
        's' if len(errored_paths) > 1 else '',
    ))

    # exit if no video collected
    if not videos:
        return

    # download best subtitles
    downloaded_subtitles = defaultdict(list)
    with AsyncProviderPool(max_workers=max_workers,
                           providers=provider,
                           provider_configs=obj['provider_configs']) as p:
        with click.progressbar(
                videos,
                label='Downloading subtitles',
                item_show_func=lambda v: os.path.split(v.name)[1]
                if v is not None else '') as bar:
            for v in bar:
                scores = get_scores(v)
                subtitles = p.download_best_subtitles(
                    p.list_subtitles(v, language - v.subtitle_languages),
                    v,
                    language,
                    min_score=scores['hash'] * min_score / 100,
                    hearing_impaired=hearing_impaired,
                    only_one=single)
                downloaded_subtitles[v] = subtitles

        if p.discarded_providers:
            click.secho(
                'Some providers have been discarded due to unexpected errors: %s'
                % ', '.join(p.discarded_providers),
                fg='yellow')

    # save subtitles
    total_subtitles = 0
    for v, subtitles in downloaded_subtitles.items():
        saved_subtitles = save_subtitles(v,
                                         subtitles,
                                         single=single,
                                         directory=directory,
                                         encoding=encoding)
        total_subtitles += len(saved_subtitles)

        if verbose > 0:
            click.echo(
                '%s subtitle%s downloaded for %s' %
                (click.style(str(len(saved_subtitles)), bold=True), 's' if
                 len(saved_subtitles) > 1 else '', os.path.split(v.name)[1]))

        if verbose > 1:
            for s in saved_subtitles:
                matches = s.get_matches(v)
                score = compute_score(s, v)

                # score color
                score_color = None
                scores = get_scores(v)
                if isinstance(v, Movie):
                    if score < scores['title']:
                        score_color = 'red'
                    elif score < scores['title'] + scores['year'] + scores[
                            'release_group']:
                        score_color = 'yellow'
                    else:
                        score_color = 'green'
                elif isinstance(v, Episode):
                    if score < scores['series'] + scores['season'] + scores[
                            'episode']:
                        score_color = 'red'
                    elif score < scores['series'] + scores['season'] + scores[
                            'episode'] + scores['release_group']:
                        score_color = 'yellow'
                    else:
                        score_color = 'green'

                # scale score from 0 to 100 taking out preferences
                scaled_score = score
                if s.hearing_impaired == hearing_impaired:
                    scaled_score -= scores['hearing_impaired']
                scaled_score *= 100 / scores['hash']

                # echo some nice colored output
                click.echo(
                    '  - [{score}] {language} subtitle from {provider_name} (match on {matches})'
                    .format(score=click.style('{:5.1f}'.format(scaled_score),
                                              fg=score_color,
                                              bold=score >= scores['hash']),
                            language=s.language.name
                            if s.language.country is None else '%s (%s)' %
                            (s.language.name, s.language.country.name),
                            provider_name=s.provider_name,
                            matches=', '.join(
                                sorted(matches, key=scores.get,
                                       reverse=True))))

    if verbose == 0:
        click.echo('Downloaded %s subtitle%s' %
                   (click.style(str(total_subtitles), bold=True),
                    's' if total_subtitles > 1 else ''))
    def download_callback(self, menuitem, files):
        # scan videos
        videos = []
        for f in files:
            # ignore non-writable locations
            if not f.can_write():
                continue

            # directories
            if f.is_directory():
                try:
                    scanned_videos = scan_videos(f.get_location().get_path())
                except:
                    continue
                for video in scanned_videos:
                    if check_video(video,
                                   languages=self.config.languages,
                                   age=self.config.age,
                                   undefined=self.config.single):
                        video.subtitle_languages |= set(
                            search_external_subtitles(video.name).values())
                        refine(
                            video,
                            episode_refiners=self.config.refiners,
                            movie_refiners=self.config.refiners,
                            embedded_subtitles=self.config.embedded_subtitles)
                        videos.append(video)
                continue

            # other inputs
            try:
                video = scan_video(f.get_location().get_path())
            except:
                continue
            if check_video(video,
                           languages=self.config.languages,
                           undefined=self.config.single):
                video.subtitle_languages |= set(
                    search_external_subtitles(video.name).values())
                refine(video,
                       episode_refiners=self.config.refiners,
                       movie_refiners=self.config.refiners,
                       embedded_subtitles=self.config.embedded_subtitles)
                videos.append(video)

        # download best subtitles
        downloaded_subtitles = defaultdict(list)
        with AsyncProviderPool(
                providers=self.config.providers,
                provider_configs=self.config.provider_configs) as pool:
            for v in videos:
                scores = get_scores(v)
                subtitles = pool.download_best_subtitles(
                    pool.list_subtitles(
                        v, self.config.languages - v.subtitle_languages),
                    v,
                    self.config.languages,
                    min_score=scores['hash'] * self.config.min_score / 100,
                    hearing_impaired=self.config.hearing_impaired,
                    only_one=self.config.single)
                downloaded_subtitles[v] = subtitles

        # save subtitles
        for v, subtitles in downloaded_subtitles.items():
            save_subtitles(v, subtitles, single=self.config.single)
示例#7
0
def download_subtitle(path, language, hi, providers, providers_auth, sceneName, media_type):
    if hi == "True":
        hi = True
    else:
        hi = False
    language_set = set()
    if language == 'pob':
        language_set.add(Language('por', 'BR'))
    else:
        language_set.add(Language(language))

    use_scenename = get_general_settings()[9]
    minimum_score = get_general_settings()[8]
    minimum_score_movie = get_general_settings()[22]
    use_postprocessing = get_general_settings()[10]
    postprocessing_cmd = get_general_settings()[11]

    try:
        if sceneName == "None" or use_scenename is False:
            used_sceneName = False
            video = scan_video(path)
        else:
            used_sceneName = True
            video = Video.fromname(sceneName)
    except Exception as e:
        logging.exception("Error trying to get video information for this file: " + path)
    else:
        if media_type == "movie":
            max_score = 120.0
        elif media_type == "series":
            max_score = 360.0

        try:
            with AsyncProviderPool(max_workers=None, providers=providers, provider_configs=providers_auth) as p:
                subtitles = p.list_subtitles(video, language_set)
        except Exception as e:
            logging.exception("Error trying to get subtitle list from provider")
        else:
            subtitles_list = []
            sorted_subtitles = sorted([(s, compute_score(s, video, hearing_impaired=hi)) for s in subtitles], key=operator.itemgetter(1), reverse=True)
            for s, preliminary_score in sorted_subtitles:
                if media_type == "movie":
                    if (preliminary_score / max_score * 100) < int(minimum_score_movie):
                        continue
                    matched = set(s.get_matches(video))
                    if hi == s.hearing_impaired:
                        matched.add('hearing_impaired')
                    not_matched = set(score.movie_scores.keys()) - matched
                    required = set(['title'])
                    if any(elem in required for elem in not_matched):
                        continue
                elif media_type == "series":
                    if (preliminary_score / max_score * 100) < int(minimum_score):
                        continue
                    matched = set(s.get_matches(video))
                    if hi == s.hearing_impaired:
                        matched.add('hearing_impaired')
                    not_matched = set(score.episode_scores.keys()) - matched
                    required = set(['series', 'season', 'episode'])
                    if any(elem in required for elem in not_matched):
                        continue
                subtitles_list.append(s)
            if len(subtitles_list) > 0:
                best_subtitle = subtitles_list[0]
                download_subtitles([best_subtitle], providers=providers, provider_configs=providers_auth)
                try:
                    calculated_score = round(float(compute_score(best_subtitle, video, hearing_impaired=hi)) / max_score * 100, 2)
                    if used_sceneName == True:
                        video = scan_video(path)
                    single = get_general_settings()[7]
                    if single is True:
                        result = save_subtitles(video, [best_subtitle], single=True, encoding='utf-8')
                    else:
                        result = save_subtitles(video, [best_subtitle], encoding='utf-8')
                except Exception as e:
                    logging.exception('Error saving subtitles file to disk.')
                    return None
                else:
                    if len(result) > 0:
                        downloaded_provider = result[0].provider_name
                        downloaded_language = language_from_alpha3(result[0].language.alpha3)
                        downloaded_language_code2 = alpha2_from_alpha3(result[0].language.alpha3)
                        downloaded_language_code3 = result[0].language.alpha3
                        downloaded_path = get_subtitle_path(path, language=language_set)
                        if used_sceneName == True:
                            message = downloaded_language + " subtitles downloaded from " + downloaded_provider + " with a score of " + unicode(calculated_score) + "% using this scene name: " + sceneName
                        else:
                            message = downloaded_language + " subtitles downloaded from " + downloaded_provider + " with a score of " + unicode(calculated_score) + "% using filename guessing."

                        if use_postprocessing is True:
                            command = pp_replace(postprocessing_cmd, path, downloaded_path, downloaded_language, downloaded_language_code2, downloaded_language_code3)
                            try:
                                if os.name == 'nt':
                                    codepage = subprocess.Popen("chcp", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                                    # wait for the process to terminate
                                    out_codepage, err_codepage = codepage.communicate()
                                    encoding = out_codepage.split(':')[-1].strip()

                                process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                                # wait for the process to terminate
                                out, err = process.communicate()

                                if os.name == 'nt':
                                    out = out.decode(encoding)

                            except:
                                if out == "":
                                    logging.error('Post-processing result for file ' + path + ' : Nothing returned from command execution')
                                else:
                                    logging.error('Post-processing result for file ' + path + ' : ' + out)
                            else:
                                if out == "":
                                    logging.info('Post-processing result for file ' + path + ' : Nothing returned from command execution')
                                else:
                                    logging.info('Post-processing result for file ' + path + ' : ' + out)

                        return message
                    else:
                        return None
            else:
                return None
示例#8
0
def manual_search(path, language, hi, providers, providers_auth, sceneName, media_type):
    if hi == "True":
        hi = True
    else:
        hi = False
    language_set = set()
    for lang in ast.literal_eval(language):
        lang = alpha3_from_alpha2(lang)
        if lang == 'pob':
            language_set.add(Language('por', 'BR'))
        else:
            language_set.add(Language(lang))

    use_scenename = get_general_settings()[9]
    use_postprocessing = get_general_settings()[10]
    postprocessing_cmd = get_general_settings()[11]

    try:
        if sceneName == "None" or use_scenename is False:
            used_sceneName = False
            video = scan_video(path)
        else:
            used_sceneName = True
            video = Video.fromname(sceneName)
    except:
        logging.error("Error trying to get video information.")
    else:
        if media_type == "movie":
            max_score = 120.0
        elif media_type == "series":
            max_score = 360.0

        try:
            with AsyncProviderPool(max_workers=None, providers=providers, provider_configs=providers_auth) as p:
                subtitles = p.list_subtitles(video, language_set)
        except Exception as e:
            logging.exception("Error trying to get subtitle list from provider")
        else:
            subtitles_list = []
            for s in subtitles:
                {s: compute_score(s, video, hearing_impaired=hi)}
                if media_type == "movie":
                    matched = set(s.get_matches(video))
                    if hi == s.hearing_impaired:
                        matched.add('hearing_impaired')
                    not_matched = set(score.movie_scores.keys()) - matched
                    required = set(['title'])
                    if any(elem in required for elem in not_matched):
                        continue
                    if used_sceneName:
                        not_matched.remove('hash')
                elif media_type == "series":
                    matched = set(s.get_matches(video))
                    if hi == s.hearing_impaired:
                        matched.add('hearing_impaired')
                    not_matched = set(score.episode_scores.keys()) - matched
                    required = set(['series', 'season', 'episode'])
                    if any(elem in required for elem in not_matched):
                        continue
                    if used_sceneName:
                        not_matched.remove('hash')
                subtitles_list.append(dict(score=round((compute_score(s, video, hearing_impaired=hi) / max_score * 100), 2), language=alpha2_from_alpha3(s.language.alpha3), hearing_impaired=str(s.hearing_impaired), provider=s.provider_name, subtitle=codecs.encode(pickle.dumps(s), "base64").decode(), url=s.page_link, matches=list(matched), dont_matches=list(not_matched)))
            subtitles_dict = {}
            subtitles_dict = sorted(subtitles_list, key=lambda x: x['score'], reverse=True)
            return(subtitles_dict)
示例#9
0
def download_subtitle(path, language, hi, providers, providers_auth, sceneName, media_type):
    logging.debug('BAZARR Searching subtitles for this file: ' + path)
    if hi == "True":
        hi = True
    else:
        hi = False
    language_set = set()
    if language == 'pob':
        language_set.add(Language('por', 'BR'))
    else:
        language_set.add(Language(language))

    use_scenename = settings.general.getboolean('use_scenename')
    minimum_score = settings.general.minimum_score
    minimum_score_movie = settings.general.minimum_score_movie
    use_postprocessing = settings.general.getboolean('use_postprocessing')
    postprocessing_cmd = settings.general.postprocessing_cmd

    try:
        if sceneName == "None" or use_scenename is False:
            used_sceneName = False
            video = scan_video(path)
        else:
            used_sceneName = True
            video = Video.fromname(sceneName)
    except Exception as e:
        logging.exception("BAZARR Error trying to get video information for this file: " + path)
        pass
    else:
        if media_type == "movie":
            max_score = 120.0
        elif media_type == "series":
            max_score = 360.0

        try:
            with AsyncProviderPool(max_workers=None, providers=providers, provider_configs=providers_auth) as p:
                subtitles = p.list_subtitles(video, language_set)
        except Exception as e:
            logging.exception("BAZARR Error trying to get subtitle list from provider for this file: " + path)
        else:
            subtitles_list = []
            try:
                sorted_subtitles = sorted([(s, compute_score(s, video, hearing_impaired=hi)) for s in subtitles], key=operator.itemgetter(1), reverse=True)
            except Exception as e:
                logging.exception('BAZARR Exception raised while trying to compute score for this file: ' + path)
                return None
            else:
                for s, preliminary_score in sorted_subtitles:
                    if media_type == "movie":
                        if (preliminary_score / max_score * 100) < int(minimum_score_movie):
                            continue
                        matched = set(s.get_matches(video))
                        if hi == s.hearing_impaired:
                            matched.add('hearing_impaired')
                        not_matched = set(score.movie_scores.keys()) - matched
                        required = set(['title'])
                        if any(elem in required for elem in not_matched):
                            continue
                    elif media_type == "series":
                        if (preliminary_score / max_score * 100) < int(minimum_score):
                            continue
                        matched = set(s.get_matches(video))
                        if hi == s.hearing_impaired:
                            matched.add('hearing_impaired')
                        not_matched = set(score.episode_scores.keys()) - matched
                        required = set(['series', 'season', 'episode'])
                        if any(elem in required for elem in not_matched):
                            continue
                    subtitles_list.append(s)
                logging.debug('BAZARR ' + str(len(subtitles_list)) + " subtitles have been found for this file: " + path)
                if len(subtitles_list) > 0:
                    try:
                        download_result = False
                        for subtitle in subtitles_list:
                            download_result = p.download_subtitle(subtitle)
                            if download_result:
                                logging.debug('BAZARR Subtitles file downloaded from ' + str(subtitle.provider_name) + ' for this file: ' + path)
                                break
                            else:
                                logging.warning('BAZARR Subtitles file skipped from ' + str(subtitle.provider_name) + ' for this file: ' + path + ' because no content was returned by the provider (probably throttled).')
                                continue
                        if not download_result:
                            logging.error('BAZARR Tried to download a subtitles for file: ' + path + " but we weren't able to do it this time (probably being throttled). Going to retry on next search.")
                            return None
                    except Exception as e:
                        logging.exception('BAZARR Error downloading subtitles for this file ' + path)
                        return None
                    else:
                        try:
                            calculated_score = round(float(compute_score(subtitle, video, hearing_impaired=hi)) / max_score * 100, 2)
                            if used_sceneName:
                                video = scan_video(path)
                            single = settings.general.getboolean('single_language')
                            if single is True:
                                result = save_subtitles(video, [subtitle], single=True, encoding='utf-8')
                            else:
                                result = save_subtitles(video, [subtitle], encoding='utf-8')
                        except Exception as e:
                            logging.exception('BAZARR Error saving subtitles file to disk for this file:' + path)
                            pass
                        else:
                            downloaded_provider = result[0].provider_name
                            downloaded_language = language_from_alpha3(result[0].language.alpha3)
                            downloaded_language_code2 = alpha2_from_alpha3(result[0].language.alpha3)
                            downloaded_language_code3 = result[0].language.alpha3
                            downloaded_path = get_subtitle_path(path, downloaded_language_code2)
                            logging.debug('BAZARR Subtitles file saved to disk: ' + downloaded_path)
                            if used_sceneName:
                                message = downloaded_language + " subtitles downloaded from " + downloaded_provider + " with a score of " + unicode(calculated_score) + "% using this scene name: " + sceneName
                            else:
                                message = downloaded_language + " subtitles downloaded from " + downloaded_provider + " with a score of " + unicode(calculated_score) + "% using filename guessing."

                            if use_postprocessing is True:
                                command = pp_replace(postprocessing_cmd, path, downloaded_path, downloaded_language, downloaded_language_code2, downloaded_language_code3)
                                try:
                                    if os.name == 'nt':
                                        codepage = subprocess.Popen("chcp", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                                        # wait for the process to terminate
                                        out_codepage, err_codepage = codepage.communicate()
                                        encoding = out_codepage.split(':')[-1].strip()

                                    process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                                    # wait for the process to terminate
                                    out, err = process.communicate()

                                    if os.name == 'nt':
                                        out = out.decode(encoding)

                                except:
                                    if out == "":
                                        logging.error('BAZARR Post-processing result for file ' + path + ' : Nothing returned from command execution')
                                    else:
                                        logging.error('BAZARR Post-processing result for file ' + path + ' : ' + out)
                                else:
                                    if out == "":
                                        logging.info('BAZARR Post-processing result for file ' + path + ' : Nothing returned from command execution')
                                    else:
                                        logging.info('BAZARR Post-processing result for file ' + path + ' : ' + out)

                            return message
                else:
                    logging.debug('BAZARR No subtitles were found for this file: ' + path)
                    return None
    logging.debug('BAZARR Ended searching subtitles for file: ' + path)
示例#10
0
def manual_search(path, language, hi, providers, providers_auth, sceneName, media_type):
    logging.debug('BAZARR Manually searching subtitles for this file: ' + path)

    subtitles_dict = {}

    if hi == "True":
        hi = True
    else:
        hi = False
    language_set = set()
    for lang in ast.literal_eval(language):
        lang = alpha3_from_alpha2(lang)
        if lang == 'pob':
            language_set.add(Language('por', 'BR'))
        else:
            language_set.add(Language(lang))

    use_scenename = settings.general.getboolean('use_scenename')
    use_postprocessing = settings.general.getboolean('use_postprocessing')
    postprocessing_cmd = settings.general.postprocessing_cmd

    try:
        if sceneName == "None" or use_scenename is False:
            used_sceneName = False
            video = scan_video(path)
        else:
            used_sceneName = True
            video = Video.fromname(sceneName)
    except:
        logging.exception("BAZARR Error trying to get video information for this file: " + path)
    else:
        if media_type == "movie":
            max_score = 120.0
        elif media_type == "series":
            max_score = 360.0

        try:
            with AsyncProviderPool(max_workers=None, providers=providers, provider_configs=providers_auth) as p:
                subtitles = p.list_subtitles(video, language_set)
        except Exception as e:
            logging.exception("BAZARR Error trying to get subtitle list from provider for this file: " + path)
        else:
            subtitles_list = []
            for s in subtitles:
                {s: compute_score(s, video, hearing_impaired=hi)}
                if media_type == "movie":
                    matched = set(s.get_matches(video))
                    if hi == s.hearing_impaired:
                        matched.add('hearing_impaired')
                    not_matched = set(score.movie_scores.keys()) - matched
                    required = set(['title'])
                    if any(elem in required for elem in not_matched):
                        continue
                    if used_sceneName:
                        not_matched.remove('hash')
                    if type(s) is LegendasTVSubtitle:
                        # The pickle doesn't work very well with RAR (rarfile.RarFile) or ZIP (zipfile.ZipFile)
                        s.archive.content = None
                elif media_type == "series":
                    matched = set(s.get_matches(video))
                    if hi == s.hearing_impaired:
                        matched.add('hearing_impaired')
                    not_matched = set(score.episode_scores.keys()) - matched
                    required = set(['series', 'season', 'episode'])
                    if any(elem in required for elem in not_matched):
                        continue
                    if used_sceneName:
                        not_matched.remove('hash')
                    if type(s) is LegendasTVSubtitle:
                        # The pickle doesn't work very well with RAR (rarfile.RarFile) or ZIP (zipfile.ZipFile)
                        s.archive.content = None
                subtitles_list.append(dict(score=round((compute_score(s, video, hearing_impaired=hi) / max_score * 100), 2), language=alpha2_from_alpha3(s.language.alpha3), hearing_impaired=str(s.hearing_impaired), provider=s.provider_name, subtitle=codecs.encode(pickle.dumps(s), "base64").decode(), url=s.page_link, matches=list(matched), dont_matches=list(not_matched)))
            subtitles_dict = sorted(subtitles_list, key=lambda x: x['score'], reverse=True)
            logging.debug('BAZARR ' + str(len(subtitles_dict)) + " subtitles have been found for this file: " + path)
            logging.debug('BAZARR Ended searching subtitles for this file: ' + path)
        return(subtitles_dict)