Remove seasons from watch list

This commit is contained in:
Luis Garcia
2024-06-02 19:38:51 -06:00
parent 21ffce674f
commit 7119956ec7
6 changed files with 384 additions and 520 deletions

View File

@@ -284,8 +284,10 @@ class JellyfinEmby:
if show["UserData"]["PlayedPercentage"] > 0:
watched_shows_filtered.append(show)
# Retrieve the seasons of each watched show
seasons_watched = []
# Create a list of tasks to retrieve the episodes
watched_episodes = []
# Retrieve the watched/partially watched list of episodes of each watched show
for show in watched_shows_filtered:
logger(
f"{self.server_type}: Adding {show.get('Name')} to {user_name} watched list",
@@ -298,75 +300,34 @@ class JellyfinEmby:
if "Path" in show
else tuple()
)
show_display_name = (
show_guids["title"]
if show_guids["title"]
else show_guids["locations"]
)
show_guids = frozenset(show_guids.items())
show_identifiers = {
"show_guids": show_guids,
"show_id": show["Id"],
}
seasons_watched.append(
self.query(
f"/Shows/{show['Id']}/Seasons"
+ f"?userId={user_id}&isPlaceHolder=false&Fields=ProviderIds,RecursiveItemCount",
"get",
identifiers=frozenset(show_identifiers.items()),
)
)
# Filter the list of seasons to only include those that have been partially or fully watched
seasons_watched_filtered = []
for seasons in seasons_watched:
seasons_watched_filtered_dict = {}
seasons_watched_filtered_dict["Identifiers"] = seasons[
"Identifiers"
]
seasons_watched_filtered_dict["Items"] = []
for season in seasons["Items"]:
if "PlayedPercentage" in season["UserData"]:
if season["UserData"]["PlayedPercentage"] > 0:
seasons_watched_filtered_dict["Items"].append(season)
if seasons_watched_filtered_dict["Items"]:
seasons_watched_filtered.append(seasons_watched_filtered_dict)
# Create a list of tasks to retrieve the episodes of each watched season
watched_episodes = []
for seasons in seasons_watched_filtered:
if len(seasons["Items"]) > 0:
for season in seasons["Items"]:
if "IndexNumber" not in season:
logger(
f"Jellyfin: Skipping show {season.get('SeriesName')} season {season.get('Name')} as it has no index number",
3,
)
continue
season_identifiers = dict(seasons["Identifiers"])
season_identifiers["season_index"] = season["IndexNumber"]
watched_task = self.query(
f"/Shows/{season_identifiers['show_id']}/Episodes"
+ f"?seasonId={season['Id']}&userId={user_id}&isPlaceHolder=false&Filters=IsPlayed&Fields=ProviderIds,MediaSources",
f"/Shows/{show['Id']}/Episodes"
+ f"?userId={user_id}&isPlaceHolder=false&Filters=IsPlayed&Fields=ProviderIds,MediaSources",
"get",
identifiers=frozenset(season_identifiers.items()),
)
in_progress_task = self.query(
f"/Shows/{season_identifiers['show_id']}/Episodes"
+ f"?seasonId={season['Id']}&userId={user_id}&isPlaceHolder=false&Filters=IsResumable&Fields=ProviderIds,MediaSources",
f"/Shows/{show['Id']}/Episodes"
+ f"?userId={user_id}&isPlaceHolder=false&Filters=IsResumable&Fields=ProviderIds,MediaSources",
"get",
identifiers=frozenset(season_identifiers.items()),
)
watched_episodes.append(watched_task)
watched_episodes.append(in_progress_task)
# Iterate through the watched episodes
for episodes in watched_episodes:
# If the season has any watched episodes
# If has any watched episodes
if len(episodes["Items"]) > 0:
# Create a dictionary for the season with its identifier and episodes
season_dict = {}
season_dict["Identifiers"] = dict(episodes["Identifiers"])
season_dict["Episodes"] = []
# Create a list to store the episodes
episodes_list = []
for episode in episodes["Items"]:
if (
"MediaSources" in episode
@@ -378,36 +339,21 @@ class JellyfinEmby:
or episode["UserData"]["PlaybackPositionTicks"]
> 600000000
):
episode_dict = get_guids(self.server_type, episode)
# Add the episode dictionary to the season's list of episodes
season_dict["Episodes"].append(episode_dict)
episode_guids = get_guids(
self.server_type, episode
)
episodes_list.append(episode_guids)
# Add the season dictionary to the show's list of seasons
if (
season_dict["Identifiers"]["show_guids"]
not in user_watched[user_name][library_title]
):
user_watched[user_name][library_title][
season_dict["Identifiers"]["show_guids"]
] = {}
if (
season_dict["Identifiers"]["season_index"]
not in user_watched[user_name][library_title][
season_dict["Identifiers"]["show_guids"]
]
):
user_watched[user_name][library_title][
season_dict["Identifiers"]["show_guids"]
][season_dict["Identifiers"]["season_index"]] = []
# Add the show dictionary to the user's watched list
if show_guids not in user_watched[user_name][library_title]:
user_watched[user_name][library_title][show_guids] = []
user_watched[user_name][library_title][
season_dict["Identifiers"]["show_guids"]
][season_dict["Identifiers"]["season_index"]] = season_dict[
"Episodes"
]
show_guids
] = episodes_list
for episode in episodes_list:
logger(
f"{self.server_type}: Added {season_dict['Episodes']} to {user_name} {season_dict['Identifiers']['show_guids']} watched list",
f"{self.server_type}: Added {episode} to {user_name} {show_display_name} watched list",
1,
)
@@ -674,7 +620,7 @@ class JellyfinEmby:
is not None
):
show_found = True
for shows, seasons in videos.items():
for shows, episodes in videos.items():
show = {k: v for k, v in shows}
if (
contains_nested(
@@ -683,8 +629,7 @@ class JellyfinEmby:
)
is not None
):
for season in seasons.values():
for episode in season:
for episode in episodes:
episode_videos.append(episode)
break
@@ -702,13 +647,12 @@ class JellyfinEmby:
]
):
show_found = True
for show, seasons in videos.items():
for show, episodes in videos.items():
show = {k: v for k, v in show}
if show_provider_id.lower() in show.get(
show_provider_source.lower(), []
):
for season in seasons.values():
for episode in season:
for episode in episodes:
episode_videos.append(episode)
break

