From 5aadcea83a395c4de5c8a067f4a5e6966d69703e Mon Sep 17 00:00:00 2001 From: morpheus65535 Date: Mon, 5 Apr 2021 00:09:39 -0400 Subject: [PATCH] Merged the series and episodes sync process. Episodes are only synced if series sizeOnDisk reported by Sonarr changes. --- bazarr/config.py | 3 +- bazarr/database.py | 1 + bazarr/get_episodes.py | 16 ++++++++--- bazarr/get_series.py | 32 +++++++++++++++++----- bazarr/init.py | 3 ++ bazarr/scheduler.py | 11 ++------ frontend/src/@types/settings.d.ts | 1 - frontend/src/Settings/Scheduler/index.tsx | 11 ++------ frontend/src/Settings/Scheduler/options.ts | 6 ++-- 9 files changed, 49 insertions(+), 35 deletions(-) diff --git a/bazarr/config.py b/bazarr/config.py index c7459eece..86ef02937 100644 --- a/bazarr/config.py +++ b/bazarr/config.py @@ -77,8 +77,7 @@ defaults = { 'full_update_day': '6', 'full_update_hour': '4', 'only_monitored': 'False', - 'series_sync': '1', - 'episodes_sync': '5', + 'series_sync': '5', 'excluded_tags': '[]', 'excluded_series_types': '[]' }, diff --git a/bazarr/database.py b/bazarr/database.py index c98e37eab..bc02fd760 100644 --- a/bazarr/database.py +++ b/bazarr/database.py @@ -102,6 +102,7 @@ def db_upgrade(): ['table_shows', 'seriesType', 'text', ''], ['table_shows', 'imdbId', 'text', ''], ['table_shows', 'profileId', 'integer'], + ['table_shows', 'sizeOnDisk', 'integer'], ['table_episodes', 'format', 'text'], ['table_episodes', 'resolution', 'text'], ['table_episodes', 'video_codec', 'text'], diff --git a/bazarr/get_episodes.py b/bazarr/get_episodes.py index 2e32e897e..a1a5548db 100644 --- a/bazarr/get_episodes.py +++ b/bazarr/get_episodes.py @@ -16,22 +16,30 @@ def update_all_episodes(): logging.info('BAZARR All existing episode subtitles indexed from disk.') -def sync_episodes(): +def sync_episodes(series_id=None): logging.debug('BAZARR Starting episodes sync from Sonarr.') apikey_sonarr = settings.sonarr.apikey # Get current episodes id in DB current_episodes_db = database.execute("SELECT sonarrEpisodeId, path, sonarrSeriesId FROM table_episodes") - current_episodes_db_list = [x['sonarrEpisodeId'] for x in current_episodes_db] + if series_id: + current_episodes_db_list = [x['sonarrEpisodeId'] for x in current_episodes_db if x['sonarrSeriesId'] == series_id] + else: + current_episodes_db_list = [x['sonarrEpisodeId'] for x in current_episodes_db] current_episodes_sonarr = [] episodes_to_update = [] episodes_to_add = [] altered_episodes = [] - # Get sonarrId for each series from database - seriesIdList = database.execute("SELECT sonarrSeriesId, title FROM table_shows") + if series_id and isinstance(series_id, int): + # Get sonarrId for each series from database + seriesIdList = database.execute("SELECT sonarrSeriesId, title FROM table_shows WHERE sonarrSeriesId = ?", + (series_id,)) + else: + # Get sonarrId for each series from database + seriesIdList = database.execute("SELECT sonarrSeriesId, title FROM table_shows") for i, seriesId in enumerate(seriesIdList): # Get episodes data for a series from Sonarr diff --git a/bazarr/get_series.py b/bazarr/get_series.py index fcdee9ddf..ff1c173b5 100644 --- a/bazarr/get_series.py +++ b/bazarr/get_series.py @@ -11,6 +11,7 @@ from database import database, dict_converter from utils import get_sonarr_version from helper import path_mappings from event_handler import event_stream +from get_episodes import sync_episodes def update_series(): @@ -56,6 +57,7 @@ def update_series(): current_shows_sonarr = [] series_to_update = [] series_to_add = [] + episodes_to_sync = [] series_list_length = len(r.json()) for i, show in enumerate(r.json(), 1): @@ -87,6 +89,13 @@ def update_series(): # Add shows in Sonarr to current shows list current_shows_sonarr.append(show['id']) + # Get sizeOnDisk for show + sizeOnDisk = show['sizeOnDisk'] if 'sizeOnDisk' in show else 0 + show_size_in_db = database.execute('SELECT sizeOnDisk FROM table_shows WHERE sonarrSeriesId = ?', (show['id'],)) + if len(show_size_in_db): + if sizeOnDisk != show_size_in_db[0]['sizeOnDisk']: + episodes_to_sync.append(show['id']) + if show['id'] in current_shows_db_list: series_to_update.append({'title': show["title"], 'path': show["path"], @@ -101,7 +110,8 @@ def update_series(): 'alternateTitles': alternate_titles, 'tags': str(tags), 'seriesType': show['seriesType'], - 'imdbId': imdbId}) + 'imdbId': imdbId, + 'sizeOnDisk': sizeOnDisk}) else: series_to_add.append({'title': show["title"], 'path': show["path"], @@ -117,19 +127,22 @@ def update_series(): 'tags': str(tags), 'seriesType': show['seriesType'], 'imdbId': imdbId, - 'profileId': serie_default_profile}) + 'profileId': serie_default_profile, + 'sizeOnDisk': sizeOnDisk}) # Remove old series from DB removed_series = list(set(current_shows_db_list) - set(current_shows_sonarr)) for series in removed_series: - database.execute("DELETE FROM table_shows WHERE sonarrSeriesId=?",(series,)) + database.execute("DELETE FROM table_shows WHERE sonarrSeriesId=?", (series,)) + database.execute("DELETE FROM table_episodes WHERE sonarrSeriesId=?", (series,)) event_stream(type='series', action='delete', series=series) # Update existing series in DB series_in_db_list = [] series_in_db = database.execute("SELECT title, path, tvdbId, sonarrSeriesId, overview, poster, fanart, " - "audio_language, sortTitle, year, alternateTitles, tags, seriesType, imdbId FROM table_shows") + "audio_language, sortTitle, year, alternateTitles, tags, seriesType, imdbId, " + "sizeOnDisk FROM table_shows") for item in series_in_db: series_in_db_list.append(item) @@ -142,6 +155,9 @@ def update_series(): query.values + (updated_series['sonarrSeriesId'],)) event_stream(type='series', action='update', series=updated_series['sonarrSeriesId']) + if updated_series['sonarrSeriesId'] in episodes_to_sync: + sync_episodes(series_id=updated_series['sonarrSeriesId']) + # Insert new series in DB for added_series in series_to_add: query = dict_converter.convert(added_series) @@ -150,13 +166,15 @@ def update_series(): query.question_marks + ''')''', query.values) if result: list_missing_subtitles(no=added_series['sonarrSeriesId']) + event_stream(type='series', action='insert', id=added_series['sonarrSeriesId']) + + if added_series['sonarrSeriesId'] in episodes_to_sync: + sync_episodes(series_id=added_series['sonarrSeriesId']) else: logging.debug('BAZARR unable to insert this series into the database:', path_mappings.path_replace(added_series['path'])) - event_stream(type='series', action='insert', series=added_series['sonarrSeriesId']) - - logging.debug('BAZARR All series synced from Sonarr into database.') + logging.debug('BAZARR All series synced from Sonarr into database.') def get_profile_list(): diff --git a/bazarr/init.py b/bazarr/init.py index cfe85c4a6..48e6196fb 100644 --- a/bazarr/init.py +++ b/bazarr/init.py @@ -163,6 +163,9 @@ if settings.analytics.visitor: with open(os.path.normpath(os.path.join(args.config_dir, 'config', 'config.ini')), 'w+') as handle: settings.remove_option('general', 'throtteled_providers') settings.remove_option('general', 'update_restart') + settings.remove_option('sonarr', 'episodes_sync') + if settings.sonarr.series_sync == '1': + settings.sonarr.series_sync = '5' settings.write(handle) diff --git a/bazarr/scheduler.py b/bazarr/scheduler.py index c24635f38..75b54e05d 100644 --- a/bazarr/scheduler.py +++ b/bazarr/scheduler.py @@ -1,6 +1,6 @@ # coding=utf-8 -from get_episodes import sync_episodes, update_all_episodes +from get_episodes import update_all_episodes from get_movies import update_movies, update_all_movies from get_series import update_series from config import settings @@ -143,18 +143,14 @@ class Scheduler: if settings.general.getboolean('use_sonarr'): self.aps_scheduler.add_job( update_series, IntervalTrigger(minutes=int(settings.sonarr.series_sync)), max_instances=1, - coalesce=True, misfire_grace_time=15, id='update_series', name='Update Series list from Sonarr', - replace_existing=True) - self.aps_scheduler.add_job( - sync_episodes, IntervalTrigger(minutes=int(settings.sonarr.episodes_sync)), max_instances=1, - coalesce=True, misfire_grace_time=15, id='sync_episodes', name='Sync episodes with Sonarr', + coalesce=True, misfire_grace_time=15, id='update_series', name='Sync with Sonarr', replace_existing=True) def __radarr_update_task(self): if settings.general.getboolean('use_radarr'): self.aps_scheduler.add_job( update_movies, IntervalTrigger(minutes=int(settings.radarr.movies_sync)), max_instances=1, - coalesce=True, misfire_grace_time=15, id='update_movies', name='Update Movie list from Radarr', + coalesce=True, misfire_grace_time=15, id='update_movies', name='Sync with Radarr', replace_existing=True) def __cache_cleanup_task(self): @@ -257,7 +253,6 @@ scheduler = Scheduler() if 'BAZARR_AUDIO_PROFILES_MIGRATION' in os.environ: if settings.general.getboolean('use_sonarr'): scheduler.aps_scheduler.modify_job('update_series', next_run_time=datetime.now()) - scheduler.aps_scheduler.modify_job('sync_episodes', next_run_time=datetime.now()) if settings.general.getboolean('use_radarr'): scheduler.aps_scheduler.modify_job('update_movies', next_run_time=datetime.now()) del os.environ['BAZARR_AUDIO_PROFILES_MIGRATION'] diff --git a/frontend/src/@types/settings.d.ts b/frontend/src/@types/settings.d.ts index bc93bd607..6891ccf9a 100644 --- a/frontend/src/@types/settings.d.ts +++ b/frontend/src/@types/settings.d.ts @@ -128,7 +128,6 @@ namespace Settings { full_update_hour: number; only_monitored: boolean; series_sync: number; - episodes_sync: number; excluded_tags: string[]; excluded_series_types: SonarrSeriesType[]; } diff --git a/frontend/src/Settings/Scheduler/index.tsx b/frontend/src/Settings/Scheduler/index.tsx index b56dfc492..ec1b458b7 100644 --- a/frontend/src/Settings/Scheduler/index.tsx +++ b/frontend/src/Settings/Scheduler/index.tsx @@ -9,7 +9,6 @@ import { import { dayOptions, diskUpdateOptions, - episodesSyncOptions, moviesSyncOptions, seriesSyncOptions, upgradeOptions, @@ -28,19 +27,13 @@ const SettingsSchedulerView: FunctionComponent = () => { return ( - + - - - - + [] = [ - { label: "1 Minute", value: 1 }, { label: "5 Minutes", value: 5 }, { label: "15 Minutes", value: 15 }, { label: "1 Hour", value: 60 }, { label: "3 Hours", value: 180 }, + { label: "6 Hours", value: 360 }, ]; -export const episodesSyncOptions: SelectorOption[] = [ +export const moviesSyncOptions: SelectorOption[] = [ { label: "5 Minutes", value: 5 }, { label: "15 Minutes", value: 15 }, { label: "1 Hour", value: 60 }, @@ -14,8 +14,6 @@ export const episodesSyncOptions: SelectorOption[] = [ { label: "6 Hours", value: 360 }, ]; -export const moviesSyncOptions = episodesSyncOptions; - export const diskUpdateOptions: SelectorOption[] = [ { label: "Manually", value: "Manually" }, { label: "Daily", value: "Daily" },