Пример #1
0
    def post(self):
        radarrIdList = request.form.getlist('radarrid')
        profileIdList = request.form.getlist('profileid')

        for idx in range(len(radarrIdList)):
            radarrId = radarrIdList[idx]
            profileId = profileIdList[idx]

            if profileId in None_Keys:
                profileId = None
            else:
                try:
                    profileId = int(profileId)
                except Exception:
                    return '', 400

            TableMovies.update({
                TableMovies.profileId: profileId
            })\
                .where(TableMovies.radarrId == radarrId)\
                .execute()

            list_missing_subtitles_movies(no=radarrId, send_event=False)

            event_stream(type='movie', payload=radarrId)
            event_stream(type='movie-wanted', payload=radarrId)
        event_stream(type='badges')

        return '', 204
Пример #2
0
def list_missing_subtitles_movies(no=None):
    movies_subtitles_clause = {TableMovies.radarr_id.is_null(False)}
    if no is not None:
        movies_subtitles_clause = {TableMovies.radarr_id**no}

    movies_subtitles = TableMovies.select(
        TableMovies.radarr_id, TableMovies.subtitles, TableMovies.languages,
        TableMovies.forced).where(movies_subtitles_clause)

    missing_subtitles_global = []
    use_embedded_subs = settings.general.getboolean('use_embedded_subs')
    for movie_subtitles in movies_subtitles:
        actual_subtitles_temp = []
        desired_subtitles_temp = []
        actual_subtitles = []
        desired_subtitles = []
        missing_subtitles = []
        if movie_subtitles.subtitles is not None:
            if use_embedded_subs:
                actual_subtitles = ast.literal_eval(movie_subtitles.subtitles)
            else:
                actual_subtitles_temp = ast.literal_eval(
                    movie_subtitles.subtitles)
                for subtitle in actual_subtitles_temp:
                    if subtitle[1] is not None:
                        actual_subtitles.append(subtitle)
        if movie_subtitles.languages is not None:
            desired_subtitles = ast.literal_eval(movie_subtitles.languages)
            if movie_subtitles.forced == "True" and desired_subtitles is not None:
                for i, desired_subtitle in enumerate(desired_subtitles):
                    desired_subtitles[i] = desired_subtitle + ":forced"
            elif movie_subtitles.forced == "Both" and desired_subtitles is not None:
                for desired_subtitle in desired_subtitles:
                    desired_subtitles_temp.append(desired_subtitle)
                    desired_subtitles_temp.append(desired_subtitle + ":forced")
                desired_subtitles = desired_subtitles_temp
        actual_subtitles_list = []
        if desired_subtitles is None:
            missing_subtitles_global.append(
                tuple(['[]', movie_subtitles.radarr_id]))
        else:
            for item in actual_subtitles:
                if item[0] == "pt-BR":
                    actual_subtitles_list.append("pb")
                elif item[0] == "pt-BR:forced":
                    actual_subtitles_list.append("pb:forced")
                else:
                    actual_subtitles_list.append(item[0])
            missing_subtitles = list(
                set(desired_subtitles) - set(actual_subtitles_list))
            missing_subtitles_global.append(
                tuple([str(missing_subtitles), movie_subtitles.radarr_id]))

    for missing_subtitles_item in missing_subtitles_global:
        TableMovies.update({
            TableMovies.missing_subtitles:
            missing_subtitles_item[0]
        }).where(TableMovies.radarr_id == missing_subtitles_item[1]).execute()
Пример #3
0
    def post(self):
        enabled_languages = request.form.getlist('languages-enabled')
        if len(enabled_languages) != 0:
            TableSettingsLanguages.update({
                TableSettingsLanguages.enabled: 0
            }).execute()
            for code in enabled_languages:
                TableSettingsLanguages.update({
                    TableSettingsLanguages.enabled: 1
                })\
                    .where(TableSettingsLanguages.code2 == code)\
                    .execute()
            event_stream("languages")

        languages_profiles = request.form.get('languages-profiles')
        if languages_profiles:
            existing_ids = TableLanguagesProfiles.select(TableLanguagesProfiles.profileId).dicts()
            existing_ids = list(existing_ids)
            existing = [x['profileId'] for x in existing_ids]
            for item in json.loads(languages_profiles):
                if item['profileId'] in existing:
                    # Update existing profiles
                    TableLanguagesProfiles.update({
                        TableLanguagesProfiles.name: item['name'],
                        TableLanguagesProfiles.cutoff: item['cutoff'] if item['cutoff'] != 'null' else None,
                        TableLanguagesProfiles.items: json.dumps(item['items']),
                        TableLanguagesProfiles.mustContain: item['mustContain'],
                        TableLanguagesProfiles.mustNotContain: item['mustNotContain'],
                    })\
                        .where(TableLanguagesProfiles.profileId == item['profileId'])\
                        .execute()
                    existing.remove(item['profileId'])
                else:
                    # Add new profiles
                    TableLanguagesProfiles.insert({
                        TableLanguagesProfiles.profileId: item['profileId'],
                        TableLanguagesProfiles.name: item['name'],
                        TableLanguagesProfiles.cutoff: item['cutoff'] if item['cutoff'] != 'null' else None,
                        TableLanguagesProfiles.items: json.dumps(item['items']),
                        TableLanguagesProfiles.mustContain: item['mustContain'],
                        TableLanguagesProfiles.mustNotContain: item['mustNotContain'],
                    }).execute()
            for profileId in existing:
                # Unassign this profileId from series and movies
                TableShows.update({
                    TableShows.profileId: None
                }).where(TableShows.profileId == profileId).execute()
                TableMovies.update({
                    TableMovies.profileId: None
                }).where(TableMovies.profileId == profileId).execute()
                # Remove deleted profiles
                TableLanguagesProfiles.delete().where(TableLanguagesProfiles.profileId == profileId).execute()

            update_profile_id_list()
            event_stream("languages")

            if settings.general.getboolean('use_sonarr'):
                scheduler.add_job(list_missing_subtitles, kwargs={'send_event': False})
            if settings.general.getboolean('use_radarr'):
                scheduler.add_job(list_missing_subtitles_movies, kwargs={'send_event': False})

        # Update Notification
        notifications = request.form.getlist('notifications-providers')
        for item in notifications:
            item = json.loads(item)
            TableSettingsNotifier.update({
                TableSettingsNotifier.enabled: item['enabled'],
                TableSettingsNotifier.url: item['url']
            }).where(TableSettingsNotifier.name == item['name']).execute()

        save_settings(zip(request.form.keys(), request.form.listvalues()))
        event_stream("settings")
        return '', 204