View File

@@ -169,27 +169,19 @@ def episode_title_dict(user_list: dict):
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
# Iterate through the shows and episodes in user_list
for show in user_list:
for season in user_list[show]:
for episode in user_list[show][season]:
for episode in user_list[show]:
# 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
@@ -202,9 +194,7 @@ def episode_title_dict(user_list: dict):
# If the key is "locations", append each location to the list
if episode_key == "locations":
episode_output_dict[episode_key.lower()].append(
episode_value
)
episode_output_dict[episode_key.lower()].append(episode_value)
# If the key is "status", append the "completed" and "time" values
elif episode_key == "status":

View File

@@ -117,11 +117,9 @@ def get_user_library_watched_show(show, process_episodes, threads=None):
episode_guids_args, threads=threads
)
episode_guids = {}
episode_guids = []
for index, episode in enumerate(process_episodes):
if episode.parentIndex not in episode_guids:
episode_guids[episode.parentIndex] = []
episode_guids[episode.parentIndex].append(episode_guids_results[index])
episode_guids.append(episode_guids_results[index])
return show_guids, episode_guids
except Exception:
@@ -220,7 +218,7 @@ def find_video(plex_search, video_ids, videos=None):
):
episode_videos = []
if videos:
for show, seasons in videos.items():
for show, episodes in videos.items():
show = {k: v for k, v in show}
if (
contains_nested(
@@ -228,8 +226,7 @@ def find_video(plex_search, video_ids, videos=None):
)
is not None
):
for season in seasons.values():
for episode in season:
for episode in episodes:
episode_videos.append(episode)
return True, episode_videos
@@ -243,12 +240,11 @@ def find_video(plex_search, video_ids, videos=None):
if guid_id in video_ids[guid_source]:
episode_videos = []
if videos:
for show, seasons in videos.items():
for show, episodes in videos.items():
show = {k: v for k, v in show}
if guid_source in show.keys():
if guid_id == show[guid_source]:
for season in seasons.values():
for episode in season:
for episode in episodes:
episode_videos.append(episode)
return True, episode_videos

View File

