diff --git a/sonar_translation.py b/sonar_translation.py index c3a8e21..009c433 100644 --- a/sonar_translation.py +++ b/sonar_translation.py @@ -28,8 +28,8 @@ HEADERS = { def tmdb_get(endpoint, params=None): """Perform a GET request against TMDb.""" - url = BASE_URL + endpoint + print(f"Set of Tmdb query: {url}") response = requests.get( url, @@ -124,16 +124,21 @@ def get_season(tmdb_id, season_number): }, ) -def get_episode_list(show): +def get_episode_list(show,series_path: Path): #_, show = find_by_tmdb_id(tmdb_id) - + file_seasons = sorted({ + int(m.group(1)) + for d in series_path.iterdir() + if d.is_dir() + and (m := re.match(r"^Season\s+0*(\d+)$", d.name, re.I)) + }) episodes = [] for season in show.get("seasons", []): season_number = season["season_number"] # skip specials if desired - if season_number == 0: + if season_number == 0 or season_number not in file_seasons: continue season_data = get_season(show.get("id"), season_number) @@ -217,111 +222,188 @@ def best_episode_match(filename, episodes,title,year): return best, best_score -def main(): +def rename_media(media_data,episodes, series_path,file_title): + series=series_path.name + episode_map = { + (ep["season"], ep["episode"]): ep + for ep in episodes + } + file_list = [] + new_file_list = [] + for file in series_path.rglob("*"): + match_SE_name = re.search(r"S(\d{2})E(\d{2})", file.name, re.I) + if not match_SE_name: + match_season_folder = re.search(r"Season (\d{2})", file.name, re.I) + if match_season_folder: + continue # witchout bothering anyone + print(f"No season/episode number found: {file.name}") + continue - parser = argparse.ArgumentParser() - parser.add_argument("series", help='Series name, e.g. "Maya the Bee (1975) [10620]"') + season = int(match_SE_name.group(1)) + episode= int(match_SE_name.group(2)) - args = parser.parse_args() + episode_number = episode_map.get((season, episode)) - if len(sys.argv) != 2 or not Path(args.series).is_dir(): - print("Usage:") - print() - print(" python tmdb_lookup.py ") - print(" Seires Folder needs to be this Style: Maya the Bee (1975) [10620]") - sys.exit(1) + if not episode_number: + print(f"Episode not found: S{season:02d}E{episode:02d}") + continue + episode_season_number_match = re.match( + r"^(.*?S\d{2}E\d{2})\s*-\s*(.*?)\s*(\[[^\]]+\].*)?$", + file.stem, + re.I, + ) + if not episode_season_number_match: + print(f"S{season:02d}E{episode:02d} not found") + continue + prefix = episode_season_number_match.group(1).replace(file_title,(media_data.get('name') + or media_data.get('title'))) # Andor (2022) - S01E07 + quality = episode_season_number_match.group(3) or "" # [WEBRip-1080p][AAC 5.1][h265] - series_path = Path(args.series) + new_name = ( + f"{prefix} - {episode_number['title']}" + f"{(' ' + quality) if quality else ''}" + f"{file.suffix}" + ) + + print(f"{file.name} -> {new_name}") + + file_list.append(file) + new_file_list.append(new_name) + + title=(f"{(media_data.get('name') or media_data.get('title'))} " + f"({(media_data.get('first_air_date') or media_data.get('release_date') or '')[:4]}) " + f"[{media_data.get('id')}]") + print(f"{series} -> {title}") + + file_list.append(series_path) + new_file_list.append(title) + has_changes = False + for file, new_file in zip(file_list, new_file_list): + if file.name != new_file: + has_changes = True + break + if not has_changes: + print("No changes necessary.") + return + answer = input("Rename files? [y/N]: ").strip().lower() + if answer in ("y", "yes"): + print("Proceeding...") + for file, new_file in zip(file_list,new_file_list): + file.rename(file.with_name(new_file)) + print("All files renamed") + return + print("Cancelled.") + return + +def process_series(series_path: Path): series = series_path.name + m = re.match(r"^(.*?)\s*\((\d{4})\)\s*\[(\d+)\]$", series) if not m: - parser.error(f"Invalid series format: {args.series}") + print(f"Skipping invalid folder: {series}") + return file_title = m.group(1).strip() file_year = int(m.group(2)) file_tmdb_id = int(m.group(3)) + print() + print("=" * 80) print(f"TITLE={file_title}") print(f"YEAR={file_year}") print(f"TMDB_ID={file_tmdb_id}") if file_tmdb_id == 0: - print("Tmdb ID required") - exit(1) + print("TMDB ID required") + return - print(f"Looking up IMDb ID: {file_tmdb_id}") + try: + data = find_by_tmdb_id(file_tmdb_id) - data = find_by_tmdb_id(file_tmdb_id) - media_type, media_data = data + if not data: + print("TMDB lookup failed") + return - print_results(data) + media_type, media_data = data - episodes = get_episode_list(media_data) - episode_map = { - (ep["season"], ep["episode"]): ep - for ep in episodes - } + print_results(data) - for file in series_path.rglob("*"): - m = re.search(r"S(\d{2})E(\d{2})", file.name, re.I) - if not m: - m_b = re.search(r"Season (\d{2})", file.name, re.I) - if m_b: - continue - print(f"No season/episode number found: {file.name}") - continue + episodes = get_episode_list(media_data) - season = int(m.group(1)) - episode= int(m.group(2)) + rename_media( + media_data, + episodes, + series_path, + file_title + ) - ep = episode_map.get((season, episode)) - file_list = [] - new_file_list = [] - if ep: - m = re.match( - r"^(.*?S\d{2}E\d{2})\s*-\s*(.*?)\s*(\[[^\]]+\].*)?$", - file.stem, - re.I, - ) + except Exception as e: + print(f"Error processing {series}: {e}") - if m: - prefix = m.group(1) # Andor (2022) - S01E07 - quality = m.group(3) or "" # [WEBRip-1080p][AAC 5.1][h265] +def process_series(series_path: Path): + series = series_path.name - new_name = ( - f"{prefix} - {ep['title']}" - f"{(' ' + quality) if quality else ''}" - f"{file.suffix}" - ) + m = re.match(r"^(.*?)\s*\((\d{4})\)\s*\[(\d+)\]$", series) - print( - f"{file.name} -> " - f"{new_name}" - ) + if not m: + print(f"Skipping invalid folder: {series}") + return - file_list.append(file) - new_file_list.append(new_name) - else: - print( - f"Episod* not found: " - f"S{season:02d}E{episode:02d}" - ) - title=(f"{(data.get('name') or data.get('title'))} " - f"({(data.get('first_air_date') or data.get('release_date') or '')[:4]})") - print(f"{series} -> {title}") + file_title = m.group(1).strip() + #file_year = int(m.group(2)) + file_tmdb_id = int(m.group(3)) - answer = input("Rename files? [y/N]: ").strip().lower() - if answer in ("y", "yes"): - print("Proceeding...") + if file_tmdb_id == 0: + print("TMDB ID required") + return - file_list.append(series_path) - new_file_list.append(title) - for file, new_file in zip(file_list,new_file_list): - file.rename(file.with_name(new_file)) + try: + data = find_by_tmdb_id(file_tmdb_id) - else: - print("Cancelled.") + if not data: + print("TMDB lookup failed") + return + + media_type, media_data = data + + #print_results(data) + + episodes = get_episode_list(media_data,series_path) + + rename_media( + media_data, + episodes, + series_path, + file_title + ) + + except Exception as e: + print(f"Error processing {series}: {e}") + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "path", + help='Either a series folder "Maya the Bee (1975) [10620]" or a root folder containing such folders' + ) + + args = parser.parse_args() + + input_path = Path(args.path) + + if not input_path.is_dir(): + parser.error(f"Directory not found: {input_path}") + + # Input is already a series folder + if re.match(r"^(.*?)\s*\((\d{4})\)\s*\[(\d+)\]$", input_path.name): + process_series(input_path) + + # Input is a root folder containing series folders + else: + for series_path in sorted(input_path.iterdir()): + if series_path.is_dir(): + process_series(series_path) if __name__ == "__main__": main() \ No newline at end of file