Пример #4
0
def parse_video_metadata(file,
                         file_size,
                         episode_file_id=None,
                         movie_file_id=None,
                         use_cache=True):
    # Define default data keys value
    data = {
        "ffprobe": {},
        "enzyme": {},
        "file_id": episode_file_id or movie_file_id,
        "file_size": file_size,
    }

    if use_cache:
        # Get the actual cache value form database
        if episode_file_id:
            cache_key = TableEpisodes.select(TableEpisodes.ffprobe_cache)\
                .where(TableEpisodes.path == path_mappings.path_replace_reverse(file))\
                .dicts()\
                .get()
        elif movie_file_id:
            cache_key = TableMovies.select(TableMovies.ffprobe_cache)\
                .where(TableMovies.path == path_mappings.path_replace_reverse_movie(file))\
                .dicts()\
                .get()
        else:
            cache_key = None

        # check if we have a value for that cache key
        try:
            # Unpickle ffprobe cache
            cached_value = pickle.loads(cache_key['ffprobe_cache'])
        except:
            pass
        else:
            # Check if file size and file id matches and if so, we return the cached value
            if cached_value['file_size'] == file_size and cached_value[
                    'file_id'] in [episode_file_id, movie_file_id]:
                return cached_value

    # if not, we retrieve the metadata from the file
    from utils import get_binary

    ffprobe_path = get_binary("ffprobe")

    # if we have ffprobe available
    if ffprobe_path:
        api.initialize({"provider": "ffmpeg", "ffmpeg": ffprobe_path})
        data["ffprobe"] = api.know(file)
    # if not, we use enzyme for mkv files
    else:
        if os.path.splitext(file)[1] == ".mkv":
            with open(file, "rb") as f:
                try:
                    mkv = enzyme.MKV(f)
                except MalformedMKVError:
                    logger.error(
                        "BAZARR cannot analyze this MKV with our built-in MKV parser, you should install "
                        "ffmpeg/ffprobe: " + file)
                else:
                    data["enzyme"] = mkv

    # we write to db the result and return the newly cached ffprobe dict
    if episode_file_id:
        TableEpisodes.update({TableEpisodes.ffprobe_cache: pickle.dumps(data, pickle.HIGHEST_PROTOCOL)})\
            .where(TableEpisodes.path == path_mappings.path_replace_reverse(file))\
            .execute()
    elif movie_file_id:
        TableMovies.update({TableEpisodes.ffprobe_cache: pickle.dumps(data, pickle.HIGHEST_PROTOCOL)})\
            .where(TableMovies.path == path_mappings.path_replace_reverse_movie(file))\
            .execute()
    return data
Пример #5
0
def store_subtitles_movie(file):
    logging.debug('BAZARR started subtitles indexing for this file: ' + file)
    actual_subtitles = []
    if os.path.exists(file):
        if settings.general.getboolean('use_embedded_subs'):
            logging.debug("BAZARR is trying to index embedded subtitles.")
            try:
                subtitle_languages = embedded_subs_reader.list_languages(file)
                for subtitle_language, subtitle_forced, subtitle_codec in subtitle_languages:
                    try:
                        if settings.general.getboolean(
                                "ignore_pgs_subs"
                        ) and subtitle_codec == "hdmv_pgs_subtitle":
                            logging.debug(
                                "BAZARR skipping pgs sub for language: " +
                                str(alpha2_from_alpha3(subtitle_language)))
                            continue

                        if alpha2_from_alpha3(subtitle_language) is not None:
                            lang = str(alpha2_from_alpha3(subtitle_language))
                            if subtitle_forced:
                                lang = lang + ':forced'
                            logging.debug(
                                "BAZARR embedded subtitles detected: " + lang)
                            actual_subtitles.append([lang, None])
                    except:
                        logging.debug(
                            "BAZARR unable to index this unrecognized language: "
                            + subtitle_language)
                        pass
            except Exception as e:
                logging.exception(
                    "BAZARR error when trying to analyze this %s file: %s" %
                    (os.path.splitext(file)[1], file))
                pass

        dest_folder = get_subtitle_destination_folder() or ''
        subliminal_patch.core.CUSTOM_PATHS = [dest_folder
                                              ] if dest_folder else []
        brazilian_portuguese = [".pt-br", ".pob", "pb"]
        brazilian_portuguese_forced = [
            ".pt-br.forced", ".pob.forced", "pb.forced"
        ]
        try:
            subtitles = search_external_subtitles(
                file,
                languages=get_language_set(),
                only_one=settings.general.getboolean('single_language'))
        except Exception as e:
            logging.exception("BAZARR unable to index external subtitles.")
            pass
        else:
            for subtitle, language in subtitles.iteritems():
                if str(os.path.splitext(subtitle)[0]).lower().endswith(
                        tuple(brazilian_portuguese)) is True:
                    logging.debug("BAZARR external subtitles detected: " +
                                  "pb")
                    actual_subtitles.append([
                        str("pb"),
                        path_replace_reverse_movie(
                            os.path.join(os.path.dirname(file), dest_folder,
                                         subtitle))
                    ])
                elif str(os.path.splitext(subtitle)[0]).lower().endswith(
                        tuple(brazilian_portuguese_forced)) is True:
                    logging.debug("BAZARR external subtitles detected: " +
                                  "pb:forced")
                    actual_subtitles.append([
                        str("pb:forced"),
                        path_replace_reverse_movie(
                            os.path.join(os.path.dirname(file), dest_folder,
                                         subtitle))
                    ])
                elif str(language) != 'und':
                    logging.debug("BAZARR external subtitles detected: " +
                                  str(language))
                    actual_subtitles.append([
                        str(language),
                        path_replace_reverse_movie(
                            os.path.join(os.path.dirname(file), dest_folder,
                                         subtitle))
                    ])
                else:
                    if os.path.splitext(subtitle)[1] != ".sub":
                        logging.debug(
                            "BAZARR falling back to file content analysis to detect language."
                        )
                        with open(
                                os.path.join(os.path.dirname(file),
                                             dest_folder, subtitle), 'r') as f:
                            text = list(islice(f, 100))
                            text = ' '.join(text)
                            encoding = UnicodeDammit(text)
                            try:
                                text = text.decode(encoding.original_encoding)
                                detected_language = langdetect.detect(text)
                            except Exception as e:
                                logging.exception(
                                    'BAZARR Error trying to detect language for this subtitles file: '
                                    + os.path.join(os.path.dirname(file),
                                                   subtitle) +
                                    ' You should try to delete this subtitles file manually and ask Bazarr to download it again.'
                                )
                            else:
                                if len(detected_language) > 0:
                                    logging.debug(
                                        "BAZARR external subtitles detected and analysis guessed this language: "
                                        + str(detected_language))
                                    actual_subtitles.append([
                                        str(detected_language),
                                        path_replace_reverse_movie(
                                            os.path.join(
                                                os.path.dirname(file),
                                                dest_folder, subtitle))
                                    ])

        update_count = TableMovies.update({
            TableMovies.subtitles:
            str(actual_subtitles)
        }).where(
            TableMovies.path == path_replace_reverse_movie(file)).execute()
        if update_count > 0:
            logging.debug("BAZARR storing those languages to DB: " +
                          str(actual_subtitles))
        else:
            logging.debug(
                "BAZARR haven't been able to update existing subtitles to DB : "
                + str(actual_subtitles))
    else:
        logging.debug(
            "BAZARR this file doesn't seems to exist or isn't accessible.")

    logging.debug('BAZARR ended subtitles indexing for this file: ' + file)

    return actual_subtitles
