Add rename "TBA" files to actual episode name from TV info source changes.

Add setting vars to rename episodes when tba type default or on any change.
This commit is contained in:
Prinz23 2023-04-29 19:18:00 +01:00 committed by JackDandy
parent a7cbf9e574
commit a323eed822
3 changed files with 69 additions and 12 deletions

View file

@ -284,6 +284,8 @@ ADD_SHOWS_METALANG = 'en'
CREATE_MISSING_SHOW_DIRS = False
SHOW_DIRS_WITH_DOTS = False
RENAME_EPISODES = False
RENAME_TBA_EPISODES = True
RENAME_NAME_CHANGED_EPISODES = False
AIRDATE_EPISODES = False
PROCESS_AUTOMATICALLY = False
KEEP_PROCESSED_DIR = False
@ -717,7 +719,8 @@ def init_stage_1(console_logging):
global TV_DOWNLOAD_DIR, PROCESS_METHOD, PROCESS_AUTOMATICALLY, MEDIAPROCESS_INTERVAL, \
POSTPONE_IF_SYNC_FILES, PROCESS_POSITIVE_LOG, EXTRA_SCRIPTS, SG_EXTRA_SCRIPTS, \
DEFAULT_MEDIAPROCESS_INTERVAL, MIN_MEDIAPROCESS_INTERVAL, \
UNPACK, SKIP_REMOVED_FILES, MOVE_ASSOCIATED_FILES, NFO_RENAME, RENAME_EPISODES, AIRDATE_EPISODES, \
UNPACK, SKIP_REMOVED_FILES, MOVE_ASSOCIATED_FILES, NFO_RENAME, RENAME_EPISODES, RENAME_TBA_EPISODES, \
RENAME_NAME_CHANGED_EPISODES, AIRDATE_EPISODES, \
USE_FAILED_DOWNLOADS, DELETE_FAILED
# Media Process/Episode Naming
global NAMING_PATTERN, NAMING_MULTI_EP, NAMING_STRIP_YEAR, NAMING_CUSTOM_ABD, NAMING_ABD_PATTERN, \
@ -1013,6 +1016,8 @@ def init_stage_1(console_logging):
PROCESS_AUTOMATICALLY = bool(check_setting_int(CFG, 'General', 'process_automatically', 0))
UNPACK = bool(check_setting_int(CFG, 'General', 'unpack', 0))
RENAME_EPISODES = bool(check_setting_int(CFG, 'General', 'rename_episodes', 1))
RENAME_TBA_EPISODES = bool(check_setting_int(CFG, 'General', 'rename_tba_episodes', 1))
RENAME_NAME_CHANGED_EPISODES = bool(check_setting_int(CFG, 'General', 'rename_name_changed_episodes', 0))
AIRDATE_EPISODES = bool(check_setting_int(CFG, 'General', 'airdate_episodes', 0))
KEEP_PROCESSED_DIR = bool(check_setting_int(CFG, 'General', 'keep_processed_dir', 1))
PROCESS_METHOD = check_setting_str(CFG, 'General', 'process_method', 'copy' if KEEP_PROCESSED_DIR else 'move')
@ -1994,6 +1999,8 @@ def save_config():
new_config['General']['process_automatically'] = int(PROCESS_AUTOMATICALLY)
new_config['General']['unpack'] = int(UNPACK)
new_config['General']['rename_episodes'] = int(RENAME_EPISODES)
new_config['General']['rename_tba_episodes'] = int(RENAME_TBA_EPISODES)
new_config['General']['rename_name_changed_episodes'] = int(RENAME_NAME_CHANGED_EPISODES)
new_config['General']['airdate_episodes'] = int(AIRDATE_EPISODES)
new_config['General']['create_missing_show_dirs'] = int(CREATE_MISSING_SHOW_DIRS)
new_config['General']['show_dirs_with_dots'] = int(SHOW_DIRS_WITH_DOTS)

View file

@ -422,7 +422,7 @@ def move_and_symlink_file(src_file, dest_file):
copy_file(src_file, dest_file)
def rename_ep_file(cur_path, new_path, old_path_length=0):
def rename_ep_file(cur_path, new_path, old_path_length=0, use_rename=False):
"""
Creates all folders needed to move a file to its new location, renames it, then cleans up any folders
left that are now empty.
@ -433,6 +433,7 @@ def rename_ep_file(cur_path, new_path, old_path_length=0):
:type new_path: AnyStr
:param old_path_length: The length of media file path (old name) WITHOUT THE EXTENSION
:type old_path_length: int or long
:param use_rename: use rename instead of shutil.move
:return: success
:rtype: bool
"""
@ -466,8 +467,11 @@ def rename_ep_file(cur_path, new_path, old_path_length=0):
# move the file
try:
logger.log(f'Renaming file from {cur_path} to {new_path}')
shutil.move(cur_path, new_path)
except (OSError, IOError) as e:
if use_rename:
os.rename(cur_path, new_path)
else:
shutil.move(cur_path, new_path)
except (OSError, IOError, IsADirectoryError, NotADirectoryError, FileExistsError) as e:
logger.error(f'Failed renaming {cur_path} to {new_path}: {ex(e)}')
return False

View file

