From 768103f113519c839d1efea8c5fe41e2ec0dced8 Mon Sep 17 00:00:00 2001 From: Luigi311 Date: Mon, 23 May 2022 02:01:28 -0600 Subject: [PATCH 1/5] Add KeyboardInterrupt handling --- main.py | 5 ++++- src/jellyfin.py | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/main.py b/main.py index 4ed4e90..f4d0c35 100644 --- a/main.py +++ b/main.py @@ -204,5 +204,8 @@ if __name__ == "__main__": logger(traceback.format_exc(), 2) logger("Retrying in {sleep_timer}", log_type=0) - + except KeyboardInterrupt: + logger("Exiting", log_type=0) + os._exit(0) + sleep(sleep_timer) \ No newline at end of file diff --git a/src/jellyfin.py b/src/jellyfin.py index 8ea012d..837ddae 100644 --- a/src/jellyfin.py +++ b/src/jellyfin.py @@ -150,6 +150,7 @@ class Jellyfin(): if jellyfin_library["Name"] == library: library_id = jellyfin_library["Id"] break + if library_id: library_search = self.query(f"/Users/{user_id}/Items?SortBy=SortName&SortOrder=Ascending&Recursive=true&ParentId={library_id}&limit=1", "get") library_type = library_search["Items"][0]["Type"] From 8d39bd6d33370adf815535acf362890cb96054b0 Mon Sep 17 00:00:00 2001 From: Luigi311 Date: Mon, 23 May 2022 04:18:02 -0600 Subject: [PATCH 2/5] Support user mapping --- .env.sample | 1 + main.py | 204 +++++++++++++++++++++++++++++------------------ src/functions.py | 9 +++ src/jellyfin.py | 21 +++-- src/plex.py | 16 +++- 5 files changed, 168 insertions(+), 83 deletions(-) diff --git a/.env.sample b/.env.sample index 9d88ece..e8d7094 100644 --- a/.env.sample +++ b/.env.sample @@ -1,6 +1,7 @@ DRYRUN = "True" SLEEP_DURATION = "3600" LOGFILE = "log.log" +#USER_MAPPING = { "test2": "test" } PLEX_BASEURL = "http://localhost:32400" PLEX_TOKEN = "SuperSecretToken" diff --git a/main.py b/main.py index f4d0c35..5eef55e 100644 --- a/main.py +++ b/main.py @@ -1,78 +1,78 @@ -import copy, os, traceback +import copy, os, traceback, json from dotenv import load_dotenv from time import sleep -from src.functions import logger, str_to_bool +from src.functions import logger, str_to_bool, search_mapping from src.plex import Plex from src.jellyfin import Jellyfin load_dotenv(override=True) -def cleanup_watched(watched_list_1, watched_list_2): +def cleanup_watched(watched_list_1, watched_list_2, user_mapping): modified_watched_list_1 = copy.deepcopy(watched_list_1) # remove entries from plex_watched that are in jellyfin_watched - for user in watched_list_1: - if user in modified_watched_list_1: - for library in watched_list_1[user]: - if library in modified_watched_list_1[user]: - for item in watched_list_1[user][library]: - if item in modified_watched_list_1[user][library]: - if user in watched_list_2 and library in watched_list_2[user]: - # Movies - if isinstance(watched_list_1[user][library], list): - for watch_list_1_key, watch_list_1_value in item.items(): - for watch_list_2_item in watched_list_2[user][library]: - 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][library]: - modified_watched_list_1[user][library].remove(item) - - # TV Shows - elif isinstance(watched_list_1[user][library], dict): - if item in watched_list_2[user][library]: - for season in watched_list_1[user][library][item]: - if season in watched_list_2[user][library][item]: - for episode in watched_list_1[user][library][item][season]: - for watch_list_1_episode_key, watch_list_1_episode_value in episode.items(): - for watch_list_2_episode in watched_list_2[user][library][item][season]: - for watch_list_2_episode_key, watch_list_2_episode_value in watch_list_2_episode.items(): - if watch_list_1_episode_key == watch_list_2_episode_key and watch_list_1_episode_value == watch_list_2_episode_value: - if episode in modified_watched_list_1[user][library][item][season]: - modified_watched_list_1[user][library][item][season].remove(episode) - - # If season is empty, remove season - if len(modified_watched_list_1[user][library][item][season]) == 0: - if season in modified_watched_list_1[user][library][item]: - del modified_watched_list_1[user][library][item][season] + for user_1 in watched_list_1: + user_2 = search_mapping(user_mapping, user_1) + if user_1 in modified_watched_list_1: + for library in watched_list_1[user_1]: + if library in modified_watched_list_1[user_1]: + for item in watched_list_1[user_1][library]: + if item in modified_watched_list_1[user_1][library]: + if user_1 in watched_list_2: + user = user_1 + elif user_2 in watched_list_2: + user = user_2 + else: + print(f"User {user_1} and {user_2} not found in watched list 2") + user = None + + if user: + if library in watched_list_2[user]: + # Movies + if isinstance(watched_list_1[user_1][library], list): + for watch_list_1_key, watch_list_1_value in item.items(): + for watch_list_2_item in watched_list_2[user][library]: + 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]: + modified_watched_list_1[user_1][library].remove(item) + + # TV Shows + elif isinstance(watched_list_1[user_1][library], dict): + if item in watched_list_2[user][library]: + for season in watched_list_1[user_1][library][item]: + if season in watched_list_2[user][library][item]: + for episode in watched_list_1[user_1][library][item][season]: + for watch_list_1_episode_key, watch_list_1_episode_value in episode.items(): + for watch_list_2_episode in watched_list_2[user][library][item][season]: + for watch_list_2_episode_key, watch_list_2_episode_value in watch_list_2_episode.items(): + if watch_list_1_episode_key == watch_list_2_episode_key and watch_list_1_episode_value == watch_list_2_episode_value: + if episode in modified_watched_list_1[user_1][library][item][season]: + modified_watched_list_1[user_1][library][item][season].remove(episode) + + # If season is empty, remove season + if len(modified_watched_list_1[user_1][library][item][season]) == 0: + if season in modified_watched_list_1[user_1][library][item]: + del modified_watched_list_1[user_1][library][item][season] - # If the show is empty, remove the show - if len(modified_watched_list_1[user][library][item]) == 0: - if item in modified_watched_list_1[user][library]: - del modified_watched_list_1[user][library][item] + # If the show is empty, remove the show + if len(modified_watched_list_1[user_1][library][item]) == 0: + if item in modified_watched_list_1[user_1][library]: + del modified_watched_list_1[user_1][library][item] # If library is empty then remove it - if len(modified_watched_list_1[user][library]) == 0: - if library in modified_watched_list_1[user]: - del modified_watched_list_1[user][library] + if len(modified_watched_list_1[user_1][library]) == 0: + if library in modified_watched_list_1[user_1]: + del modified_watched_list_1[user_1][library] # If user is empty delete user - if len(modified_watched_list_1[user]) == 0: - del modified_watched_list_1[user] + if len(modified_watched_list_1[user_1]) == 0: + del modified_watched_list_1[user_1] return modified_watched_list_1 -def main(): - logfile = os.getenv("LOGFILE","log.log") - # Delete logfile if it exists - if os.path.exists(logfile): - os.remove(logfile) - - dryrun = str_to_bool(os.getenv("DRYRUN", "False")) - logger(f"Dryrun: {dryrun}", 1) - plex = Plex() - jellyfin = Jellyfin() - +def setup_black_white_lists(): blacklist_library = os.getenv("BLACKLIST_LIBRARY") if blacklist_library: if len(blacklist_library) > 0: @@ -130,43 +130,95 @@ def main(): whitelist_users = [] logger(f"Whitelist Users: {whitelist_users}", 1) + return blacklist_library, whitelist_library, blacklist_library_type, whitelist_library_type, blacklist_users, whitelist_users + +def setup_users(plex, jellyfin, blacklist_users, whitelist_users, user_mapping=None): + # generate list of users from plex.users plex_users = [ x.title.lower() for x in plex.users ] jellyfin_users = [ key.lower() for key in jellyfin.users.keys() ] # combined list of overlapping users from plex and jellyfin - users = [x for x in plex_users if x in jellyfin_users] + users = {} + + for plex_user in plex_users: + if user_mapping: + jellyfin_plex_mapped_user = search_mapping(user_mapping, plex_user) + if jellyfin_plex_mapped_user: + users[plex_user] = jellyfin_plex_mapped_user + break + + if plex_user in jellyfin_users: + users[plex_user] = plex_user + + for jellyfin_user in jellyfin_users: + if user_mapping: + plex_jellyfin_mapped_user = search_mapping(user_mapping, jellyfin_user) + if plex_jellyfin_mapped_user: + users[plex_jellyfin_mapped_user] = jellyfin_user + break + + if jellyfin_user in plex_users: + users[jellyfin_user] = jellyfin_user + logger(f"User list that exist on both servers {users}", 1) - users_filtered = [] + users_filtered = {} for user in users: # whitelist_user is not empty and user lowercase is not in whitelist lowercase - if len(whitelist_users) > 0 and user.lower() not in whitelist_users: - logger(f"{user} is not in whitelist", 1) - else: - if user.lower() not in blacklist_users: - users_filtered.append(user) + if len(whitelist_users) > 0: + if user not in whitelist_users and users[user] not in whitelist_users: + logger(f"{user} or {users[user]} is not in whitelist", 1) + break + + if user not in blacklist_users and users[user] not in blacklist_users: + users_filtered[user] = users[user] + logger(f"Filtered user list {users_filtered}", 1) + plex_users = [] for plex_user in plex.users: - if plex_user.title.lower() in users_filtered: + if plex_user.title.lower() in users_filtered.keys() or plex_user.title.lower() in users_filtered.values(): plex_users.append(plex_user) jellyfin_users = {} for jellyfin_user, jellyfin_id in jellyfin.users.items(): - if jellyfin_user.lower() in users_filtered: + if jellyfin_user.lower() in users_filtered.keys() or jellyfin_user.lower() in users_filtered.values(): jellyfin_users[jellyfin_user] = jellyfin_id + if len(plex_users) == 0: + raise Exception("No plex users found") + + if len(jellyfin_users) == 0: + raise Exception("No jellyfin users found") + logger(f"plex_users: {plex_users}", 1) logger(f"jellyfin_users: {jellyfin_users}", 1) - if len(plex_users) == 0: - logger("No users found", 2) - raise Exception("No users found") + return plex_users, jellyfin_users - if len(jellyfin_users) == 0: - logger("No users found", 2) - raise Exception("No users found") +def main(): + logfile = os.getenv("LOGFILE","log.log") + # Delete logfile if it exists + if os.path.exists(logfile): + os.remove(logfile) + + dryrun = str_to_bool(os.getenv("DRYRUN", "False")) + logger(f"Dryrun: {dryrun}", 1) + + user_mapping = os.getenv("USER_MAPPING") + if user_mapping: + user_mapping = json.loads(user_mapping.lower()) + logger(f"User Mapping: {user_mapping}", 1) + + plex = Plex() + jellyfin = Jellyfin() + + # Create (black/white)lists + blacklist_library, whitelist_library, blacklist_library_type, whitelist_library_type, blacklist_users, whitelist_users = setup_black_white_lists() + + # Create users list + plex_users, jellyfin_users = setup_users(plex, jellyfin, blacklist_users, whitelist_users, user_mapping) plex_watched = plex.get_plex_watched(plex_users, blacklist_library, whitelist_library, blacklist_library_type, whitelist_library_type) jellyfin_watched = jellyfin.get_jellyfin_watched(jellyfin_users, blacklist_library, whitelist_library, blacklist_library_type, whitelist_library_type) @@ -175,15 +227,15 @@ def main(): plex_watched_filtered = copy.deepcopy(plex_watched) jellyfin_watched_filtered = copy.deepcopy(jellyfin_watched) - plex_watched = cleanup_watched(plex_watched_filtered, jellyfin_watched_filtered) + plex_watched = cleanup_watched(plex_watched_filtered, jellyfin_watched_filtered, user_mapping) logger(f"plex_watched that needs to be synced to jellyfin:\n{plex_watched}", 1) - jellyfin_watched = cleanup_watched(jellyfin_watched_filtered, plex_watched_filtered) + jellyfin_watched = cleanup_watched(jellyfin_watched_filtered, plex_watched_filtered, user_mapping) logger(f"jellyfin_watched that needs to be synced to plex:\n{jellyfin_watched}", 1) # Update watched status - plex.update_watched(jellyfin_watched, dryrun) - jellyfin.update_watched(plex_watched, dryrun) + plex.update_watched(jellyfin_watched, user_mapping, dryrun) + jellyfin.update_watched(plex_watched, user_mapping, dryrun) if __name__ == "__main__": @@ -202,7 +254,7 @@ if __name__ == "__main__": logger(traceback.format_exc(), 2) - logger("Retrying in {sleep_timer}", log_type=0) + logger(f"Retrying in {sleep_timer}", log_type=0) except KeyboardInterrupt: logger("Exiting", log_type=0) diff --git a/src/functions.py b/src/functions.py index b5ce86d..90333ac 100644 --- a/src/functions.py +++ b/src/functions.py @@ -27,3 +27,12 @@ def str_to_bool(value: any) -> bool: if not value: return False return str(value).lower() in ("y", "yes", "t", "true", "on", "1") + +# Get mapped value +def search_mapping(dictionary: dict, key_value: str): + if key_value in dictionary.keys(): + return dictionary[key_value] + elif key_value in dictionary.values(): + return list(dictionary.keys())[list(dictionary.values()).index(key_value)] + else: + return None diff --git a/src/jellyfin.py b/src/jellyfin.py index 837ddae..85ed3e8 100644 --- a/src/jellyfin.py +++ b/src/jellyfin.py @@ -1,6 +1,6 @@ import requests, os from dotenv import load_dotenv -from src.functions import logger +from src.functions import logger, search_mapping load_dotenv(override=True) @@ -67,14 +67,15 @@ class Jellyfin(): for library in libraries: library_title = library["Name"] - logger(f"Jellyfin: Generating watched for {user_name} in library {library_title}", 0) library_id = library["Id"] # if whitelist is not empty and library is not in whitelist - if len(whitelist_library) > 0 and library_title.lower() not in [x.lower() for x in whitelist_library]: + if len(whitelist_library) > 0 and library_title.lower() not in whitelist_library: pass else: - if library_title.lower() not in [x.lower() for x in blacklist_library]: + logger(f"Jellyfin: Generating watched for {user_name} in library {library_title}", 0) + + if library_title.lower() not in blacklist_library: watched = self.query(f"/Users/{user_id}/Items?SortBy=SortName&SortOrder=Ascending&Recursive=true&ParentId={library_id}&Filters=IsPlayed&limit=1", "get") if len(watched["Items"]) == 0: @@ -129,8 +130,18 @@ class Jellyfin(): return users_watched - def update_watched(self, watched_list, dryrun=False): + def update_watched(self, watched_list, user_mapping, dryrun=False): for user, libraries in watched_list.items(): + other = None + if user in user_mapping.keys(): + other = user_mapping[user] + + elif user in user_mapping.values(): + other = search_mapping(user_mapping, user) + + if other: + logger(f"Swapping user {user} with {other}", 1) + user = other user_id = None for key, value in self.users.items(): diff --git a/src/plex.py b/src/plex.py index 3c6213c..82987ea 100644 --- a/src/plex.py +++ b/src/plex.py @@ -1,7 +1,7 @@ import re, os from dotenv import load_dotenv -from src.functions import logger +from src.functions import logger, search_mapping from plexapi.server import PlexServer from plexapi.myplex import MyPlexAccount @@ -119,13 +119,25 @@ class Plex: return users_watched - def update_watched(self, watched_list, dryrun=False): + def update_watched(self, watched_list, user_mapping, dryrun=False): for user, libraries in watched_list.items(): + other = None + if user in user_mapping.keys(): + other = user_mapping[user] + + elif user in user_mapping.values(): + other = search_mapping(user_mapping, user) + + if other: + logger(f"Swapping user {user} with {other}", 1) + user = other + for index, value in enumerate(self.users): if user.lower() == value.title.lower(): user = self.users[index] break + print(user) if self.admin_user == user: user_plex = self.plex else: From 26a9c85d3b1e85151b0d7322b2f09988daa4a4dc Mon Sep 17 00:00:00 2001 From: Luigi311 Date: Mon, 23 May 2022 04:33:55 -0600 Subject: [PATCH 3/5] Cleanup. Add debug variable --- .env.sample | 1 + main.py | 3 +-- src/functions.py | 5 +++-- src/jellyfin.py | 23 ++++++++++++----------- src/plex.py | 24 ++++++++++++------------ 5 files changed, 29 insertions(+), 27 deletions(-) diff --git a/.env.sample b/.env.sample index e8d7094..2519263 100644 --- a/.env.sample +++ b/.env.sample @@ -1,4 +1,5 @@ DRYRUN = "True" +DEBUG = "True" SLEEP_DURATION = "3600" LOGFILE = "log.log" #USER_MAPPING = { "test2": "test" } diff --git a/main.py b/main.py index 5eef55e..0fa4925 100644 --- a/main.py +++ b/main.py @@ -24,7 +24,7 @@ def cleanup_watched(watched_list_1, watched_list_2, user_mapping): elif user_2 in watched_list_2: user = user_2 else: - print(f"User {user_1} and {user_2} not found in watched list 2") + logger(f"User {user_1} and {user_2} not found in watched list 2", 1) user = None if user: @@ -119,7 +119,6 @@ def setup_black_white_lists(): logger(f"Blacklist Users: {blacklist_users}", 1) whitelist_users = os.getenv("WHITELIST_USERS") - # print whitelist_users object type if whitelist_users: if len(whitelist_users) > 0: whitelist_users = whitelist_users.split(",") diff --git a/src/functions.py b/src/functions.py index 90333ac..3a61ae4 100644 --- a/src/functions.py +++ b/src/functions.py @@ -5,11 +5,12 @@ load_dotenv(override=True) logfile = os.getenv("LOGFILE","log.log") def logger(message, log_type=0): - + debug = str_to_bool(os.getenv("DEBUG", "True")) + output = str(message) if log_type == 0: pass - elif log_type == 1: + elif log_type == 1 and debug: output = f"[INFO]: {output}" elif log_type == 2: output = f"[ERROR]: {output}" diff --git a/src/jellyfin.py b/src/jellyfin.py index 85ed3e8..d502014 100644 --- a/src/jellyfin.py +++ b/src/jellyfin.py @@ -130,18 +130,19 @@ class Jellyfin(): return users_watched - def update_watched(self, watched_list, user_mapping, dryrun=False): + def update_watched(self, watched_list, user_mapping=None, dryrun=False): for user, libraries in watched_list.items(): - other = None - if user in user_mapping.keys(): - other = user_mapping[user] + if user_mapping: + other = None + + if user in user_mapping.keys(): + other = user_mapping[user] + elif user in user_mapping.values(): + other = search_mapping(user_mapping, user) - elif user in user_mapping.values(): - other = search_mapping(user_mapping, user) - - if other: - logger(f"Swapping user {user} with {other}", 1) - user = other + if other: + logger(f"Swapping user {user} with {other}", 1) + user = other user_id = None for key, value in self.users.items(): @@ -175,7 +176,7 @@ class Jellyfin(): for video in videos: for key, value in jellyfin_video["ProviderIds"].items(): if key.lower() in video.keys() and value.lower() == video[key.lower()].lower(): - msg = f"{jellyfin_video['Name']} as watched for {user}" + msg = f"{jellyfin_video['Name']} as watched for {user} in Jellyfin" if not dryrun: logger(f"Marking {msg}", 0) self.query(f"/Users/{user_id}/PlayedItems/{jellyfin_video_id}", "post") diff --git a/src/plex.py b/src/plex.py index 82987ea..8460826 100644 --- a/src/plex.py +++ b/src/plex.py @@ -119,25 +119,25 @@ class Plex: return users_watched - def update_watched(self, watched_list, user_mapping, dryrun=False): + def update_watched(self, watched_list, user_mapping=None, dryrun=False): for user, libraries in watched_list.items(): - other = None - if user in user_mapping.keys(): - other = user_mapping[user] + if user_mapping: + other = None + + if user in user_mapping.keys(): + other = user_mapping[user] + elif user in user_mapping.values(): + other = search_mapping(user_mapping, user) - elif user in user_mapping.values(): - other = search_mapping(user_mapping, user) - - if other: - logger(f"Swapping user {user} with {other}", 1) - user = other + if other: + logger(f"Swapping user {user} with {other}", 1) + user = other for index, value in enumerate(self.users): if user.lower() == value.title.lower(): user = self.users[index] break - print(user) if self.admin_user == user: user_plex = self.plex else: @@ -156,7 +156,7 @@ class Plex: for video_keys, video_id in video.items(): if video_keys == guid_source and video_id == guid_id: if movies_search.viewCount == 0: - msg = f"{movies_search.title} watched" + msg = f"{movies_search.title} as watched for {user.title} in Plex" if not dryrun: logger(f"Marked {msg}", 0) movies_search.markWatched() From e56b5445934fc987d9142078f9fd8aa0f8051e43 Mon Sep 17 00:00:00 2001 From: Luigi311 Date: Mon, 23 May 2022 14:00:51 -0600 Subject: [PATCH 4/5] Add library mapping --- .env.sample | 3 +- main.py | 166 +++++++++++++++++++++++++++------------------ src/jellyfin.py | 177 +++++++++++++++++++++++++++++------------------- src/plex.py | 102 ++++++++++++++++++++-------- 4 files changed, 284 insertions(+), 164 deletions(-) diff --git a/.env.sample b/.env.sample index 2519263..5a725fc 100644 --- a/.env.sample +++ b/.env.sample @@ -2,7 +2,8 @@ DRYRUN = "True" DEBUG = "True" SLEEP_DURATION = "3600" LOGFILE = "log.log" -#USER_MAPPING = { "test2": "test" } +#USER_MAPPING = { "testuser2": "testuser3" } +#LIBRARY_MAPPING = { "Shows": "TV Shows" } PLEX_BASEURL = "http://localhost:32400" PLEX_TOKEN = "SuperSecretToken" diff --git a/main.py b/main.py index 0fa4925..5d47dc8 100644 --- a/main.py +++ b/main.py @@ -8,63 +8,73 @@ from src.jellyfin import Jellyfin load_dotenv(override=True) -def cleanup_watched(watched_list_1, watched_list_2, user_mapping): +def cleanup_watched(watched_list_1, watched_list_2, user_mapping=None, library_mapping=None): modified_watched_list_1 = copy.deepcopy(watched_list_1) # remove entries from plex_watched that are in jellyfin_watched for user_1 in watched_list_1: - user_2 = search_mapping(user_mapping, user_1) + user_other = None + if user_mapping: + user_other = search_mapping(user_mapping, user_1) if user_1 in modified_watched_list_1: - for library in watched_list_1[user_1]: - if library in modified_watched_list_1[user_1]: - for item in watched_list_1[user_1][library]: - if item in modified_watched_list_1[user_1][library]: - if user_1 in watched_list_2: - user = user_1 - elif user_2 in watched_list_2: - user = user_2 - else: - logger(f"User {user_1} and {user_2} not found in watched list 2", 1) - user = None - - if user: - if library in watched_list_2[user]: - # Movies - if isinstance(watched_list_1[user_1][library], list): - for watch_list_1_key, watch_list_1_value in item.items(): - for watch_list_2_item in watched_list_2[user][library]: - 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]: - modified_watched_list_1[user_1][library].remove(item) - - # TV Shows - elif isinstance(watched_list_1[user_1][library], dict): - if item in watched_list_2[user][library]: - for season in watched_list_1[user_1][library][item]: - if season in watched_list_2[user][library][item]: - for episode in watched_list_1[user_1][library][item][season]: - for watch_list_1_episode_key, watch_list_1_episode_value in episode.items(): - for watch_list_2_episode in watched_list_2[user][library][item][season]: - for watch_list_2_episode_key, watch_list_2_episode_value in watch_list_2_episode.items(): - if watch_list_1_episode_key == watch_list_2_episode_key and watch_list_1_episode_value == watch_list_2_episode_value: - if episode in modified_watched_list_1[user_1][library][item][season]: - modified_watched_list_1[user_1][library][item][season].remove(episode) - - # If season is empty, remove season - if len(modified_watched_list_1[user_1][library][item][season]) == 0: - if season in modified_watched_list_1[user_1][library][item]: - del modified_watched_list_1[user_1][library][item][season] + if user_1 in watched_list_2: + user_2 = user_1 + elif user_other in watched_list_2: + user_2 = user_other + else: + logger(f"User {user_1} and {user_other} not found in watched list 2", 1) + continue - # If the show is empty, remove the show - if len(modified_watched_list_1[user_1][library][item]) == 0: - if item in modified_watched_list_1[user_1][library]: - del modified_watched_list_1[user_1][library][item] + for library_1 in watched_list_1[user_1]: + library_other = None + if library_mapping: + library_other = search_mapping(library_mapping, library_1) + if library_1 in modified_watched_list_1[user_1]: + if library_1 in watched_list_2[user_2]: + library_2 = library_1 + elif library_other in watched_list_2[user_2]: + library_2 = library_other + else: + logger(f"User {library_1} and {library_other} not found in watched list 2", 1) + continue + for item in watched_list_1[user_1][library_1]: + if item in modified_watched_list_1[user_1][library_1]: + # Movies + if isinstance(watched_list_1[user_1][library_1], list): + 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]: + modified_watched_list_1[user_1][library_1].remove(item) + + # TV Shows + elif isinstance(watched_list_1[user_1][library_1], dict): + if item in watched_list_2[user_2][library_2]: + for season in watched_list_1[user_1][library_1][item]: + if season in watched_list_2[user_2][library_2][item]: + for episode in watched_list_1[user_1][library_1][item][season]: + for watch_list_1_episode_key, watch_list_1_episode_value in episode.items(): + for watch_list_2_episode in watched_list_2[user_2][library_2][item][season]: + for watch_list_2_episode_key, watch_list_2_episode_value in watch_list_2_episode.items(): + if watch_list_1_episode_key == watch_list_2_episode_key and watch_list_1_episode_value == watch_list_2_episode_value: + if episode in modified_watched_list_1[user_1][library_1][item][season]: + modified_watched_list_1[user_1][library_1][item][season].remove(episode) + + # If season is empty, remove season + if len(modified_watched_list_1[user_1][library_1][item][season]) == 0: + if season in modified_watched_list_1[user_1][library_1][item]: + del modified_watched_list_1[user_1][library_1][item][season] + + # If the show is empty, remove the show + if len(modified_watched_list_1[user_1][library_1][item]) == 0: + if item in modified_watched_list_1[user_1][library_1]: + del modified_watched_list_1[user_1][library_1][item] # If library is empty then remove it - if len(modified_watched_list_1[user_1][library]) == 0: - if library in modified_watched_list_1[user_1]: - del modified_watched_list_1[user_1][library] + if len(modified_watched_list_1[user_1][library_1]) == 0: + if library_1 in modified_watched_list_1[user_1]: + del modified_watched_list_1[user_1][library_1] # If user is empty delete user if len(modified_watched_list_1[user_1]) == 0: @@ -72,21 +82,38 @@ def cleanup_watched(watched_list_1, watched_list_2, user_mapping): return modified_watched_list_1 -def setup_black_white_lists(): +def setup_black_white_lists(library_mapping=None): blacklist_library = os.getenv("BLACKLIST_LIBRARY") if blacklist_library: if len(blacklist_library) > 0: blacklist_library = blacklist_library.split(",") - blacklist_library = [x.lower().trim() for x in blacklist_library] + blacklist_library = [x.strip() for x in blacklist_library] + if library_mapping: + temp_library = [] + for library in blacklist_library: + library_other = search_mapping(library_mapping, library) + if library_other: + temp_library.append(library_other) + + blacklist_library = blacklist_library + temp_library else: blacklist_library = [] + logger(f"Blacklist Library: {blacklist_library}", 1) whitelist_library = os.getenv("WHITELIST_LIBRARY") if whitelist_library: if len(whitelist_library) > 0: whitelist_library = whitelist_library.split(",") - whitelist_library = [x.lower().strip() for x in whitelist_library] + whitelist_library = [x.strip() for x in whitelist_library] + if library_mapping: + temp_library = [] + for library in whitelist_library: + library_other = search_mapping(library_mapping, library) + if library_other: + temp_library.append(library_other) + + whitelist_library = whitelist_library + temp_library else: whitelist_library = [] logger(f"Whitelist Library: {whitelist_library}", 1) @@ -113,7 +140,7 @@ def setup_black_white_lists(): if blacklist_users: if len(blacklist_users) > 0: blacklist_users = blacklist_users.split(",") - blacklist_users = [x.lower().strip() for x in blacklist_users] + blacklist_users = [x.lower().strip() for x in blacklist_users] else: blacklist_users = [] logger(f"Blacklist Users: {blacklist_users}", 1) @@ -145,7 +172,7 @@ def setup_users(plex, jellyfin, blacklist_users, whitelist_users, user_mapping=N jellyfin_plex_mapped_user = search_mapping(user_mapping, plex_user) if jellyfin_plex_mapped_user: users[plex_user] = jellyfin_plex_mapped_user - break + continue if plex_user in jellyfin_users: users[plex_user] = plex_user @@ -155,7 +182,7 @@ def setup_users(plex, jellyfin, blacklist_users, whitelist_users, user_mapping=N plex_jellyfin_mapped_user = search_mapping(user_mapping, jellyfin_user) if plex_jellyfin_mapped_user: users[plex_jellyfin_mapped_user] = jellyfin_user - break + continue if jellyfin_user in plex_users: users[jellyfin_user] = jellyfin_user @@ -168,7 +195,7 @@ def setup_users(plex, jellyfin, blacklist_users, whitelist_users, user_mapping=N if len(whitelist_users) > 0: if user not in whitelist_users and users[user] not in whitelist_users: logger(f"{user} or {users[user]} is not in whitelist", 1) - break + continue if user not in blacklist_users and users[user] not in blacklist_users: users_filtered[user] = users[user] @@ -186,10 +213,10 @@ def setup_users(plex, jellyfin, blacklist_users, whitelist_users, user_mapping=N jellyfin_users[jellyfin_user] = jellyfin_id if len(plex_users) == 0: - raise Exception("No plex users found") + raise Exception(f"No plex users found, users found {users} filtered users {users_filtered}") if len(jellyfin_users) == 0: - raise Exception("No jellyfin users found") + raise Exception(f"No jellyfin users found, users found {users} filtered users {users_filtered}") logger(f"plex_users: {plex_users}", 1) logger(f"jellyfin_users: {jellyfin_users}", 1) @@ -209,32 +236,37 @@ def main(): if user_mapping: user_mapping = json.loads(user_mapping.lower()) logger(f"User Mapping: {user_mapping}", 1) - + + library_mapping = os.getenv("LIBRARY_MAPPING") + if library_mapping: + library_mapping = json.loads(library_mapping) + logger(f"Library Mapping: {library_mapping}", 1) + plex = Plex() jellyfin = Jellyfin() # Create (black/white)lists - blacklist_library, whitelist_library, blacklist_library_type, whitelist_library_type, blacklist_users, whitelist_users = setup_black_white_lists() + blacklist_library, whitelist_library, blacklist_library_type, whitelist_library_type, blacklist_users, whitelist_users = setup_black_white_lists(library_mapping) # Create users list plex_users, jellyfin_users = setup_users(plex, jellyfin, blacklist_users, whitelist_users, user_mapping) - plex_watched = plex.get_plex_watched(plex_users, blacklist_library, whitelist_library, blacklist_library_type, whitelist_library_type) - jellyfin_watched = jellyfin.get_jellyfin_watched(jellyfin_users, blacklist_library, whitelist_library, blacklist_library_type, whitelist_library_type) + plex_watched = plex.get_plex_watched(plex_users, blacklist_library, whitelist_library, blacklist_library_type, whitelist_library_type, library_mapping) + jellyfin_watched = jellyfin.get_jellyfin_watched(jellyfin_users, blacklist_library, whitelist_library, blacklist_library_type, whitelist_library_type, library_mapping) # clone watched so it isnt modified in the cleanup function so all duplicates are actually removed plex_watched_filtered = copy.deepcopy(plex_watched) jellyfin_watched_filtered = copy.deepcopy(jellyfin_watched) - plex_watched = cleanup_watched(plex_watched_filtered, jellyfin_watched_filtered, user_mapping) + plex_watched = cleanup_watched(plex_watched_filtered, jellyfin_watched_filtered, user_mapping, library_mapping) logger(f"plex_watched that needs to be synced to jellyfin:\n{plex_watched}", 1) - jellyfin_watched = cleanup_watched(jellyfin_watched_filtered, plex_watched_filtered, user_mapping) + jellyfin_watched = cleanup_watched(jellyfin_watched_filtered, plex_watched_filtered, user_mapping, library_mapping) logger(f"jellyfin_watched that needs to be synced to plex:\n{jellyfin_watched}", 1) # Update watched status - plex.update_watched(jellyfin_watched, user_mapping, dryrun) - jellyfin.update_watched(plex_watched, user_mapping, dryrun) + plex.update_watched(jellyfin_watched, user_mapping, library_mapping, dryrun) + jellyfin.update_watched(plex_watched, user_mapping, library_mapping, dryrun) if __name__ == "__main__": @@ -259,4 +291,4 @@ if __name__ == "__main__": logger("Exiting", log_type=0) os._exit(0) - sleep(sleep_timer) \ No newline at end of file + sleep(sleep_timer) diff --git a/src/jellyfin.py b/src/jellyfin.py index d502014..4b15fa5 100644 --- a/src/jellyfin.py +++ b/src/jellyfin.py @@ -1,6 +1,6 @@ import requests, os from dotenv import load_dotenv -from src.functions import logger, search_mapping +from src.functions import logger, search_mapping, str_to_bool load_dotenv(override=True) @@ -56,7 +56,7 @@ class Jellyfin(): return users - def get_jellyfin_watched(self, users, blacklist_library, whitelist_library, blacklist_library_type, whitelist_library_type): + def get_jellyfin_watched(self, users, blacklist_library, whitelist_library, blacklist_library_type, whitelist_library_type, library_mapping=None): users_watched = {} for user_name, user_id in users.items(): @@ -67,82 +67,105 @@ class Jellyfin(): for library in libraries: library_title = library["Name"] - library_id = library["Id"] - # if whitelist is not empty and library is not in whitelist - if len(whitelist_library) > 0 and library_title.lower() not in whitelist_library: - pass + watched = self.query(f"/Users/{user_id}/Items?SortBy=SortName&SortOrder=Ascending&Recursive=true&ParentId={library_id}&Filters=IsPlayed&limit=1", "get") + + if len(watched["Items"]) == 0: + logger(f"Jellyfin: No watched items found in library {library_title}", 1) + continue else: - logger(f"Jellyfin: Generating watched for {user_name} in library {library_title}", 0) + library_type = watched["Items"][0]["Type"] - if library_title.lower() not in blacklist_library: - watched = self.query(f"/Users/{user_id}/Items?SortBy=SortName&SortOrder=Ascending&Recursive=true&ParentId={library_id}&Filters=IsPlayed&limit=1", "get") - - if len(watched["Items"]) == 0: - pass - else: - library_type = watched["Items"][0]["Type"] + if library_type.lower() in blacklist_library_type: + logger(f"Jellyfin: Library type {library_type} is blacklist_library_type", 1) + continue - # if Type in blacklist_library_type then break - if library_type in blacklist_library_type or (len(whitelist_library_type) > 0 and library_type.lower() not in whitelist_library_type): - break - - # Movies - if library_type == "Movie": - watched = self.query(f"/Users/{user_id}/Items?SortBy=SortName&SortOrder=Ascending&Recursive=true&ParentId={library_id}&Filters=IsPlayed&Fields=ItemCounts,ProviderIds", "get") - for movie in watched["Items"]: - if movie["UserData"]["Played"] == True: - if movie["ProviderIds"]: - if user_name not in users_watched: - users_watched[user_name] = {} - if library_title not in users_watched[user_name]: - users_watched[user_name][library_title] = [] - # Lowercase movie["ProviderIds"] keys - movie["ProviderIds"] = {k.lower(): v for k, v in movie["ProviderIds"].items()} - users_watched[user_name][library_title].append(movie["ProviderIds"]) + if library_title.lower() in [x.lower() for x in blacklist_library]: + logger(f"Jellyfin: Library {library_title} is blacklist_library", 1) + continue - # TV Shows - if library_type == "Episode": - watched = self.query(f"/Users/{user_id}/Items?SortBy=SortName&SortOrder=Ascending&Recursive=true&ParentId={library_id}", "get") - watched_shows = [x for x in watched["Items"] if x["Type"] == "Series"] + library_other = None + if library_mapping: + library_other = search_mapping(library_mapping, library_title) + if library_other: + library_other.lower() + if library_other not in [x.lower() for x in blacklist_library]: + logger(f"Jellyfin: Library {library_other} is blacklist_library", 1) + continue - for show in watched_shows: - seasons = self.query(f"/Shows/{show['Id']}/Seasons?userId={user_id}&Fields=ItemCounts", "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") - if len(episodes["Items"]) > 0: - for episode in episodes["Items"]: - if episode["UserData"]["Played"] == True: - if episode["ProviderIds"]: - if user_name not in users_watched: - users_watched[user_name] = {} - if library_title not in users_watched[user_name]: - users_watched[user_name][library_title] = {} - if show["Name"] not in users_watched[user_name][library_title]: - users_watched[user_name][library_title][show["Name"]] = {} - if season["Name"] not in users_watched[user_name][library_title][show["Name"]]: - users_watched[user_name][library_title][show["Name"]][season["Name"]] = [] - - # Lowercase episode["ProviderIds"] keys - episode["ProviderIds"] = {k.lower(): v for k, v in episode["ProviderIds"].items()} - users_watched[user_name][library_title][show["Name"]][season["Name"]].append(episode["ProviderIds"]) + if len(whitelist_library_type) > 0: + if library_type.lower() not in whitelist_library_type: + logger(f"Jellyfin: Library type {library_type} is not whitelist_library_type", 1) + continue + + # if whitelist is not empty and library is not in whitelist + if len(whitelist_library) > 0: + if library_title.lower() not in [x.lower() for x in whitelist_library]: + logger(f"Jellyfin: Library {library_title} is not whitelist_library", 1) + continue + + if library_other: + if library_other not in [x.lower() for x in whitelist_library]: + logger(f"Jellyfin: Library {library_other} is not whitelist_library", 1) + continue + + logger(f"Jellyfin: Generating watched for {user_name} in library {library_title}", 0) + # Movies + if library_type == "Movie": + watched = self.query(f"/Users/{user_id}/Items?SortBy=SortName&SortOrder=Ascending&Recursive=true&ParentId={library_id}&Filters=IsPlayed&Fields=ItemCounts,ProviderIds", "get") + for movie in watched["Items"]: + if movie["UserData"]["Played"] == True: + if movie["ProviderIds"]: + if user_name not in users_watched: + users_watched[user_name] = {} + if library_title not in users_watched[user_name]: + users_watched[user_name][library_title] = [] + # Lowercase movie["ProviderIds"] keys + movie["ProviderIds"] = {k.lower(): v for k, v in movie["ProviderIds"].items()} + users_watched[user_name][library_title].append(movie["ProviderIds"]) + + # TV Shows + if library_type == "Episode": + watched = self.query(f"/Users/{user_id}/Items?SortBy=SortName&SortOrder=Ascending&Recursive=true&ParentId={library_id}", "get") + watched_shows = [x for x in watched["Items"] if x["Type"] == "Series"] + + for show in watched_shows: + seasons = self.query(f"/Shows/{show['Id']}/Seasons?userId={user_id}&Fields=ItemCounts", "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") + if len(episodes["Items"]) > 0: + for episode in episodes["Items"]: + if episode["UserData"]["Played"] == True: + if episode["ProviderIds"]: + if user_name not in users_watched: + users_watched[user_name] = {} + if library_title not in users_watched[user_name]: + users_watched[user_name][library_title] = {} + if show["Name"] not in users_watched[user_name][library_title]: + users_watched[user_name][library_title][show["Name"]] = {} + if season["Name"] not in users_watched[user_name][library_title][show["Name"]]: + users_watched[user_name][library_title][show["Name"]][season["Name"]] = [] + + # Lowercase episode["ProviderIds"] keys + episode["ProviderIds"] = {k.lower(): v for k, v in episode["ProviderIds"].items()} + users_watched[user_name][library_title][show["Name"]][season["Name"]].append(episode["ProviderIds"]) return users_watched - def update_watched(self, watched_list, user_mapping=None, dryrun=False): + def update_watched(self, watched_list, user_mapping=None, library_mapping=None, dryrun=False): for user, libraries in watched_list.items(): if user_mapping: - other = None + user_other = None if user in user_mapping.keys(): - other = user_mapping[user] + user_other = user_mapping[user] elif user in user_mapping.values(): - other = search_mapping(user_mapping, user) + user_other = search_mapping(user_mapping, user) - if other: - logger(f"Swapping user {user} with {other}", 1) - user = other + if user_other: + logger(f"Swapping user {user} with {user_other}", 1) + user = user_other user_id = None for key, value in self.users.items(): @@ -157,13 +180,30 @@ class Jellyfin(): jellyfin_libraries = self.query(f"/Users/{user_id}/Views", "get")["Items"] for library, videos in libraries.items(): + if library_mapping: + library_other = None + + if library in library_mapping.keys(): + library_other = library_mapping[library] + elif library in library_mapping.values(): + library_other = search_mapping(library_mapping, library) + + if library_other: + logger(f"Swapping library {library} with {library_other}", 1) + library = library_other + + if library not in [x["Name"] for x in jellyfin_libraries]: + logger(f"{library} not found in Jellyfin", 2) + continue + library_id = None for jellyfin_library in jellyfin_libraries: if jellyfin_library["Name"] == library: library_id = jellyfin_library["Id"] - break + continue if library_id: + logger(f"Jellyfin: Updating watched for {user} in library {library}", 1) library_search = self.query(f"/Users/{user_id}/Items?SortBy=SortName&SortOrder=Ascending&Recursive=true&ParentId={library_id}&limit=1", "get") library_type = library_search["Items"][0]["Type"] @@ -171,12 +211,12 @@ class Jellyfin(): if library_type == "Movie": jellyfin_search = self.query(f"/Users/{user_id}/Items?SortBy=SortName&SortOrder=Ascending&Recursive=true&ParentId={library_id}&isPlayed=false&Fields=ItemCounts,ProviderIds", "get") for jellyfin_video in jellyfin_search["Items"]: - if jellyfin_video["UserData"]["Played"] == False: + if str_to_bool(jellyfin_video["UserData"]["Played"]) == False: jellyfin_video_id = jellyfin_video["Id"] for video in videos: for key, value in jellyfin_video["ProviderIds"].items(): if key.lower() in video.keys() and value.lower() == video[key.lower()].lower(): - msg = f"{jellyfin_video['Name']} as watched for {user} in Jellyfin" + 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") @@ -194,18 +234,17 @@ class Jellyfin(): 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 jellyfin_episode["UserData"]["Played"] == False: + if str_to_bool(jellyfin_episode["UserData"]["Played"]) == False: jellyfin_episode_id = jellyfin_episode["Id"] for show in videos: for season in videos[show]: for episode in videos[show][season]: for key, value in jellyfin_episode["ProviderIds"].items(): if key.lower() in episode.keys() and value.lower() == episode[key.lower()].lower(): - msg = f"{jellyfin_episode['SeriesName']} {jellyfin_episode['SeasonName']} {jellyfin_episode['Name']} as watched for {user} in Jellyfin" + msg = f"{jellyfin_episode['SeriesName']} {jellyfin_episode['SeasonName']} {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 - \ No newline at end of file diff --git a/src/plex.py b/src/plex.py index 8460826..9efb05d 100644 --- a/src/plex.py +++ b/src/plex.py @@ -93,7 +93,7 @@ class Plex: return watched - def get_plex_watched(self, users, blacklist_library, whitelist_library, blacklist_library_type, whitelist_library_type): + def get_plex_watched(self, users, blacklist_library, whitelist_library, blacklist_library_type, whitelist_library_type, library_mapping): # Get all libraries libraries = self.plex.library.sections() users_watched = {} @@ -101,37 +101,67 @@ class Plex: # for not in blacklist for library in libraries: library_title = library.title + library_type = library.type + + if library_type.lower() in blacklist_library_type: + logger(f"Plex: Library type {library_type} is blacklist_library_type", 1) + continue + + if library_title.lower() in [x.lower() for x in blacklist_library]: + logger(f"Plex: Library {library_title} is blacklist_library", 1) + continue + + library_other = None + if library_mapping: + library_other = search_mapping(library_mapping, library_title) + if library_other: + library_other.lower() + if library_other not in [x.lower() for x in blacklist_library]: + logger(f"Plex: Library {library_other} is blacklist_library", 1) + continue + + if len(whitelist_library_type) > 0: + if library_type.lower() not in whitelist_library_type: + logger(f"Plex: Library type {library_type} is not whitelist_library_type", 1) + continue + # if whitelist is not empty and library is not in whitelist - if (len(whitelist_library) > 0 and library_title.lower() not in [x.lower() for x in whitelist_library]) or (len(whitelist_library_type) > 0 and library_title.type() not in [x.lower() for x in whitelist_library_type]): - pass - else: - if library_title.lower() not in [x.lower() for x in blacklist_library] and library.type not in [x.lower() for x in blacklist_library_type]: - for user in users: - logger(f"Plex: Generating watched for {user.title} in library {library_title}", 0) - user_name = user.title.lower() - watched = self.get_plex_user_watched(user, library) - if watched: - if user_name not in users_watched: - users_watched[user_name] = {} - if library_title not in users_watched[user_name]: - users_watched[user_name][library_title] = [] - users_watched[user_name][library_title] = watched + if len(whitelist_library) > 0: + if library_title.lower() not in [x.lower() for x in whitelist_library]: + logger(f"Plex: Library {library_title} is not whitelist_library", 1) + continue + + if library_other: + if library_other not in [x.lower() for x in whitelist_library]: + logger(f"Plex: Library {library_other} is not whitelist_library", 1) + continue + + for user in users: + logger(f"Plex: Generating watched for {user.title} in library {library_title}", 0) + user_name = user.title.lower() + watched = self.get_plex_user_watched(user, library) + if watched: + if user_name not in users_watched: + users_watched[user_name] = {} + if library_title not in users_watched[user_name]: + users_watched[user_name][library_title] = [] + users_watched[user_name][library_title] = watched return users_watched - def update_watched(self, watched_list, user_mapping=None, dryrun=False): + def update_watched(self, watched_list, user_mapping=None, library_mapping=None, dryrun=False): for user, libraries in watched_list.items(): if user_mapping: - other = None + user_other = None if user in user_mapping.keys(): - other = user_mapping[user] + user_other = user_mapping[user] elif user in user_mapping.values(): - other = search_mapping(user_mapping, user) + user_other = search_mapping(user_mapping, user) - if other: - logger(f"Swapping user {user} with {other}", 1) - user = other + if user_other: + logger(f"Swapping user {user} with {user_other}", 1) + user = user_other for index, value in enumerate(self.users): if user.lower() == value.title.lower(): @@ -143,10 +173,28 @@ class Plex: else: user_plex = PlexServer(self.baseurl, user.get_token(self.plex.machineIdentifier)) - logger(f"Updating watched for {user.title}", 1) for library, videos in libraries.items(): + if library_mapping: + library_other = None + + if library in library_mapping.keys(): + library_other = library_mapping[library] + elif library in library_mapping.values(): + library_other = search_mapping(library_mapping, library) + + if library_other: + logger(f"Swapping library {library} with {library_other}", 1) + library = library_other + + # if library in plex library list + library_list = user_plex.library.sections() + if library.lower() not in [x.title.lower() for x in library_list]: + logger(f"Library {library} not found in Plex library list", 2) + continue + + logger(f"Plex: Updating watched for {user.title} in library {library}", 1) library_videos = user_plex.library.section(library) - + if library_videos.type == "movie": for movies_search in library_videos.search(unmatched=False, unwatched=True): for guid in movies_search.guids: @@ -156,12 +204,12 @@ class Plex: for video_keys, video_id in video.items(): if video_keys == guid_source and video_id == guid_id: if movies_search.viewCount == 0: - msg = f"{movies_search.title} as watched for {user.title} in Plex" + 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"Dyrun {msg}", 0) + logger(f"Dryrun {msg}", 0) break elif library_videos.type == "show": @@ -178,7 +226,7 @@ class Plex: for episode_keys, episode_id in episode.items(): if episode_keys == guid_source and episode_id == guid_id: if episode_search.viewCount == 0: - msg = f"{show_search.title} {season_search.title} {episode_search.title} as watched for {user.title} in Plex" + msg = f"{show_search.title} {season_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() From b3b5bd8cd203f9ed6468c7adf64e38fcac20fed6 Mon Sep 17 00:00:00 2001 From: Luigi311 Date: Mon, 23 May 2022 14:03:12 -0600 Subject: [PATCH 5/5] Update workflow --- .github/workflows/ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cb14fe5..cbb63c3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,8 +24,6 @@ jobs: uses: docker/metadata-action@v3 with: images: ${{ secrets.DOCKER_USERNAME }}/jellyplex-watched # list of Docker images to use as base name for tags - flavor: | - latest=true tags: | type=ref,event=branch type=ref,event=pr