Пример #6
0
def update_movies(send_event=True):
    check_radarr_rootfolder()
    logging.debug('BAZARR Starting movie sync from Radarr.')
    apikey_radarr = settings.radarr.apikey

    movie_default_enabled = settings.general.getboolean(
        'movie_default_enabled')

    if movie_default_enabled is True:
        movie_default_profile = settings.general.movie_default_profile
        if movie_default_profile == '':
            movie_default_profile = None
    else:
        movie_default_profile = None

    if apikey_radarr is None:
        pass
    else:
        audio_profiles = get_profile_list()
        tagsDict = get_tags()

        # Get movies data from radarr
        movies = get_movies_from_radarr_api(url=url_radarr(),
                                            apikey_radarr=apikey_radarr)
        if not movies:
            return
        else:
            # Get current movies in DB
            current_movies_db = TableMovies.select(
                TableMovies.tmdbId, TableMovies.path,
                TableMovies.radarrId).dicts()

            current_movies_db_list = [x['tmdbId'] for x in current_movies_db]

            current_movies_radarr = []
            movies_to_update = []
            movies_to_add = []
            altered_movies = []

            # Build new and updated movies
            movies_count = len(movies)
            for i, movie in enumerate(movies):
                if send_event:
                    show_progress(id='movies_progress',
                                  header='Syncing movies...',
                                  name=movie['title'],
                                  value=i,
                                  count=movies_count)

                if movie['hasFile'] is True:
                    if 'movieFile' in movie:
                        if movie['movieFile']['size'] > 20480:
                            # Add movies in radarr to current movies list
                            current_movies_radarr.append(str(movie['tmdbId']))

                            if str(movie['tmdbId']) in current_movies_db_list:
                                movies_to_update.append(
                                    movieParser(movie,
                                                action='update',
                                                tags_dict=tagsDict,
                                                movie_default_profile=
                                                movie_default_profile,
                                                audio_profiles=audio_profiles))
                            else:
                                movies_to_add.append(
                                    movieParser(movie,
                                                action='insert',
                                                tags_dict=tagsDict,
                                                movie_default_profile=
                                                movie_default_profile,
                                                audio_profiles=audio_profiles))

            if send_event:
                hide_progress(id='movies_progress')

            # Remove old movies from DB
            removed_movies = list(
                set(current_movies_db_list) - set(current_movies_radarr))

            for removed_movie in removed_movies:
                try:
                    TableMovies.delete().where(
                        TableMovies.tmdbId == removed_movie).execute()
                except Exception as e:
                    logging.error(
                        f"BAZARR cannot remove movie tmdbId {removed_movie} because of {e}"
                    )
                    continue

            # Update movies in DB
            movies_in_db_list = []
            movies_in_db = TableMovies.select(
                TableMovies.radarrId, TableMovies.title, TableMovies.path,
                TableMovies.tmdbId, TableMovies.overview, TableMovies.poster,
                TableMovies.fanart, TableMovies.audio_language,
                TableMovies.sceneName, TableMovies.monitored,
                TableMovies.sortTitle, TableMovies.year,
                TableMovies.alternativeTitles, TableMovies.format,
                TableMovies.resolution, TableMovies.video_codec,
                TableMovies.audio_codec, TableMovies.imdbId,
                TableMovies.movie_file_id, TableMovies.tags,
                TableMovies.file_size).dicts()

            for item in movies_in_db:
                movies_in_db_list.append(item)

            movies_to_update_list = [
                i for i in movies_to_update if i not in movies_in_db_list
            ]

            for updated_movie in movies_to_update_list:
                try:
                    TableMovies.update(updated_movie).where(
                        TableMovies.tmdbId ==
                        updated_movie['tmdbId']).execute()
                except IntegrityError as e:
                    logging.error(
                        f"BAZARR cannot update movie {updated_movie['path']} because of {e}"
                    )
                    continue
                else:
                    altered_movies.append([
                        updated_movie['tmdbId'], updated_movie['path'],
                        updated_movie['radarrId'], updated_movie['monitored']
                    ])

            # Insert new movies in DB
            for added_movie in movies_to_add:
                try:
                    result = TableMovies.insert(added_movie).on_conflict(
                        action='IGNORE').execute()
                except IntegrityError as e:
                    logging.error(
                        f"BAZARR cannot insert movie {added_movie['path']} because of {e}"
                    )
                    continue
                else:
                    if result > 0:
                        altered_movies.append([
                            added_movie['tmdbId'], added_movie['path'],
                            added_movie['radarrId'], added_movie['monitored']
                        ])
                        if send_event:
                            event_stream(type='movie',
                                         action='update',
                                         payload=int(added_movie['radarrId']))
                    else:
                        logging.debug(
                            'BAZARR unable to insert this movie into the database:',
                            path_mappings.path_replace_movie(
                                added_movie['path']))

            # Store subtitles for added or modified movies
            for i, altered_movie in enumerate(altered_movies, 1):
                store_subtitles_movie(
                    altered_movie[1],
                    path_mappings.path_replace_movie(altered_movie[1]))

            logging.debug(
                'BAZARR All movies synced from Radarr into database.')
