def get(self): episodes_conditions = [ (TableEpisodes.missing_subtitles.is_null(False)), (TableEpisodes.missing_subtitles != '[]') ] episodes_conditions += get_exclusion_clause('series') missing_episodes = TableEpisodes.select(TableShows.tags, TableShows.seriesType, TableEpisodes.monitored)\ .join(TableShows, on=(TableEpisodes.sonarrSeriesId == TableShows.sonarrSeriesId))\ .where(reduce(operator.and_, episodes_conditions))\ .count() movies_conditions = [(TableMovies.missing_subtitles.is_null(False)), (TableMovies.missing_subtitles != '[]')] movies_conditions += get_exclusion_clause('movie') missing_movies = TableMovies.select(TableMovies.tags, TableMovies.monitored)\ .where(reduce(operator.and_, movies_conditions))\ .count() throttled_providers = len(get_throttled_providers()) health_issues = len(get_health_issues()) result = { "episodes": missing_episodes, "movies": missing_movies, "providers": throttled_providers, "status": health_issues } return jsonify(result)
def get(self): query = request.args.get('query') search_list = [] if query: if settings.general.getboolean('use_sonarr'): # Get matching series series = TableShows.select(TableShows.title, TableShows.sonarrSeriesId, TableShows.year)\ .where(TableShows.title.contains(query))\ .order_by(TableShows.title)\ .dicts() series = list(series) search_list += series if settings.general.getboolean('use_radarr'): # Get matching movies movies = TableMovies.select(TableMovies.title, TableMovies.radarrId, TableMovies.year) \ .where(TableMovies.title.contains(query)) \ .order_by(TableMovies.title) \ .dicts() movies = list(movies) search_list += movies return jsonify(search_list)
def post(self): radarr_id = int(request.args.get('radarrid')) provider = request.form.get('provider') subs_id = request.form.get('subs_id') language = request.form.get('language') # TODO forced = False hi = False data = TableMovies.select(TableMovies.path).where(TableMovies.radarrId == radarr_id).dicts().get() media_path = data['path'] subtitles_path = request.form.get('subtitles_path') blacklist_log_movie(radarr_id=radarr_id, provider=provider, subs_id=subs_id, language=language) delete_subtitles(media_type='movie', language=language, forced=forced, hi=hi, media_path=path_mappings.path_replace_movie(media_path), subtitles_path=subtitles_path, radarr_id=radarr_id) movies_download_subtitles(radarr_id) event_stream(type='movie-history') return '', 200
def get(self): # Manual Search radarrId = request.args.get('radarrid') movieInfo = TableMovies.select(TableMovies.title, TableMovies.path, TableMovies.sceneName, TableMovies.profileId) \ .where(TableMovies.radarrId == radarrId) \ .dicts() \ .get_or_none() if not movieInfo: return 'Movie not found', 500 title = movieInfo['title'] moviePath = path_mappings.path_replace_movie(movieInfo['path']) sceneName = movieInfo['sceneName'] or "None" profileId = movieInfo['profileId'] providers_list = get_providers() data = manual_search(moviePath, profileId, providers_list, sceneName, title, 'movie') if not data: data = [] return jsonify(data=data)
def wanted_search_missing_subtitles_movies(): conditions = [(TableMovies.missing_subtitles != '[]')] conditions += get_exclusion_clause('movie') movies = TableMovies.select(TableMovies.radarrId, TableMovies.tags, TableMovies.monitored, TableMovies.title) \ .where(reduce(operator.and_, conditions)) \ .dicts() movies = list(movies) count_movies = len(movies) for i, movie in enumerate(movies): show_progress(id='wanted_movies_progress', header='Searching subtitles...', name=movie['title'], value=i, count=count_movies) providers = get_providers() if providers: wanted_download_subtitles_movie(movie['radarrId']) else: logging.info("BAZARR All providers are throttled") break hide_progress(id='wanted_movies_progress') logging.info('BAZARR Finished searching for missing Movies Subtitles. Check History for more information.')
def delete(self): # Delete radarrId = request.args.get('radarrid') movieInfo = TableMovies.select(TableMovies.path) \ .where(TableMovies.radarrId == radarrId) \ .dicts() \ .get_or_none() if not movieInfo: return 'Movie not found', 500 moviePath = path_mappings.path_replace_movie(movieInfo['path']) language = request.form.get('language') forced = request.form.get('forced') hi = request.form.get('hi') subtitlesPath = request.form.get('path') subtitlesPath = path_mappings.path_replace_reverse_movie(subtitlesPath) result = delete_subtitles(media_type='movie', language=language, forced=forced, hi=hi, media_path=moviePath, subtitles_path=subtitlesPath, radarr_id=radarrId) if result: return '', 202 else: return '', 204
def get_movie(radarr_id): data = TableMovies.select(TableMovies.title, TableMovies.year)\ .where(TableMovies.radarrId == radarr_id)\ .dicts()\ .get() return {'title': data['title'], 'year': data['year']}
def get(self): radarrid = request.args.getlist("radarrid[]") wanted_conditions = [(TableMovies.missing_subtitles != '[]')] if len(radarrid) > 0: wanted_conditions.append((TableMovies.radarrId.in_(radarrid))) wanted_conditions += get_exclusion_clause('movie') wanted_condition = reduce(operator.and_, wanted_conditions) if len(radarrid) > 0: result = TableMovies.select(TableMovies.title, TableMovies.missing_subtitles, TableMovies.radarrId, TableMovies.sceneName, TableMovies.failedAttempts, TableMovies.tags, TableMovies.monitored)\ .where(wanted_condition)\ .dicts() else: start = request.args.get('start') or 0 length = request.args.get('length') or -1 result = TableMovies.select(TableMovies.title, TableMovies.missing_subtitles, TableMovies.radarrId, TableMovies.sceneName, TableMovies.failedAttempts, TableMovies.tags, TableMovies.monitored)\ .where(wanted_condition)\ .order_by(TableMovies.rowid.desc())\ .limit(length)\ .offset(start)\ .dicts() result = list(result) for item in result: postprocessMovie(item) count_conditions = [(TableMovies.missing_subtitles != '[]')] count_conditions += get_exclusion_clause('movie') count = TableMovies.select(TableMovies.monitored, TableMovies.tags)\ .where(reduce(operator.and_, count_conditions))\ .count() return jsonify(data=result, total=count)
def movies_scan_subtitles(no): movies = TableMovies.select( TableMovies.path).where(TableMovies.radarr_id == no) for movie in movies: store_subtitles_movie(path_replace_movie(movie.path)) list_missing_subtitles_movies(no)
def movies_scan_subtitles(no): movies = TableMovies.select(TableMovies.path)\ .where(TableMovies.radarrId == no)\ .order_by(TableMovies.radarrId)\ .dicts() for movie in movies: store_subtitles_movie(movie['path'], path_mappings.path_replace_movie(movie['path']), use_cache=False)
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()
def refine_from_ffprobe(path, video): if isinstance(video, Movie): file_id = TableMovies.select(TableMovies.movie_file_id, TableMovies.file_size)\ .where(TableMovies.path == path_mappings.path_replace_reverse_movie(path))\ .dicts()\ .get_or_none() else: file_id = TableEpisodes.select(TableEpisodes.episode_file_id, TableEpisodes.file_size)\ .where(TableEpisodes.path == path_mappings.path_replace_reverse(path))\ .dicts()\ .get_or_none() if not file_id: return video if isinstance(video, Movie): data = parse_video_metadata(file=path, file_size=file_id['file_size'], movie_file_id=file_id['movie_file_id']) else: data = parse_video_metadata(file=path, file_size=file_id['file_size'], episode_file_id=file_id['episode_file_id']) if not data['ffprobe']: logging.debug("No FFprobe available in cache for this file: {}".format(path)) return video logging.debug('FFprobe found: %s', data['ffprobe']) if 'video' not in data['ffprobe']: logging.debug('BAZARR FFprobe was unable to find video tracks in the file!') else: if 'resolution' in data['ffprobe']['video'][0]: if not video.resolution: video.resolution = data['ffprobe']['video'][0]['resolution'] if 'codec' in data['ffprobe']['video'][0]: if not video.video_codec: video.video_codec = data['ffprobe']['video'][0]['codec'] if 'frame_rate' in data['ffprobe']['video'][0]: if not video.fps: if isinstance(data['ffprobe']['video'][0]['frame_rate'], float): video.fps = data['ffprobe']['video'][0]['frame_rate'] else: try: video.fps = data['ffprobe']['video'][0]['frame_rate'].magnitude except AttributeError: video.fps = data['ffprobe']['video'][0]['frame_rate'] if 'audio' not in data['ffprobe']: logging.debug('BAZARR FFprobe was unable to find audio tracks in the file!') else: if 'codec' in data['ffprobe']['audio'][0]: if not video.audio_codec: video.audio_codec = data['ffprobe']['audio'][0]['codec'] for track in data['ffprobe']['audio']: if 'language' in track: video.audio_languages.add(track['language'].alpha3) return video
def post(self): # Manual Download radarrId = request.args.get('radarrid') movieInfo = TableMovies.select(TableMovies.title, TableMovies.path, TableMovies.sceneName, TableMovies.audio_language) \ .where(TableMovies.radarrId == radarrId) \ .dicts() \ .get() title = movieInfo['title'] moviePath = path_mappings.path_replace_movie(movieInfo['path']) sceneName = movieInfo['sceneName'] if sceneName is None: sceneName = "None" audio_language = movieInfo['audio_language'] language = request.form.get('language') hi = request.form.get('hi').capitalize() forced = request.form.get('forced').capitalize() selected_provider = request.form.get('provider') subtitle = request.form.get('subtitle') providers_auth = get_providers_auth() audio_language_list = get_audio_profile_languages(movie_id=radarrId) if len(audio_language_list) > 0: audio_language = audio_language_list[0]['name'] else: audio_language = 'None' try: result = manual_download_subtitle(moviePath, language, audio_language, hi, forced, subtitle, selected_provider, providers_auth, sceneName, title, 'movie', profile_id=get_profile_id(movie_id=radarrId)) if result is not None: 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] history_log_movie(2, radarrId, message, path, language_code, provider, score, subs_id, subs_path) if not settings.general.getboolean('dont_notify_manual_actions'): send_notifications_movie(radarrId, message) store_subtitles_movie(path, moviePath) except OSError: pass return '', 204
def get(self): start = request.args.get('start') or 0 length = request.args.get('length') or -1 radarrId = request.args.getlist('radarrid[]') count = TableMovies.select().count() if len(radarrId) != 0: result = TableMovies.select()\ .where(TableMovies.radarrId.in_(radarrId))\ .order_by(TableMovies.sortTitle)\ .dicts() else: result = TableMovies.select().order_by( TableMovies.sortTitle).limit(length).offset(start).dicts() result = list(result) for item in result: postprocessMovie(item) return jsonify(data=result, total=count)
def movies_full_scan_subtitles(): movies = TableMovies.select(TableMovies.path) count_movies = movies.count() for i, movie in enumerate(movies, 1): notifications.write(msg='Updating all movies subtitles from disk...', queue='list_subtitles_movies', item=i, length=count_movies) store_subtitles_movie(path_replace_movie(movie.path)) gc.collect()
def movies_full_scan_subtitles(): use_ffprobe_cache = settings.radarr.getboolean('use_ffprobe_cache') movies = TableMovies.select(TableMovies.path).dicts() count_movies = len(movies) for i, movie in enumerate(movies): show_progress(id='movies_disk_scan', header='Full disk scan...', name='Movies subtitles', value=i, count=count_movies) store_subtitles_movie(movie['path'], path_mappings.path_replace_movie(movie['path']), use_cache=use_ffprobe_cache) hide_progress(id='movies_disk_scan') gc.collect()
def get_radarr_rootfolder(): apikey_radarr = settings.radarr.apikey radarr_rootfolder = [] # Get root folder data from Radarr if get_radarr_info.is_legacy(): url_radarr_api_rootfolder = url_radarr() + "/api/rootfolder?apikey=" + apikey_radarr else: url_radarr_api_rootfolder = url_radarr() + "/api/v3/rootfolder?apikey=" + apikey_radarr try: rootfolder = requests.get(url_radarr_api_rootfolder, timeout=60, verify=False, headers=headers) except requests.exceptions.ConnectionError: logging.exception("BAZARR Error trying to get rootfolder from Radarr. Connection Error.") return [] except requests.exceptions.Timeout: logging.exception("BAZARR Error trying to get rootfolder from Radarr. Timeout Error.") return [] except requests.exceptions.RequestException: logging.exception("BAZARR Error trying to get rootfolder from Radarr.") return [] else: radarr_movies_paths = list(TableMovies.select(TableMovies.path).dicts()) for folder in rootfolder.json(): if any(item['path'].startswith(folder['path']) for item in radarr_movies_paths): radarr_rootfolder.append({'id': folder['id'], 'path': folder['path']}) db_rootfolder = TableMoviesRootfolder.select(TableMoviesRootfolder.id, TableMoviesRootfolder.path).dicts() rootfolder_to_remove = [x for x in db_rootfolder if not next((item for item in radarr_rootfolder if item['id'] == x['id']), False)] rootfolder_to_update = [x for x in radarr_rootfolder if next((item for item in db_rootfolder if item['id'] == x['id']), False)] rootfolder_to_insert = [x for x in radarr_rootfolder if not next((item for item in db_rootfolder if item['id'] == x['id']), False)] for item in rootfolder_to_remove: TableMoviesRootfolder.delete().where(TableMoviesRootfolder.id == item['id']).execute() for item in rootfolder_to_update: TableMoviesRootfolder.update({TableMoviesRootfolder.path: item['path']})\ .where(TableMoviesRootfolder.id == item['id']).execute() for item in rootfolder_to_insert: TableMoviesRootfolder.insert({TableMoviesRootfolder.id: item['id'], TableMoviesRootfolder.path: item['path']}).execute()
def wanted_download_subtitles_movie(radarr_id): movies_details = TableMovies.select(TableMovies.path, TableMovies.missing_subtitles, TableMovies.radarrId, TableMovies.audio_language, TableMovies.sceneName, TableMovies.failedAttempts, TableMovies.title)\ .where((TableMovies.radarrId == radarr_id))\ .dicts() movies_details = list(movies_details) for movie in movies_details: providers_list = get_providers() if providers_list: _wanted_movie(movie) else: logging.info("BAZARR All providers are throttled") break
def manual_upload_subtitle(path, language, forced, hi, title, scene_name, media_type, subtitle, audio_language): logging.debug('BAZARR Manually uploading subtitles for this file: ' + path) single = settings.general.getboolean('single_language') use_postprocessing = settings.general.getboolean('use_postprocessing') postprocessing_cmd = settings.general.postprocessing_cmd chmod = int(settings.general.chmod, 8) if not sys.platform.startswith( 'win') and settings.general.getboolean('chmod_enabled') else None language = alpha3_from_alpha2(language) custom = CustomLanguage.from_value(language, "alpha3") if custom is None: lang_obj = Language(language) else: lang_obj = custom.subzero_language() if forced: lang_obj = Language.rebuild(lang_obj, forced=True) sub = Subtitle( lang_obj, mods=get_array_from(settings.general.subzero_mods) ) sub.content = subtitle.read() if not sub.is_valid(): logging.exception('BAZARR Invalid subtitle file: ' + subtitle.filename) sub.mods = None if settings.general.getboolean('utf8_encode'): sub.set_encoding("utf-8") saved_subtitles = [] try: saved_subtitles = save_subtitles(path, [sub], single=single, tags=None, # fixme directory=get_target_folder(path), chmod=chmod, # formats=("srt", "vtt") path_decoder=force_unicode) except Exception: logging.exception('BAZARR Error saving Subtitles file to disk for this file:' + path) return if len(saved_subtitles) < 1: logging.exception('BAZARR Error saving Subtitles file to disk for this file:' + path) return subtitle_path = saved_subtitles[0].storage_path if hi: modifier_string = " HI" elif forced: modifier_string = " forced" else: modifier_string = "" message = language_from_alpha3(language) + modifier_string + " Subtitles manually uploaded." if hi: modifier_code = ":hi" elif forced: modifier_code = ":forced" else: modifier_code = "" uploaded_language_code3 = language + modifier_code uploaded_language = language_from_alpha3(language) + modifier_string uploaded_language_code2 = alpha2_from_alpha3(language) + modifier_code audio_language_code2 = alpha2_from_language(audio_language) audio_language_code3 = alpha3_from_language(audio_language) if media_type == 'series': episode_metadata = TableEpisodes.select(TableEpisodes.sonarrSeriesId, TableEpisodes.sonarrEpisodeId) \ .where(TableEpisodes.path == path_mappings.path_replace_reverse(path)) \ .dicts() \ .get_or_none() if not episode_metadata: return series_id = episode_metadata['sonarrSeriesId'] episode_id = episode_metadata['sonarrEpisodeId'] sync_subtitles(video_path=path, srt_path=subtitle_path, srt_lang=uploaded_language_code2, media_type=media_type, percent_score=100, sonarr_series_id=episode_metadata['sonarrSeriesId'], forced=forced, sonarr_episode_id=episode_metadata['sonarrEpisodeId']) else: movie_metadata = TableMovies.select(TableMovies.radarrId) \ .where(TableMovies.path == path_mappings.path_replace_reverse_movie(path)) \ .dicts() \ .get_or_none() if not movie_metadata: return series_id = "" episode_id = movie_metadata['radarrId'] sync_subtitles(video_path=path, srt_path=subtitle_path, srt_lang=uploaded_language_code2, media_type=media_type, percent_score=100, radarr_id=movie_metadata['radarrId'], forced=forced) if use_postprocessing: command = pp_replace(postprocessing_cmd, path, subtitle_path, uploaded_language, uploaded_language_code2, uploaded_language_code3, audio_language, audio_language_code2, audio_language_code3, forced, 100, "1", "manual", series_id, episode_id, hi=hi) postprocessing(command, path) if media_type == 'series': reversed_path = path_mappings.path_replace_reverse(path) reversed_subtitles_path = path_mappings.path_replace_reverse(subtitle_path) notify_sonarr(episode_metadata['sonarrSeriesId']) event_stream(type='series', action='update', payload=episode_metadata['sonarrSeriesId']) event_stream(type='episode-wanted', action='delete', payload=episode_metadata['sonarrEpisodeId']) else: reversed_path = path_mappings.path_replace_reverse_movie(path) reversed_subtitles_path = path_mappings.path_replace_reverse_movie(subtitle_path) notify_radarr(movie_metadata['radarrId']) event_stream(type='movie', action='update', payload=movie_metadata['radarrId']) event_stream(type='movie-wanted', action='delete', payload=movie_metadata['radarrId']) return message, reversed_path, reversed_subtitles_path
def post(self): # Upload # TODO: Support Multiply Upload radarrId = request.args.get('radarrid') movieInfo = TableMovies.select(TableMovies.title, TableMovies.path, TableMovies.sceneName, TableMovies.audio_language) \ .where(TableMovies.radarrId == radarrId) \ .dicts() \ .get_or_none() if not movieInfo: return 'Movie not found', 500 moviePath = path_mappings.path_replace_movie(movieInfo['path']) sceneName = movieInfo['sceneName'] or 'None' title = movieInfo['title'] audioLanguage = movieInfo['audio_language'] language = request.form.get('language') forced = True if request.form.get('forced') == 'true' else False hi = True if request.form.get('hi') == 'true' else False subFile = request.files.get('file') _, ext = os.path.splitext(subFile.filename) if ext not in SUBTITLE_EXTENSIONS: raise ValueError('A subtitle of an invalid format was uploaded.') try: result = manual_upload_subtitle(path=moviePath, language=language, forced=forced, hi=hi, title=title, scene_name=sceneName, media_type='movie', subtitle=subFile, audio_language=audioLanguage) if not result: logging.debug( f"BAZARR unable to process subtitles for this movie: {moviePath}" ) else: message = result[0] path = result[1] subs_path = result[2] if hi: language_code = language + ":hi" elif forced: language_code = language + ":forced" else: language_code = language provider = "manual" score = 120 history_log_movie(4, radarrId, message, path, language_code, provider, score, subtitles_path=subs_path) if not settings.general.getboolean( 'dont_notify_manual_actions'): send_notifications_movie(radarrId, message) store_subtitles_movie(path, moviePath) except OSError: pass return '', 204
def patch(self): # Download radarrId = request.args.get('radarrid') movieInfo = TableMovies.select(TableMovies.title, TableMovies.path, TableMovies.sceneName, TableMovies.audio_language)\ .where(TableMovies.radarrId == radarrId)\ .dicts()\ .get_or_none() if not movieInfo: return 'Movie not found', 500 moviePath = path_mappings.path_replace_movie(movieInfo['path']) sceneName = movieInfo['sceneName'] or 'None' title = movieInfo['title'] audio_language = movieInfo['audio_language'] language = request.form.get('language') hi = request.form.get('hi').capitalize() forced = request.form.get('forced').capitalize() audio_language_list = get_audio_profile_languages(movie_id=radarrId) if len(audio_language_list) > 0: audio_language = audio_language_list[0]['name'] else: audio_language = None try: result = list( generate_subtitles( moviePath, [(language, hi, forced)], audio_language, sceneName, title, 'movie', profile_id=get_profile_id(movie_id=radarrId))) if result: result = result[0] 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] history_log_movie(1, radarrId, message, path, language_code, provider, score, subs_id, subs_path) send_notifications_movie(radarrId, message) store_subtitles_movie(path, moviePath) else: event_stream(type='movie', payload=radarrId) except OSError: pass return '', 204
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)
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
def patch(self): action = request.args.get('action') language = request.form.get('language') subtitles_path = request.form.get('path') media_type = request.form.get('type') id = request.form.get('id') if media_type == 'episode': subtitles_path = path_mappings.path_replace(subtitles_path) metadata = TableEpisodes.select(TableEpisodes.path, TableEpisodes.sonarrSeriesId)\ .where(TableEpisodes.sonarrEpisodeId == id)\ .dicts()\ .get_or_none() if not metadata: return 'Episode not found', 500 video_path = path_mappings.path_replace(metadata['path']) else: subtitles_path = path_mappings.path_replace_movie(subtitles_path) metadata = TableMovies.select(TableMovies.path).where( TableMovies.radarrId == id).dicts().get_or_none() if not metadata: return 'Movie not found', 500 video_path = path_mappings.path_replace_movie(metadata['path']) if action == 'sync': subsync = SubSyncer() if media_type == 'episode': subsync.sync(video_path=video_path, srt_path=subtitles_path, srt_lang=language, media_type='series', sonarr_series_id=metadata['sonarrSeriesId'], sonarr_episode_id=int(id)) else: subsync.sync(video_path=video_path, srt_path=subtitles_path, srt_lang=language, media_type='movies', radarr_id=id) del subsync gc.collect() elif action == 'translate': dest_language = language forced = True if request.form.get('forced') == 'true' else False hi = True if request.form.get('hi') == 'true' else False result = translate_subtitles_file(video_path=video_path, source_srt_file=subtitles_path, to_lang=dest_language, forced=forced, hi=hi) if result: if media_type == 'episode': store_subtitles( path_mappings.path_replace_reverse(video_path), video_path) else: store_subtitles_movie( path_mappings.path_replace_reverse_movie(video_path), video_path) return '', 200 else: return '', 404 else: subtitles_apply_mods(language, subtitles_path, [action]) # apply chmod if required chmod = int(settings.general.chmod, 8) if not sys.platform.startswith( 'win') and settings.general.getboolean('chmod_enabled') else None if chmod: os.chmod(subtitles_path, chmod) return '', 204
def movies_download_subtitles(no): conditions = [(TableMovies.radarrId == no)] conditions += get_exclusion_clause('movie') movies = TableMovies.select(TableMovies.path, TableMovies.missing_subtitles, TableMovies.audio_language, TableMovies.radarrId, TableMovies.sceneName, TableMovies.title, TableMovies.tags, TableMovies.monitored)\ .where(reduce(operator.and_, conditions))\ .dicts() if not len(movies): logging.debug( "BAZARR no movie with that radarrId can be found in database:", str(no)) return else: movie = movies[0] if ast.literal_eval(movie['missing_subtitles']): count_movie = len(ast.literal_eval(movie['missing_subtitles'])) else: count_movie = 0 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 = [] providers_list = None for i, language in enumerate(ast.literal_eval(movie['missing_subtitles'])): providers_list = get_providers() if language is not None: hi_ = "True" if language.endswith(':hi') else "False" forced_ = "True" if language.endswith(':forced') else "False" languages.append((language.split(":")[0], hi_, forced_)) if providers_list: # 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 show_progress(id='movie_search_progress_{}'.format(no), header='Searching missing subtitles...', name=movie['title'], value=i, count=count_movie) if providers_list: 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, no, message, path, language_code, provider, score, subs_id, subs_path) send_notifications_movie(no, message) else: logging.info("BAZARR All providers are throttled") hide_progress(id='movie_search_progress_{}'.format(no))
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." )
def process_subtitle(subtitle, media_type, audio_language, path, max_score, is_upgrade=False, is_manual=False): use_postprocessing = settings.general.getboolean('use_postprocessing') postprocessing_cmd = settings.general.postprocessing_cmd downloaded_provider = subtitle.provider_name downloaded_language_code3 = _get_download_code3(subtitle) downloaded_language = language_from_alpha3(downloaded_language_code3) downloaded_language_code2 = alpha2_from_alpha3(downloaded_language_code3) audio_language_code2 = alpha2_from_language(audio_language) audio_language_code3 = alpha3_from_language(audio_language) downloaded_path = subtitle.storage_path subtitle_id = subtitle.id if subtitle.language.hi: modifier_string = " HI" elif subtitle.language.forced: modifier_string = " forced" else: modifier_string = "" logging.debug('BAZARR Subtitles file saved to disk: ' + downloaded_path) if is_upgrade: action = "upgraded" elif is_manual: action = "manually downloaded" else: action = "downloaded" percent_score = round(subtitle.score * 100 / max_score, 2) message = downloaded_language + modifier_string + " subtitles " + action + " from " + \ downloaded_provider + " with a score of " + str(percent_score) + "%." if media_type == 'series': episode_metadata = TableEpisodes.select(TableEpisodes.sonarrSeriesId, TableEpisodes.sonarrEpisodeId) \ .where(TableEpisodes.path == path_mappings.path_replace_reverse(path)) \ .dicts() \ .get_or_none() if not episode_metadata: return series_id = episode_metadata['sonarrSeriesId'] episode_id = episode_metadata['sonarrEpisodeId'] sync_subtitles(video_path=path, srt_path=downloaded_path, forced=subtitle.language.forced, srt_lang=downloaded_language_code2, media_type=media_type, percent_score=percent_score, sonarr_series_id=episode_metadata['sonarrSeriesId'], sonarr_episode_id=episode_metadata['sonarrEpisodeId']) else: movie_metadata = TableMovies.select(TableMovies.radarrId) \ .where(TableMovies.path == path_mappings.path_replace_reverse_movie(path)) \ .dicts() \ .get_or_none() if not movie_metadata: return series_id = "" episode_id = movie_metadata['radarrId'] sync_subtitles(video_path=path, srt_path=downloaded_path, forced=subtitle.language.forced, srt_lang=downloaded_language_code2, media_type=media_type, percent_score=percent_score, radarr_id=movie_metadata['radarrId']) if use_postprocessing is True: command = pp_replace(postprocessing_cmd, path, downloaded_path, downloaded_language, downloaded_language_code2, downloaded_language_code3, audio_language, audio_language_code2, audio_language_code3, subtitle.language.forced, percent_score, subtitle_id, downloaded_provider, series_id, episode_id, subtitle.language.hi) if media_type == 'series': use_pp_threshold = settings.general.getboolean( 'use_postprocessing_threshold') pp_threshold = int(settings.general.postprocessing_threshold) else: use_pp_threshold = settings.general.getboolean( 'use_postprocessing_threshold_movie') pp_threshold = int(settings.general.postprocessing_threshold_movie) if not use_pp_threshold or (use_pp_threshold and percent_score < pp_threshold): logging.debug( "BAZARR Using post-processing command: {}".format(command)) postprocessing(command, path) else: logging.debug( "BAZARR post-processing skipped because subtitles score isn't below this " "threshold value: " + str(pp_threshold) + "%") if media_type == 'series': reversed_path = path_mappings.path_replace_reverse(path) reversed_subtitles_path = path_mappings.path_replace_reverse( downloaded_path) notify_sonarr(episode_metadata['sonarrSeriesId']) event_stream(type='series', action='update', payload=episode_metadata['sonarrSeriesId']) event_stream(type='episode-wanted', action='delete', payload=episode_metadata['sonarrEpisodeId']) else: reversed_path = path_mappings.path_replace_reverse_movie(path) reversed_subtitles_path = path_mappings.path_replace_reverse_movie( downloaded_path) notify_radarr(movie_metadata['radarrId']) event_stream(type='movie-wanted', action='delete', payload=movie_metadata['radarrId']) track_event(category=downloaded_provider, action=action, label=downloaded_language) return message, reversed_path, downloaded_language_code2, downloaded_provider, subtitle.score, \ subtitle.language.forced, subtitle.id, reversed_subtitles_path, subtitle.language.hi
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.')
def post(self): json_webhook = request.form.get('payload') parsed_json_webhook = json.loads(json_webhook) event = parsed_json_webhook['event'] if event not in ['media.play']: return '', 204 media_type = parsed_json_webhook['Metadata']['type'] if media_type == 'episode': season = parsed_json_webhook['Metadata']['parentIndex'] episode = parsed_json_webhook['Metadata']['index'] else: season = episode = None ids = [] for item in parsed_json_webhook['Metadata']['Guid']: splitted_id = item['id'].split('://') if len(splitted_id) == 2: ids.append({splitted_id[0]: splitted_id[1]}) if not ids: return '', 404 if media_type == 'episode': try: episode_imdb_id = [x['imdb'] for x in ids if 'imdb' in x][0] r = requests.get( 'https://imdb.com/title/{}'.format(episode_imdb_id), headers={"User-Agent": os.environ["SZ_USER_AGENT"]}) soup = bso(r.content, "html.parser") series_imdb_id = soup.find( 'a', {'class': re.compile(r'SeriesParentLink__ParentTextLink') })['href'].split('/')[2] except: return '', 404 else: sonarrEpisodeId = TableEpisodes.select(TableEpisodes.sonarrEpisodeId) \ .join(TableShows, on=(TableEpisodes.sonarrSeriesId == TableShows.sonarrSeriesId)) \ .where(TableShows.imdbId == series_imdb_id, TableEpisodes.season == season, TableEpisodes.episode == episode) \ .dicts() \ .get() if sonarrEpisodeId: episode_download_subtitles( no=sonarrEpisodeId['sonarrEpisodeId'], send_progress=True) else: try: movie_imdb_id = [x['imdb'] for x in ids if 'imdb' in x][0] except: return '', 404 else: radarrId = TableMovies.select(TableMovies.radarrId)\ .where(TableMovies.imdbId == movie_imdb_id)\ .dicts()\ .get() if radarrId: movies_download_subtitles(no=radarrId['radarrId']) return '', 200
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)