@@ -122,17 +122,14 @@ def cleanup_watched(
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]:
# 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
episode_watched_list_2_keys_dict, show_key_dict
)
)
for episode in watched_list_1[user_1][library_1][show_key_1][
season
]:
for episode in watched_list_1[user_1][library_1][show_key_1]:
episode_index = get_episode_index_in_dict(
episode, filtered_episode_watched_list_2_keys_dict
)
@@ -145,30 +142,7 @@ def cleanup_watched(
):
modified_watched_list_1[user_1][library_1][
show_key_1
][season].remove(episode)
# Remove empty seasons
if (
len(
modified_watched_list_1[user_1][library_1][show_key_1][
season
]
)
== 0
):
if (
season
in modified_watched_list_1[user_1][library_1][
show_key_1
]
):
logger(
f"Removing {season} from {show_key_dict['title']} because it is empty",
3,
)
del modified_watched_list_1[user_1][library_1][
show_key_1
][season]
].remove(episode)
# Remove empty shows
if len(modified_watched_list_1[user_1][library_1][show_key_1]) == 0:
@@ -231,27 +205,18 @@ def get_movie_index_in_dict(movie, movies_watched_list_2_keys_dict):
def filter_episode_watched_list_2_keys_dict(
episode_watched_list_2_keys_dict, show_key_dict, season
episode_watched_list_2_keys_dict, show_key_dict
):
# If the episode_watched_list_2_keys_dict dictionary is empty, missing season or show then return an empty dictionary
# If the episode_watched_list_2_keys_dict dictionary is empty, missing show then return an empty dictionary
if (
len(episode_watched_list_2_keys_dict) == 0
or "season" not in episode_watched_list_2_keys_dict.keys()
or "show" not in episode_watched_list_2_keys_dict.keys()
):
return {}
# Filter the episode_watched_list_2_keys_dict dictionary to only include values for the correct show and season
# Filter the episode_watched_list_2_keys_dict dictionary to only include values for the correct show
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.get("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"]):
@@ -273,14 +238,14 @@ def filter_episode_watched_list_2_keys_dict(
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))
# lists
indecies = list(set(show_indecies))
# If there are no indecies that match the show and season, return an empty dictionary
# If there are no indecies that match the show, return an empty dictionary
if len(indecies) == 0:
return {}
# Create a copy of the dictionary with indecies that match the show and season and none that don't
# Create a copy of the dictionary with indecies that match the show and none that don't
for key, value in episode_watched_list_2_keys_dict.items():
if key not in filtered_episode_watched_list_2_keys_dict:
filtered_episode_watched_list_2_keys_dict[key] = []

View File