Пример #7
0
def update_one_movie(movie_id, action):
    logging.debug(
        'BAZARR syncing this specific movie from Radarr: {}'.format(movie_id))

    # Check if there's a row in database for this movie ID
    existing_movie = TableMovies.select(TableMovies.path)\
        .where(TableMovies.radarrId == movie_id)\
        .dicts()\
        .get_or_none()

    # Remove movie from DB
    if action == 'deleted':
        if existing_movie:
            try:
                TableMovies.delete().where(
                    TableMovies.radarrId == movie_id).execute()
            except Exception as e:
                logging.error(
                    f"BAZARR cannot delete movie {existing_movie['path']} because of {e}"
                )
            else:
                event_stream(type='movie',
                             action='delete',
                             payload=int(movie_id))
                logging.debug(
                    'BAZARR deleted this movie from the database:{}'.format(
                        path_mappings.path_replace_movie(
                            existing_movie['path'])))
        return

    movie_default_enabled = settings.general.getboolean(
        'movie_default_enabled')

    if movie_default_enabled is True:
        movie_default_profile = settings.general.movie_default_profile
        if movie_default_profile == '':
            movie_default_profile = None
    else:
        movie_default_profile = None

    audio_profiles = get_profile_list()
    tagsDict = get_tags()

    try:
        # Get movie data from radarr api
        movie = None
        movie_data = get_movies_from_radarr_api(
            url=url_radarr(),
            apikey_radarr=settings.radarr.apikey,
            radarr_id=movie_id)
        if not movie_data:
            return
        else:
            if action == 'updated' and existing_movie:
                movie = movieParser(
                    movie_data,
                    action='update',
                    tags_dict=tagsDict,
                    movie_default_profile=movie_default_profile,
                    audio_profiles=audio_profiles)
            elif action == 'updated' and not existing_movie:
                movie = movieParser(
                    movie_data,
                    action='insert',
                    tags_dict=tagsDict,
                    movie_default_profile=movie_default_profile,
                    audio_profiles=audio_profiles)
    except Exception:
        logging.debug(
            'BAZARR cannot get movie returned by SignalR feed from Radarr API.'
        )
        return

    # Drop useless events
    if not movie and not existing_movie:
        return

    # Remove movie from DB
    if not movie and existing_movie:
        try:
            TableMovies.delete().where(
                TableMovies.radarrId == movie_id).execute()
        except Exception as e:
            logging.error(
                f"BAZARR cannot insert episode {existing_movie['path']} because of {e}"
            )
        else:
            event_stream(type='movie', action='delete', payload=int(movie_id))
            logging.debug(
                'BAZARR deleted this movie from the database:{}'.format(
                    path_mappings.path_replace_movie(existing_movie['path'])))
            return

    # Update existing movie in DB
    elif movie and existing_movie:
        try:
            TableMovies.update(movie).where(
                TableMovies.radarrId == movie['radarrId']).execute()
        except IntegrityError as e:
            logging.error(
                f"BAZARR cannot insert episode {movie['path']} because of {e}")
        else:
            event_stream(type='movie', action='update', payload=int(movie_id))
            logging.debug(
                'BAZARR updated this movie into the database:{}'.format(
                    path_mappings.path_replace_movie(movie['path'])))

    # Insert new movie in DB
    elif movie and not existing_movie:
        try:
            TableMovies.insert(movie).on_conflict(action='IGNORE').execute()
        except IntegrityError as e:
            logging.error(
                f"BAZARR cannot insert movie {movie['path']} because of {e}")
        else:
            event_stream(type='movie', action='update', payload=int(movie_id))
            logging.debug(
                'BAZARR inserted this movie into the database:{}'.format(
                    path_mappings.path_replace_movie(movie['path'])))

    # Storing existing subtitles
    logging.debug('BAZARR storing subtitles for this movie: {}'.format(
        path_mappings.path_replace_movie(movie['path'])))
    store_subtitles_movie(movie['path'],
                          path_mappings.path_replace_movie(movie['path']))

    # Downloading missing subtitles
    logging.debug(
        'BAZARR downloading missing subtitles for this movie: {}'.format(
            path_mappings.path_replace_movie(movie['path'])))
    movies_download_subtitles(movie_id)
