diff --git a/README.md b/README.md index 2deb027..1b01b4a 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,9 @@ Downloading trailers from links provided from emby and move them into the movie Trailers are named in this style, a more flexible solution is in pending: **{movie-name} {Year}_{youtube-id}_trailer.mkv** +## bad_id +Sometimes Emby get's it wrong. Sometimes this script can get it wrong too. The *Fix Movie Names* function goes through the movie library looking for filenames that don't match with the movie name as identified in emby. + ## setup ### install These are the none standard Python libraries in use in this project: diff --git a/interface.py b/interface.py index 61be54f..f686fcb 100755 --- a/interface.py +++ b/interface.py @@ -13,6 +13,7 @@ import src.tvsort_id as tvsort_id import src.moviesort as moviesort import src.db_export as db_export import src.trailers as trailers +import src.id_fix as id_fix def get_config(): @@ -61,12 +62,14 @@ def get_pending_all(config): pending_movie = moviesort.get_pending(config['movie_downpath']) pending_tv = tvsort.get_pending(config['tv_downpath']) pending_trailer = len(trailers.get_pending(config)) - pending_total = pending_movie + pending_tv + pending_trailer + pending_movie_fix = len(id_fix.get_pending(config)) + pending_total = pending_movie + pending_tv + pending_trailer + pending_movie_fix # build dict pending = {} pending['movies'] = pending_movie pending['tv'] = pending_tv pending['trailer'] = pending_trailer + pending['movie_fix'] = pending_movie_fix pending['total'] = pending_total return pending @@ -90,6 +93,8 @@ def print_menu(stdscr, current_row_idx, menu, config, pending): pending_count = pending['tv'] elif row == 'Trailer download': pending_count = pending['trailer'] + elif row == 'Fix Movie Names': + pending_count = pending['movie_fix'] else: pending_count = ' ' # center whole @@ -112,6 +117,8 @@ def sel_handler(menu_item, config): moviesort.main(config) tvsort.main(config, tvsort_id) db_export.main(config) + trailers.main(config) + id_fix.main(config) elif menu_item == 'Movies': moviesort.main(config) elif menu_item == 'TV shows': @@ -120,6 +127,8 @@ def sel_handler(menu_item, config): db_export.main(config) elif menu_item == 'Trailer download': trailers.main(config) + elif menu_item == 'Fix Movie Names': + id_fix.main(config) def curses_main(stdscr, menu, config): @@ -158,7 +167,7 @@ def curses_main(stdscr, menu, config): def main(): """ main wraps the curses menu """ # setup - menu = ['All', 'Movies', 'TV shows', 'DB export', 'Trailer download', 'Exit'] + menu = ['All', 'Movies', 'TV shows', 'DB export', 'Trailer download', 'Fix Movie Names', 'Exit'] config = get_config() log_file = path.join(config["log_folder"], 'rename.log') logging.basicConfig(filename=log_file,level=logging.INFO,format='%(asctime)s:%(message)s') diff --git a/src/id_fix.py b/src/id_fix.py new file mode 100644 index 0000000..834ddfe --- /dev/null +++ b/src/id_fix.py @@ -0,0 +1,120 @@ +""" looks for movies wrongly identified in emby """ + +import os +import re +import requests + +from time import sleep + + +def get_emby_list(config): + """ get current emby movie list """ + emby_url = config['emby_url'] + emby_user_id = config['emby_user_id'] + emby_api_key = config['emby_api_key'] + + url = (emby_url + '/Users/' + emby_user_id + '/Items?api_key=' + emby_api_key + + '&Recursive=True&IncludeItemTypes=Movie&Fields=Path,PremiereDate') + r_emby = requests.get(url).json() + movie_list = r_emby['Items'] + return movie_list + + +def compare_list(movie_list): + """ compare the movie_list and look for wong ids """ + errors_list = [] + for movie in movie_list: + # from file name + file_name = os.path.basename(os.path.splitext(movie['Path'])[0]) + year_id_pattern = re.compile(r'\(\d{4}\)') + year_str = year_id_pattern.findall(file_name)[-1] + file_year = year_str.replace('(', '').replace(')', '') + file_base_name = file_name.replace(year_str, '').strip() + # dedected in emby + movie_name = movie['Name'] + try: + premier_year = movie['PremiereDate'].split('-')[0] + except KeyError: + premier_year = file_year + # check for error + error = False + if file_base_name != movie_name: + for i, j in enumerate(file_base_name): + if j != movie_name[i] and j != '-': + error = True + break + if file_year != premier_year: + error = True + # add to list on error + if error: + new_name = f'{movie_name} ({premier_year})'.replace('/', '-') + old = {'filename': file_name, 'year': file_year} + new = {'filename': new_name, 'year': premier_year} + errors_list.append([old, new]) + return errors_list + + +def rename(config, errors_list): + """ rename files with correct names """ + print(f'renaming {len(errors_list)} movies.') + moviepath = config['moviepath'] + skipped = [] + for movie in errors_list: + old_year = movie[0]['year'] + old_name = movie[0]['filename'] + old_folder = os.path.join(moviepath, old_year, old_name) + + rename_files = os.listdir(old_folder) + new_year = movie[1]['year'] + new_name = movie[1]['filename'] + # prompt + print(f'\nrenaming from-to:\n{old_name}\n{new_name}') + print('[0]: skip') + print('[1]: rename') + print('[c]: cancel') + select = input() + if select == 0: + skipped.append(old_name) + break + elif select == 'c': + return + # continue + for item in rename_files: + old_file_name = os.path.join(old_folder, item) + new_file_name = os.path.join(old_folder, item.replace(old_name, new_name)) + os.rename(old_file_name, new_file_name) + # movie folder + os.rename(old_folder, old_folder.replace(old_name, new_name)) + # year folder + if old_year != new_year: + old_folder_name = old_folder.replace(f'({old_year})', f'({new_year})') + new_folder_name = old_folder_name.replace(old_year, new_year) + os.rename(old_folder_name, new_folder_name) + return skipped + + +def get_pending(config): + """ returns a list of movies with errors """ + movie_list = get_emby_list(config) + errors_list = compare_list(movie_list) + return errors_list + + +def main(config): + """ main to lunch the id_fix """ + errors_list = get_pending(config) + if not errors_list: + print('no errors found') + sleep(2) + return + else: + skipped = rename(config, errors_list) + + if skipped: + print('skipped following movies:') + for movie in skipped: + print(movie) + input('continue?') + else: + print(f'fixed {len(errors_list)} movie names.') + sleep(2)