Simplify get watched process. Only get watched for syncing libraries

Signed-off-by: Luis Garcia <git@luigi311.com>
This commit is contained in:
Luis Garcia
2024-10-27 13:43:09 -06:00
parent 8428be9dda
commit bc09c873e9
5 changed files with 185 additions and 155 deletions

View File

@@ -92,6 +92,18 @@ def search_mapping(dictionary: dict, key_value: str):
else: else:
return None return None
# Return list of objects that exist in both lists including mappings
def match_list(list1, list2, list_mapping=None):
output = []
for element in list1:
if element in list2:
output.append(element)
elif list_mapping:
element_other = search_mapping(list_mapping, element)
if element_other in list2:
output.append(element)
return output
def future_thread_executor( def future_thread_executor(
args: list, threads: int = None, override_threads: bool = False args: list, threads: int = None, override_threads: bool = False

View File

@@ -223,13 +223,54 @@ class JellyfinEmby:
logger(f"{self.server_type}: Get users failed {e}", 2) logger(f"{self.server_type}: Get users failed {e}", 2)
raise Exception(e) raise Exception(e)
def get_libraries(self):
try:
libraries = {}
# Theres no way to get all libraries so individually get list of libraries from all users
users = self.get_users()
for _, user_id in users.items():
user_libraries = self.query(f"/Users/{user_id}/Views", "get")
for library in user_libraries["Items"]:
library_id = library["Id"]
library_title = library["Name"]
# Get library items to check the type
media_info = self.query(
f"/Users/{user_id}/Items"
+ f"?ParentId={library_id}&Filters=IsPlayed&Recursive=True&excludeItemTypes=Folder&limit=100",
"get",
)
types = set(
[
x["Type"]
for x in media_info["Items"]
if x["Type"] in ["Movie", "Series", "Episode"]
]
)
all_types = set([x["Type"] for x in media_info["Items"]])
if not types:
logger(
f"{self.server_type}: Skipping Library {library_title} found wanted types: {all_types}",
1,
)
else:
libraries[library_title] = str(types)
return libraries
except Exception as e:
logger(f"{self.server_type}: Get libraries failed {e}", 2)
raise Exception(e)
def get_user_library_watched( def get_user_library_watched(
self, user_name, user_id, library_type, library_id, library_title self, user_name, user_id, library_type, library_id, library_title
): ):
try: try:
user_name = user_name.lower() user_name = user_name.lower()
user_watched = {} user_watched = {}
user_watched[user_name] = {}
logger( logger(
f"{self.server_type}: Generating watched for {user_name} in library {library_title}", f"{self.server_type}: Generating watched for {user_name} in library {library_title}",
@@ -238,7 +279,7 @@ class JellyfinEmby:
# Movies # Movies
if library_type == "Movie": if library_type == "Movie":
user_watched[user_name][library_title] = [] user_watched[library_title] = []
watched = self.query( watched = self.query(
f"/Users/{user_id}/Items" f"/Users/{user_id}/Items"
+ f"?ParentId={library_id}&Filters=IsPlayed&IncludeItemTypes=Movie&Recursive=True&Fields=ItemCounts,ProviderIds,MediaSources", + f"?ParentId={library_id}&Filters=IsPlayed&IncludeItemTypes=Movie&Recursive=True&Fields=ItemCounts,ProviderIds,MediaSources",
@@ -274,7 +315,7 @@ class JellyfinEmby:
movie_guids = get_guids(self.server_type, movie) movie_guids = get_guids(self.server_type, movie)
# Append the movie dictionary to the list for the given user and library # Append the movie dictionary to the list for the given user and library
user_watched[user_name][library_title].append(movie_guids) user_watched[library_title].append(movie_guids)
logger( logger(
f"{self.server_type}: Added {movie_guids} to {user_name} watched list", f"{self.server_type}: Added {movie_guids} to {user_name} watched list",
3, 3,
@@ -283,7 +324,7 @@ class JellyfinEmby:
# TV Shows # TV Shows
if library_type in ["Series", "Episode"]: if library_type in ["Series", "Episode"]:
# Initialize an empty dictionary for the given user and library # Initialize an empty dictionary for the given user and library
user_watched[user_name][library_title] = {} user_watched[library_title] = {}
# Retrieve a list of watched TV shows # Retrieve a list of watched TV shows
watched_shows = self.query( watched_shows = self.query(
@@ -352,10 +393,10 @@ class JellyfinEmby:
if mark_episodes_list: if mark_episodes_list:
# Add the show dictionary to the user's watched list # Add the show dictionary to the user's watched list
if show_guids not in user_watched[user_name][library_title]: if show_guids not in user_watched[library_title]:
user_watched[user_name][library_title][show_guids] = [] user_watched[library_title][show_guids] = []
user_watched[user_name][library_title][ user_watched[library_title][
show_guids show_guids
] = mark_episodes_list ] = mark_episodes_list
for episode in mark_episodes_list: for episode in mark_episodes_list:
@@ -368,9 +409,9 @@ class JellyfinEmby:
f"{self.server_type}: Got watched for {user_name} in library {library_title}", f"{self.server_type}: Got watched for {user_name} in library {library_title}",
1, 1,
) )
if library_title in user_watched[user_name]: if library_title in user_watched:
logger( logger(
f"{self.server_type}: {user_watched[user_name][library_title]}", 3 f"{self.server_type}: {user_watched[library_title]}", 3
) )
return user_watched return user_watched
@@ -383,130 +424,68 @@ class JellyfinEmby:
logger(traceback.format_exc(), 2) logger(traceback.format_exc(), 2)
return {} return {}
def get_users_watched(
self,
user_name,
user_id,
blacklist_library,
whitelist_library,
blacklist_library_type,
whitelist_library_type,
library_mapping,
):
try:
# Get all libraries
user_name = user_name.lower()
watched = []
libraries = []
all_libraries = self.query(f"/Users/{user_id}/Views", "get")
for library in all_libraries["Items"]:
library_id = library["Id"]
library_title = library["Name"]
identifiers = {
"library_id": library_id,
"library_title": library_title,
}
libraries.append(
self.query(
f"/Users/{user_id}/Items"
+ f"?ParentId={library_id}&Filters=IsPlayed&Recursive=True&excludeItemTypes=Folder&limit=100",
"get",
identifiers=identifiers,
)
)
for library in libraries:
if len(library["Items"]) == 0:
continue
library_id = library["Identifiers"]["library_id"]
library_title = library["Identifiers"]["library_title"]
# Get all library types excluding "Folder"
types = set(
[
x["Type"]
for x in library["Items"]
if x["Type"] in ["Movie", "Series", "Episode"]
]
)
skip_reason = check_skip_logic(
library_title,
types,
blacklist_library,
whitelist_library,
blacklist_library_type,
whitelist_library_type,
library_mapping,
)
if skip_reason:
logger(
f"{self.server_type}: Skipping library {library_title}: {skip_reason}",
1,
)
continue
# If there are multiple types in library raise error
if types is None or len(types) < 1:
all_types = set([x["Type"] for x in library["Items"]])
logger(
f"{self.server_type}: Skipping Library {library_title} found types: {types}, all types: {all_types}",
1,
)
continue
for library_type in types:
# Get watched for user
watched.append(
self.get_user_library_watched(
user_name,
user_id,
library_type,
library_id,
library_title,
)
)
return watched
except Exception as e:
logger(f"{self.server_type}: Failed to get users watched, Error: {e}", 2)
raise Exception(e)
def get_watched( def get_watched(
self, self,
users, users,
blacklist_library, sync_libraries
whitelist_library,
blacklist_library_type,
whitelist_library_type,
library_mapping=None,
): ):
try: try:
users_watched = {} users_watched = {}
watched = [] watched = []
for user_name, user_id in users.items(): for user_name, user_id in users.items():
watched.append( libraries = []
self.get_users_watched(
user_name,
user_id,
blacklist_library,
whitelist_library,
blacklist_library_type,
whitelist_library_type,
library_mapping,
)
)
for user_watched in watched: all_libraries = self.query(f"/Users/{user_id}/Views", "get")
user_watched_combine = combine_watched_dicts(user_watched) for library in all_libraries["Items"]:
for user, user_watched_temp in user_watched_combine.items(): library_id = library["Id"]
if user not in users_watched: library_title = library["Name"]
users_watched[user] = {} identifiers = {
users_watched[user].update(user_watched_temp) "library_id": library_id,
"library_title": library_title,
}
libraries.append(
self.query(
f"/Users/{user_id}/Items"
+ f"?ParentId={library_id}&Filters=IsPlayed&Recursive=True&excludeItemTypes=Folder&limit=100",
"get",
identifiers=identifiers,
)
)
for library in libraries:
if len(library["Items"]) == 0:
continue
library_id = library["Identifiers"]["library_id"]
library_title = library["Identifiers"]["library_title"]
if library_title not in sync_libraries:
continue
# Get all library types excluding "Folder"
types = set(
[
x["Type"]
for x in library["Items"]
if x["Type"] in ["Movie", "Series", "Episode"]
]
)
for library_type in types:
# Get watched for user
watched = self.get_user_library_watched(
user_name,
user_id,
library_type,
library_id,
library_title,
)
if user_name.lower() not in users_watched:
users_watched[user_name.lower()] = {}
users_watched[user_name.lower()].update(watched)
return users_watched return users_watched
except Exception as e: except Exception as e:

View File

@@ -1,5 +1,6 @@
from src.functions import ( from src.functions import (
logger, logger,
match_list,
search_mapping, search_mapping,
) )
@@ -128,6 +129,49 @@ def check_whitelist_logic(
return skip_reason return skip_reason
def filter_libaries(
server_libraries, blacklist_library, blacklist_library_type, whitelist_library, whitelist_library_type, library_mapping=None
):
filtered_libaries = []
for library in server_libraries:
skip_reason = check_skip_logic(
library,
server_libraries[library],
blacklist_library,
whitelist_library,
blacklist_library_type,
whitelist_library_type,
library_mapping,
)
if skip_reason:
logger(
f"Skipping library {library}: {skip_reason}", 1
)
continue
filtered_libaries.append(library)
return filtered_libaries
def setup_libraries(
server_1, server_2, blacklist_library, blacklist_library_type, whitelist_library, whitelist_library_type, library_mapping=None
):
server_1_libraries = server_1.get_libraries()
server_2_libraries = server_2.get_libraries()
logger(f"Server 1 libraries: {server_1_libraries}", 1)
logger(f"Server 2 libraries: {server_2_libraries}", 1)
# Filter out all blacklist, whitelist libaries
filtered_server_1_libraries = filter_libaries(server_1_libraries, blacklist_library, blacklist_library_type, whitelist_library, whitelist_library_type, library_mapping)
filtered_server_2_libraries = filter_libaries(server_2_libraries, blacklist_library, blacklist_library_type, whitelist_library, whitelist_library_type, library_mapping)
output_server_1_libaries = match_list(filtered_server_1_libraries, filtered_server_2_libraries, library_mapping)
output_server_2_libaries = match_list(filtered_server_2_libraries, filtered_server_1_libraries, library_mapping)
return output_server_1_libaries, output_server_2_libaries
def show_title_dict(user_list: dict): def show_title_dict(user_list: dict):
try: try:

View File

@@ -2,6 +2,7 @@ import os, traceback, json
from dotenv import load_dotenv from dotenv import load_dotenv
from time import sleep, perf_counter from time import sleep, perf_counter
from src.library import setup_libraries
from src.functions import ( from src.functions import (
logger, logger,
str_to_bool, str_to_bool,
@@ -153,24 +154,20 @@ def main_loop():
server_1, server_2, blacklist_users, whitelist_users, user_mapping server_1, server_2, blacklist_users, whitelist_users, user_mapping
) )
server_1_libraries, server_2_libraries = setup_libraries(
server_1[1], server_2[1], blacklist_library, blacklist_library_type, whitelist_library, whitelist_library_type, library_mapping
)
logger("Creating watched lists", 1) logger("Creating watched lists", 1)
server_1_watched = server_1[1].get_watched( server_1_watched = server_1[1].get_watched(
server_1_users, server_1_users,
blacklist_library, server_1_libraries
whitelist_library,
blacklist_library_type,
whitelist_library_type,
library_mapping,
) )
logger("Finished creating watched list server 1", 1) logger("Finished creating watched list server 1", 1)
server_2_watched = server_2[1].get_watched( server_2_watched = server_2[1].get_watched(
server_2_users, server_2_users,
blacklist_library, server_2_libraries
whitelist_library,
blacklist_library_type,
whitelist_library_type,
library_mapping,
) )
logger("Finished creating watched list server 2", 1) logger("Finished creating watched list server 2", 1)

View File

@@ -466,14 +466,28 @@ class Plex:
logger(f"Plex: Failed to get users, Error: {e}", 2) logger(f"Plex: Failed to get users, Error: {e}", 2)
raise Exception(e) raise Exception(e)
def get_libraries(self):
try:
output = {}
libraries = self.plex.library.sections()
for library in libraries:
library_title = library.title
library_type = library.type
output[library_title] = library_type
return output
except Exception as e:
logger(f"Plex: Failed to get libraries, Error: {e}", 2)
raise Exception(e)
def get_watched( def get_watched(
self, self,
users, users,
blacklist_library, sync_libraries
whitelist_library,
blacklist_library_type,
whitelist_library_type,
library_mapping,
): ):
try: try:
# Get all libraries # Get all libraries
@@ -500,23 +514,7 @@ class Plex:
libraries = user_plex.library.sections() libraries = user_plex.library.sections()
for library in libraries: for library in libraries:
library_title = library.title if library.title not in sync_libraries:
library_type = library.type
skip_reason = check_skip_logic(
library_title,
library_type,
blacklist_library,
whitelist_library,
blacklist_library_type,
whitelist_library_type,
library_mapping,
)
if skip_reason:
logger(
f"Plex: Skipping library {library_title}: {skip_reason}", 1
)
continue continue
user_watched = get_user_library_watched(user, user_plex, library) user_watched = get_user_library_watched(user, user_plex, library)