diff --git a/.vscode/launch.json b/.vscode/launch.json index ae8f15f..aa73483 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,16 +1,16 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Python", - "type": "python", - "request": "launch", - "program": "main.py", - "console": "integratedTerminal", - "justMyCode": true - } - ] -} \ No newline at end of file + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Main", + "type": "python", + "request": "launch", + "program": "main.py", + "console": "integratedTerminal", + "justMyCode": true + } + ] +} diff --git a/src/functions.py b/src/functions.py index 64050aa..8b404ec 100644 --- a/src/functions.py +++ b/src/functions.py @@ -97,7 +97,8 @@ def generate_library_guids_dict(user_list: dict, generate_output: int): if provider_key.lower() not in show_output_dict: show_output_dict[provider_key.lower()] = [] if provider_key.lower() == "locations": - show_output_dict[provider_key.lower()].append(provider_value) + for show_location in provider_value: + show_output_dict[provider_key.lower()].append(show_location) else: show_output_dict[provider_key.lower()].append(provider_value.lower()) @@ -109,7 +110,8 @@ def generate_library_guids_dict(user_list: dict, generate_output: int): if episode_key.lower() not in episode_output_dict: episode_output_dict[episode_key.lower()] = [] if episode_key == "locations": - episode_output_dict[episode_key.lower()].append(episode_value) + for episode_location in episode_value: + episode_output_dict[episode_key.lower()].append(episode_location) else: episode_output_dict[episode_key.lower()].append(episode_value.lower()) @@ -119,7 +121,8 @@ def generate_library_guids_dict(user_list: dict, generate_output: int): if movie_key.lower() not in movies_output_dict: movies_output_dict[movie_key.lower()] = [] if movie_key == "locations": - movies_output_dict[movie_key.lower()].append(movie_value) + for movie_location in movie_value: + movies_output_dict[movie_key.lower()].append(movie_location) else: movies_output_dict[movie_key.lower()].append(movie_value.lower()) diff --git a/src/jellyfin.py b/src/jellyfin.py index b0a753d..f16ac3c 100644 --- a/src/jellyfin.py +++ b/src/jellyfin.py @@ -39,7 +39,7 @@ def query(self, query, query_type): response = self.session.post(self.baseurl + query, headers=headers) return response.json() - + except Exception as e: logger(f"Jellyfin: Query failed {e}", 2) raise Exception(e) @@ -71,40 +71,49 @@ def get_user_watched(self, user_name, user_id, library_type, library_id, library # Movies if library_type == "Movie": user_watched[user_name][library_title] = [] - watched = self.query(f"/Users/{user_id}/Items?SortBy=SortName&SortOrder=Ascending&Recursive=true&ParentId={library_id}&Filters=IsPlayed&Fields=ItemCounts,ProviderIds", "get") + watched = self.query(f"/Users/{user_id}/Items?SortBy=SortName&SortOrder=Ascending&Recursive=true&ParentId={library_id}&Filters=IsPlayed&Fields=ItemCounts,ProviderIds,MediaSources", "get") for movie in watched["Items"]: if movie["UserData"]["Played"] == True: + movie_guids = {} + movie_guids["title"] = movie["Name"] if movie["ProviderIds"]: # Lowercase movie["ProviderIds"] keys - movie["ProviderIds"] = {k.lower(): v for k, v in movie["ProviderIds"].items()} - user_watched[user_name][library_title].append(movie["ProviderIds"]) + movie_guids = {k.lower(): v for k, v in movie["ProviderIds"].items()} + if movie["MediaSources"]: + movie_guids["locations"] = tuple([x["Path"].split("/")[-1] for x in movie["MediaSources"]]) + user_watched[user_name][library_title].append(movie_guids) # TV Shows if library_type == "Episode": user_watched[user_name][library_title] = {} - watched = self.query(f"/Users/{user_id}/Items?SortBy=SortName&SortOrder=Ascending&Recursive=true&ParentId={library_id}&Fields=ItemCounts,ProviderIds", "get") + watched = self.query(f"/Users/{user_id}/Items?SortBy=SortName&SortOrder=Ascending&Recursive=true&ParentId={library_id}&Fields=ItemCounts,ProviderIds,Path", "get") watched_shows = [x for x in watched["Items"] if x["Type"] == "Series"] for show in watched_shows: show_guids = {k.lower(): v for k, v in show["ProviderIds"].items()} show_guids["title"] = show["Name"] + show_guids["locations"] = tuple([show["Path"].split("/")[-1]]) show_guids = frozenset(show_guids.items()) seasons = self.query(f"/Shows/{show['Id']}/Seasons?userId={user_id}&Fields=ItemCounts,ProviderIds", "get") if len(seasons["Items"]) > 0: for season in seasons["Items"]: - episodes = self.query(f"/Shows/{show['Id']}/Episodes?seasonId={season['Id']}&userId={user_id}&Fields=ItemCounts,ProviderIds", "get") + episodes = self.query(f"/Shows/{show['Id']}/Episodes?seasonId={season['Id']}&userId={user_id}&Fields=ItemCounts,ProviderIds,MediaSources", "get") if len(episodes["Items"]) > 0: for episode in episodes["Items"]: if episode["UserData"]["Played"] == True: - if episode["ProviderIds"]: + if episode["ProviderIds"] or episode["MediaSources"]: if show_guids not in user_watched[user_name][library_title]: user_watched[user_name][library_title][show_guids] = {} if season["Name"] not in user_watched[user_name][library_title][show_guids]: user_watched[user_name][library_title][show_guids][season["Name"]] = [] # Lowercase episode["ProviderIds"] keys - episode["ProviderIds"] = {k.lower(): v for k, v in episode["ProviderIds"].items()} - user_watched[user_name][library_title][show_guids][season["Name"]].append(episode["ProviderIds"]) + episode_guids = {} + if episode["ProviderIds"]: + episode_guids = {k.lower(): v for k, v in episode["ProviderIds"].items()} + if episode["MediaSources"]: + episode_guids["locations"] = tuple([x["Path"].split("/")[-1] for x in episode["MediaSources"]]) + user_watched[user_name][library_title][show_guids][season["Name"]].append(episode_guids) return user_watched except Exception as e: @@ -163,55 +172,86 @@ def update_user_watched(self, user, user_id, library, library_id, videos, dryrun if library_type == "Movie": _, _, videos_movies_ids = generate_library_guids_dict(videos, 2) - jellyfin_search = self.query(f"/Users/{user_id}/Items?SortBy=SortName&SortOrder=Ascending&Recursive=false&ParentId={library_id}&isPlayed=false&Fields=ItemCounts,ProviderIds", "get") + jellyfin_search = self.query(f"/Users/{user_id}/Items?SortBy=SortName&SortOrder=Ascending&Recursive=false&ParentId={library_id}&isPlayed=false&Fields=ItemCounts,ProviderIds,MediaSources", "get") for jellyfin_video in jellyfin_search["Items"]: - if str_to_bool(jellyfin_video["UserData"]["Played"]) == False: - jellyfin_video_id = jellyfin_video["Id"] - - for movie_provider_source, movie_provider_id in jellyfin_video["ProviderIds"].items(): - if movie_provider_source.lower() in videos_movies_ids: - if movie_provider_id.lower() in videos_movies_ids[movie_provider_source.lower()]: - msg = f"{jellyfin_video['Name']} as watched for {user} in {library} for Jellyfin" - if not dryrun: - logger(f"Marking {msg}", 0) - self.query(f"/Users/{user_id}/PlayedItems/{jellyfin_video_id}", "post") - else: - logger(f"Dryrun {msg}", 0) + movie_found = False + + if "MediaSources" in jellyfin_video: + for movie_location in jellyfin_video["MediaSources"]: + if movie_location["Path"].split("/")[-1] in videos_movies_ids["locations"]: + movie_found = True break + if not movie_found: + for movie_provider_source, movie_provider_id in jellyfin_video["ProviderIds"].items(): + if movie_provider_source.lower() in videos_movies_ids: + if movie_provider_id.lower() in videos_movies_ids[movie_provider_source.lower()]: + movie_found = True + break + + if movie_found: + jellyfin_video_id = jellyfin_video["Id"] + msg = f"{jellyfin_video['Name']} as watched for {user} in {library} for Jellyfin" + if not dryrun: + logger(f"Marking {msg}", 0) + self.query(f"/Users/{user_id}/PlayedItems/{jellyfin_video_id}", "post") + else: + logger(f"Dryrun {msg}", 0) + + # TV Shows if library_type == "Episode": videos_shows_ids, videos_episode_ids, _ = generate_library_guids_dict(videos, 3) - jellyfin_search = self.query(f"/Users/{user_id}/Items?SortBy=SortName&SortOrder=Ascending&Recursive=false&ParentId={library_id}&isPlayed=false&Fields=ItemCounts,ProviderIds", "get") + jellyfin_search = self.query(f"/Users/{user_id}/Items?SortBy=SortName&SortOrder=Ascending&Recursive=false&ParentId={library_id}&isPlayed=false&Fields=ItemCounts,ProviderIds,Path", "get") jellyfin_shows = [x for x in jellyfin_search["Items"]] for jellyfin_show in jellyfin_shows: show_found = False - for show_provider_source, show_provider_id in jellyfin_show["ProviderIds"].items(): - if show_provider_source.lower() in videos_shows_ids: - if show_provider_id.lower() in videos_shows_ids[show_provider_source.lower()]: - show_found = True - jellyfin_show_id = jellyfin_show["Id"] - jellyfin_episodes = self.query(f"/Shows/{jellyfin_show_id}/Episodes?userId={user_id}&Fields=ItemCounts,ProviderIds", "get") - for jellyfin_episode in jellyfin_episodes["Items"]: - if str_to_bool(jellyfin_episode["UserData"]["Played"]) == False: - jellyfin_episode_id = jellyfin_episode["Id"] - - for episode_provider_source, episode_provider_id in jellyfin_episode["ProviderIds"].items(): - if episode_provider_source.lower() in videos_episode_ids: - if episode_provider_id.lower() in videos_episode_ids[episode_provider_source.lower()]: - msg = f"{jellyfin_episode['SeriesName']} {jellyfin_episode['SeasonName']} Episode {jellyfin_episode['IndexNumber']} {jellyfin_episode['Name']} as watched for {user} in {library} for Jellyfin" - if not dryrun: - logger(f"Marked {msg}", 0) - self.query(f"/Users/{user_id}/PlayedItems/{jellyfin_episode_id}", "post") - else: - logger(f"Dryrun {msg}", 0) - break - - if show_found: - break - + + if jellyfin_show["Name"] == "The 13 Ghosts of Scooby-Doo": + print(jellyfin_show) + + if "Path" in jellyfin_show: + if jellyfin_show["Path"].split("/")[-1] in videos_shows_ids["locations"]: + show_found = True + + if not show_found: + for show_provider_source, show_provider_id in jellyfin_show["ProviderIds"].items(): + if show_provider_source.lower() in videos_shows_ids: + if show_provider_id.lower() in videos_shows_ids[show_provider_source.lower()]: + show_found = True + break + + if show_found: + jellyfin_show_id = jellyfin_show["Id"] + jellyfin_episodes = self.query(f"/Shows/{jellyfin_show_id}/Episodes?userId={user_id}&Fields=ItemCounts,ProviderIds,MediaSources", "get") + + for jellyfin_episode in jellyfin_episodes["Items"]: + episode_found = False + + if "MediaSources" in jellyfin_episode: + for episode_location in jellyfin_episode["MediaSources"]: + if episode_location["Path"].split("/")[-1] in videos_episode_ids["locations"]: + episode_found = True + break + + if not episode_found: + for episode_provider_source, episode_provider_id in jellyfin_episode["ProviderIds"].items(): + if episode_provider_source.lower() in videos_episode_ids: + if episode_provider_id.lower() in videos_episode_ids[episode_provider_source.lower()]: + episode_found = True + break + + if episode_found: + jellyfin_episode_id = jellyfin_episode["Id"] + msg = f"{jellyfin_episode['SeriesName']} {jellyfin_episode['SeasonName']} Episode {jellyfin_episode['IndexNumber']} {jellyfin_episode['Name']} as watched for {user} in {library} for Jellyfin" + if not dryrun: + logger(f"Marked {msg}", 0) + self.query(f"/Users/{user_id}/PlayedItems/{jellyfin_episode_id}", "post") + else: + logger(f"Dryrun {msg}", 0) + except Exception as e: logger(f"Jellyfin: Error updating watched for {user} in library {library}", 2) raise Exception(e) diff --git a/src/main.py b/src/main.py index 177ba5e..a4cffdb 100644 --- a/src/main.py +++ b/src/main.py @@ -40,32 +40,54 @@ def cleanup_watched(watched_list_1, watched_list_2, user_mapping=None, library_m # Movies if isinstance(watched_list_1[user_1][library_1], list): - for item in watched_list_1[user_1][library_1]: - for watch_list_1_key, watch_list_1_value in item.items(): - for watch_list_2_item in watched_list_2[user_2][library_2]: - for watch_list_2_item_key, watch_list_2_item_value in watch_list_2_item.items(): - if watch_list_1_key == watch_list_2_item_key and watch_list_1_value == watch_list_2_item_value: - if item in modified_watched_list_1[user_1][library_1]: - logger(f"Removing {item} from {library_1}", 3) - modified_watched_list_1[user_1][library_1].remove(item) + _, _, movies_watched_list_2_keys_dict = generate_library_guids_dict(watched_list_2[user_2][library_2], 2) + for movie in watched_list_1[user_1][library_1]: + movie_found = False + for movie_key, movie_value in movie.items(): + if movie_key == "locations": + for location in movie_value: + if location in movies_watched_list_2_keys_dict["locations"]: + movie_found = True + break + else: + if movie_key in movies_watched_list_2_keys_dict.keys(): + if movie_value in movies_watched_list_2_keys_dict[movie_key]: + movie_found = True + + if movie_found: + logger(f"Removing {movie} from {library_1}", 3) + modified_watched_list_1[user_1][library_1].remove(movie) + break # TV Shows elif isinstance(watched_list_1[user_1][library_1], dict): # Generate full list of provider ids for episodes in watch_list_2 to easily compare if they exist in watch_list_1 - _, episode_watched_list_2_keys_dict, _ = generate_library_guids_dict(watched_list_2[user_2][library_2], 1) + show_watched_list_2_keys_dict, episode_watched_list_2_keys_dict, _ = generate_library_guids_dict(watched_list_2[user_2][library_2], 3) for show_key_1 in watched_list_1[user_1][library_1].keys(): show_key_dict = dict(show_key_1) for season in watched_list_1[user_1][library_1][show_key_1]: for episode in watched_list_1[user_1][library_1][show_key_1][season]: - for episode_key, episode_item in episode.items(): - # If episode_key and episode_item are in episode_watched_list_2_keys_dict exactly, then remove from watch_list_1 - if episode_key in episode_watched_list_2_keys_dict.keys(): - if episode_item in episode_watched_list_2_keys_dict[episode_key]: - if episode in modified_watched_list_1[user_1][library_1][show_key_1][season]: - logger(f"Removing {show_key_dict['title']} {episode} from {library_1}", 3) - modified_watched_list_1[user_1][library_1][show_key_1][season].remove(episode) + episode_found = False + for episode_key, episode_value in episode.items(): + # If episode_key and episode_value are in episode_watched_list_2_keys_dict exactly, then remove from watch_list_1 + if episode_key == "locations": + for location in episode_value: + if location in episode_watched_list_2_keys_dict["locations"]: + episode_found = True + break + + else: + if episode_key in episode_watched_list_2_keys_dict.keys(): + if episode_value in episode_watched_list_2_keys_dict[episode_key]: + episode_found = True + + if episode_found: + if episode in modified_watched_list_1[user_1][library_1][show_key_1][season]: + logger(f"Removing {show_key_dict['title']} {episode} from {library_1}", 3) + modified_watched_list_1[user_1][library_1][show_key_1][season].remove(episode) + break # Remove empty seasons if len(modified_watched_list_1[user_1][library_1][show_key_1][season]) == 0: @@ -154,7 +176,7 @@ def setup_black_white_lists(blacklist_library: str, whitelist_library: str, blac user_other = search_mapping(user_mapping, user) if user_other: temp_users.append(user_other) - + blacklist_users = blacklist_users + temp_users else: blacklist_users = [] diff --git a/src/plex.py b/src/plex.py index a1c6874..825c3a0 100644 --- a/src/plex.py +++ b/src/plex.py @@ -64,26 +64,32 @@ def get_user_watched(self, user, user_plex, library): user_watched[user_name][library.title] = [] library_videos = user_plex.library.section(library.title) - for video in library_videos.search(unmatched=False, unwatched=False): - guids = {} + for video in library_videos.search(unwatched=False): + movie_guids = {} for guid in video.guids: guid_source = re.search(r'(.*)://', guid.id).group(1).lower() guid_id = re.search(r'://(.*)', guid.id).group(1) - guids[guid_source] = guid_id - user_watched[user_name][library.title].append(guids) + movie_guids[guid_source] = guid_id + + movie_guids["title"] = video.title + movie_guids["locations"] = tuple([x.split("/")[-1] for x in video.locations]) + + user_watched[user_name][library.title].append(movie_guids) elif library.type == "show": user_watched[user_name][library.title] = {} library_videos = user_plex.library.section(library.title) - for show in library_videos.search(unmatched=False, unwatched=False): + for show in library_videos.search(unwatched=False): show_guids = {} for show_guid in show.guids: - show_guids["title"] = show.title # Extract after :// from guid.id show_guid_source = re.search(r'(.*)://', show_guid.id).group(1).lower() show_guid_id = re.search(r'://(.*)', show_guid.id).group(1) show_guids[show_guid_source] = show_guid_id + + show_guids["title"] = show.title + show_guids["locations"] = tuple([x.split("/")[-1] for x in show.locations]) show_guids = frozenset(show_guids.items()) for season in show.seasons(): @@ -97,6 +103,7 @@ def get_user_watched(self, user, user_plex, library): guid_id = re.search(r'://(.*)', guid.id).group(1) episode_guids_temp[guid_source] = guid_id + episode_guids_temp["locations"] = tuple([x.split("/")[-1] for x in episode.locations]) episode_guids.append(episode_guids_temp) if episode_guids: @@ -159,56 +166,83 @@ def update_user_watched (self, user, user_plex, library, videos, dryrun): if library_videos.type == "movie": _, _, videos_movies_ids = generate_library_guids_dict(videos, 2) - for movies_search in library_videos.search(unmatched=False, unwatched=True): - for movie_guid in movies_search.guids: - movie_guid_source = re.search(r'(.*)://', movie_guid.id).group(1).lower() - movie_guid_id = re.search(r'://(.*)', movie_guid.id).group(1) - - # If movie provider source and movie provider id are in videos_movie_ids exactly, then the movie is in the list - if movie_guid_source in videos_movies_ids.keys(): - if movie_guid_id in videos_movies_ids[movie_guid_source]: - if movies_search.viewCount == 0: - msg = f"{movies_search.title} as watched for {user.title} in {library} for Plex" - if not dryrun: - logger(f"Marked {msg}", 0) - movies_search.markWatched() - else: - logger(f"Dryrun {msg}", 0) - break + for movies_search in library_videos.search(unwatched=True): + movie_found = False + for movie_location in movies_search.locations: + if movie_location.split("/")[-1] in videos_movies_ids["locations"]: + movie_found = True + break + + if not movie_found: + for movie_guid in movies_search.guids: + movie_guid_source = re.search(r'(.*)://', movie_guid.id).group(1).lower() + movie_guid_id = re.search(r'://(.*)', movie_guid.id).group(1) + + # If movie provider source and movie provider id are in videos_movie_ids exactly, then the movie is in the list + if movie_guid_source in videos_movies_ids.keys(): + if movie_guid_id in videos_movies_ids[movie_guid_source]: + movie_found = True + break + + if movie_found: + if movies_search.viewCount == 0: + msg = f"{movies_search.title} as watched for {user.title} in {library} for Plex" + if not dryrun: + logger(f"Marked {msg}", 0) + movies_search.markWatched() + else: + logger(f"Dryrun {msg}", 0) elif library_videos.type == "show": videos_shows_ids, videos_episode_ids, _ = generate_library_guids_dict(videos, 3) - for show_search in library_videos.search(unmatched=False, unwatched=True): + for show_search in library_videos.search(unwatched=True): show_found = False - for show_guid in show_search.guids: - show_guid_source = re.search(r'(.*)://', show_guid.id).group(1).lower() - show_guid_id = re.search(r'://(.*)', show_guid.id).group(1) - - # If show provider source and show provider id are in videos_shows_ids exactly, then the show is in the list - if show_guid_source in videos_shows_ids.keys(): - if show_guid_id in videos_shows_ids[show_guid_source]: - show_found = True - for episode_search in show_search.episodes(): - for episode_guid in episode_search.guids: - episode_guid_source = re.search(r'(.*)://', episode_guid.id).group(1).lower() - episode_guid_id = re.search(r'://(.*)', episode_guid.id).group(1) - - # If episode provider source and episode provider id are in videos_episode_ids exactly, then the episode is in the list - if episode_guid_source in videos_episode_ids.keys(): - if episode_guid_id in videos_episode_ids[episode_guid_source]: - if episode_search.viewCount == 0: - msg = f"{show_search.title} {episode_search.title} as watched for {user.title} in {library} for Plex" - if not dryrun: - logger(f"Marked {msg}", 0) - episode_search.markWatched() - else: - logger(f"Dryrun {msg}", 0) - break - - if show_found: + for show_location in show_search.locations: + if show_location.split("/")[-1] in videos_shows_ids["locations"]: + show_found = True break + + if not show_found: + for show_guid in show_search.guids: + show_guid_source = re.search(r'(.*)://', show_guid.id).group(1).lower() + show_guid_id = re.search(r'://(.*)', show_guid.id).group(1) + + # If show provider source and show provider id are in videos_shows_ids exactly, then the show is in the list + if show_guid_source in videos_shows_ids.keys(): + if show_guid_id in videos_shows_ids[show_guid_source]: + show_found = True + break + + if show_found: + for episode_search in show_search.episodes(): + episode_found = False + + for episode_location in episode_search.locations: + if episode_location.split("/")[-1] in videos_episode_ids["locations"]: + episode_found = True + break + + if not episode_found: + for episode_guid in episode_search.guids: + episode_guid_source = re.search(r'(.*)://', episode_guid.id).group(1).lower() + episode_guid_id = re.search(r'://(.*)', episode_guid.id).group(1) + + # If episode provider source and episode provider id are in videos_episode_ids exactly, then the episode is in the list + if episode_guid_source in videos_episode_ids.keys(): + if episode_guid_id in videos_episode_ids[episode_guid_source]: + episode_found = True + break + + if episode_found: + if episode_search.viewCount == 0: + msg = f"{show_search.title} {episode_search.title} as watched for {user.title} in {library} for Plex" + if not dryrun: + logger(f"Marked {msg}", 0) + episode_search.markWatched() + else: + logger(f"Dryrun {msg}", 0) except Exception as e: logger(f"Plex: Failed to update watched for {user.title} in library {library}, Error: {e}", 2) raise Exception(e) diff --git a/test/test_main_.py b/test/test_main_.py index b1c350e..2b15392 100644 --- a/test/test_main_.py +++ b/test/test_main_.py @@ -1,15 +1,15 @@ import sys import os - + # getting the name of the directory # where the this file is present. current = os.path.dirname(os.path.realpath(__file__)) - + # Getting the parent directory name # where the current directory is present. parent = os.path.dirname(current) - -# adding the parent directory to + +# adding the parent directory to # the sys.path. sys.path.append(parent) diff --git a/test/test_main_cleanup_watched.py b/test/test_main_cleanup_watched.py index b010542..4d2bbcd 100644 --- a/test/test_main_cleanup_watched.py +++ b/test/test_main_cleanup_watched.py @@ -1,15 +1,15 @@ import sys import os - + # getting the name of the directory # where the this file is present. current = os.path.dirname(os.path.realpath(__file__)) - + # Getting the parent directory name # where the current directory is present. parent = os.path.dirname(current) - -# adding the parent directory to + +# adding the parent directory to # the sys.path. sys.path.append(parent) @@ -21,6 +21,12 @@ {'imdb': 'tt0550489', 'tmdb': '282843', 'tvdb': '176357', 'locations': ('Criminal Minds S01E01 Extreme Aggressor WEBDL-720p.mkv',)}, {'imdb': 'tt0550487', 'tmdb': '282861', 'tvdb': '300385', 'locations': ('Criminal Minds S01E02 Compulsion WEBDL-720p.mkv',)} ] + }, + frozenset({("title", "Test"), ("locations", ("Test",))}): { + "Season 1": [ + {'locations': ('Test S01E01.mkv',)}, + {'locations': ('Test S01E02.mkv',)} + ] } } @@ -35,6 +41,12 @@ {'imdb': 'tt0550487', 'tmdb': '282861', 'tvdb': '300385', 'locations': ('Criminal Minds S01E02 Compulsion WEBDL-720p.mkv',)}, {'imdb': 'tt0550498', 'tmdb': '282865', 'tvdb': '300474', 'locations': ("Criminal Minds S01E03 Won't Get Fooled Again WEBDL-720p.mkv",)} ] + }, + frozenset({("title", "Test"), ("locations", ("Test",))}): { + "Season 1": [ + {'locations': ('Test S01E02.mkv',)}, + {'locations': ('Test S01E03.mkv',)} + ] } } @@ -57,6 +69,11 @@ "Season 1": [ {'imdb': 'tt0550489', 'tmdb': '282843', 'tvdb': '176357', 'locations': ('Criminal Minds S01E01 Extreme Aggressor WEBDL-720p.mkv',)} ] + }, + frozenset({("title", "Test"), ("locations", ("Test",))}): { + "Season 1": [ + {'locations': ('Test S01E01.mkv',)} + ] } } @@ -69,6 +86,11 @@ "Season 1": [ {'imdb': 'tt0550498', 'tmdb': '282865', 'tvdb': '300474', 'locations': ("Criminal Minds S01E03 Won't Get Fooled Again WEBDL-720p.mkv",)} ] + }, + frozenset({("title", "Test"), ("locations", ("Test",))}): { + "Season 1": [ + {'locations': ('Test S01E03.mkv',)} + ] } } @@ -106,7 +128,7 @@ def test_simple_cleanup_watched(): , "Movies": expected_movie_watched_list_2 } } - + return_watched_list_1 = cleanup_watched(user_watched_list_1, user_watched_list_2) return_watched_list_2 = cleanup_watched(user_watched_list_2, user_watched_list_1) @@ -149,6 +171,6 @@ def test_mapping_cleanup_watched(): return_watched_list_1 = cleanup_watched(user_watched_list_1, user_watched_list_2, user_mapping=user_mapping, library_mapping=library_mapping) return_watched_list_2 = cleanup_watched(user_watched_list_2, user_watched_list_1, user_mapping=user_mapping, library_mapping=library_mapping) - + assert return_watched_list_1 == expected_watched_list_1 assert return_watched_list_2 == expected_watched_list_2