From 8346ea9dc857d6f9bcd2ed3a452e0cbd1c38cfd9 Mon Sep 17 00:00:00 2001 From: morpheus65535 Date: Wed, 25 Dec 2024 14:22:30 -0500 Subject: [PATCH 1/5] Improved Sonarr and Radarr syncing to prevent database integrity exception being raised by relying on proper primary keys instead of other values. --- bazarr/radarr/sync/movies.py | 16 ++++++++-------- bazarr/sonarr/sync/series.py | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/bazarr/radarr/sync/movies.py b/bazarr/radarr/sync/movies.py index c4cb5ab96..7dc6b3a03 100644 --- a/bazarr/radarr/sync/movies.py +++ b/bazarr/radarr/sync/movies.py @@ -53,7 +53,7 @@ def update_movie(updated_movie, send_event): updated_movie['updated_at_timestamp'] = datetime.now() database.execute( update(TableMovies).values(updated_movie) - .where(TableMovies.tmdbId == updated_movie['tmdbId'])) + .where(TableMovies.radarrId == updated_movie['radarrId'])) except IntegrityError as e: logging.error(f"BAZARR cannot update movie {updated_movie['path']} because of {e}") else: @@ -66,7 +66,7 @@ def update_movie(updated_movie, send_event): def get_movie_monitored_status(movie_id): existing_movie_monitored = database.execute( select(TableMovies.monitored) - .where(TableMovies.tmdbId == str(movie_id)))\ + .where(TableMovies.radarrId == str(movie_id)))\ .first() if existing_movie_monitored is None: return True @@ -124,16 +124,16 @@ def update_movies(send_event=True): return else: # Get current movies in DB - current_movies_id_db = [x.tmdbId for x in + current_movies_id_db = [x.radarrId for x in database.execute( - select(TableMovies.tmdbId)) + select(TableMovies.radarrId)) .all()] current_movies_db_kv = [x.items() for x in [y._asdict()['TableMovies'].__dict__ for y in database.execute( select(TableMovies)) .all()]] - current_movies_radarr = [str(movie['tmdbId']) for movie in movies if movie['hasFile'] and + current_movies_radarr = [str(movie['id']) for movie in movies if movie['hasFile'] and 'movieFile' in movie and (movie['movieFile']['size'] > MINIMUM_VIDEO_SIZE or get_movie_file_size_from_db(movie['movieFile']['path']) > MINIMUM_VIDEO_SIZE)] @@ -143,7 +143,7 @@ def update_movies(send_event=True): movies_deleted = [] if len(movies_to_delete): try: - database.execute(delete(TableMovies).where(TableMovies.tmdbId.in_(movies_to_delete))) + database.execute(delete(TableMovies).where(TableMovies.radarrId.in_(movies_to_delete))) except IntegrityError as e: logging.error(f"BAZARR cannot delete movies because of {e}") else: @@ -172,7 +172,7 @@ def update_movies(send_event=True): if movie['hasFile'] is True: if 'movieFile' in movie: if sync_monitored: - if get_movie_monitored_status(movie['tmdbId']) != movie['monitored']: + if get_movie_monitored_status(movie['id']) != movie['monitored']: # monitored status is not the same as our DB trace(f"{i}: (Monitor Status Mismatch) {movie['title']}") elif not movie['monitored']: @@ -184,7 +184,7 @@ def update_movies(send_event=True): get_movie_file_size_from_db(movie['movieFile']['path']) > MINIMUM_VIDEO_SIZE): # Add/update movies from Radarr that have a movie file to current movies list trace(f"{i}: (Processing) {movie['title']}") - if str(movie['tmdbId']) in current_movies_id_db: + if str(movie['id']) in current_movies_id_db: parsed_movie = movieParser(movie, action='update', tags_dict=tagsDict, language_profiles=language_profiles, diff --git a/bazarr/sonarr/sync/series.py b/bazarr/sonarr/sync/series.py index 065fdaa21..f04a4d375 100644 --- a/bazarr/sonarr/sync/series.py +++ b/bazarr/sonarr/sync/series.py @@ -34,7 +34,7 @@ def get_language_profiles(): def get_series_monitored_table(): series_monitored = database.execute( - select(TableShows.tvdbId, TableShows.monitored))\ + select(TableShows.sonarrSeriesId, TableShows.monitored))\ .all() series_dict = dict((x, y) for x, y in series_monitored) return series_dict @@ -95,7 +95,7 @@ def update_series(send_event=True): if sync_monitored: try: - monitored_status_db = bool_map[series_monitored[show['tvdbId']]] + monitored_status_db = bool_map[series_monitored[show['id']]] except KeyError: monitored_status_db = None if monitored_status_db is None: From b71daad7fb6a8a0a9d47a29471c24989eabef88c Mon Sep 17 00:00:00 2001 From: morpheus65535 Date: Thu, 26 Dec 2024 09:46:22 -0500 Subject: [PATCH 2/5] Fixed Bazarr not starting when configured IP isn't available for binding. --- bazarr/app/server.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazarr/app/server.py b/bazarr/app/server.py index 85c2eb680..11cadbe1c 100644 --- a/bazarr/app/server.py +++ b/bazarr/app/server.py @@ -49,12 +49,12 @@ def configure_server(self): threads=100) self.connected = True except OSError as error: - if error.errno == 49: + if error.errno == errno.EADDRNOTAVAIL: logging.exception("BAZARR cannot bind to specified IP, trying with 0.0.0.0") self.address = '0.0.0.0' self.connected = False super(Server, self).__init__() - elif error.errno == 48: + elif error.errno == errno.EADDRINUSE: if self.port != '6767': logging.exception("BAZARR cannot bind to specified TCP port, trying with default (6767)") self.port = '6767' @@ -64,7 +64,7 @@ def configure_server(self): logging.exception("BAZARR cannot bind to default TCP port (6767) because it's already in use, " "exiting...") self.shutdown(EXIT_PORT_ALREADY_IN_USE_ERROR) - elif error.errno == 97: + elif error.errno == errno.ENOLINK: logging.exception("BAZARR cannot bind to IPv6 (*), trying with 0.0.0.0") self.address = '0.0.0.0' self.connected = False From 4809b403ca3b98f0f38f4e7ef62565b5a40e9aed Mon Sep 17 00:00:00 2001 From: Xewdy Date: Thu, 26 Dec 2024 13:49:49 -0600 Subject: [PATCH 3/5] Added check to opensubtitles.com for SDH subtitles being classified as forced --- .../subliminal_patch/providers/opensubtitlescom.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/custom_libs/subliminal_patch/providers/opensubtitlescom.py b/custom_libs/subliminal_patch/providers/opensubtitlescom.py index 0f0c2eaff..39171b6af 100644 --- a/custom_libs/subliminal_patch/providers/opensubtitlescom.py +++ b/custom_libs/subliminal_patch/providers/opensubtitlescom.py @@ -290,6 +290,10 @@ def search_titles(self, title): if not title_id: logger.debug(f'No match found for {title}') + @staticmethod + def is_real_forced(attributes): + return attributes['foreign_parts_only'] and not attributes['hearing_impaired'] + def query(self, languages, video): self.video = video if self.use_hash: @@ -363,11 +367,11 @@ def query(self, languages, video): # filter out forced subtitles or not depending on the required languages if all([lang.forced for lang in languages]): # only forced - result['data'] = [x for x in result['data'] if x['attributes']['foreign_parts_only']] + result['data'] = [x for x in result['data'] if self.is_real_forced(x['attributes'])] elif any([lang.forced for lang in languages]): # also forced pass else: # not forced - result['data'] = [x for x in result['data'] if not x['attributes']['foreign_parts_only']] + result['data'] = [x for x in result['data'] if not self.is_real_forced(x['attributes'])] logger.debug(f"Query returned {len(result['data'])} subtitles") @@ -407,7 +411,7 @@ def query(self, languages, video): if len(item['attributes']['files']): subtitle = OpenSubtitlesComSubtitle( language=Language.fromietf(from_opensubtitlescom(item['attributes']['language'])), - forced=item['attributes']['foreign_parts_only'], + forced=self.is_real_forced(item['attributes']), hearing_impaired=item['attributes']['hearing_impaired'], page_link=item['attributes']['url'], file_id=item['attributes']['files'][0]['file_id'], From 60febe3d12b75d534b64d56839ee79ee063958fd Mon Sep 17 00:00:00 2001 From: morpheus65535 Date: Sat, 28 Dec 2024 14:01:25 -0500 Subject: [PATCH 4/5] Fixed sync issue with Radarr that would remove all movies from database on every sync. --- bazarr/radarr/sync/movies.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bazarr/radarr/sync/movies.py b/bazarr/radarr/sync/movies.py index 7dc6b3a03..72d18f511 100644 --- a/bazarr/radarr/sync/movies.py +++ b/bazarr/radarr/sync/movies.py @@ -133,7 +133,7 @@ def update_movies(send_event=True): select(TableMovies)) .all()]] - current_movies_radarr = [str(movie['id']) for movie in movies if movie['hasFile'] and + current_movies_radarr = [movie['id'] for movie in movies if movie['hasFile'] and 'movieFile' in movie and (movie['movieFile']['size'] > MINIMUM_VIDEO_SIZE or get_movie_file_size_from_db(movie['movieFile']['path']) > MINIMUM_VIDEO_SIZE)] @@ -184,7 +184,7 @@ def update_movies(send_event=True): get_movie_file_size_from_db(movie['movieFile']['path']) > MINIMUM_VIDEO_SIZE): # Add/update movies from Radarr that have a movie file to current movies list trace(f"{i}: (Processing) {movie['title']}") - if str(movie['id']) in current_movies_id_db: + if movie['id'] in current_movies_id_db: parsed_movie = movieParser(movie, action='update', tags_dict=tagsDict, language_profiles=language_profiles, From 0413dbaa4cf632df0f560f5df2cd67851c3eee02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20Lofj=C3=A4rd?= Date: Mon, 30 Dec 2024 16:43:57 +0100 Subject: [PATCH 5/5] Improved languages profile health check to include default assigned profiles --- bazarr/utilities/health.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bazarr/utilities/health.py b/bazarr/utilities/health.py index 84a313cf0..ae32d3a0a 100644 --- a/bazarr/utilities/health.py +++ b/bazarr/utilities/health.py @@ -75,11 +75,13 @@ def get_health_issues(): .where(TableShows.profileId.is_not(None))).scalar() movies_with_profile = database.execute(select(func.count(TableMovies.radarrId)) .where(TableMovies.profileId.is_not(None))).scalar() + default_series_profile_empty = settings.general.serie_default_enabled and settings.general.serie_default_profile == '' + default_movies_profile_empty = settings.general.movie_default_enabled and settings.general.movie_default_profile == '' if languages_profiles_count == 0: health_issues.append({'object': 'Missing languages profile', 'issue': 'You must create at least one languages profile and assign it to your content.'}) - elif languages_profiles_count > 0 and ((settings.general.use_sonarr and series_with_profile == 0) or - (settings.general.use_radarr and movies_with_profile == 0)): + elif languages_profiles_count > 0 and ((settings.general.use_sonarr and series_with_profile == 0 and default_series_profile_empty) or + (settings.general.use_radarr and movies_with_profile == 0 and default_movies_profile_empty)): health_issues.append({'object': 'No assigned languages profile', 'issue': 'Although you have created at least one languages profile, you must assign it ' 'to your content.'})