Пример #8
0
def update_movies():
    logging.debug('BAZARR Starting movie sync from Radarr.')
    apikey_radarr = settings.radarr.apikey
    movie_default_enabled = settings.general.getboolean(
        'movie_default_enabled')
    movie_default_language = settings.general.movie_default_language
    movie_default_hi = settings.general.movie_default_hi
    movie_default_forced = settings.general.movie_default_forced

    if apikey_radarr is None:
        pass
    else:
        audio_profiles = get_profile_list()

        # Get movies data from radarr
        url_radarr_api_movies = url_radarr + "/api/movie?apikey=" + apikey_radarr
        try:
            r = requests.get(url_radarr_api_movies, timeout=60, verify=False)
            r.raise_for_status()
        except requests.exceptions.HTTPError as errh:
            logging.exception(
                "BAZARR Error trying to get movies from Radarr. Http error.")
            return
        except requests.exceptions.ConnectionError as errc:
            logging.exception(
                "BAZARR Error trying to get movies from Radarr. Connection Error."
            )
            return
        except requests.exceptions.Timeout as errt:
            logging.exception(
                "BAZARR Error trying to get movies from Radarr. Timeout Error."
            )
            return
        except requests.exceptions.RequestException as err:
            logging.exception("BAZARR Error trying to get movies from Radarr.")
            return
        else:
            # Get current movies in DB
            current_movies_db = TableMovies.select(TableMovies.tmdb_id,
                                                   TableMovies.path,
                                                   TableMovies.radarr_id)

            current_movies_db_list = [x.tmdb_id for x in current_movies_db]

            current_movies_radarr = []
            movies_to_update = []
            movies_to_add = []
            altered_movies = []

            moviesIdListLength = len(r.json())
            for i, movie in enumerate(r.json(), 1):
                notifications.write(msg="Getting movies data from Radarr...",
                                    queue='get_movies',
                                    item=i,
                                    length=moviesIdListLength)
                if movie['hasFile'] is True:
                    if 'movieFile' in movie:
                        # Detect file separator
                        if movie['path'][0] == "/":
                            separator = "/"
                        else:
                            separator = "\\"

                        if movie["path"] != None and movie['movieFile'][
                                'relativePath'] != None:
                            try:
                                overview = unicode(movie['overview'])
                            except:
                                overview = ""
                            try:
                                poster_big = movie['images'][0]['url']
                                poster = os.path.splitext(
                                    poster_big)[0] + '-500' + os.path.splitext(
                                        poster_big)[1]
                            except:
                                poster = ""
                            try:
                                fanart = movie['images'][1]['url']
                            except:
                                fanart = ""

                            if 'sceneName' in movie['movieFile']:
                                sceneName = movie['movieFile']['sceneName']
                            else:
                                sceneName = None

                            if 'alternativeTitles' in movie:
                                alternativeTitles = str([
                                    item['title']
                                    for item in movie['alternativeTitles']
                                ])
                            else:
                                alternativeTitles = None

                            if 'imdbId' in movie: imdbId = movie['imdbId']
                            else: imdbId = None

                            try:
                                format, resolution = movie['movieFile'][
                                    'quality']['quality']['name'].split('-')
                            except:
                                format = movie['movieFile']['quality'][
                                    'quality']['name']
                            try:
                                resolution = movie['movieFile']['quality'][
                                    'quality']['resolution'].lstrip(
                                        'r').lower()
                            except:
                                resolution = None

                            if 'mediaInfo' in movie['movieFile']:
                                videoFormat = videoCodecID = videoProfile = videoCodecLibrary = None
                                if 'videoFormat' in movie['movieFile'][
                                        'mediaInfo']:
                                    videoFormat = movie['movieFile'][
                                        'mediaInfo']['videoFormat']
                                if 'videoCodecID' in movie['movieFile'][
                                        'mediaInfo']:
                                    videoCodecID = movie['movieFile'][
                                        'mediaInfo']['videoCodecID']
                                if 'videoProfile' in movie['movieFile'][
                                        'mediaInfo']:
                                    videoProfile = movie['movieFile'][
                                        'mediaInfo']['videoProfile']
                                if 'videoCodecLibrary' in movie['movieFile'][
                                        'mediaInfo']:
                                    videoCodecLibrary = movie['movieFile'][
                                        'mediaInfo']['videoCodecLibrary']
                                videoCodec = RadarrFormatVideoCodec(
                                    videoFormat, videoCodecID, videoProfile,
                                    videoCodecLibrary)

                                audioFormat = audioCodecID = audioProfile = audioAdditionalFeatures = None
                                if 'audioFormat' in movie['movieFile'][
                                        'mediaInfo']:
                                    audioFormat = movie['movieFile'][
                                        'mediaInfo']['audioFormat']
                                if 'audioCodecID' in movie['movieFile'][
                                        'mediaInfo']:
                                    audioCodecID = movie['movieFile'][
                                        'mediaInfo']['audioCodecID']
                                if 'audioProfile' in movie['movieFile'][
                                        'mediaInfo']:
                                    audioProfile = movie['movieFile'][
                                        'mediaInfo']['audioProfile']
                                if 'audioAdditionalFeatures' in movie[
                                        'movieFile']['mediaInfo']:
                                    audioAdditionalFeatures = movie[
                                        'movieFile']['mediaInfo'][
                                            'audioAdditionalFeatures']
                                audioCodec = RadarrFormatAudioCodec(
                                    audioFormat, audioCodecID, audioProfile,
                                    audioAdditionalFeatures)
                            else:
                                videoCodec = None
                                audioCodec = None

                            # Add movies in radarr to current movies list
                            current_movies_radarr.append(
                                unicode(movie['tmdbId']))

                            if unicode(
                                    movie['tmdbId']) in current_movies_db_list:
                                movies_to_update.append({
                                    'radarr_id':
                                    movie["id"],
                                    'title':
                                    unicode(movie["title"]),
                                    'path':
                                    unicode(
                                        movie["path"] + separator +
                                        movie['movieFile']['relativePath']),
                                    'tmdb_id':
                                    unicode(movie["tmdbId"]),
                                    'poster':
                                    unicode(poster),
                                    'fanart':
                                    unicode(fanart),
                                    'audio_language':
                                    unicode(
                                        profile_id_to_language(
                                            movie['qualityProfileId'],
                                            audio_profiles)),
                                    'scene_name':
                                    sceneName,
                                    'monitored':
                                    unicode(bool(movie['monitored'])),
                                    'year':
                                    unicode(movie['year']),
                                    'sort_title':
                                    unicode(movie['sortTitle']),
                                    'alternative_titles':
                                    unicode(alternativeTitles),
                                    'format':
                                    unicode(format),
                                    'resolution':
                                    unicode(resolution),
                                    'video_codec':
                                    unicode(videoCodec),
                                    'audio_codec':
                                    unicode(audioCodec),
                                    'overview':
                                    unicode(overview),
                                    'imdb_id':
                                    unicode(imdbId),
                                    'movie_file_id':
                                    movie['movieFile']['id']
                                })
                            else:
                                if movie_default_enabled is True:
                                    movies_to_add.append({
                                        'radarr_id':
                                        movie["id"],
                                        'title':
                                        movie["title"],
                                        'path':
                                        movie["path"] + separator +
                                        movie['movieFile']['relativePath'],
                                        'tmdb_id':
                                        movie["tmdbId"],
                                        'languages':
                                        movie_default_language,
                                        'subtitles':
                                        '[]',
                                        'hearing_impaired':
                                        movie_default_hi,
                                        'overview':
                                        overview,
                                        'poster':
                                        poster,
                                        'fanart':
                                        fanart,
                                        'audio_language':
                                        profile_id_to_language(
                                            movie['qualityProfileId'],
                                            audio_profiles),
                                        'scene_name':
                                        sceneName,
                                        'monitored':
                                        unicode(bool(movie['monitored'])),
                                        'sort_title':
                                        movie['sortTitle'],
                                        'year':
                                        movie['year'],
                                        'alternative_titles':
                                        alternativeTitles,
                                        'format':
                                        format,
                                        'resolution':
                                        resolution,
                                        'video_codec':
                                        videoCodec,
                                        'audio_codec':
                                        audioCodec,
                                        'imdb_id':
                                        imdbId,
                                        'forced':
                                        movie_default_forced,
                                        'movie_file_id':
                                        movie['movieFile']['id']
                                    })
                                else:
                                    movies_to_add.append({
                                        'radarr_id':
                                        movie["id"],
                                        'title':
                                        movie["title"],
                                        'path':
                                        movie["path"] + separator +
                                        movie['movieFile']['relativePath'],
                                        'tmdb_id':
                                        movie["tmdbId"],
                                        'overview':
                                        overview,
                                        'poster':
                                        poster,
                                        'fanart':
                                        fanart,
                                        'audio_language':
                                        profile_id_to_language(
                                            movie['qualityProfileId'],
                                            audio_profiles),
                                        'scene_name':
                                        sceneName,
                                        'monitored':
                                        unicode(bool(movie['monitored'])),
                                        'sort_title':
                                        movie['sortTitle'],
                                        'year':
                                        movie['year'],
                                        'alternative_titles':
                                        alternativeTitles,
                                        'format':
                                        format,
                                        'resolution':
                                        resolution,
                                        'video_codec':
                                        videoCodec,
                                        'audio_codec':
                                        audioCodec,
                                        'imdb_id':
                                        imdbId,
                                        'movie_file_id':
                                        movie['movieFile']['id']
                                    })
                        else:
                            logging.error(
                                'BAZARR Radarr returned a movie without a file path: '
                                + movie["path"] + separator +
                                movie['movieFile']['relativePath'])

            # Update or insert movies in DB
            movies_in_db_list = []
            movies_in_db = TableMovies.select(
                TableMovies.radarr_id, TableMovies.title, TableMovies.path,
                TableMovies.tmdb_id, TableMovies.overview, TableMovies.poster,
                TableMovies.fanart, TableMovies.audio_language,
                TableMovies.scene_name, TableMovies.monitored,
                TableMovies.sort_title, TableMovies.year,
                TableMovies.alternative_titles, TableMovies.format,
                TableMovies.resolution, TableMovies.video_codec,
                TableMovies.audio_codec, TableMovies.imdb_id,
                TableMovies.movie_file_id).dicts()

            for item in movies_in_db:
                movies_in_db_list.append(item)

            movies_to_update_list = [
                i for i in movies_to_update if i not in movies_in_db_list
            ]

            for updated_movie in movies_to_update_list:
                TableMovies.update(updated_movie).where(
                    TableMovies.radarr_id ==
                    updated_movie['radarr_id']).execute()
                altered_movies.append([
                    updated_movie['tmdb_id'], updated_movie['path'],
                    updated_movie['radarr_id']
                ])

            # Insert new movies in DB
            for added_movie in movies_to_add:
                TableMovies.insert(added_movie).on_conflict_ignore().execute()
                altered_movies.append([
                    added_movie['tmdb_id'], added_movie['path'],
                    added_movie['radarr_id']
                ])

            # Remove old movies from DB
            removed_movies = list(
                set(current_movies_db_list) - set(current_movies_radarr))

            for removed_movie in removed_movies:
                TableMovies.delete().where(
                    TableMovies.tmdb_id == removed_movie).execute()

            # Store subtitles for added or modified movies
            for i, altered_movie in enumerate(altered_movies, 1):
                notifications.write(
                    msg='Indexing movies embedded subtitles...',
                    queue='get_movies',
                    item=i,
                    length=len(altered_movies))
                store_subtitles_movie(path_replace_movie(altered_movie[1]))
                list_missing_subtitles_movies(altered_movie[2])

            logging.debug(
                'BAZARR All movies synced from Radarr into database.')

            # Search for desired subtitles if no more than 5 movies have been added.
            if len(altered_movies) <= 5:
                logging.debug(
                    "BAZARR No more than 5 movies were added during this sync then we'll search for subtitles."
                )
                for altered_movie in altered_movies:
                    movies_download_subtitles(altered_movie[2])
            else:
                logging.debug(
                    "BAZARR More than 5 movies were added during this sync then we wont search for subtitles."
                )
