From de9180a124fa597fa30a802ddd50369bd2f19426 Mon Sep 17 00:00:00 2001 From: Luigi311 Date: Tue, 2 Jan 2024 23:43:59 -0700 Subject: [PATCH] Handle episode names are not unique --- .vscode/launch.json | 11 + src/functions.py | 7 + src/library.py | 16 ++ src/watched.py | 61 ++++- test/test_library.py | 10 + test/test_watched.py | 469 +++++++++++++++++++++++++----------- test/validate_ci_marklog.py | 16 +- 7 files changed, 449 insertions(+), 141 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 5092265..60cea81 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -11,6 +11,17 @@ "program": "main.py", "console": "integratedTerminal", "justMyCode": true + }, + { + "name": "Pytest", + "type": "python", + "request": "launch", + "module": "pytest", + "args": [ + "-vv" + ], + "console": "integratedTerminal", + "justMyCode": true } ] } diff --git a/src/functions.py b/src/functions.py index b7ae693..c1c160b 100644 --- a/src/functions.py +++ b/src/functions.py @@ -64,9 +64,16 @@ def str_to_bool(value: any) -> bool: # Search for nested element in list def contains_nested(element, lst): + if lst is None: + return None + for i, item in enumerate(lst): + if item is None: + continue if element in item: return i + elif element == item: + return i return None diff --git a/src/library.py b/src/library.py index 6112539..c33c962 100644 --- a/src/library.py +++ b/src/library.py @@ -168,12 +168,28 @@ def episode_title_dict(user_list: dict): episode_output_dict["completed"] = [] episode_output_dict["time"] = [] episode_output_dict["locations"] = [] + episode_output_dict["show"] = [] + episode_output_dict["season"] = [] episode_counter = 0 # Initialize a counter for the current episode position # Iterate through the shows, seasons, and episodes in user_list for show in user_list: for season in user_list[show]: for episode in user_list[show][season]: + # Add the show title to the episode_output_dict if it doesn't exist + if "show" not in episode_output_dict: + episode_output_dict["show"] = [None] * episode_counter + + # Add the season number to the episode_output_dict if it doesn't exist + if "season" not in episode_output_dict: + episode_output_dict["season"] = [None] * episode_counter + + # Add the show title to the episode_output_dict + episode_output_dict["show"].append(dict(show)) + + # Add the season number to the episode_output_dict + episode_output_dict["season"].append(season) + # Iterate through the keys and values in each episode for episode_key, episode_value in episode.items(): # If the key is not "status", add the key to episode_output_dict if it doesn't exist diff --git a/src/watched.py b/src/watched.py index 7890ca0..8fa60fa 100644 --- a/src/watched.py +++ b/src/watched.py @@ -97,7 +97,7 @@ def cleanup_watched( continue ( - _, + show_watched_list_2_keys_dict, episode_watched_list_2_keys_dict, movies_watched_list_2_keys_dict, ) = generate_library_guids_dict(watched_list_2[user_2][library_2]) @@ -123,11 +123,18 @@ def cleanup_watched( show_key_dict = dict(show_key_1) for season in watched_list_1[user_1][library_1][show_key_1]: + # Filter the episode_watched_list_2_keys_dict dictionary to handle cases + # where episode location names are not unique such as S01E01.mkv + filtered_episode_watched_list_2_keys_dict = ( + filter_episode_watched_list_2_keys_dict( + episode_watched_list_2_keys_dict, show_key_dict, season + ) + ) for episode in watched_list_1[user_1][library_1][show_key_1][ season ]: episode_index = get_episode_index_in_dict( - episode, episode_watched_list_2_keys_dict + episode, filtered_episode_watched_list_2_keys_dict ) if episode_index is not None: if check_remove_entry( @@ -223,6 +230,56 @@ def get_movie_index_in_dict(movie, movies_watched_list_2_keys_dict): return None +def filter_episode_watched_list_2_keys_dict( + episode_watched_list_2_keys_dict, show_key_dict, season +): + # Filter the episode_watched_list_2_keys_dict dictionary to only include values for the correct show and season + filtered_episode_watched_list_2_keys_dict = {} + show_indecies = [] + season_indecies = [] + + # Iterate through episode_watched_list_2_keys_dict["season"] and find the indecies that match season + for season_index, season_value in enumerate( + episode_watched_list_2_keys_dict["season"] + ): + if season_value == season: + season_indecies.append(season_index) + + # Iterate through episode_watched_list_2_keys_dict["show"] and find the indecies that match show_key_dict + for show_index, show_value in enumerate(episode_watched_list_2_keys_dict["show"]): + # Iterate through the keys and values of the show_value dictionary and check if they match show_key_dict + for show_key, show_key_value in show_value.items(): + if show_key == "locations": + # Iterate through the locations in the show_value dictionary + for location in show_key_value: + # If the location is in the episode_watched_list_2_keys_dict dictionary, return index of the key + if ( + contains_nested(location, show_key_dict["locations"]) + is not None + ): + show_indecies.append(show_index) + break + else: + if show_key in show_key_dict.keys(): + if show_key_value == show_key_dict[show_key]: + show_indecies.append(show_index) + break + + # Find the intersection of the show_indecies and season_indecies lists + indecies = list(set(show_indecies) & set(season_indecies)) + + # Create a copy of the dictionary with indecies that match the show and season and none that don't + filtered_episode_watched_list_2_keys_dict = copy.deepcopy( + episode_watched_list_2_keys_dict + ) + for key, value in filtered_episode_watched_list_2_keys_dict.items(): + for index, item in enumerate(value): + if index not in indecies: + filtered_episode_watched_list_2_keys_dict[key][index] = None + + return filtered_episode_watched_list_2_keys_dict + + def get_episode_index_in_dict(episode, episode_watched_list_2_keys_dict): # Iterate through the keys and values of the episode dictionary for episode_key, episode_value in episode.items(): diff --git a/test/test_library.py b/test/test_library.py index 834ff6e..e506ebb 100644 --- a/test/test_library.py +++ b/test/test_library.py @@ -83,6 +83,16 @@ episode_titles = { "tvdb": ["8444132"], "completed": [True], "time": [0], + "season": ["Season 1"], + "show": [ + { + "imdb": "tt3581920", + "locations": ("The Last of Us",), + "title": "The Last of Us", + "tmdb": "100088", + "tvdb": "392256", + } + ], } movie_titles = { "imdb": ["tt2380307"], diff --git a/test/test_watched.py b/test/test_watched.py index 105541a..e66be17 100644 --- a/test/test_watched.py +++ b/test/test_watched.py @@ -18,102 +18,225 @@ from src.watched import cleanup_watched, combine_watched_dicts tv_shows_watched_list_1 = { frozenset( { - ("tvdb", "75710"), - ("title", "Criminal Minds"), - ("imdb", "tt0452046"), - ("locations", ("Criminal Minds",)), - ("tmdb", "4057"), + ("locations", ("Doctor Who (2005) {tvdb-78804} {imdb-tt0436992}",)), + ("imdb", "tt0436992"), + ("tmdb", "57243"), + ("tvdb", "78804"), + ("title", "Doctor Who (2005)"), } ): { - "Season 1": [ + 1: [ { - "imdb": "tt0550489", - "tmdb": "282843", - "tvdb": "176357", - "title": "Extreme Aggressor", - "locations": ( - "Criminal Minds S01E01 Extreme Aggressor WEBDL-720p.mkv", - ), + "imdb": "tt0563001", + "tmdb": "968589", + "tvdb": "295296", + "title": "The Unquiet Dead", + "locations": ("S01E03.mkv",), "status": {"completed": True, "time": 0}, }, { - "imdb": "tt0550487", - "tmdb": "282861", - "tvdb": "300385", - "title": "Compulsion", - "locations": ("Criminal Minds S01E02 Compulsion WEBDL-720p.mkv",), + "imdb": "tt0562985", + "tmdb": "968590", + "tvdb": "295297", + "title": "Aliens of London (1)", + "locations": ("S01E04.mkv",), + "status": {"completed": False, "time": 240000}, + }, + { + "imdb": "tt0563003", + "tmdb": "968592", + "tvdb": "295298", + "title": "World War Three (2)", + "locations": ("S01E05.mkv",), "status": {"completed": True, "time": 0}, }, ] }, - frozenset({("title", "Test"), ("locations", ("Test",))}): { - "Season 1": [ + frozenset( + { + ("title", "Monarch: Legacy of Monsters"), + ("imdb", "tt17220216"), + ("tvdb", "422598"), + ("tmdb", "202411"), + ( + "locations", + ("Monarch - Legacy of Monsters {tvdb-422598} {imdb-tt17220216}",), + ), + } + ): { + 1: [ { - "title": "S01E01", - "locations": ("Test S01E01.mkv",), + "imdb": "tt21255044", + "tmdb": "4661246", + "tvdb": "10009418", + "title": "Secrets and Lies", + "locations": ("S01E03.mkv",), "status": {"completed": True, "time": 0}, }, { - "title": "S01E02", - "locations": ("Test S01E02.mkv",), + "imdb": "tt21255050", + "tmdb": "4712059", + "tvdb": "10009419", + "title": "Parallels and Interiors", + "locations": ("S01E04.mkv",), + "status": {"completed": False, "time": 240000}, + }, + { + "imdb": "tt23787572", + "tmdb": "4712061", + "tvdb": "10009420", + "title": "The Way Out", + "locations": ("S01E05.mkv",), + "status": {"completed": True, "time": 0}, + }, + ] + }, + frozenset( + { + ("tmdb", "125928"), + ("imdb", "tt14681924"), + ("tvdb", "403172"), + ( + "locations", + ("My Adventures with Superman {tvdb-403172} {imdb-tt14681924}",), + ), + ("title", "My Adventures with Superman"), + } + ): { + 1: [ + { + "imdb": "tt15699926", + "tmdb": "3070048", + "tvdb": "8438181", + "title": "Adventures of a Normal Man (1)", + "locations": ("S01E01.mkv",), "status": {"completed": True, "time": 0}, }, { - "title": "S01E04", - "locations": ("Test S01E04.mkv",), - "status": {"completed": False, "time": 5}, + "imdb": "tt20413322", + "tmdb": "4568681", + "tvdb": "9829910", + "title": "Adventures of a Normal Man (2)", + "locations": ("S01E02.mkv",), + "status": {"completed": True, "time": 0}, + }, + { + "imdb": "tt20413328", + "tmdb": "4497012", + "tvdb": "9870382", + "title": "My Interview with Superman", + "locations": ("S01E03.mkv",), + "status": {"completed": True, "time": 0}, }, ] }, } + tv_shows_watched_list_2 = { frozenset( { - ("tvdb", "75710"), - ("title", "Criminal Minds"), - ("imdb", "tt0452046"), - ("locations", ("Criminal Minds",)), - ("tmdb", "4057"), + ("locations", ("Doctor Who (2005) {tvdb-78804} {imdb-tt0436992}",)), + ("imdb", "tt0436992"), + ("tmdb", "57243"), + ("title", "Doctor Who"), + ("tvdb", "78804"), + ("tvrage", "3332"), } ): { - "Season 1": [ + 1: [ { - "imdb": "tt0550487", - "tmdb": "282861", - "tvdb": "300385", - "title": "Compulsion", - "locations": ("Criminal Minds S01E02 Compulsion WEBDL-720p.mkv",), + "tvdb": "295294", + "imdb": "tt0562992", + "title": "Rose", + "locations": ("S01E01.mkv",), "status": {"completed": True, "time": 0}, }, { - "imdb": "tt0550498", - "tmdb": "282865", - "tvdb": "300474", - "title": "Won't Get Fooled Again", - "locations": ( - "Criminal Minds S01E03 Won't Get Fooled Again WEBDL-720p.mkv", - ), + "tvdb": "295295", + "imdb": "tt0562997", + "title": "The End of the World", + "locations": ("S01E02.mkv",), + "status": {"completed": False, "time": 300670}, + }, + { + "tvdb": "295298", + "imdb": "tt0563003", + "title": "World War Three (2)", + "locations": ("S01E05.mkv",), "status": {"completed": True, "time": 0}, }, ] }, - frozenset({("title", "Test"), ("locations", ("Test",))}): { - "Season 1": [ + frozenset( + { + ("title", "Monarch: Legacy of Monsters"), + ("imdb", "tt17220216"), + ("tvdb", "422598"), + ("tmdb", "202411"), + ( + "locations", + ("Monarch - Legacy of Monsters {tvdb-422598} {imdb-tt17220216}",), + ), + } + ): { + 1: [ { - "title": "S01E02", - "locations": ("Test S01E02.mkv",), - "status": {"completed": False, "time": 10}, - }, - { - "title": "S01E03", - "locations": ("Test S01E03.mkv",), + "tvdb": "9959300", + "imdb": "tt20412166", + "title": "Aftermath", + "locations": ("S01E01.mkv",), "status": {"completed": True, "time": 0}, }, { - "title": "S01E04", - "locations": ("Test S01E04.mkv",), - "status": {"completed": False, "time": 10}, + "tvdb": "10009417", + "imdb": "tt22866594", + "title": "Departure", + "locations": ("S01E02.mkv",), + "status": {"completed": False, "time": 300741}, + }, + { + "tvdb": "10009420", + "imdb": "tt23787572", + "title": "The Way Out", + "locations": ("S01E05.mkv",), + "status": {"completed": True, "time": 0}, + }, + ] + }, + frozenset( + { + ("tmdb", "125928"), + ("imdb", "tt14681924"), + ("tvdb", "403172"), + ( + "locations", + ("My Adventures with Superman {tvdb-403172} {imdb-tt14681924}",), + ), + ("title", "My Adventures with Superman"), + } + ): { + 1: [ + { + "tvdb": "8438181", + "imdb": "tt15699926", + "title": "Adventures of a Normal Man (1)", + "locations": ("S01E01.mkv",), + "status": {"completed": True, "time": 0}, + }, + { + "tvdb": "9829910", + "imdb": "tt20413322", + "title": "Adventures of a Normal Man (2)", + "locations": ("S01E02.mkv",), + "status": {"completed": True, "time": 0}, + }, + { + "tvdb": "9870382", + "imdb": "tt20413328", + "title": "My Interview with Superman", + "locations": ("S01E03.mkv",), + "status": {"completed": True, "time": 0}, }, ] }, @@ -122,38 +245,61 @@ tv_shows_watched_list_2 = { expected_tv_show_watched_list_1 = { frozenset( { - ("tvdb", "75710"), - ("title", "Criminal Minds"), - ("imdb", "tt0452046"), - ("locations", ("Criminal Minds",)), - ("tmdb", "4057"), + ("locations", ("Doctor Who (2005) {tvdb-78804} {imdb-tt0436992}",)), + ("imdb", "tt0436992"), + ("tmdb", "57243"), + ("tvdb", "78804"), + ("title", "Doctor Who (2005)"), } ): { - "Season 1": [ + 1: [ { - "imdb": "tt0550489", - "tmdb": "282843", - "tvdb": "176357", - "title": "Extreme Aggressor", - "locations": ( - "Criminal Minds S01E01 Extreme Aggressor WEBDL-720p.mkv", - ), - "status": {"completed": True, "time": 0}, - } - ] - }, - frozenset({("title", "Test"), ("locations", ("Test",))}): { - "Season 1": [ - { - "title": "S01E01", - "locations": ("Test S01E01.mkv",), + "imdb": "tt0563001", + "tmdb": "968589", + "tvdb": "295296", + "title": "The Unquiet Dead", + "locations": ("S01E03.mkv",), "status": {"completed": True, "time": 0}, }, { - "title": "S01E02", - "locations": ("Test S01E02.mkv",), + "imdb": "tt0562985", + "tmdb": "968590", + "tvdb": "295297", + "title": "Aliens of London (1)", + "locations": ("S01E04.mkv",), + "status": {"completed": False, "time": 240000}, + }, + ] + }, + frozenset( + { + ("title", "Monarch: Legacy of Monsters"), + ("imdb", "tt17220216"), + ("tvdb", "422598"), + ("tmdb", "202411"), + ( + "locations", + ("Monarch - Legacy of Monsters {tvdb-422598} {imdb-tt17220216}",), + ), + } + ): { + 1: [ + { + "imdb": "tt21255044", + "tmdb": "4661246", + "tvdb": "10009418", + "title": "Secrets and Lies", + "locations": ("S01E03.mkv",), "status": {"completed": True, "time": 0}, }, + { + "imdb": "tt21255050", + "tmdb": "4712059", + "tvdb": "10009419", + "title": "Parallels and Interiors", + "locations": ("S01E04.mkv",), + "status": {"completed": False, "time": 240000}, + }, ] }, } @@ -161,37 +307,57 @@ expected_tv_show_watched_list_1 = { expected_tv_show_watched_list_2 = { frozenset( { - ("tvdb", "75710"), - ("title", "Criminal Minds"), - ("imdb", "tt0452046"), - ("locations", ("Criminal Minds",)), - ("tmdb", "4057"), + ("locations", ("Doctor Who (2005) {tvdb-78804} {imdb-tt0436992}",)), + ("imdb", "tt0436992"), + ("tmdb", "57243"), + ("title", "Doctor Who"), + ("tvdb", "78804"), + ("tvrage", "3332"), } ): { - "Season 1": [ + 1: [ { - "imdb": "tt0550498", - "tmdb": "282865", - "tvdb": "300474", - "title": "Won't Get Fooled Again", - "locations": ( - "Criminal Minds S01E03 Won't Get Fooled Again WEBDL-720p.mkv", - ), - "status": {"completed": True, "time": 0}, - } - ] - }, - frozenset({("title", "Test"), ("locations", ("Test",))}): { - "Season 1": [ - { - "title": "S01E03", - "locations": ("Test S01E03.mkv",), + "tvdb": "295294", + "imdb": "tt0562992", + "title": "Rose", + "locations": ("S01E01.mkv",), "status": {"completed": True, "time": 0}, }, { - "title": "S01E04", - "locations": ("Test S01E04.mkv",), - "status": {"completed": False, "time": 10}, + "tvdb": "295295", + "imdb": "tt0562997", + "title": "The End of the World", + "locations": ("S01E02.mkv",), + "status": {"completed": False, "time": 300670}, + }, + ] + }, + frozenset( + { + ("title", "Monarch: Legacy of Monsters"), + ("imdb", "tt17220216"), + ("tvdb", "422598"), + ("tmdb", "202411"), + ( + "locations", + ("Monarch - Legacy of Monsters {tvdb-422598} {imdb-tt17220216}",), + ), + } + ): { + 1: [ + { + "tvdb": "9959300", + "imdb": "tt20412166", + "title": "Aftermath", + "locations": ("S01E01.mkv",), + "status": {"completed": True, "time": 0}, + }, + { + "tvdb": "10009417", + "imdb": "tt22866594", + "title": "Departure", + "locations": ("S01E02.mkv",), + "status": {"completed": False, "time": 300741}, }, ] }, @@ -199,61 +365,92 @@ expected_tv_show_watched_list_2 = { movies_watched_list_1 = [ { - "imdb": "tt2380307", - "tmdb": "354912", - "title": "Coco", - "locations": ("Coco (2017) Remux-1080p.mkv",), + "imdb": "tt1254207", + "tmdb": "10378", + "tvdb": "12352", + "title": "Big Buck Bunny", + "locations": ("Big Buck Bunny.mkv",), "status": {"completed": True, "time": 0}, }, { - "tmdbcollection": "448150", - "imdb": "tt1431045", - "tmdb": "293660", - "title": "Deadpool", - "locations": ("Deadpool (2016) Remux-1080p.mkv",), + "imdb": "tt16431870", + "tmdb": "1029575", + "tvdb": "351194", + "title": "The Family Plan", + "locations": ("The Family Plan (2023).mkv",), "status": {"completed": True, "time": 0}, }, + { + "imdb": "tt5537002", + "tmdb": "466420", + "tvdb": "135852", + "title": "Killers of the Flower Moon", + "locations": ("Killers of the Flower Moon (2023).mkv",), + "status": {"completed": False, "time": 240000}, + }, ] movies_watched_list_2 = [ { - "imdb": "tt2380307", - "tmdb": "354912", - "title": "Coco", - "locations": ("Coco (2017) Remux-1080p.mkv",), + "imdb": "tt16431870", + "tmdb": "1029575", + "title": "The Family Plan", + "locations": ("The Family Plan (2023).mkv",), "status": {"completed": True, "time": 0}, }, { - "imdb": "tt0384793", - "tmdb": "9788", - "tvdb": "9103", - "title": "Accepted", - "locations": ("Accepted (2006) Remux-1080p.mkv",), + "imdb": "tt4589218", + "tmdb": "507089", + "title": "Five Nights at Freddy's", + "locations": ("Five Nights at Freddy's (2023).mkv",), "status": {"completed": True, "time": 0}, }, + { + "imdb": "tt10545296", + "tmdb": "695721", + "tmdbcollection": "131635", + "title": "The Hunger Games: The Ballad of Songbirds & Snakes", + "locations": ("The Hunger Games The Ballad of Songbirds & Snakes (2023).mkv",), + "status": {"completed": False, "time": 301215}, + }, ] expected_movie_watched_list_1 = [ { - "tmdbcollection": "448150", - "imdb": "tt1431045", - "tmdb": "293660", - "title": "Deadpool", - "locations": ("Deadpool (2016) Remux-1080p.mkv",), + "imdb": "tt1254207", + "tmdb": "10378", + "tvdb": "12352", + "title": "Big Buck Bunny", + "locations": ("Big Buck Bunny.mkv",), "status": {"completed": True, "time": 0}, - } + }, + { + "imdb": "tt5537002", + "tmdb": "466420", + "tvdb": "135852", + "title": "Killers of the Flower Moon", + "locations": ("Killers of the Flower Moon (2023).mkv",), + "status": {"completed": False, "time": 240000}, + }, ] expected_movie_watched_list_2 = [ { - "imdb": "tt0384793", - "tmdb": "9788", - "tvdb": "9103", - "title": "Accepted", - "locations": ("Accepted (2006) Remux-1080p.mkv",), + "imdb": "tt4589218", + "tmdb": "507089", + "title": "Five Nights at Freddy's", + "locations": ("Five Nights at Freddy's (2023).mkv",), "status": {"completed": True, "time": 0}, - } + }, + { + "imdb": "tt10545296", + "tmdb": "695721", + "tmdbcollection": "131635", + "title": "The Hunger Games: The Ballad of Songbirds & Snakes", + "locations": ("The Hunger Games The Ballad of Songbirds & Snakes (2023).mkv",), + "status": {"completed": False, "time": 301215}, + }, ] # Test to see if objects get deleted all the way up to the root. diff --git a/test/validate_ci_marklog.py b/test/validate_ci_marklog.py index 34099f6..4943bcb 100644 --- a/test/validate_ci_marklog.py +++ b/test/validate_ci_marklog.py @@ -2,12 +2,14 @@ import os + def read_marklog(): marklog = os.path.join(os.getcwd(), "mark.log") with open(marklog, "r") as f: lines = f.readlines() return lines + def check_marklog(lines, expected_values): for line in lines: # Remove the newline character @@ -17,11 +19,18 @@ def check_marklog(lines, expected_values): return False return True + def main(): expected_values = [ - "jellyplex_watched/TV Shows/Blender Shorts/Episode 2" - , "JellyUser/Movies/Big Buck Bunny" - , "JellyUser/Shows/Blender Shorts/S01E01" + "jellyplex_watched/Movies/Five Nights at Freddy's", + "jellyplex_watched/Movies/The Hunger Games: The Ballad of Songbirds & Snakes/301215", + "jellyplex_watched/TV Shows/Doctor Who (2005)/Rose", + "jellyplex_watched/TV Shows/Doctor Who (2005)/The End of the World/300670", + "jellyplex_watched/TV Shows/Monarch: Legacy of Monsters/Aftermath", + "jellyplex_watched/TV Shows/Monarch: Legacy of Monsters/Departure/300741", + "JellyUser/Movies/Big Buck Bunny", + "JellyUser/Shows/Doctor Who/The Unquiet Dead", + "JellyUser/Shows/Monarch: Legacy of Monsters/Secrets and Lies", ] lines = read_marklog() @@ -31,5 +40,6 @@ def main(): else: print("Marklog contained the expected values") + if __name__ == "__main__": main()