import os from urllib.parse import urlparse from common import sanitize_filename, download_with_aria2c, download_file_with_progress, aria2c_exists def show_series_categories(series_dict): print("\nSeries Categories\n" + "*" * 30) categories = sorted(series_dict.keys()) for i, cat in enumerate(categories, 1): print(f"{i}. {cat}") try: cat_index = int(input("\nSelect a category number: ").strip()) if 1 <= cat_index <= len(categories): selected_category = categories[cat_index - 1] show_series_names(series_dict, selected_category) except ValueError: print("Invalid input.") def show_series_names(series_dict, category): while True: print(f"\nSeries in Category: {category}\n" + "*" * 30) series_names = sorted(series_dict[category].keys()) for i, name in enumerate(series_names, 1): print(f"{i}. {name}") print(f"\nMenu for Category: {category} \n" + "*" * 30) print(f"1. Download all series from category: {category}") print("2. Select a series name number") choice = input("Select (1 or 2): ").strip() if choice == '1': for name in series_dict[category]: for season in series_dict[category][name]: for episode in series_dict[category][name][season]: download_series_episode(category, name, season, episode) elif choice == '2': try: name_index = int(input("Enter series number: ").strip()) series_names = sorted(series_dict[category].keys()) if 1 <= name_index <= len(series_names): selected_name = series_names[name_index - 1] result = open_series_menu(series_dict, category, selected_name) if result == "mainmenu": return except ValueError: print("Invalid input.") else: print("Invalid input.") def open_series_menu(series_dict, category, selected_name): while True: print(f"\nMenu for Series: {selected_name} \n" + "*" * 30) print(f"1. Show all seasons and episodes for: {selected_name}") print(f"2. Download all seasons and episodes for: {selected_name}") print("3. Go Back (to Series List)") print("4. Go to Main Menu") print("5. Exit the script") sub_choice = input("Select: ").strip() if sub_choice == '1': result = show_seasons(series_dict, category, selected_name) if result == "mainmenu": return "mainmenu" elif sub_choice == '2': for season in series_dict[category][selected_name]: for episode in series_dict[category][selected_name][season]: download_series_episode(category, selected_name, season, episode) elif sub_choice == '3': return elif sub_choice == '4': return "mainmenu" elif sub_choice == '5': print("\nExiting the script. Goodbye!") exit() else: print("Invalid selection.") def show_seasons(series_dict, category, series_name): print(f"\nSeasons for {series_name} in {category}\n" + "*" * 30) seasons = sorted(series_dict[category][series_name].keys()) for i, season in enumerate(seasons, 1): print(f"{i}. {season}") try: season_index = int(input("\nSelect a season: ").strip()) if 1 <= season_index <= len(seasons): selected_season = seasons[season_index - 1] result = show_episodes(series_dict, category, series_name, selected_season) if result == "mainmenu": return "mainmenu" except ValueError: print("Invalid input.") def show_episodes(series_dict, category, series_name, season): episodes = series_dict[category][series_name][season] print(f"\nEpisodes in {season} of {series_name} ({category})\n" + "*" * 30) for i, ep in enumerate(episodes, 1): print(f"{i}. {ep['title']}") while True: print("\nEpisode Menu\n" + "*" * 30) print("1. Download selected Episodes") print("2. Download all Episodes") print("3. Go back (to Seasons List)") print("4. Go to Main Menu") print("5. Exit the script") choice = input("Select: ").strip() if choice == '1': selected = input_range("Enter episode numbers (e.g., 1,2,4-6): ", len(episodes)) for idx in selected: download_series_episode(category, series_name, season, episodes[idx - 1]) elif choice == '2': for ep in episodes: download_series_episode(category, series_name, season, ep) elif choice == '3': return elif choice == '4': return "mainmenu" elif choice == '5': exit() else: print("Invalid choice.") def input_range(prompt, max_val): inp = input(prompt) selected = set() for part in inp.split(','): if '-' in part: start, end = map(int, part.split('-')) selected.update(range(start, end + 1)) else: selected.add(int(part)) return [i for i in selected if 1 <= i <= max_val] def download_series_episode(category, series_name, season, episode): title = sanitize_filename(episode['title']) group = sanitize_filename(category) s_name = sanitize_filename(series_name) base_dir = os.path.join("Series", group, s_name, season, episode['episode']) os.makedirs(base_dir, exist_ok=True) media_ext = os.path.splitext(episode['media_url'])[1] media_path = os.path.join(base_dir, f"{title}{media_ext}") if not os.path.exists(media_path) or os.path.getsize(media_path) < 5 * 1024 * 1024: if aria2c_exists(): download_with_aria2c(episode['media_url'], media_path) else: download_file_with_progress(episode['media_url'], media_path, title) else: print(f"✔ Already downloaded: {title}") if episode['logo_url']: logo_filename = os.path.basename(urlparse(episode['logo_url']).path) logo_path = os.path.join(base_dir, logo_filename) if not os.path.exists(logo_path): download_file_with_progress(episode['logo_url'], logo_path, f"{title} (logo)") else: print(f"✔ Logo exists for {title}")