Пример #9
0
def _wanted_movie(movie):
    audio_language_list = get_audio_profile_languages(movie_id=movie['radarrId'])
    if len(audio_language_list) > 0:
        audio_language = audio_language_list[0]['name']
    else:
        audio_language = 'None'

    languages = []

    for language in ast.literal_eval(movie['missing_subtitles']):
        # confirm if language is still missing or if cutoff have been reached
        confirmed_missing_subs = TableMovies.select(TableMovies.missing_subtitles) \
            .where(TableMovies.radarrId == movie['radarrId']) \
            .dicts() \
            .get_or_none()
        if not confirmed_missing_subs:
            continue

        if language not in ast.literal_eval(confirmed_missing_subs['missing_subtitles']):
            continue

        if is_search_active(desired_language=language, attempt_string=movie['failedAttempts']):
            TableMovies.update({TableMovies.failedAttempts:
                                updateFailedAttempts(desired_language=language,
                                                     attempt_string=movie['failedAttempts'])}) \
                .where(TableMovies.radarrId == movie['radarrId']) \
                .execute()

            hi_ = "True" if language.endswith(':hi') else "False"
            forced_ = "True" if language.endswith(':forced') else "False"
            languages.append((language.split(":")[0], hi_, forced_))

        else:
            logging.info(f"BAZARR Search is throttled by adaptive search for this movie {movie['path']} and "
                         f"language: {language}")

    for result in generate_subtitles(path_mappings.path_replace_movie(movie['path']),
                                     languages,
                                     audio_language,
                                     str(movie['sceneName']),
                                     movie['title'], 'movie'):

        if result:
            message = result[0]
            path = result[1]
            forced = result[5]
            if result[8]:
                language_code = result[2] + ":hi"
            elif forced:
                language_code = result[2] + ":forced"
            else:
                language_code = result[2]
            provider = result[3]
            score = result[4]
            subs_id = result[6]
            subs_path = result[7]
            store_subtitles_movie(movie['path'], path_mappings.path_replace_movie(movie['path']))
            history_log_movie(1, movie['radarrId'], message, path, language_code, provider, score,
                              subs_id, subs_path)
            event_stream(type='movie-wanted', action='delete', payload=movie['radarrId'])
            send_notifications_movie(movie['radarrId'], message)
