Splitting path substitution for Radarr to address the case where Sonarr and Radarr access files trough the same path.

This commit is contained in:
morpheus65535 2018-06-05 20:06:00 -04:00
parent a40e203188
commit 6e4bc14144
8 changed files with 180 additions and 27 deletions

View File

@ -337,7 +337,7 @@ def movies():
single_language = get_general_settings()[7]
db = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'), timeout=30)
db.create_function("path_substitution", 1, path_replace)
db.create_function("path_substitution", 1, path_replace_movie)
c = db.cursor()
c.execute("SELECT COUNT(*) FROM table_movies")
@ -362,7 +362,7 @@ def movieseditor():
single_language = get_general_settings()[7]
db = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'), timeout=30)
db.create_function("path_substitution", 1, path_replace)
db.create_function("path_substitution", 1, path_replace_movie)
c = db.cursor()
c.execute("SELECT COUNT(*) FROM table_movies")
@ -444,7 +444,7 @@ def movie(no):
url_radarr_short = get_radarr_settings()[1]
conn = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'), timeout=30)
conn.create_function("path_substitution", 1, path_replace)
conn.create_function("path_substitution", 1, path_replace_movie)
c = conn.cursor()
movies_details = []
@ -589,7 +589,7 @@ def wantedseries():
@route(base_url + 'wantedmovies')
def wantedmovies():
db = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'), timeout=30)
db.create_function("path_substitution", 1, path_replace)
db.create_function("path_substitution", 1, path_replace_movie)
c = db.cursor()
c.execute("SELECT COUNT(*) FROM table_movies WHERE missing_subtitles != '[]'")
@ -648,6 +648,10 @@ def save_settings():
settings_general_destpath = request.forms.getall('settings_general_destpath')
settings_general_pathmapping = []
settings_general_pathmapping.extend([list(a) for a in zip(settings_general_sourcepath, settings_general_destpath)])
settings_general_sourcepath_movie = request.forms.getall('settings_general_sourcepath_movie')
settings_general_destpath_movie = request.forms.getall('settings_general_destpath_movie')
settings_general_pathmapping_movie = []
settings_general_pathmapping_movie.extend([list(a) for a in zip(settings_general_sourcepath_movie, settings_general_destpath_movie)])
settings_general_branch = request.forms.get('settings_general_branch')
settings_general_automatic = request.forms.get('settings_general_automatic')
if settings_general_automatic is None:
@ -682,9 +686,9 @@ def save_settings():
else:
settings_general_use_radarr = 'True'
before = c.execute("SELECT ip, port, base_url, log_level, path_mapping, use_sonarr, use_radarr FROM table_settings_general").fetchone()
after = (unicode(settings_general_ip), int(settings_general_port), unicode(settings_general_baseurl), unicode(settings_general_loglevel), unicode(settings_general_pathmapping), unicode(settings_general_use_sonarr), unicode(settings_general_use_radarr))
c.execute("UPDATE table_settings_general SET ip = ?, port = ?, base_url = ?, path_mapping = ?, log_level = ?, branch=?, auto_update=?, single_language=?, minimum_score=?, use_scenename=?, use_postprocessing=?, postprocessing_cmd=?, use_sonarr=?, use_radarr=?", (unicode(settings_general_ip), int(settings_general_port), unicode(settings_general_baseurl), unicode(settings_general_pathmapping), unicode(settings_general_loglevel), unicode(settings_general_branch), unicode(settings_general_automatic), unicode(settings_general_single_language), unicode(settings_general_minimum_score), unicode(settings_general_scenename), unicode(settings_general_use_postprocessing), unicode(settings_general_postprocessing_cmd), unicode(settings_general_use_sonarr), unicode(settings_general_use_radarr)))
before = c.execute("SELECT ip, port, base_url, log_level, path_mapping, use_sonarr, use_radarr, path_mapping_movie FROM table_settings_general").fetchone()
after = (unicode(settings_general_ip), int(settings_general_port), unicode(settings_general_baseurl), unicode(settings_general_loglevel), unicode(settings_general_pathmapping), unicode(settings_general_use_sonarr), unicode(settings_general_use_radarr), unicode(settings_general_pathmapping_movie))
c.execute("UPDATE table_settings_general SET ip = ?, port = ?, base_url = ?, path_mapping = ?, log_level = ?, branch=?, auto_update=?, single_language=?, minimum_score=?, use_scenename=?, use_postprocessing=?, postprocessing_cmd=?, use_sonarr=?, use_radarr=?, path_mapping_movie=?", (unicode(settings_general_ip), int(settings_general_port), unicode(settings_general_baseurl), unicode(settings_general_pathmapping), unicode(settings_general_loglevel), unicode(settings_general_branch), unicode(settings_general_automatic), unicode(settings_general_single_language), unicode(settings_general_minimum_score), unicode(settings_general_scenename), unicode(settings_general_use_postprocessing), unicode(settings_general_postprocessing_cmd), unicode(settings_general_use_sonarr), unicode(settings_general_use_radarr), unicode(settings_general_pathmapping_movie)))
conn.commit()
if after != before:
configured()