@ -78,6 +78,10 @@ if coreid_warnings:
tz_p = du_parser()
invalid_date_limit = datetime.date(1900, 1, 1)
tba_ep_name = re.compile(r'^(episode \d+|tba)$', flags=re.I)
tba_ep_filename = re.compile(r'\b(episode \d+|tba)\b', flags=re.I)
ep_name_regex = re.compile(r'%E[._]?N', flags=re.I)
# status codes for switching tv show source
TVSWITCH_DUPLICATE_SHOW = 0
TVSWITCH_ID_CONFLICT = 1
@ -4301,6 +4305,8 @@ class TVEpisode(TVEpisodeBase):
if self._name != self.dict_prevent_nonetype(ep_info, 'episodename'):
switch_list.append(self.show_obj.switch_ep_change_sql(old_tvid, old_prodid, episode, season,
TVSWITCH_EP_RENAMED))
old_name = self._name or ''
self.name = self.dict_prevent_nonetype(ep_info, 'episodename')
self.season = season
self.episode = episode
@ -4462,6 +4468,23 @@ class TVEpisode(TVEpisodeBase):
self.status = Quality.status_from_name_or_file(self._location, anime=self._show_obj.is_anime)
logger.debug('%s%s' % (msg, statusStrings[self._status]))
if sickgear.RENAME_EPISODES and self.with_ep_name():
ep_filename = os.path.basename(self._location or '')
ep_basename, ep_ext = os.path.splitext(ep_filename)
ep_name_changed = (bool(self._location) and old_name != self._name) or \
(sickgear.RENAME_NAME_CHANGED_EPISODES and bool(ep_basename)
and ep_basename != os.path.basename(self.proper_path()))
ep_name_tba_changed = (ep_name_changed and bool(tba_ep_name.search(old_name))) or \
(not bool(tba_ep_name.search(self._name or ''))
and bool(tba_ep_filename.search(ep_filename or '')))
if ((ep_name_tba_changed and sickgear.RENAME_TBA_EPISODES)
or (ep_name_changed and sickgear.RENAME_NAME_CHANGED_EPISODES)):
if (re_res := self.rename()):
notifiers.notify_update_library(self)
elif False == re_res:
# rename failed
logger.debug('Failed to change changed episode name based filename')
# shouldn't get here probably
else:
msg = '(2) Status changes from %s to ' % statusStrings[self._status]
@ -5141,6 +5164,20 @@ class TVEpisode(TVEpisodeBase):
return ''
return self._format_pattern(os.sep.join(name_groups[:-1]), multi)
def with_ep_name(self):
"""
returns if the episode naming contain the episode name
"""
# type: (...) -> bool
if self._show_obj.air_by_date and sickgear.NAMING_CUSTOM_ABD and not self.related_ep_obj:
return bool(ep_name_regex.search(sickgear.NAMING_ABD_PATTERN))
elif self._show_obj.sports and sickgear.NAMING_CUSTOM_SPORTS and not self.related_ep_obj:
return bool(ep_name_regex.search(sickgear.NAMING_SPORTS_PATTERN))
elif self._show_obj.anime and sickgear.NAMING_CUSTOM_ANIME:
return bool(ep_name_regex.search(sickgear.NAMING_ANIME_PATTERN))
else:
return bool(ep_name_regex.search(sickgear.NAMING_PATTERN))
def formatted_filename(self, pattern=None, multi=None, anime_type=None):
"""
Just the filename of the episode, formatted based on the naming settings
@ -5163,6 +5200,7 @@ class TVEpisode(TVEpisodeBase):
return self._format_pattern(name_groups[-1], multi, anime_type)
def rename(self):
# type: (...) -> Optional[bool]
"""
Renames an episode file and all related files to the location and filename as specified
in the naming settings.
@ -5202,25 +5240,31 @@ class TVEpisode(TVEpisodeBase):
logger.debug('Files associated to %s: %s' % (self.location, related_files))
# move the ep file
result = helpers.rename_ep_file(self.location, absolute_proper_path, absolute_current_path_no_ext_length)
result = helpers.rename_ep_file(self.location, absolute_proper_path, absolute_current_path_no_ext_length,
use_rename=True)
any_renamed = all_renamed = result
# move related files
for cur_related_file in related_files:
renamed = helpers.rename_ep_file(cur_related_file, absolute_proper_path,
absolute_current_path_no_ext_length)
absolute_current_path_no_ext_length, use_rename=True)
any_renamed |= renamed
all_renamed &= renamed
if not renamed:
logger.error('%s: Unable to rename file %s' % (self._epid, cur_related_file))
for cur_related_sub in related_subs:
absolute_proper_subs_path = os.path.join(sickgear.SUBTITLES_DIR, self.formatted_filename())
renamed = helpers.rename_ep_file(cur_related_sub, absolute_proper_subs_path,
absolute_current_path_no_ext_length)
absolute_current_path_no_ext_length, use_rename=True)
any_renamed |= renamed
all_renamed &= renamed
if not renamed:
logger.error('%s: Unable to rename file %s' % (self._epid, cur_related_sub))
# save the ep
with self.lock:
if result:
if any_renamed:
with self.lock:
self.location = absolute_proper_path + file_ext
for ep_obj in self.related_ep_obj:
ep_obj.location = absolute_proper_path + file_ext
@ -5233,14 +5277,16 @@ class TVEpisode(TVEpisodeBase):
sql_l = []
with self.lock:
for ep_obj in [self] + self.related_ep_obj:
result = ep_obj.get_sql()
if None is not result:
sql_l.append(result)
ep_sql = ep_obj.get_sql()
if None is not ep_sql:
sql_l.append(ep_sql)
if 0 < len(sql_l):
my_db = db.DBConnection()
my_db.mass_action(sql_l)
return all_renamed
def airdate_modify_stamp(self):
"""
Make modify date and time of a file reflect the show air date and time.