Пример #10
0
def list_missing_subtitles_movies(no=None, send_event=True):
    movies_subtitles = TableMovies.select(TableMovies.radarrId,
                                          TableMovies.subtitles,
                                          TableMovies.profileId,
                                          TableMovies.audio_language)\
        .where((TableMovies.radarrId == no) if no else None)\
        .dicts()
    if isinstance(movies_subtitles, str):
        logging.error("BAZARR list missing subtitles query to DB returned this instead of rows: " + movies_subtitles)
        return

    use_embedded_subs = settings.general.getboolean('use_embedded_subs')

    for movie_subtitles in movies_subtitles:
        missing_subtitles_text = '[]'
        if movie_subtitles['profileId']:
            # get desired subtitles
            desired_subtitles_temp = get_profiles_list(profile_id=movie_subtitles['profileId'])
            desired_subtitles_list = []
            if desired_subtitles_temp:
                for language in desired_subtitles_temp['items']:
                    if language['audio_exclude'] == "True":
                        if language_from_alpha2(language['language']) in ast.literal_eval(
                                movie_subtitles['audio_language']):
                            continue
                    desired_subtitles_list.append([language['language'], language['forced'], language['hi']])

            # get existing subtitles
            actual_subtitles_list = []
            if movie_subtitles['subtitles'] is not None:
                if use_embedded_subs:
                    actual_subtitles_temp = ast.literal_eval(movie_subtitles['subtitles'])
                else:
                    actual_subtitles_temp = [x for x in ast.literal_eval(movie_subtitles['subtitles']) if x[1]]

                for subtitles in actual_subtitles_temp:
                    subtitles = subtitles[0].split(':')
                    lang = subtitles[0]
                    forced = False
                    hi = False
                    if len(subtitles) > 1:
                        if subtitles[1] == 'forced':
                            forced = True
                            hi = False
                        elif subtitles[1] == 'hi':
                            forced = False
                            hi = True
                    actual_subtitles_list.append([lang, str(forced), str(hi)])

            # check if cutoff is reached and skip any further check
            cutoff_met = False
            cutoff_temp_list = get_profile_cutoff(profile_id=movie_subtitles['profileId'])

            if cutoff_temp_list:
                for cutoff_temp in cutoff_temp_list:
                    cutoff_language = [cutoff_temp['language'], cutoff_temp['forced'], cutoff_temp['hi']]
                    if cutoff_temp['audio_exclude'] == 'True' and language_from_alpha2(cutoff_temp['language']) in \
                            ast.literal_eval(movie_subtitles['audio_language']):
                        cutoff_met = True
                    elif cutoff_language in actual_subtitles_list:
                        cutoff_met = True
                    elif cutoff_language and [cutoff_language[0], 'True', 'False'] in actual_subtitles_list:
                        cutoff_met = True
                    elif cutoff_language and [cutoff_language[0], 'False', 'True'] in actual_subtitles_list:
                        cutoff_met = True

            if cutoff_met:
                missing_subtitles_text = str([])
            else:
                # get difference between desired and existing subtitles
                missing_subtitles_list = []
                for item in desired_subtitles_list:
                    if item not in actual_subtitles_list:
                        missing_subtitles_list.append(item)

                # remove missing that have forced or hi subtitles for this language in existing
                for item in actual_subtitles_list:
                    if item[2] == 'True':
                        try:
                            missing_subtitles_list.remove([item[0], 'False', 'False'])
                        except ValueError:
                            pass

                # make the missing languages list looks like expected
                missing_subtitles_output_list = []
                for item in missing_subtitles_list:
                    lang = item[0]
                    if item[1] == 'True':
                        lang += ':forced'
                    elif item[2] == 'True':
                        lang += ':hi'
                    missing_subtitles_output_list.append(lang)

                missing_subtitles_text = str(missing_subtitles_output_list)

        TableMovies.update({TableMovies.missing_subtitles: missing_subtitles_text})\
            .where(TableMovies.radarrId == movie_subtitles['radarrId'])\
            .execute()

        if send_event:
            event_stream(type='movie', payload=movie_subtitles['radarrId'])
            event_stream(type='badges')