View File

@ -34,8 +34,12 @@ def get_general_settings():
postprocessing_cmd = general_settings[13]
use_sonarr = general_settings[14]
use_radarr = general_settings[15]
if general_settings[16] is None:
path_mappings_movie = []
else:
path_mappings_movie = ast.literal_eval(general_settings[16])
return [ip, port, base_url, path_mappings, log_level, branch, automatic, single_language, minimum_score, use_scenename, use_postprocessing, postprocessing_cmd, use_sonarr, use_radarr]
return [ip, port, base_url, path_mappings, log_level, branch, automatic, single_language, minimum_score, use_scenename, use_postprocessing, postprocessing_cmd, use_sonarr, use_radarr, path_mappings_movie]
def path_replace(path):
for path_mapping in path_mappings:
@ -59,6 +63,28 @@ def path_replace_reverse(path):
break
return path
def path_replace_movie(path):
for path_mapping in path_mappings_movie:
if path_mapping[0] in path:
path = path.replace(path_mapping[0], path_mapping[1])
if path.startswith('\\\\') or re.match(r'^[a-zA-Z]:\\', path):
path = path.replace('/', '\\')
elif path.startswith('/'):
path = path.replace('\\', '/')
break
return path
def path_replace_reverse_movie(path):
for path_mapping in path_mappings_movie:
if path_mapping[1] in path:
path = path.replace(path_mapping[1], path_mapping[0])
if path.startswith('\\\\') or re.match(r'^[a-zA-Z]:\\', path):
path = path.replace('/', '\\')
elif path.startswith('/'):
path = path.replace('\\', '/')
break
return path
def pp_replace(pp_command, episode, subtitles, language, language_code2, language_code3):
pp_command = pp_command.replace('{{directory}}', os.path.dirname(episode))
pp_command = pp_command.replace('{{episode}}', episode)
@ -83,4 +109,5 @@ use_scenename = result[9]
use_processing = result[10]
postprocessing_cmd = result[11]
use_sonarr = result[12]
use_radarr = result[13]
use_radarr = result[13]
path_mappings_movie = result[14]

View File

@ -81,7 +81,7 @@ def update_movies():
for added_movie in added_movies:
added_path = c.execute('SELECT path FROM table_movies WHERE tmdbId = ?', (added_movie,)).fetchone()
store_subtitles_movie(path_replace(added_path[0]))
store_subtitles_movie(path_replace_movie(added_path[0]))
# Close database connection
db.close()

View File