@@ -42,8 +42,7 @@ show_list = {
("tvdb", "392256"),
("title", "The Last of Us"),
}
): {
"Season 1": [
): [
{
"imdb": "tt11957006",
"tmdb": "2181581",
@@ -56,7 +55,6 @@ show_list = {
"status": {"completed": True, "time": 0},
}
]
}
}
movie_list = [
{
@@ -83,7 +81,6 @@ episode_titles = {
"tvdb": ["8444132"],
"completed": [True],
"time": [0],
"season": ["Season 1"],
"show": [
{
"imdb": "tt3581920",

View File

@@ -24,8 +24,7 @@ tv_shows_watched_list_1 = {
("tvdb", "78804"),
("title", "Doctor Who (2005)"),
}
): {
1: [
): [
{
"imdb": "tt0563001",
"tmdb": "968589",
@@ -50,8 +49,7 @@ tv_shows_watched_list_1 = {
"locations": ("S01E05.mkv",),
"status": {"completed": True, "time": 0},
},
]
},
],
frozenset(
{
("title", "Monarch: Legacy of Monsters"),
@@ -63,8 +61,7 @@ tv_shows_watched_list_1 = {
("Monarch - Legacy of Monsters {tvdb-422598} {imdb-tt17220216}",),
),
}
): {
1: [
): [
{
"imdb": "tt21255044",
"tmdb": "4661246",
@@ -89,8 +86,7 @@ tv_shows_watched_list_1 = {
"locations": ("S01E05.mkv",),
"status": {"completed": True, "time": 0},
},
]
},
],
frozenset(
{
("tmdb", "125928"),
@@ -102,8 +98,7 @@ tv_shows_watched_list_1 = {
),
("title", "My Adventures with Superman"),
}
): {
1: [
): [
{
"imdb": "tt15699926",
"tmdb": "3070048",
@@ -128,8 +123,7 @@ tv_shows_watched_list_1 = {
"locations": ("S01E03.mkv",),
"status": {"completed": True, "time": 0},
},
]
},
],
}
@@ -143,8 +137,7 @@ tv_shows_watched_list_2 = {
("tvdb", "78804"),
("tvrage", "3332"),
}
): {
1: [
): [
{
"tvdb": "295294",
"imdb": "tt0562992",
@@ -166,8 +159,7 @@ tv_shows_watched_list_2 = {
"locations": ("S01E05.mkv",),
"status": {"completed": True, "time": 0},
},
]
},
],
frozenset(
{
("title", "Monarch: Legacy of Monsters"),
@@ -179,8 +171,7 @@ tv_shows_watched_list_2 = {
("Monarch - Legacy of Monsters {tvdb-422598} {imdb-tt17220216}",),
),
}
): {
1: [
): [
{
"tvdb": "9959300",
"imdb": "tt20412166",
@@ -202,8 +193,7 @@ tv_shows_watched_list_2 = {
"locations": ("S01E05.mkv",),
"status": {"completed": True, "time": 0},
},
]
},
],
frozenset(
{
("tmdb", "125928"),
@@ -215,8 +205,7 @@ tv_shows_watched_list_2 = {
),
("title", "My Adventures with Superman"),
}
): {
1: [
): [
{
"tvdb": "8438181",
"imdb": "tt15699926",
@@ -238,8 +227,7 @@ tv_shows_watched_list_2 = {
"locations": ("S01E03.mkv",),
"status": {"completed": True, "time": 0},
},
]
},
],
}
expected_tv_show_watched_list_1 = {
@@ -251,8 +239,7 @@ expected_tv_show_watched_list_1 = {
("tvdb", "78804"),
("title", "Doctor Who (2005)"),
}
): {
1: [
): [
{
"imdb": "tt0563001",
"tmdb": "968589",
@@ -269,8 +256,7 @@ expected_tv_show_watched_list_1 = {
"locations": ("S01E04.mkv",),
"status": {"completed": False, "time": 240000},
},
]
},
],
frozenset(
{
("title", "Monarch: Legacy of Monsters"),
@@ -282,8 +268,7 @@ expected_tv_show_watched_list_1 = {
("Monarch - Legacy of Monsters {tvdb-422598} {imdb-tt17220216}",),
),
}
): {
1: [
): [
{
"imdb": "tt21255044",
"tmdb": "4661246",
@@ -300,8 +285,7 @@ expected_tv_show_watched_list_1 = {
"locations": ("S01E04.mkv",),
"status": {"completed": False, "time": 240000},
},
]
},
],
}
expected_tv_show_watched_list_2 = {
@@ -314,8 +298,7 @@ expected_tv_show_watched_list_2 = {
("tvdb", "78804"),
("tvrage", "3332"),
}
): {
1: [
): [
{
"tvdb": "295294",
"imdb": "tt0562992",
@@ -330,8 +313,7 @@ expected_tv_show_watched_list_2 = {
"locations": ("S01E02.mkv",),
"status": {"completed": False, "time": 300670},
},
]
},
],
frozenset(
{
("title", "Monarch: Legacy of Monsters"),
@@ -343,8 +325,7 @@ expected_tv_show_watched_list_2 = {
("Monarch - Legacy of Monsters {tvdb-422598} {imdb-tt17220216}",),
),
}
): {
1: [
): [
{
"tvdb": "9959300",
"imdb": "tt20412166",
@@ -359,8 +340,7 @@ expected_tv_show_watched_list_2 = {
"locations": ("S01E02.mkv",),
"status": {"completed": False, "time": 300741},
},
]
},
],
}
movies_watched_list_1 = [
@@ -463,20 +443,16 @@ tv_shows_2_watched_list_1 = {
("locations", ("Criminal Minds",)),
("tmdb", "4057"),
}
): {
"Season 1": [
): [
{
"imdb": "tt0550489",
"tmdb": "282843",
"tvdb": "176357",
"title": "Extreme Aggressor",
"locations": (
"Criminal Minds S01E01 Extreme Aggressor WEBDL-720p.mkv",
),
"locations": ("Criminal Minds S01E01 Extreme Aggressor WEBDL-720p.mkv",),
"status": {"completed": True, "time": 0},
},
]
}
}
@@ -610,8 +586,7 @@ def test_combine_watched_dicts():
("locations", ("11.22.63",)),
("imdb", "tt2879552"),
}
): {
"Season 1": [
): [
{
"imdb": "tt4460418",
"title": "The Rabbit Hole",
@@ -623,7 +598,6 @@ def test_combine_watched_dicts():
]
}
}
}
},
{"test3": {"Subbed Anime": {}}},
]
@@ -664,8 +638,7 @@ def test_combine_watched_dicts():
("locations", ("11.22.63",)),
("imdb", "tt2879552"),
}
): {
"Season 1": [
): [
{
"imdb": "tt4460418",
"title": "The Rabbit Hole",
@@ -675,7 +648,6 @@ def test_combine_watched_dicts():
"status": {"completed": True, "time": 0},
}
]
}
},
"Subbed Anime": {},
}