Пример #11
0
def store_subtitles_movie(original_path, reversed_path, use_cache=True):
    logging.debug('BAZARR started subtitles indexing for this file: ' + reversed_path)
    actual_subtitles = []
    if os.path.exists(reversed_path):
        if settings.general.getboolean('use_embedded_subs'):
            logging.debug("BAZARR is trying to index embedded subtitles.")
            item = TableMovies.select(TableMovies.movie_file_id, TableMovies.file_size)\
                .where(TableMovies.path == original_path)\
                .dicts()\
                .get_or_none()
            if not item:
                logging.exception(f"BAZARR error when trying to select this movie from database: {reversed_path}")
            else:
                try:
                    subtitle_languages = embedded_subs_reader(reversed_path,
                                                              file_size=item['file_size'],
                                                              movie_file_id=item['movie_file_id'],
                                                              use_cache=use_cache)
                    for subtitle_language, subtitle_forced, subtitle_hi, subtitle_codec in subtitle_languages:
                        try:
                            if (settings.general.getboolean("ignore_pgs_subs") and subtitle_codec.lower() == "pgs") or \
                                    (settings.general.getboolean("ignore_vobsub_subs") and subtitle_codec.lower() ==
                                     "vobsub") or \
                                    (settings.general.getboolean("ignore_ass_subs") and subtitle_codec.lower() ==
                                     "ass"):
                                logging.debug("BAZARR skipping %s sub for language: %s" % (subtitle_codec, alpha2_from_alpha3(subtitle_language)))
                                continue

                            if alpha2_from_alpha3(subtitle_language) is not None:
                                lang = str(alpha2_from_alpha3(subtitle_language))
                                if subtitle_forced:
                                    lang = lang + ':forced'
                                if subtitle_hi:
                                    lang = lang + ':hi'
                                logging.debug("BAZARR embedded subtitles detected: " + lang)
                                actual_subtitles.append([lang, None])
                        except Exception:
                            logging.debug("BAZARR unable to index this unrecognized language: " + subtitle_language)
                            pass
                except Exception:
                    logging.exception(
                        "BAZARR error when trying to analyze this %s file: %s" % (os.path.splitext(reversed_path)[1],
                                                                                  reversed_path))
                    pass

        try:
            dest_folder = get_subtitle_destination_folder() or ''
            core.CUSTOM_PATHS = [dest_folder] if dest_folder else []
            subtitles = search_external_subtitles(reversed_path, languages=get_language_set())
            full_dest_folder_path = os.path.dirname(reversed_path)
            if dest_folder:
                if settings.general.subfolder == "absolute":
                    full_dest_folder_path = dest_folder
                elif settings.general.subfolder == "relative":
                    full_dest_folder_path = os.path.join(os.path.dirname(reversed_path), dest_folder)
            subtitles = guess_external_subtitles(full_dest_folder_path, subtitles)
        except Exception:
            logging.exception("BAZARR unable to index external subtitles.")
            pass
        else:
            for subtitle, language in subtitles.items():
                valid_language = False
                if language:
                    if hasattr(language, 'alpha3'):
                        valid_language = alpha2_from_alpha3(language.alpha3)
                else:
                    logging.debug(f"Skipping subtitles because we are unable to define language: {subtitle}")
                    continue

                if not valid_language:
                    logging.debug(f'{language.alpha3} is an unsupported language code.')
                    continue

                subtitle_path = get_external_subtitles_path(reversed_path, subtitle)
                custom = CustomLanguage.found_external(subtitle, subtitle_path)

                if custom is not None:
                    actual_subtitles.append([custom, path_mappings.path_replace_reverse_movie(subtitle_path)])

                elif str(language.basename) != 'und':
                    if language.forced:
                        language_str = str(language)
                    elif language.hi:
                        language_str = str(language) + ':hi'
                    else:
                        language_str = str(language)
                    logging.debug("BAZARR external subtitles detected: " + language_str)
                    actual_subtitles.append([language_str, path_mappings.path_replace_reverse_movie(subtitle_path)])

        TableMovies.update({TableMovies.subtitles: str(actual_subtitles)})\
            .where(TableMovies.path == original_path)\
            .execute()
        matching_movies = TableMovies.select(TableMovies.radarrId).where(TableMovies.path == original_path).dicts()

        for movie in matching_movies:
            if movie:
                logging.debug("BAZARR storing those languages to DB: " + str(actual_subtitles))
                list_missing_subtitles_movies(no=movie['radarrId'])
            else:
                logging.debug("BAZARR haven't been able to update existing subtitles to DB : " + str(actual_subtitles))
    else:
        logging.debug("BAZARR this file doesn't seems to exist or isn't accessible.")

    logging.debug('BAZARR ended subtitles indexing for this file: ' + reversed_path)

    return actual_subtitles