@ -159,9 +159,9 @@ def movies_download_subtitles(no):
providers_auth = None
for language in ast.literal_eval(movie[1]):
message = download_subtitle(path_replace(movie[0]), str(pycountry.languages.lookup(language).alpha_3), movie[4], providers_list, providers_auth, movie[3], 'movies')
message = download_subtitle(path_replace_movie(movie[0]), str(pycountry.languages.lookup(language).alpha_3), movie[4], providers_list, providers_auth, movie[3], 'movies')
if message is not None:
store_subtitles_movie(path_replace(movie[0]))
store_subtitles_movie(path_replace_movie(movie[0]))
history_log_movie(1, no, message)
send_notifications_movie(no, message)
list_missing_subtitles_movies(no)
@ -200,20 +200,63 @@ def wanted_download_subtitles(path):
history_log(1, episode[3], episode[2], message)
send_notifications(episode[3], episode[2], message)
def wanted_download_subtitles_movie(path):
conn_db = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'), timeout=30)
c_db = conn_db.cursor()
movies_details = c_db.execute("SELECT path, missing_subtitles, radarrId, radarrId, hearing_impaired, sceneName FROM table_movies WHERE path = ? AND missing_subtitles != '[]'", (path_replace_reverse_movie(path),)).fetchall()
enabled_providers = c_db.execute("SELECT * FROM table_settings_providers WHERE enabled = 1").fetchall()
c_db.close()
providers_list = []
providers_auth = {}
if len(enabled_providers) > 0:
for provider in enabled_providers:
providers_list.append(provider[0])
try:
if provider[2] is not '' and provider[3] is not '':
provider_auth = providers_auth.append(provider[0])
provider_auth.update({'username': providers[2], 'password': providers[3]})
else:
providers_auth = None
except:
providers_auth = None
else:
providers_list = None
providers_auth = None
for movie in movies_details:
for language in ast.literal_eval(movie[1]):
message = download_subtitle(path_replace_movie(movie[0]), str(pycountry.languages.lookup(language).alpha_3), movie[4], providers_list, providers_auth, movie[5], 'movies')
if message is not None:
store_subtitles_movie(path_replace_movie(movie[0]))
list_missing_subtitles_movies(movie[3])
history_log_movie(1, movie[3], message)
send_notifications_movie(movie[3], message)
def wanted_search_missing_subtitles():
db = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/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()
c.execute("SELECT path_substitution(path) FROM table_episodes WHERE missing_subtitles != '[]'")
episodes = c.fetchall()
c.execute("SELECT path_substitution(path) FROM table_movies WHERE missing_subtitles != '[]'")
c.execute("SELECT path_substitution_movie(path) FROM table_movies WHERE missing_subtitles != '[]'")
movies = c.fetchall()
c.close()
for episode in episodes:
wanted_download_subtitles(episode[0])
integration = get_general_settings()
if integration[12] == "True":
for episode in episodes:
wanted_download_subtitles(episode[0])
if integration[13] == "True":
for movie in movies:
wanted_download_subtitles_movie(movie[0])
logging.info('Finished searching for missing subtitles. Check histories for more information.')

View File

