def update_from_source(): tar_download_url = 'https://github.com/morpheus65535/bazarr/tarball/{}'.format(settings.general.branch) update_dir = os.path.join(os.path.dirname(__file__), '..', 'update') logging.info('BAZARR Downloading update from: ' + tar_download_url) notifications.write(msg='Downloading update from: ' + tar_download_url, queue='check_update') data = request_content(tar_download_url) if not data: logging.error("BAZARR Unable to retrieve new version from '%s', can't update", tar_download_url) notifications.write(msg=("Unable to retrieve new version from '%s', can't update", tar_download_url), type='error', queue='check_update') return download_name = settings.general.branch + '-github' tar_download_path = os.path.join(os.path.dirname(__file__), '..', download_name) # Save tar to disk with open(tar_download_path, 'wb') as f: f.write(data) # Extract the tar to update folder logging.info('BAZARR Extracting file: ' + tar_download_path) notifications.write(msg='Extracting file: ' + tar_download_path, queue='check_update') tar = tarfile.open(tar_download_path) tar.extractall(update_dir) tar.close() # Delete the tar.gz logging.info('BAZARR Deleting file: ' + tar_download_path) notifications.write(msg='Deleting file: ' + tar_download_path, queue='check_update') os.remove(tar_download_path) # Find update dir name update_dir_contents = [x for x in os.listdir(update_dir) if os.path.isdir(os.path.join(update_dir, x))] if len(update_dir_contents) != 1: logging.error("BAZARR Invalid update data, update failed: " + str(update_dir_contents)) notifications.write(msg="BAZARR Invalid update data, update failed: " + str(update_dir_contents), type='error', queue='check_update') return content_dir = os.path.join(update_dir, update_dir_contents[0]) # walk temp folder and move files to main folder for dirname, dirnames, filenames in os.walk(content_dir): dirname = dirname[len(content_dir) + 1:] for curfile in filenames: old_path = os.path.join(content_dir, dirname, curfile) new_path = os.path.join(os.path.dirname(__file__), '..', dirname, curfile) if os.path.isfile(new_path): os.remove(new_path) os.renames(old_path, new_path) updated()
def movies_full_scan_subtitles(): movies = database.execute("SELECT path FROM table_movies") count_movies = len(movies) 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(movie['path'], path_replace_movie(movie['path'])) gc.collect()
def series_full_scan_subtitles(): episodes = TableEpisodes.select(TableEpisodes.path) count_episodes = episodes.count() for i, episode in enumerate(episodes, 1): notifications.write(msg='Updating all episodes subtitles from disk...', queue='list_subtitles_series', item=i, length=count_episodes) store_subtitles(path_replace(episode.path)) gc.collect()
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 series_download_subtitles(no): if settings.sonarr.getboolean('only_monitored'): monitored_only_query_string = ' AND monitored = "True"' else: monitored_only_query_string = "" conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() episodes_details = c_db.execute( 'SELECT path, missing_subtitles, sonarrEpisodeId, scene_name FROM table_episodes WHERE sonarrSeriesId = ? AND missing_subtitles != "[]"' + monitored_only_query_string, (no, )).fetchall() series_details = c_db.execute( "SELECT hearing_impaired, title FROM table_shows WHERE sonarrSeriesId = ?", (no, )).fetchone() c_db.close() providers_list = get_providers() providers_auth = get_providers_auth() count_episodes_details = len(episodes_details) for i, episode in enumerate(episodes_details, 1): for language in ast.literal_eval(episode[1]): if language is not None: notifications.write(msg='Searching for series subtitles...', queue='get_subtitle', item=i, length=count_episodes_details) result = download_subtitle(path_replace(episode[0]), str(alpha3_from_alpha2(language)), series_details[0], providers_list, providers_auth, str(episode[3]), series_details[1], 'series') if result is not None: message = result[0] path = result[1] language_code = result[2] provider = result[3] score = result[4] store_subtitles(path_replace(episode[0])) history_log(1, no, episode[2], message, path, language_code, provider, score) send_notifications(no, episode[2], message) list_missing_subtitles(no) if count_episodes_details: notifications.write(msg='Searching completed. Please reload the page.', type='success', duration='permanent', button='refresh', queue='get_subtitle')
def series_full_scan_subtitles(): episodes = database.execute("SELECT path FROM table_episodes") count_episodes = len(episodes) for i, episode in enumerate(episodes, 1): notifications.write(msg='Updating all episodes subtitles from disk...', queue='list_subtitles_series', item=i, length=count_episodes) store_subtitles(path_replace(episode['path'])) gc.collect()
def movies_full_scan_subtitles(): conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() movies = c_db.execute("SELECT path FROM table_movies").fetchall() c_db.close() count_movies = len(movies) 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[0])) gc.collect()
def episode_download_subtitles(no): if settings.sonarr.getboolean('only_monitored'): monitored_only_query_string = ' AND monitored = "True"' else: monitored_only_query_string = "" conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() episodes_details = c_db.execute( 'SELECT table_episodes.path, table_episodes.missing_subtitles, table_episodes.sonarrEpisodeId, table_episodes.scene_name, table_shows.hearing_impaired, table_shows.title, table_shows.sonarrSeriesId FROM table_episodes INNER JOIN table_shows on table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId WHERE table_episodes.sonarrEpisodeId = ?' + monitored_only_query_string, (no, )).fetchall() c_db.close() providers_list = get_providers() providers_auth = get_providers_auth() for episode in episodes_details: for language in ast.literal_eval(episode[1]): if language is not None: notifications.write(msg='Searching for ' + str(language_from_alpha2(language)) + ' subtitles for this episode: ' + path_replace(episode[0]), queue='get_subtitle') result = download_subtitle(path_replace(episode[0]), str(alpha3_from_alpha2(language)), episode[4], providers_list, providers_auth, str(episode[3]), episode[5], 'series') if result is not None: message = result[0] path = result[1] language_code = result[2] provider = result[3] score = result[4] store_subtitles(path_replace(episode[0])) history_log(1, episode[6], episode[2], message, path, language_code, provider, score) send_notifications(episode[6], episode[2], message) list_missing_subtitles(episode[6])
def movies_download_subtitles(no): conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() movie = c_db.execute( "SELECT path, missing_subtitles, radarrId, sceneName, hearing_impaired, title FROM table_movies WHERE radarrId = ?", (no, )).fetchone() c_db.close() providers_list = get_providers() providers_auth = get_providers_auth() count_movie = len(ast.literal_eval(movie[1])) for i, language in enumerate(ast.literal_eval(movie[1]), 1): if language is not None: notifications.write(msg='Searching for movies subtitles', queue='get_subtitle', item=i, length=count_movie) result = download_subtitle(path_replace_movie(movie[0]), str(alpha3_from_alpha2(language)), movie[4], providers_list, providers_auth, str(movie[3]), movie[5], 'movie') if result is not None: message = result[0] path = result[1] language_code = result[2] provider = result[3] score = result[4] store_subtitles_movie(path_replace_movie(movie[0])) history_log_movie(1, no, message, path, language_code, provider, score) send_notifications_movie(no, message) list_missing_subtitles_movies(no) if count_movie: notifications.write(msg='Searching completed. Please reload the page.', type='success', duration='permanent', button='refresh', queue='get_subtitle')
def check_and_apply_update(): check_releases() if not args.release_update: gitconfig() branch = settings.general.branch g = git.cmd.Git(current_working_directory) g.fetch('origin') result = g.diff('--shortstat', 'origin/' + branch) if len(result) == 0: notifications.write(msg='No new version of Bazarr available.', queue='check_update') logging.info('BAZARR No new version of Bazarr available.') else: g.reset('--hard', 'HEAD') g.checkout(branch) g.reset('--hard', 'origin/' + branch) g.pull() logging.info( 'BAZARR Updated to latest version. Restart required. ' + result) updated() else: url = 'https://api.github.com/repos/morpheus65535/bazarr/releases' releases = request_json(url, timeout=20, whitelist_status_code=404, validator=lambda x: type(x) == list) if releases is None: notifications.write(msg='Could not get releases from GitHub.', queue='check_update', type='warning') logging.warn('BAZARR Could not get releases from GitHub.') return else: release = releases[0] latest_release = release['tag_name'] if ('v' + os.environ["BAZARR_VERSION"] ) != latest_release and settings.general.branch == 'master': update_from_source() elif settings.general.branch != 'master': notifications.write( msg="Can't update development branch from source", queue='check_update') # fixme logging.info( "BAZARR Can't update development branch from source") # fixme else: notifications.write(msg='Bazarr is up to date', queue='check_update') logging.info('BAZARR is up to date')
def wanted_search_missing_subtitles(): db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) db.create_function("path_substitution", 1, path_replace) db.create_function("path_substitution_movie", 1, path_replace_movie) c = db.cursor() if settings.sonarr.getboolean('only_monitored'): monitored_only_query_string_sonarr = ' AND monitored = "True"' else: monitored_only_query_string_sonarr = "" if settings.radarr.getboolean('only_monitored'): monitored_only_query_string_radarr = ' AND monitored = "True"' else: monitored_only_query_string_radarr = "" c.execute( "SELECT path_substitution(path) FROM table_episodes WHERE missing_subtitles != '[]'" + monitored_only_query_string_sonarr) episodes = c.fetchall() c.execute( "SELECT path_substitution_movie(path) FROM table_movies WHERE missing_subtitles != '[]'" + monitored_only_query_string_radarr) movies = c.fetchall() c.close() providers = get_providers() if settings.general.getboolean('use_sonarr'): if providers: count_episodes = len(episodes) for i, episode in enumerate(episodes, 1): wanted_download_subtitles(episode[0], i, count_episodes) else: notifications.write(msg='BAZARR All providers are throttled', queue='get_subtitle', duration='long') logging.info("BAZARR All providers are throttled") if settings.general.getboolean('use_radarr'): if providers: count_movies = len(movies) for i, movie in enumerate(movies, 1): wanted_download_subtitles_movie(movie[0], i, count_movies) else: notifications.write(msg='BAZARR All providers are throttled', queue='get_subtitle', duration='long') logging.info("BAZARR All providers are throttled") logging.info( 'BAZARR Finished searching for missing subtitles. Check histories for more information.' ) notifications.write(msg='Searching completed. Please reload the page.', type='success', duration='permanent', button='refresh', queue='get_subtitle')
def update_series(): notifications.write(msg="Update series list from Sonarr is running...", queue='get_series') apikey_sonarr = settings.sonarr.apikey serie_default_enabled = settings.general.getboolean( 'serie_default_enabled') serie_default_language = settings.general.serie_default_language serie_default_hi = settings.general.serie_default_hi serie_default_forced = settings.general.serie_default_forced if apikey_sonarr is None: pass else: get_profile_list() # Get shows data from Sonarr url_sonarr_api_series = url_sonarr + "/api/series?apikey=" + apikey_sonarr try: r = requests.get(url_sonarr_api_series, timeout=60, verify=False) r.raise_for_status() except requests.exceptions.HTTPError as errh: logging.exception( "BAZARR Error trying to get series from Sonarr. Http error.") except requests.exceptions.ConnectionError as errc: logging.exception( "BAZARR Error trying to get series from Sonarr. Connection Error." ) except requests.exceptions.Timeout as errt: logging.exception( "BAZARR Error trying to get series from Sonarr. Timeout Error." ) except requests.exceptions.RequestException as err: logging.exception("BAZARR Error trying to get series from Sonarr.") else: # Open database connection db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() # Get current shows in DB current_shows_db = c.execute( 'SELECT tvdbId FROM table_shows').fetchall() # Close database connection db.close() current_shows_db_list = [x[0] for x in current_shows_db] current_shows_sonarr = [] series_to_update = [] series_to_add = [] seriesListLength = len(r.json()) for i, show in enumerate(r.json(), 1): notifications.write(msg="Getting series data from Sonarr...", queue='get_series', item=i, length=seriesListLength) try: overview = unicode(show['overview']) except: overview = "" try: poster_big = show['images'][2]['url'].split('?')[0] poster = os.path.splitext(poster_big)[ 0] + '-250' + os.path.splitext(poster_big)[1] except: poster = "" try: fanart = show['images'][0]['url'].split('?')[0] except: fanart = "" if show['alternateTitles'] != None: alternateTitles = str( [item['title'] for item in show['alternateTitles']]) # Add shows in Sonarr to current shows list current_shows_sonarr.append(show['tvdbId']) if show['tvdbId'] in current_shows_db_list: series_to_update.append( (show["title"], show["path"], show["tvdbId"], show["id"], overview, poster, fanart, profile_id_to_language( (show['qualityProfileId'] if sonarr_version == 2 else show['languageProfileId'])), show['sortTitle'], show['year'], alternateTitles, show["tvdbId"])) else: if serie_default_enabled is True: series_to_add.append( (show["title"], show["path"], show["tvdbId"], serie_default_language, serie_default_hi, show["id"], overview, poster, fanart, profile_id_to_language(show['qualityProfileId']), show['sortTitle'], show['year'], alternateTitles, serie_default_forced)) else: series_to_add.append( (show["title"], show["path"], show["tvdbId"], show["tvdbId"], show["tvdbId"], show["id"], overview, poster, fanart, profile_id_to_language(show['qualityProfileId']), show['sortTitle'], show['year'], alternateTitles, show["id"])) # Update or insert series in DB db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() updated_result = c.executemany( '''UPDATE table_shows SET title = ?, path = ?, tvdbId = ?, sonarrSeriesId = ?, overview = ?, poster = ?, fanart = ?, `audio_language` = ? , sortTitle = ?, year = ?, alternateTitles = ? WHERE tvdbid = ?''', series_to_update) db.commit() if serie_default_enabled is True: added_result = c.executemany( '''INSERT OR IGNORE INTO table_shows(title, path, tvdbId, languages,`hearing_impaired`, sonarrSeriesId, overview, poster, fanart, `audio_language`, sortTitle, year, alternateTitles, forced) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', series_to_add) db.commit() else: added_result = c.executemany( '''INSERT OR IGNORE INTO table_shows(title, path, tvdbId, languages,`hearing_impaired`, sonarrSeriesId, overview, poster, fanart, `audio_language`, sortTitle, year, alternateTitles, forced) VALUES (?,?,?,(SELECT languages FROM table_shows WHERE tvdbId = ?),(SELECT `hearing_impaired` FROM table_shows WHERE tvdbId = ?), ?, ?, ?, ?, ?, ?, ?, ?, (SELECT `forced` FROM table_shows WHERE tvdbId = ?))''', series_to_add) db.commit() db.close() for show in series_to_add: list_missing_subtitles(show[5]) # Delete shows not in Sonarr anymore deleted_items = [] for item in current_shows_db_list: if item not in current_shows_sonarr: deleted_items.append(tuple([item])) db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() c.executemany('DELETE FROM table_shows WHERE tvdbId = ?', deleted_items) db.commit() db.close()
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: 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.") except requests.exceptions.ConnectionError as errc: logging.exception( "BAZARR Error trying to get movies from Radarr. Connection Error." ) except requests.exceptions.Timeout as errt: logging.exception( "BAZARR Error trying to get movies from Radarr. Timeout Error." ) except requests.exceptions.RequestException as err: logging.exception("BAZARR Error trying to get movies from Radarr.") else: # Get current movies in DB db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() current_movies_db = c.execute( 'SELECT tmdbId, path, radarrId FROM table_movies').fetchall() db.close() current_movies_db_list = [x[0] for x in current_movies_db] current_movies_radarr = [] movies_to_update = [] movies_to_add = [] 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: 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 movie['alternativeTitles'] != None: alternativeTitles = str([ item['title'] for item in movie['alternativeTitles'] ]) 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'])) # Detect file separator if movie['path'][0] == "/": separator = "/" else: separator = "\\" if unicode( movie['tmdbId']) in current_movies_db_list: movies_to_update.append( (movie["title"], movie["path"] + separator + movie['movieFile']['relativePath'], movie["tmdbId"], movie["id"], overview, poster, fanart, profile_id_to_language( movie['qualityProfileId']), sceneName, unicode(bool(movie['monitored'])), movie['sortTitle'], movie['year'], alternativeTitles, format, resolution, videoCodec, audioCodec, imdbId, movie["tmdbId"])) else: if movie_default_enabled is True: movies_to_add.append( (movie["title"], movie["path"] + separator + movie['movieFile']['relativePath'], movie["tmdbId"], movie_default_language, '[]', movie_default_hi, movie["id"], overview, poster, fanart, profile_id_to_language( movie['qualityProfileId']), sceneName, unicode(bool(movie['monitored'])), movie['sortTitle'], movie['year'], alternativeTitles, format, resolution, videoCodec, audioCodec, imdbId, movie_default_forced)) else: movies_to_add.append( (movie["title"], movie["path"] + separator + movie['movieFile']['relativePath'], movie["tmdbId"], movie["tmdbId"], movie["tmdbId"], movie["id"], overview, poster, fanart, profile_id_to_language( movie['qualityProfileId']), sceneName, unicode(bool(movie['monitored'])), movie['sortTitle'], movie['year'], alternativeTitles, format, resolution, videoCodec, audioCodec, imdbId, movie["tmdbId"])) else: logging.error( 'BAZARR Radarr returned a movie without a file path: ' + movie["path"] + separator + movie['movieFile']['relativePath']) # Update or insert movies in DB db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() updated_result = c.executemany( '''UPDATE table_movies SET title = ?, path = ?, tmdbId = ?, radarrId = ?, overview = ?, poster = ?, fanart = ?, `audio_language` = ?, sceneName = ?, monitored = ?, sortTitle = ?, year = ?, alternativeTitles = ?, format = ?, resolution = ?, video_codec = ?, audio_codec = ?, imdbId = ? WHERE tmdbid = ?''', movies_to_update) db.commit() if movie_default_enabled is True: added_result = c.executemany( '''INSERT OR IGNORE INTO table_movies(title, path, tmdbId, languages, subtitles,`hearing_impaired`, radarrId, overview, poster, fanart, `audio_language`, sceneName, monitored, sortTitle, year, alternativeTitles, format, resolution, video_codec, audio_codec, imdbId, forced) VALUES (?,?,?,?,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', movies_to_add) db.commit() else: added_result = c.executemany( '''INSERT OR IGNORE INTO table_movies(title, path, tmdbId, languages, subtitles,`hearing_impaired`, radarrId, overview, poster, fanart, `audio_language`, sceneName, monitored, sortTitle, year, alternativeTitles, format, resolution, video_codec, audio_codec, imdbId, forced) VALUES (?,?,?,(SELECT languages FROM table_movies WHERE tmdbId = ?), '[]',(SELECT `hearing_impaired` FROM table_movies WHERE tmdbId = ?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, (SELECT `forced` FROM table_movies WHERE tmdbId = ?))''', movies_to_add) db.commit() removed_movies = list( set(current_movies_db_list) - set(current_movies_radarr)) for removed_movie in removed_movies: c.execute('DELETE FROM table_movies WHERE tmdbId = ?', (removed_movie, )) db.commit() # Get movies list after INSERT and UPDATE movies_now_in_db = c.execute( 'SELECT tmdbId, path, radarrId FROM table_movies').fetchall() # Close database connection db.close() # Get only movies added or modified and store subtitles for them altered_movies = set(movies_now_in_db).difference( set(current_movies_db)) for altered_movie in altered_movies: store_subtitles_movie(path_replace_movie(altered_movie[1])) list_missing_subtitles_movies(altered_movie[2]) # 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." ) logging.debug('BAZARR All movies synced from Radarr into database.')
def upgrade_subtitles(): days_to_upgrade_subs = settings.general.days_to_upgrade_subs minimum_timestamp = ( (datetime.now() - timedelta(days=int(days_to_upgrade_subs))) - datetime(1970, 1, 1)).total_seconds() if settings.general.getboolean('upgrade_manual'): query_actions = [1, 2, 3] else: query_actions = [1, 3] db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() episodes_list = c.execute( """SELECT table_history.video_path, table_history.language, table_history.score, table_shows.hearing_impaired, table_episodes.scene_name, table_episodes.title, table_episodes.sonarrSeriesId, table_episodes.sonarrEpisodeId, MAX(table_history.timestamp), table_shows.languages FROM table_history INNER JOIN table_shows on table_shows.sonarrSeriesId = table_history.sonarrSeriesId INNER JOIN table_episodes on table_episodes.sonarrEpisodeId = table_history.sonarrEpisodeId WHERE action IN (""" + ','.join(map(str, query_actions)) + """) AND timestamp > ? AND score is not null GROUP BY table_history.video_path, table_history.language""", (minimum_timestamp, )).fetchall() movies_list = c.execute( """SELECT table_history_movie.video_path, table_history_movie.language, table_history_movie.score, table_movies.hearing_impaired, table_movies.sceneName, table_movies.title, table_movies.radarrId, MAX(table_history_movie.timestamp), table_movies.languages FROM table_history_movie INNER JOIN table_movies on table_movies.radarrId = table_history_movie.radarrId WHERE action IN (""" + ','.join(map(str, query_actions)) + """) AND timestamp > ? AND score is not null GROUP BY table_history_movie.video_path, table_history_movie.language""", (minimum_timestamp, )).fetchall() db.close() episodes_to_upgrade = [] for episode in episodes_list: if os.path.exists(path_replace(episode[0])) and int(episode[2]) < 360: episodes_to_upgrade.append(episode) movies_to_upgrade = [] for movie in movies_list: if os.path.exists(path_replace_movie( movie[0])) and int(movie[2]) < 120: movies_to_upgrade.append(movie) providers_list = get_providers() providers_auth = get_providers_auth() count_episode_to_upgrade = len(episodes_to_upgrade) count_movie_to_upgrade = len(movies_to_upgrade) for i, episode in enumerate(episodes_to_upgrade, 1): if episode[1] in ast.literal_eval(str(episode[9])): notifications.write(msg='Upgrading series subtitles : ' + str(i) + '/' + str(count_episode_to_upgrade), queue='get_subtitle', duration='long') result = download_subtitle(path_replace(episode[0]), str(alpha3_from_alpha2(episode[1])), episode[3], providers_list, providers_auth, str(episode[4]), episode[5], 'series', forced_minimum_score=int(episode[2]), is_upgrade=True) if result is not None: message = result[0] path = result[1] language_code = result[2] provider = result[3] score = result[4] store_subtitles(path_replace(episode[0])) history_log(3, episode[6], episode[7], message, path, language_code, provider, score) send_notifications(episode[6], episode[7], message) for i, movie in enumerate(movies_to_upgrade, 1): if movie[1] in ast.literal_eval(str(movie[8])): notifications.write(msg='Upgrading movie subtitles : ' + str(i) + '/' + str(count_movie_to_upgrade), queue='get_subtitle', duration='long') result = download_subtitle(path_replace_movie(movie[0]), str(alpha3_from_alpha2(movie[1])), movie[3], providers_list, providers_auth, str(movie[4]), movie[5], 'movie', forced_minimum_score=int(movie[2]), is_upgrade=True) if result is not None: message = result[0] path = result[1] language_code = result[2] provider = result[3] score = result[4] store_subtitles_movie(path_replace_movie(movie[0])) history_log_movie(3, movie[6], message, path, language_code, provider, score) send_notifications_movie(movie[6], message)
def wanted_download_subtitles_movie(path): conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() movies_details = c_db.execute( "SELECT path, missing_subtitles, radarrId, radarrId, hearing_impaired, sceneName, failedAttempts, title FROM table_movies WHERE path = ? AND missing_subtitles != '[]'", (path_replace_reverse_movie(path), )).fetchall() c_db.close() providers_list = get_providers() providers_auth = get_providers_auth() for movie in movies_details: attempt = movie[6] if type(attempt) == unicode: attempt = ast.literal_eval(attempt) for language in ast.literal_eval(movie[1]): if attempt is None: attempt = [] attempt.append([language, time.time()]) else: att = zip(*attempt)[0] if language not in att: attempt.append([language, time.time()]) conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() c_db.execute( 'UPDATE table_movies SET failedAttempts = ? WHERE radarrId = ?', (unicode(attempt), movie[2])) conn_db.commit() c_db.close() for i in range(len(attempt)): if attempt[i][0] == language: if search_active(attempt[i][1]) is True: notifications.write( msg='Searching ' + str(language_from_alpha2(language)) + ' subtitles for this movie: ' + path, queue='get_subtitle') result = download_subtitle( path_replace_movie(movie[0]), str(alpha3_from_alpha2(language)), movie[4], providers_list, providers_auth, str(movie[5]), movie[7], 'movie') if result is not None: message = result[0] path = result[1] language_code = result[2] provider = result[3] score = result[4] store_subtitles_movie(path_replace_movie(movie[0])) list_missing_subtitles_movies(movie[3]) history_log_movie(1, movie[3], message, path, language_code, provider, score) send_notifications_movie(movie[3], message) else: logging.info('BAZARR Search is not active for movie ' + movie[0] + ' Language: ' + attempt[i][0])
def wanted_download_subtitles(path): conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() episodes_details = c_db.execute( "SELECT table_episodes.path, table_episodes.missing_subtitles, table_episodes.sonarrEpisodeId, table_episodes.sonarrSeriesId, table_shows.hearing_impaired, table_episodes.scene_name, table_episodes.failedAttempts, table_shows.title FROM table_episodes INNER JOIN table_shows on table_shows.sonarrSeriesId = table_episodes.sonarrSeriesId WHERE table_episodes.path = ? AND missing_subtitles != '[]'", (path_replace_reverse(path), )).fetchall() c_db.close() providers_list = get_providers() providers_auth = get_providers_auth() for episode in episodes_details: attempt = episode[6] if type(attempt) == unicode: attempt = ast.literal_eval(attempt) for language in ast.literal_eval(episode[1]): if attempt is None: attempt = [] attempt.append([language, time.time()]) else: att = zip(*attempt)[0] if language not in att: attempt.append([language, time.time()]) conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() c_db.execute( 'UPDATE table_episodes SET failedAttempts = ? WHERE sonarrEpisodeId = ?', (unicode(attempt), episode[2])) conn_db.commit() c_db.close() for i in range(len(attempt)): if attempt[i][0] == language: if search_active(attempt[i][1]): notifications.write( msg='Searching ' + str(language_from_alpha2(language)) + ' subtitles for this episode: ' + path, queue='get_subtitle') result = download_subtitle( path_replace(episode[0]), str(alpha3_from_alpha2(language)), episode[4], providers_list, providers_auth, str(episode[5]), episode[7], 'series') if result is not None: message = result[0] path = result[1] language_code = result[2] provider = result[3] score = result[4] store_subtitles(path_replace(episode[0])) list_missing_subtitles(episode[3]) history_log(1, episode[3], episode[2], message, path, language_code, provider, score) send_notifications(episode[3], episode[2], message) else: logging.debug( 'BAZARR Search is not active for episode ' + episode[0] + ' Language: ' + attempt[i][0])
def manual_download_subtitle(path, language, hi, subtitle, provider, providers_auth, sceneName, title, media_type): logging.debug('BAZARR Manually downloading subtitles for this file: ' + path) subtitle = pickle.loads(codecs.decode(subtitle.encode(), "base64")) use_scenename = settings.general.getboolean('use_scenename') use_postprocessing = settings.general.getboolean('use_postprocessing') postprocessing_cmd = settings.general.postprocessing_cmd single = settings.general.getboolean('single_language') video = get_video(path, title, sceneName, use_scenename, providers={provider}, media_type=media_type) if video: min_score, max_score, scores = get_scores(video, media_type) try: if provider: download_subtitles([subtitle], providers={provider}, provider_configs=providers_auth, pool_class=provider_pool(), throttle_callback=provider_throttle) logging.debug( 'BAZARR Subtitles file downloaded for this file:' + path) else: logging.info("BAZARR All providers are throttled") return None except Exception as e: logging.exception( 'BAZARR Error downloading subtitles for this file ' + path) return None else: if not subtitle.is_valid(): notifications.write( msg='No valid subtitles file found for this file: ' + path, queue='get_subtitle') logging.exception( 'BAZARR No valid subtitles file found for this file: ' + path) return logging.debug('BAZARR Subtitles file downloaded for this file:' + path) try: score = round(subtitle.score / max_score * 100, 2) fld = get_target_folder(path) chmod = int(settings.general.chmod, 8) if not sys.platform.startswith( 'win') and settings.general.getboolean( 'chmod_enabled') else None saved_subtitles = save_subtitles( video.original_path, [subtitle], single=single, tags=None, # fixme directory=fld, chmod=chmod, # formats=("srt", "vtt") path_decoder=force_unicode) except Exception as e: logging.exception( 'BAZARR Error saving subtitles file to disk for this file:' + path) return else: if saved_subtitles: for saved_subtitle in saved_subtitles: downloaded_provider = saved_subtitle.provider_name if saved_subtitle.language == 'pt-BR': downloaded_language_code3 = 'pob' else: downloaded_language_code3 = subtitle.language.alpha3 downloaded_language = language_from_alpha3( downloaded_language_code3) downloaded_language_code2 = alpha2_from_alpha3( downloaded_language_code3) downloaded_path = saved_subtitle.storage_path logging.debug('BAZARR Subtitles file saved to disk: ' + downloaded_path) message = downloaded_language + " subtitles downloaded from " + downloaded_provider + " with a score of " + unicode( score) + "% using manual search." if use_postprocessing is True: command = pp_replace(postprocessing_cmd, path, downloaded_path, downloaded_language, downloaded_language_code2, downloaded_language_code3) try: if os.name == 'nt': codepage = subprocess.Popen( "chcp", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # wait for the process to terminate out_codepage, err_codepage = codepage.communicate( ) encoding = out_codepage.split( ':')[-1].strip() process = subprocess.Popen( command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # wait for the process to terminate out, err = process.communicate() if os.name == 'nt': out = out.decode(encoding) except: if out == "": logging.error( 'BAZARR Post-processing result for file ' + path + ' : Nothing returned from command execution' ) else: logging.error( 'BAZARR Post-processing result for file ' + path + ' : ' + out) else: if out == "": logging.info( 'BAZARR Post-processing result for file ' + path + ' : Nothing returned from command execution' ) else: logging.info( 'BAZARR Post-processing result for file ' + path + ' : ' + out) if media_type == 'series': reversed_path = path_replace_reverse(path) else: reversed_path = path_replace_reverse_movie(path) return message, reversed_path, downloaded_language_code2, downloaded_provider, subtitle.score else: logging.error( "BAZARR Tried to manually download a subtitles for file: " + path + " but we weren't able to do (probably throttled by " + str(subtitle.provider_name) + ". Please retry later or select a subtitles from another provider." ) return None logging.debug('BAZARR Ended manually downloading subtitles for file: ' + path)
def store_subtitles(file): logging.debug('BAZARR started subtitles indexing for this file: ' + file) actual_subtitles = [] if os.path.exists(file): notifications.write(msg='Analyzing this file for subtitles: ' + file, queue='list_subtitles') if os.path.splitext(file)[1] == '.mkv': logging.debug("BAZARR is trying to index embedded subtitles.") try: with open(file, 'rb') as f: mkv = enzyme.MKV(f) for subtitle_track in mkv.subtitle_tracks: try: if alpha2_from_alpha3(subtitle_track.language) is not None: lang = str(alpha2_from_alpha3(subtitle_track.language)) logging.debug("BAZARR embedded subtitles detected: " + lang) actual_subtitles.append([lang, None]) except: logging.debug("BAZARR unable to index this unrecognized language: " + subtitle_track.language) pass except Exception as e: logging.exception("BAZARR error when trying to analyze this mkv file: " + file) pass else: logging.debug("BAZARR This file isn't an .mkv file.") brazilian_portuguese = [".pt-br", ".pob", "pb"] try: dest_folder = get_subtitle_destination_folder() subliminal_patch.core.CUSTOM_PATHS = [dest_folder] if dest_folder else [] 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(): subtitle_path = get_external_subtitles_path(file, subtitle) if str(os.path.splitext(subtitle)[0]).lower().endswith(tuple(brazilian_portuguese)): logging.debug("BAZARR external subtitles detected: " + "pb") actual_subtitles.append( [str("pb"), path_replace_reverse(subtitle_path)]) elif str(language) != 'und': logging.debug("BAZARR external subtitles detected: " + str(language)) actual_subtitles.append( [str(language), path_replace_reverse(subtitle_path)]) else: if os.path.splitext(subtitle)[1] != ".sub": logging.debug("BAZARR falling back to file content analysis to detect language.") with open(path_replace(os.path.join(os.path.dirname(file), 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: ' + path_replace( 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( os.path.join(os.path.dirname(file), subtitle))]) conn_db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c_db = conn_db.cursor() logging.debug("BAZARR storing those languages to DB: " + str(actual_subtitles)) c_db.execute("UPDATE table_episodes SET subtitles = ? WHERE path = ?", (str(actual_subtitles), path_replace_reverse(file))) conn_db.commit() c_db.close() 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
def update_series(): notifications.write(msg="Update series list from Sonarr is running...", queue='get_series') apikey_sonarr = settings.sonarr.apikey sonarr_version = get_sonarr_version() serie_default_enabled = settings.general.getboolean('serie_default_enabled') serie_default_language = settings.general.serie_default_language serie_default_hi = settings.general.serie_default_hi serie_default_forced = settings.general.serie_default_forced if apikey_sonarr is None: pass else: audio_profiles = get_profile_list() # Get shows data from Sonarr url_sonarr_api_series = url_sonarr + "/api/series?apikey=" + apikey_sonarr try: r = requests.get(url_sonarr_api_series, timeout=60, verify=False) r.raise_for_status() except requests.exceptions.HTTPError as errh: logging.exception("BAZARR Error trying to get series from Sonarr. Http error.") return except requests.exceptions.ConnectionError as errc: logging.exception("BAZARR Error trying to get series from Sonarr. Connection Error.") return except requests.exceptions.Timeout as errt: logging.exception("BAZARR Error trying to get series from Sonarr. Timeout Error.") return except requests.exceptions.RequestException as err: logging.exception("BAZARR Error trying to get series from Sonarr.") return else: # Get current shows in DB current_shows_db = TableShows.select( TableShows.tvdb_id ) current_shows_db_list = [x.tvdb_id for x in current_shows_db] current_shows_sonarr = [] series_to_update = [] series_to_add = [] altered_series = [] seriesListLength = len(r.json()) for i, show in enumerate(r.json(), 1): notifications.write(msg="Getting series data from Sonarr...", queue='get_series', item=i, length=seriesListLength) try: overview = unicode(show['overview']) except: overview = "" try: poster_big = show['images'][2]['url'].split('?')[0] poster = os.path.splitext(poster_big)[0] + '-250' + os.path.splitext(poster_big)[1] except: poster = "" try: fanart = show['images'][0]['url'].split('?')[0] except: fanart = "" if show['alternateTitles'] != None: alternateTitles = str([item['title'] for item in show['alternateTitles']]) else: alternateTitles = None # Add shows in Sonarr to current shows list current_shows_sonarr.append(show['tvdbId']) if show['tvdbId'] in current_shows_db_list: series_to_update.append({'title': unicode(show["title"]), 'path': unicode(show["path"]), 'tvdb_id': int(show["tvdbId"]), 'sonarr_series_id': int(show["id"]), 'overview': unicode(overview), 'poster': unicode(poster), 'fanart': unicode(fanart), 'audio_language': unicode(profile_id_to_language((show['qualityProfileId'] if sonarr_version.startswith('2') else show['languageProfileId']), audio_profiles)), 'sort_title': unicode(show['sortTitle']), 'year': unicode(show['year']), 'alternate_titles': unicode(alternateTitles)}) else: if serie_default_enabled is True: series_to_add.append({'title': show["title"], 'path': show["path"], 'tvdb_id': show["tvdbId"], 'languages': serie_default_language, 'hearing_impaired': serie_default_hi, 'sonarr_series_id': show["id"], 'overview': overview, 'poster': poster, 'fanart': fanart, 'audio_language': profile_id_to_language((show['qualityProfileId'] if sonarr_version.startswith('2') else show['languageProfileId']), audio_profiles), 'sort_title': show['sortTitle'], 'year': show['year'], 'alternate_titles': alternateTitles, 'forced': serie_default_forced}) else: series_to_add.append({'title': show["title"], 'path': show["path"], 'tvdb_id': show["tvdbId"], 'sonarr_series_id': show["id"], 'overview': overview, 'poster': poster, 'fanart': fanart, 'audio_language': profile_id_to_language((show['qualityProfileId'] if sonarr_version.startswith('2') else show['languageProfileId']), audio_profiles), 'sort_title': show['sortTitle'], 'year': show['year'], 'alternate_titles': alternateTitles}) # Update existing series in DB series_in_db_list = [] series_in_db = TableShows.select( TableShows.title, TableShows.path, TableShows.tvdb_id, TableShows.sonarr_series_id, TableShows.overview, TableShows.poster, TableShows.fanart, TableShows.audio_language, TableShows.sort_title, TableShows.year, TableShows.alternate_titles ).dicts() for item in series_in_db: series_in_db_list.append(item) series_to_update_list = [i for i in series_to_update if i not in series_in_db_list] for updated_series in series_to_update_list: TableShows.update( updated_series ).where( TableShows.sonarr_series_id == updated_series['sonarr_series_id'] ).execute() # Insert new series in DB for added_series in series_to_add: TableShows.insert( added_series ).on_conflict_ignore().execute() list_missing_subtitles(added_series['sonarr_series_id']) # Remove old series from DB removed_series = list(set(current_shows_db_list) - set(current_shows_sonarr)) for series in removed_series: TableShows.delete().where( TableShows.tvdb_id == series ).execute() logging.debug('BAZARR All series synced from Sonarr into database.')
def sync_episodes(): notifications.write(msg='Episodes sync from Sonarr started...', queue='get_episodes') logging.debug('BAZARR Starting episodes sync from Sonarr.') apikey_sonarr = settings.sonarr.apikey # Open database connection db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() # Get current episodes id in DB current_episodes_db = c.execute('SELECT sonarrEpisodeId, path, sonarrSeriesId FROM table_episodes').fetchall() current_episodes_db_list = [x[0] for x in current_episodes_db] current_episodes_sonarr = [] episodes_to_update = [] episodes_to_add = [] # Get sonarrId for each series from database seriesIdList = c.execute("SELECT sonarrSeriesId, title FROM table_shows").fetchall() # Close database connection c.close() seriesIdListLength = len(seriesIdList) for i, seriesId in enumerate(seriesIdList, 1): notifications.write(msg='Getting episodes data from Sonarr...', queue='get_episodes', item=i, length=seriesIdListLength) # Get episodes data for a series from Sonarr url_sonarr_api_episode = url_sonarr + "/api/episode?seriesId=" + str(seriesId[0]) + "&apikey=" + apikey_sonarr try: r = requests.get(url_sonarr_api_episode, timeout=60, verify=False) r.raise_for_status() except requests.exceptions.HTTPError as errh: logging.exception("BAZARR Error trying to get episodes from Sonarr. Http error.") except requests.exceptions.ConnectionError as errc: logging.exception("BAZARR Error trying to get episodes from Sonarr. Connection Error.") except requests.exceptions.Timeout as errt: logging.exception("BAZARR Error trying to get episodes from Sonarr. Timeout Error.") except requests.exceptions.RequestException as err: logging.exception("BAZARR Error trying to get episodes from Sonarr.") else: for episode in r.json(): if 'hasFile' in episode: if episode['hasFile'] is True: if 'episodeFile' in episode: if episode['episodeFile']['size'] > 20480: # Add shows in Sonarr to current shows list if 'sceneName' in episode['episodeFile']: sceneName = episode['episodeFile']['sceneName'] else: sceneName = None try: format, resolution = episode['episodeFile']['quality']['quality']['name'].split('-') except: format = episode['episodeFile']['quality']['quality']['name'] try: resolution = str(episode['episodeFile']['quality']['quality']['resolution']) + 'p' except: resolution = None if 'mediaInfo' in episode['episodeFile']: if 'videoCodec' in episode['episodeFile']['mediaInfo']: videoCodec = episode['episodeFile']['mediaInfo']['videoCodec'] videoCodec = SonarrFormatVideoCodec(videoCodec) else: videoCodec = None if 'audioCodec' in episode['episodeFile']['mediaInfo']: audioCodec = episode['episodeFile']['mediaInfo']['audioCodec'] audioCodec = SonarrFormatAudioCodec(audioCodec) else: audioCodec = None else: videoCodec = None audioCodec = None # Add episodes in sonarr to current episode list current_episodes_sonarr.append(episode['id']) if episode['id'] in current_episodes_db_list: episodes_to_update.append((episode['title'], episode['episodeFile']['path'], episode['seasonNumber'], episode['episodeNumber'], sceneName, str(bool(episode['monitored'])), format, resolution, videoCodec, audioCodec, episode['id'])) else: episodes_to_add.append((episode['seriesId'], episode['id'], episode['title'], episode['episodeFile']['path'], episode['seasonNumber'], episode['episodeNumber'], sceneName, str(bool(episode['monitored'])), format, resolution, videoCodec, audioCodec)) removed_episodes = list(set(current_episodes_db_list) - set(current_episodes_sonarr)) # Update or insert movies in DB db = sqlite3.connect(os.path.join(args.config_dir, 'db', 'bazarr.db'), timeout=30) c = db.cursor() updated_result = c.executemany( '''UPDATE table_episodes SET title = ?, path = ?, season = ?, episode = ?, scene_name = ?, monitored = ?, format = ?, resolution = ?, video_codec = ?, audio_codec = ? WHERE sonarrEpisodeId = ?''', episodes_to_update) db.commit() added_result = c.executemany( '''INSERT OR IGNORE INTO table_episodes(sonarrSeriesId, sonarrEpisodeId, title, path, season, episode, scene_name, monitored, format, resolution, video_codec, audio_codec) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', episodes_to_add) db.commit() for removed_episode in removed_episodes: c.execute('DELETE FROM table_episodes WHERE sonarrEpisodeId = ?', (removed_episode,)) db.commit() # Get episodes list after INSERT and UPDATE episodes_now_in_db = c.execute('SELECT sonarrEpisodeId, path, sonarrSeriesId FROM table_episodes').fetchall() # Close database connection c.close() # Get only episodes added or modified and store subtitles for them altered_episodes = set(episodes_now_in_db).difference(set(current_episodes_db)) for altered_episode in altered_episodes: store_subtitles(path_replace(altered_episode[1])) list_missing_subtitles(altered_episode[2]) logging.debug('BAZARR All episodes synced from Sonarr into database.') # Search for desired subtitles if no more than 5 episodes have been added. if len(altered_episodes) <= 5: logging.debug("BAZARR No more than 5 episodes were added during this sync then we'll search for subtitles.") for altered_episode in altered_episodes: episode_download_subtitles(altered_episode[0]) else: logging.debug("BAZARR More than 5 episodes were added during this sync then we wont search for subtitles.")
def sync_episodes(): notifications.write(msg='Episodes sync from Sonarr started...', queue='get_episodes') logging.debug('BAZARR Starting episodes sync from Sonarr.') apikey_sonarr = settings.sonarr.apikey # Get current episodes id in DB current_episodes_db = TableEpisodes.select(TableEpisodes.sonarr_episode_id, TableEpisodes.path, TableEpisodes.sonarr_series_id) current_episodes_db_list = [ x.sonarr_episode_id 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 = TableShows.select(TableShows.sonarr_series_id, TableShows.title) seriesIdListLength = seriesIdList.count() for i, seriesId in enumerate(seriesIdList, 1): notifications.write(msg='Getting episodes data from Sonarr...', queue='get_episodes', item=i, length=seriesIdListLength) # Get episodes data for a series from Sonarr url_sonarr_api_episode = url_sonarr + "/api/episode?seriesId=" + str( seriesId.sonarr_series_id) + "&apikey=" + apikey_sonarr try: r = requests.get(url_sonarr_api_episode, timeout=60, verify=False) r.raise_for_status() except requests.exceptions.HTTPError as errh: logging.exception( "BAZARR Error trying to get episodes from Sonarr. Http error.") return except requests.exceptions.ConnectionError as errc: logging.exception( "BAZARR Error trying to get episodes from Sonarr. Connection Error." ) return except requests.exceptions.Timeout as errt: logging.exception( "BAZARR Error trying to get episodes from Sonarr. Timeout Error." ) return except requests.exceptions.RequestException as err: logging.exception( "BAZARR Error trying to get episodes from Sonarr.") return else: for episode in r.json(): if 'hasFile' in episode: if episode['hasFile'] is True: if 'episodeFile' in episode: if episode['episodeFile']['size'] > 20480: # Add shows in Sonarr to current shows list if 'sceneName' in episode['episodeFile']: sceneName = episode['episodeFile'][ 'sceneName'] else: sceneName = None try: format, resolution = episode[ 'episodeFile']['quality']['quality'][ 'name'].split('-') except: format = episode['episodeFile']['quality'][ 'quality']['name'] try: resolution = str( episode['episodeFile']['quality'] ['quality']['resolution']) + 'p' except: resolution = None if 'mediaInfo' in episode['episodeFile']: if 'videoCodec' in episode['episodeFile'][ 'mediaInfo']: videoCodec = episode['episodeFile'][ 'mediaInfo']['videoCodec'] videoCodec = SonarrFormatVideoCodec( videoCodec) else: videoCodec = None if 'audioCodec' in episode['episodeFile'][ 'mediaInfo']: audioCodec = episode['episodeFile'][ 'mediaInfo']['audioCodec'] audioCodec = SonarrFormatAudioCodec( audioCodec) else: audioCodec = None else: videoCodec = None audioCodec = None # Add episodes in sonarr to current episode list current_episodes_sonarr.append(episode['id']) if episode['id'] in current_episodes_db_list: episodes_to_update.append({ 'sonarr_series_id': episode['seriesId'], 'sonarr_episode_id': episode['id'], 'title': episode['title'], 'path': episode['episodeFile']['path'], 'season': episode['seasonNumber'], 'episode': episode['episodeNumber'], 'scene_name': sceneName, 'monitored': str(bool(episode['monitored'])), 'format': format, 'resolution': resolution, 'video_codec': videoCodec, 'audio_codec': audioCodec, 'episode_file_id': episode['episodeFile']['id'] }) else: episodes_to_add.append({ 'sonarr_series_id': episode['seriesId'], 'sonarr_episode_id': episode['id'], 'title': episode['title'], 'path': episode['episodeFile']['path'], 'season': episode['seasonNumber'], 'episode': episode['episodeNumber'], 'scene_name': sceneName, 'monitored': str(bool(episode['monitored'])), 'format': format, 'resolution': resolution, 'video_codec': videoCodec, 'audio_codec': audioCodec, 'episode_file_id': episode['episodeFile']['id'] }) # Update existing episodes in DB episode_in_db_list = [] episodes_in_db = TableEpisodes.select( TableEpisodes.sonarr_series_id, TableEpisodes.sonarr_episode_id, TableEpisodes.title, TableEpisodes.path, TableEpisodes.season, TableEpisodes.episode, TableEpisodes.scene_name, TableEpisodes.monitored, TableEpisodes.format, TableEpisodes.resolution, TableEpisodes.video_codec, TableEpisodes.audio_codec, TableEpisodes.episode_file_id).dicts() for item in episodes_in_db: episode_in_db_list.append(item) episodes_to_update_list = [ i for i in episodes_to_update if i not in episode_in_db_list ] for updated_episode in episodes_to_update_list: TableEpisodes.update(updated_episode).where( TableEpisodes.sonarr_episode_id == updated_episode['sonarr_episode_id']).execute() altered_episodes.append([ updated_episode['sonarr_episode_id'], updated_episode['path'], updated_episode['sonarr_series_id'] ]) # Insert new episodes in DB for added_episode in episodes_to_add: TableEpisodes.insert(added_episode).on_conflict_ignore().execute() altered_episodes.append([ added_episode['sonarr_episode_id'], added_episode['path'], added_episode['sonarr_series_id'] ]) # Remove old episodes from DB removed_episodes = list( set(current_episodes_db_list) - set(current_episodes_sonarr)) for removed_episode in removed_episodes: TableEpisodes.delete().where( TableEpisodes.sonarr_episode_id == removed_episode).execute() # Store subtitles for added or modified episodes for i, altered_episode in enumerate(altered_episodes, 1): notifications.write(msg='Indexing episodes embedded subtitles...', queue='get_episodes', item=i, length=len(altered_episodes)) store_subtitles(path_replace(altered_episode[1])) list_missing_subtitles(altered_episode[2]) logging.debug('BAZARR All episodes synced from Sonarr into database.') # Search for desired subtitles if no more than 5 episodes have been added. if len(altered_episodes) <= 5: logging.debug( "BAZARR No more than 5 episodes were added during this sync then we'll search for subtitles." ) for altered_episode in altered_episodes: episode_download_subtitles(altered_episode[0]) else: logging.debug( "BAZARR More than 5 episodes were added during this sync then we wont search for subtitles right now." )
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 = database.execute( "SELECT tmdbId, path, radarrId FROM table_movies") current_movies_db_list = [x['tmdbId'] 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({ 'radarrId': movie["id"], 'title': unicode(movie["title"]), 'path': unicode( movie["path"] + separator + movie['movieFile']['relativePath']), 'tmdbId': unicode(movie["tmdbId"]), 'poster': unicode(poster), 'fanart': unicode(fanart), 'audio_language': unicode( profile_id_to_language( movie['qualityProfileId'], audio_profiles)), 'sceneName': sceneName, 'monitored': unicode(bool(movie['monitored'])), 'year': unicode(movie['year']), 'sortTitle': unicode(movie['sortTitle']), 'alternativeTitles': unicode(alternativeTitles), 'format': unicode(format), 'resolution': unicode(resolution), 'video_codec': unicode(videoCodec), 'audio_codec': unicode(audioCodec), 'overview': unicode(overview), 'imdbId': unicode(imdbId), 'movie_file_id': movie['movieFile']['id'] }) else: if movie_default_enabled is True: movies_to_add.append({ 'radarrId': movie["id"], 'title': movie["title"], 'path': movie["path"] + separator + movie['movieFile']['relativePath'], 'tmdbId': 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), 'sceneName': sceneName, 'monitored': unicode(bool(movie['monitored'])), 'sortTitle': movie['sortTitle'], 'year': movie['year'], 'alternativeTitles': alternativeTitles, 'format': format, 'resolution': resolution, 'video_codec': videoCodec, 'audio_codec': audioCodec, 'imdbId': imdbId, 'forced': movie_default_forced, 'movie_file_id': movie['movieFile']['id'] }) else: movies_to_add.append({ 'radarrId': movie["id"], 'title': movie["title"], 'path': movie["path"] + separator + movie['movieFile']['relativePath'], 'tmdbId': movie["tmdbId"], 'languages': None, 'subtitles': '[]', 'hearing_impaired': None, 'overview': overview, 'poster': poster, 'fanart': fanart, 'audio_language': profile_id_to_language( movie['qualityProfileId'], audio_profiles), 'sceneName': sceneName, 'monitored': unicode(bool(movie['monitored'])), 'sortTitle': movie['sortTitle'], 'year': movie['year'], 'alternativeTitles': alternativeTitles, 'format': format, 'resolution': resolution, 'video_codec': videoCodec, 'audio_codec': audioCodec, 'imdbId': imdbId, 'forced': None, 'movie_file_id': movie['movieFile']['id'] }) else: logging.error( 'BAZARR Radarr returned a movie without a file path: ' + movie["path"] + separator + movie['movieFile']['relativePath']) # Remove old movies from DB removed_movies = list( set(current_movies_db_list) - set(current_movies_radarr)) for removed_movie in removed_movies: database.execute("DELETE FROM table_movies WHERE tmdbId=?", (removed_movie, )) # Update movies in DB movies_in_db_list = [] movies_in_db = database.execute( "SELECT radarrId, title, path, tmdbId, overview, poster, fanart, " "audio_language, sceneName, monitored, sortTitle, year, " "alternativeTitles, format, resolution, video_codec, audio_codec, imdbId," "movie_file_id FROM table_movies") 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: query = dict_converter.convert(updated_movie) database.execute( '''UPDATE table_movies SET ''' + query.keys_update + ''' WHERE radarrId = ?''', query.values + (updated_movie['radarrId'], )) 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: query = dict_converter.convert(added_movie) result = database.execute( '''INSERT OR IGNORE INTO table_movies(''' + query.keys_insert + ''') VALUES(''' + query.question_marks + ''')''', query.values) if result > 0: altered_movies.append([ added_movie['tmdbId'], added_movie['path'], added_movie['radarrId'], added_movie['monitored'] ]) else: logging.debug( 'BAZARR unable to insert this movie into the database:', path_replace_movie(added_movie['path'])) # 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])) 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: if settings.radarr.getboolean('only_monitored'): if altered_movie[3] == 'True': movies_download_subtitles(altered_movie[2]) else: 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 sync_episodes(): notifications.write(msg='Episodes sync from Sonarr started...', queue='get_episodes') 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 ] 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") seriesIdListLength = len(seriesIdList) for i, seriesId in enumerate(seriesIdList, 1): notifications.write(msg='Getting episodes data from Sonarr...', queue='get_episodes', item=i, length=seriesIdListLength) # Get episodes data for a series from Sonarr url_sonarr_api_episode = url_sonarr() + "/api/episode?seriesId=" + str( seriesId['sonarrSeriesId']) + "&apikey=" + apikey_sonarr try: r = requests.get(url_sonarr_api_episode, timeout=60, verify=False) r.raise_for_status() except requests.exceptions.HTTPError as errh: logging.exception( "BAZARR Error trying to get episodes from Sonarr. Http error.") return except requests.exceptions.ConnectionError as errc: logging.exception( "BAZARR Error trying to get episodes from Sonarr. Connection Error." ) return except requests.exceptions.Timeout as errt: logging.exception( "BAZARR Error trying to get episodes from Sonarr. Timeout Error." ) return except requests.exceptions.RequestException as err: logging.exception( "BAZARR Error trying to get episodes from Sonarr.") return else: for episode in r.json(): if 'hasFile' in episode: if episode['hasFile'] is True: if 'episodeFile' in episode: if episode['episodeFile']['size'] > 20480: # Add shows in Sonarr to current shows list if 'sceneName' in episode['episodeFile']: sceneName = episode['episodeFile'][ 'sceneName'] else: sceneName = None try: format, resolution = episode[ 'episodeFile']['quality']['quality'][ 'name'].split('-') except: format = episode['episodeFile']['quality'][ 'quality']['name'] try: resolution = str( episode['episodeFile']['quality'] ['quality']['resolution']) + 'p' except: resolution = None if 'mediaInfo' in episode['episodeFile']: if 'videoCodec' in episode['episodeFile'][ 'mediaInfo']: videoCodec = episode['episodeFile'][ 'mediaInfo']['videoCodec'] videoCodec = SonarrFormatVideoCodec( videoCodec) else: videoCodec = None if 'audioCodec' in episode['episodeFile'][ 'mediaInfo']: audioCodec = episode['episodeFile'][ 'mediaInfo']['audioCodec'] audioCodec = SonarrFormatAudioCodec( audioCodec) else: audioCodec = None else: videoCodec = None audioCodec = None # Add episodes in sonarr to current episode list current_episodes_sonarr.append(episode['id']) if episode['id'] in current_episodes_db_list: episodes_to_update.append({ 'sonarrSeriesId': episode['seriesId'], 'sonarrEpisodeId': episode['id'], 'title': episode['title'], 'path': episode['episodeFile']['path'], 'season': episode['seasonNumber'], 'episode': episode['episodeNumber'], 'scene_name': sceneName, 'monitored': str(bool(episode['monitored'])), 'format': format, 'resolution': resolution, 'video_codec': videoCodec, 'audio_codec': audioCodec, 'episode_file_id': episode['episodeFile']['id'] }) else: episodes_to_add.append({ 'sonarrSeriesId': episode['seriesId'], 'sonarrEpisodeId': episode['id'], 'title': episode['title'], 'path': episode['episodeFile']['path'], 'season': episode['seasonNumber'], 'episode': episode['episodeNumber'], 'scene_name': sceneName, 'monitored': str(bool(episode['monitored'])), 'format': format, 'resolution': resolution, 'video_codec': videoCodec, 'audio_codec': audioCodec, 'episode_file_id': episode['episodeFile']['id'] }) # Remove old episodes from DB removed_episodes = list( set(current_episodes_db_list) - set(current_episodes_sonarr)) for removed_episode in removed_episodes: database.execute("DELETE FROM table_episodes WHERE sonarrEpisodeId=?", (removed_episode, )) # Update existing episodes in DB episode_in_db_list = [] episodes_in_db = database.execute( "SELECT sonarrSeriesId, sonarrEpisodeId, title, path, season, episode, " "scene_name, monitored, format, resolution, video_codec, audio_codec, " "episode_file_id FROM table_episodes") for item in episodes_in_db: episode_in_db_list.append(item) episodes_to_update_list = [ i for i in episodes_to_update if i not in episode_in_db_list ] for updated_episode in episodes_to_update_list: query = dict_converter.convert(updated_episode) database.execute( '''UPDATE table_episodes SET ''' + query.keys_update + ''' WHERE sonarrEpisodeId = ?''', query.values + (updated_episode['sonarrEpisodeId'], )) altered_episodes.append([ updated_episode['sonarrEpisodeId'], updated_episode['path'], updated_episode['sonarrSeriesId'] ]) # Insert new episodes in DB for added_episode in episodes_to_add: query = dict_converter.convert(added_episode) result = database.execute( '''INSERT OR IGNORE INTO table_episodes(''' + query.keys_insert + ''') VALUES(''' + query.question_marks + ''')''', query.values) if result > 0: altered_episodes.append( [added_episode['sonarrEpisodeId'], added_episode['path']]) else: logging.debug( 'BAZARR unable to insert this episode into the database:', path_replace(added_episode['path'])) # Store subtitles for added or modified episodes for i, altered_episode in enumerate(altered_episodes, 1): notifications.write(msg='Indexing episodes embedded subtitles...', queue='get_episodes', item=i, length=len(altered_episodes)) store_subtitles(altered_episode[1], path_replace(altered_episode[1])) logging.debug('BAZARR All episodes synced from Sonarr into database.') # Search for desired subtitles if no more than 5 episodes have been added. if len(altered_episodes) <= 5: logging.debug( "BAZARR No more than 5 episodes were added during this sync then we'll search for subtitles." ) for altered_episode in altered_episodes: episode_download_subtitles(altered_episode[0]) else: logging.debug( "BAZARR More than 5 episodes were added during this sync then we wont search for subtitles right now." )
def update_series(): notifications.write(msg="Update series list from Sonarr is running...", queue='get_series') apikey_sonarr = settings.sonarr.apikey if apikey_sonarr is None: return sonarr_version = get_sonarr_version() serie_default_enabled = settings.general.getboolean( 'serie_default_enabled') serie_default_language = settings.general.serie_default_language serie_default_hi = settings.general.serie_default_hi serie_default_forced = settings.general.serie_default_forced audio_profiles = get_profile_list() # Get shows data from Sonarr url_sonarr_api_series = url_sonarr( ) + "/api/series?apikey=" + apikey_sonarr try: r = requests.get(url_sonarr_api_series, timeout=60, verify=False) r.raise_for_status() except requests.exceptions.HTTPError: logging.exception( "BAZARR Error trying to get series from Sonarr. Http error.") return except requests.exceptions.ConnectionError: logging.exception( "BAZARR Error trying to get series from Sonarr. Connection Error.") return except requests.exceptions.Timeout: logging.exception( "BAZARR Error trying to get series from Sonarr. Timeout Error.") return except requests.exceptions.RequestException: logging.exception("BAZARR Error trying to get series from Sonarr.") return # Get current shows in DB current_shows_db = database.execute( "SELECT sonarrSeriesId FROM table_shows") current_shows_db_list = [x['sonarrSeriesId'] for x in current_shows_db] current_shows_sonarr = [] series_to_update = [] series_to_add = [] series_list_length = len(r.json()) for i, show in enumerate(r.json(), 1): notifications.write(msg="Getting series data from Sonarr...", queue='get_series', item=i, length=series_list_length) overview = show['overview'] if 'overview' in show else '' poster = '' fanart = '' for image in show['images']: if image['coverType'] == 'poster': poster_big = image['url'].split('?')[0] poster = os.path.splitext( poster_big)[0] + '-250' + os.path.splitext(poster_big)[1] if image['coverType'] == 'fanart': fanart = image['url'].split('?')[0] alternate_titles = None if show['alternateTitles'] is not None: alternate_titles = str( [item['title'] for item in show['alternateTitles']]) if sonarr_version.startswith('2'): audio_language = profile_id_to_language(show['qualityProfileId'], audio_profiles) else: audio_language = profile_id_to_language(show['languageProfileId'], audio_profiles) # Add shows in Sonarr to current shows list current_shows_sonarr.append(show['id']) if show['id'] in current_shows_db_list: series_to_update.append({ 'title': show["title"], 'path': show["path"], 'tvdbId': int(show["tvdbId"]), 'sonarrSeriesId': int(show["id"]), 'overview': overview, 'poster': poster, 'fanart': fanart, 'audio_language': audio_language, 'sortTitle': show['sortTitle'], 'year': show['year'], 'alternateTitles': alternate_titles }) else: if serie_default_enabled is True: series_to_add.append({ 'title': show["title"], 'path': show["path"], 'tvdbId': show["tvdbId"], 'languages': serie_default_language, 'hearing_impaired': serie_default_hi, 'sonarrSeriesId': show["id"], 'overview': overview, 'poster': poster, 'fanart': fanart, 'audio_language': audio_language, 'sortTitle': show['sortTitle'], 'year': show['year'], 'alternateTitles': alternate_titles, 'forced': serie_default_forced }) else: series_to_add.append({ 'title': show["title"], 'path': show["path"], 'tvdbId': show["tvdbId"], 'sonarrSeriesId': show["id"], 'overview': overview, 'poster': poster, 'fanart': fanart, 'audio_language': audio_language, 'sortTitle': show['sortTitle'], 'year': show['year'], 'alternateTitles': alternate_titles }) # 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, )) # 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 FROM table_shows") for item in series_in_db: series_in_db_list.append(item) series_to_update_list = [ i for i in series_to_update if i not in series_in_db_list ] for updated_series in series_to_update_list: query = dict_converter.convert(updated_series) database.execute( '''UPDATE table_shows SET ''' + query.keys_update + ''' WHERE sonarrSeriesId = ?''', query.values + (updated_series['sonarrSeriesId'], )) # Insert new series in DB for added_series in series_to_add: query = dict_converter.convert(added_series) result = database.execute( '''INSERT OR IGNORE INTO table_shows(''' + query.keys_insert + ''') VALUES(''' + query.question_marks + ''')''', query.values) if result: list_missing_subtitles(no=added_series['sonarrSeriesId']) else: logging.debug( 'BAZARR unable to insert this series into the database:', path_replace(added_series['path'])) logging.debug('BAZARR All series synced from Sonarr into database.')