@ -83,25 +83,25 @@ def store_subtitles_movie(file):
for subtitle, language in subtitles.iteritems():
if str(language) != 'und':
actual_subtitles.append([str(language), path_replace_reverse(os.path.join(os.path.dirname(file), subtitle))])
actual_subtitles.append([str(language), path_replace_reverse_movie(os.path.join(os.path.dirname(file), subtitle))])
else:
with open(path_replace(os.path.join(os.path.dirname(file), subtitle)), 'r') as f:
with open(path_replace_movie(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)
except Exception as e:
logging.exception('Error trying to detect character encoding 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.')
logging.exception('Error trying to detect character encoding for this subtitles file: ' + path_replace_movie(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:
detected_language = langdetect.detect(text)
if len(detected_language) > 0:
actual_subtitles.append([str(detected_language), path_replace_reverse(os.path.join(os.path.dirname(file), subtitle))])
actual_subtitles.append([str(detected_language), path_replace_reverse_movie(os.path.join(os.path.dirname(file), subtitle))])
conn_db = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'), timeout=30)
c_db = conn_db.cursor()
c_db.execute("UPDATE table_movies SET subtitles = ? WHERE path = ?", (str(actual_subtitles), path_replace_reverse(file)))
c_db.execute("UPDATE table_movies SET subtitles = ? WHERE path = ?", (str(actual_subtitles), path_replace_reverse_movie(file)))
conn_db.commit()
c_db.close()
@ -200,7 +200,7 @@ def movies_full_scan_subtitles():
c_db.close()
for movie in movies:
store_subtitles_movie(path_replace(movie[0]))
store_subtitles_movie(path_replace_movie(movie[0]))
gc.collect()
@ -223,6 +223,6 @@ def movies_scan_subtitles(no):
c_db.close()
for movie in movies:
store_subtitles_movie(path_replace(movie[0]))
store_subtitles_movie(path_replace_movie(movie[0]))
list_missing_subtitles_movies(no)

View File

@ -118,6 +118,11 @@ if os.path.exists(os.path.join(os.path.dirname(__file__), 'data/db/bazarr.db'))
else:
c.execute('UPDATE table_settings_general SET use_radarr="False"')
try:
c.execute('alter table table_settings_general add column "path_mapping_movie" "text"')
except:
pass
# Commit change to db
db.commit()

View File

@ -120,11 +120,11 @@
for subtitles_file in subtitles_files:
%>
<tr>
<td>{{path_replace(subtitles_file[1]) if subtitles_file[1] is not None else 'Video file subtitles track'}}</td>
<td>{{path_replace_movie(subtitles_file[1]) if subtitles_file[1] is not None else 'Video file subtitles track'}}</td>
<td><div class="ui tiny inverted label" style='background-color: #777777;'>{{pycountry.languages.lookup(str(subtitles_file[0])).name}}</div></td>
<td>
%if subtitles_file[1] is not None:
<a class="remove_subtitles ui inverted basic compact icon" data-tooltip="Delete subtitles file from disk" data-inverted="" data-moviePath="{{details[8]}}" data-subtitlesPath="{{path_replace(subtitles_file[1])}}" data-language="{{pycountry.languages.lookup(str(subtitles_file[0])).alpha_3}}" data-radarrId={{details[10]}}>
<a class="remove_subtitles ui inverted basic compact icon" data-tooltip="Delete subtitles file from disk" data-inverted="" data-moviePath="{{details[8]}}" data-subtitlesPath="{{path_replace_movie(subtitles_file[1])}}" data-language="{{pycountry.languages.lookup(str(subtitles_file[0])).alpha_3}}" data-radarrId={{details[10]}}>
<i class="ui black delete icon"></i>
</a>
%end

View File

@ -205,7 +205,7 @@
</div>
</div>
<div class="ui dividing header">Path Mappings</div>
<div class="ui dividing header">Path Mappings for shows</div>
<div class="twelve wide column">
<div class="ui grid">
%import ast
@ -221,13 +221,13 @@
<div class="two wide column">
<div class="ui fluid input">
<h4 class="ui header">
Path for Sonarr / Radarr:
Path for Sonarr:
</h4>
</div>
</div>
<div class="collapsed column">
<div class="collapsed center aligned column">
<div class="ui basic icon" data-tooltip="Root path to the directory Sonarr or Radarr accesses." data-inverted="">
<div class="ui basic icon" data-tooltip="Root path to the directory Sonarr accesses." data-inverted="">
<i class="help circle large icon"></i>
</div>
</div>
@ -279,6 +279,80 @@
</div>
</div>
<div class="ui dividing header">Path Mappings for movies</div>
<div class="twelve wide column">
<div class="ui grid">
%import ast
%if settings_general[16] is not None:
% path_substitutions_movie = ast.literal_eval(settings_general[16])
%else:
% path_substitutions_movie = []
%end
<div class="middle aligned row">
<div class="right aligned four wide column">
</div>
<div class="two wide column">
<div class="ui fluid input">
<h4 class="ui header">
Path for Radarr:
</h4>
</div>
</div>
<div class="collapsed column">
<div class="collapsed center aligned column">
<div class="ui basic icon" data-tooltip="Root path to the directory Radarr accesses." data-inverted="">
<i class="help circle large icon"></i>
</div>
</div>
</div>
<div class="two wide center aligned column">
</div>
<div class="two wide column">
<div class="ui fluid input">
<h4 class="ui header">
Path for Bazarr:
</h4>
</div>
</div>
<div class="collapsed column">
<div class="collapsed center aligned column">
<div class="ui basic icon" data-tooltip="Path that Bazarr should use to access the same directory remotely." data-inverted="">
<i class="help circle large icon"></i>
</div>
</div>
</div>
</div>
%for x in range(0, 5):
% path_movie = []
% try:
% path_movie = path_substitutions_movie[x]
% except IndexError:
% path_movie = ["", ""]
% end
<div class="middle aligned row">
<div class="right aligned four wide column">
</div>
<div class="four wide column">
<div class="ui fluid input">
<input name="settings_general_sourcepath_movie" type="text" value="{{path_movie[0]}}">
</div>
</div>
<div class="center aligned column">
<i class="arrow circle right icon"></i>
</div>
<div class="four wide column">
<div class="ui fluid input">
<input name="settings_general_destpath_movie" type="text" value="{{path_movie[1]}}">
</div>
</div>
</div>
%end
</div>
</div>
<div class="ui dividing header">Post-processing</div>
<div class="twelve wide column">
<div class="ui orange message">