Treewide: MyPy type fixes

Signed-off-by: Luis Garcia <git@luigi311.com>
This commit is contained in:
Luis Garcia
2025-03-07 23:24:33 +00:00
parent 5b644a54a2
commit e6fa8ae745
11 changed files with 177 additions and 106 deletions

View File

@@ -12,7 +12,7 @@ def setup_black_white_lists(
whitelist_users: list[str] | None, whitelist_users: list[str] | None,
library_mapping: dict[str, str] | None = None, library_mapping: dict[str, str] | None = None,
user_mapping: dict[str, str] | None = None, user_mapping: dict[str, str] | None = None,
): ) -> tuple[list[str], list[str], list[str], list[str], list[str], list[str]]:
blacklist_library, blacklist_library_type, blacklist_users = setup_x_lists( blacklist_library, blacklist_library_type, blacklist_users = setup_x_lists(
blacklist_library, blacklist_library,
blacklist_library_type, blacklist_library_type,

View File

@@ -25,17 +25,17 @@ def jellyfin_emby_server_connection(
f"{server_type.upper()}_BASEURL and {server_type.upper()}_TOKEN must have the same number of entries" f"{server_type.upper()}_BASEURL and {server_type.upper()}_TOKEN must have the same number of entries"
) )
for i, baseurl in enumerate(server_baseurls): for i, base_url in enumerate(server_baseurls):
baseurl = baseurl.strip() base_url = base_url.strip()
if baseurl[-1] == "/": if base_url[-1] == "/":
baseurl = baseurl[:-1] base_url = base_url[:-1]
if server_type == "jellyfin": if server_type == "jellyfin":
server = Jellyfin(baseurl=baseurl, token=server_tokens[i].strip()) server = Jellyfin(base_url=base_url, token=server_tokens[i].strip())
servers.append(server) servers.append(server)
elif server_type == "emby": elif server_type == "emby":
server = Emby(baseurl=baseurl, token=server_tokens[i].strip()) server = Emby(base_url=base_url, token=server_tokens[i].strip())
servers.append(server) servers.append(server)
else: else:
raise Exception("Unknown server type") raise Exception("Unknown server type")

View File

@@ -4,7 +4,7 @@ from loguru import logger
class Emby(JellyfinEmby): class Emby(JellyfinEmby):
def __init__(self, baseurl, token): def __init__(self, base_url: str, token: str) -> None:
authorization = ( authorization = (
"Emby , " "Emby , "
'Client="JellyPlex-Watched", ' 'Client="JellyPlex-Watched", '
@@ -19,7 +19,7 @@ class Emby(JellyfinEmby):
} }
super().__init__( super().__init__(
server_type="Emby", baseurl=baseurl, token=token, headers=headers server_type="Emby", base_url=base_url, token=token, headers=headers
) )
def is_partial_update_supported(self, server_version: Version) -> bool: def is_partial_update_supported(self, server_version: Version) -> bool:

View File

@@ -16,7 +16,7 @@ def log_marked(
movie_show: str, movie_show: str,
episode: str | None = None, episode: str | None = None,
duration: float | None = None, duration: float | None = None,
): ) -> None:
output = f"{server_type}/{server_name}/{username}/{library}/{movie_show}" output = f"{server_type}/{server_name}/{username}/{library}/{movie_show}"
if episode: if episode:

View File

@@ -4,7 +4,7 @@ from loguru import logger
class Jellyfin(JellyfinEmby): class Jellyfin(JellyfinEmby):
def __init__(self, baseurl, token): def __init__(self, base_url: str, token: str) -> None:
authorization = ( authorization = (
"MediaBrowser , " "MediaBrowser , "
'Client="JellyPlex-Watched", ' 'Client="JellyPlex-Watched", '
@@ -19,7 +19,7 @@ class Jellyfin(JellyfinEmby):
} }
super().__init__( super().__init__(
server_type="Jellyfin", baseurl=baseurl, token=token, headers=headers server_type="Jellyfin", base_url=base_url, token=token, headers=headers
) )
def is_partial_update_supported(self, server_version: Version) -> bool: def is_partial_update_supported(self, server_version: Version) -> bool:

View File

@@ -30,7 +30,9 @@ generate_guids = str_to_bool(os.getenv("GENERATE_GUIDS", "True"))
generate_locations = str_to_bool(os.getenv("GENERATE_LOCATIONS", "True")) generate_locations = str_to_bool(os.getenv("GENERATE_LOCATIONS", "True"))
def extract_identifiers_from_item(server_type: str, item: dict) -> MediaIdentifiers: def extract_identifiers_from_item(
server_type: str, item: dict[str, Any]
) -> MediaIdentifiers:
title = item.get("Name") title = item.get("Name")
id = None id = None
if not title: if not title:
@@ -45,7 +47,7 @@ def extract_identifiers_from_item(server_type: str, item: dict) -> MediaIdentifi
f"{server_type}: {title if title else id} has no guids", f"{server_type}: {title if title else id} has no guids",
) )
locations: tuple = tuple() locations: tuple[str, ...] = tuple()
if generate_locations: if generate_locations:
if item.get("Path"): if item.get("Path"):
locations = tuple([item["Path"].split("/")[-1]]) locations = tuple([item["Path"].split("/")[-1]])
@@ -70,7 +72,7 @@ def extract_identifiers_from_item(server_type: str, item: dict) -> MediaIdentifi
) )
def get_mediaitem(server_type: str, item: dict) -> MediaItem: def get_mediaitem(server_type: str, item: dict[str, Any]) -> MediaItem:
return MediaItem( return MediaItem(
identifiers=extract_identifiers_from_item(server_type, item), identifiers=extract_identifiers_from_item(server_type, item),
status=WatchedStatus( status=WatchedStatus(
@@ -86,20 +88,20 @@ class JellyfinEmby:
def __init__( def __init__(
self, self,
server_type: Literal["Jellyfin", "Emby"], server_type: Literal["Jellyfin", "Emby"],
baseurl: str, base_url: str,
token: str, token: str,
headers: dict[str, str], headers: dict[str, str],
): ) -> None:
if server_type not in ["Jellyfin", "Emby"]: if server_type not in ["Jellyfin", "Emby"]:
raise Exception(f"Server type {server_type} not supported") raise Exception(f"Server type {server_type} not supported")
self.server_type: str = server_type self.server_type: str = server_type
self.baseurl: str = baseurl self.base_url: str = base_url
self.token: str = token self.token: str = token
self.headers: dict[str, str] = headers self.headers: dict[str, str] = headers
self.timeout: int = int(os.getenv("REQUEST_TIMEOUT", 300)) self.timeout: int = int(os.getenv("REQUEST_TIMEOUT", 300))
if not self.baseurl: if not self.base_url:
raise Exception(f"{self.server_type} baseurl not set") raise Exception(f"{self.server_type} base_url not set")
if not self.token: if not self.token:
raise Exception(f"{self.server_type} token not set") raise Exception(f"{self.server_type} token not set")
@@ -118,13 +120,13 @@ class JellyfinEmby:
query_type: Literal["get", "post"], query_type: Literal["get", "post"],
identifiers: dict[str, str] | None = None, identifiers: dict[str, str] | None = None,
json: dict[str, float] | None = None, json: dict[str, float] | None = None,
): ) -> list[dict[str, Any]] | dict[str, Any] | None:
try: try:
results = None results = None
if query_type == "get": if query_type == "get":
response = self.session.get( response = self.session.get(
self.baseurl + query, headers=self.headers, timeout=self.timeout self.base_url + query, headers=self.headers, timeout=self.timeout
) )
if response.status_code not in [200, 204]: if response.status_code not in [200, 204]:
raise Exception( raise Exception(
@@ -137,7 +139,7 @@ class JellyfinEmby:
elif query_type == "post": elif query_type == "post":
response = self.session.post( response = self.session.post(
self.baseurl + query, self.base_url + query,
headers=self.headers, headers=self.headers,
json=json, json=json,
timeout=self.timeout, timeout=self.timeout,
@@ -173,9 +175,9 @@ class JellyfinEmby:
try: try:
query_string = "/System/Info/Public" query_string = "/System/Info/Public"
response: dict[str, Any] | None = self.query(query_string, "get") response = self.query(query_string, "get")
if response: if response and isinstance(response, dict):
if name_only: if name_only:
return response.get("ServerName") return response.get("ServerName")
elif version_only: elif version_only:
@@ -194,14 +196,11 @@ class JellyfinEmby:
users: dict[str, str] = {} users: dict[str, str] = {}
query_string = "/Users" query_string = "/Users"
response: list[dict[str, str | bool]] | None = self.query( response = self.query(query_string, "get")
query_string, "get"
)
if response: if response and isinstance(response, list):
for user in response: for user in response:
if isinstance(user["Name"], str) and isinstance(user["Id"], str): users[user["Name"]] = user["Id"]
users[user["Name"]] = user["Id"]
return users return users
except Exception as e: except Exception as e:
@@ -216,11 +215,9 @@ class JellyfinEmby:
users = self.get_users() users = self.get_users()
for user_name, user_id in users.items(): for user_name, user_id in users.items():
user_libraries: dict[str, Any] | None = self.query( user_libraries = self.query(f"/Users/{user_id}/Views", "get")
f"/Users/{user_id}/Views", "get"
)
if not user_libraries: if not user_libraries or not isinstance(user_libraries, dict):
logger.error( logger.error(
f"{self.server_type}: Failed to get libraries for {user_name}" f"{self.server_type}: Failed to get libraries for {user_name}"
) )
@@ -264,19 +261,26 @@ class JellyfinEmby:
# Movies # Movies
if library_type == "Movie": if library_type == "Movie":
movie_items = []
watched_items = self.query( watched_items = 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",
"get", "get",
).get("Items", []) )
if watched_items and isinstance(watched_items, dict):
movie_items += watched_items.get("Items", [])
in_progress_items = self.query( in_progress_items = self.query(
f"/Users/{user_id}/Items" f"/Users/{user_id}/Items"
+ f"?ParentId={library_id}&Filters=IsResumable&IncludeItemTypes=Movie&Recursive=True&Fields=ItemCounts,ProviderIds,MediaSources", + f"?ParentId={library_id}&Filters=IsResumable&IncludeItemTypes=Movie&Recursive=True&Fields=ItemCounts,ProviderIds,MediaSources",
"get", "get",
).get("Items", []) )
for movie in watched_items + in_progress_items: if in_progress_items and isinstance(in_progress_items, dict):
movie_items += in_progress_items.get("Items", [])
for movie in movie_items:
# Skip if theres no user data which means the movie has not been watched # Skip if theres no user data which means the movie has not been watched
if not movie.get("UserData"): if not movie.get("UserData"):
continue continue
@@ -295,15 +299,21 @@ class JellyfinEmby:
# TV Shows # TV Shows
if library_type in ["Series", "Episode"]: if library_type in ["Series", "Episode"]:
# Retrieve a list of watched TV shows # Retrieve a list of watched TV shows
watched_shows = self.query( all_shows = self.query(
f"/Users/{user_id}/Items" f"/Users/{user_id}/Items"
+ f"?ParentId={library_id}&isPlaceHolder=false&IncludeItemTypes=Series&Recursive=True&Fields=ProviderIds,Path,RecursiveItemCount", + f"?ParentId={library_id}&isPlaceHolder=false&IncludeItemTypes=Series&Recursive=True&Fields=ProviderIds,Path,RecursiveItemCount",
"get", "get",
).get("Items", []) )
if not all_shows or not isinstance(all_shows, dict):
logger.debug(
f"{self.server_type}: Failed to get shows for {user_name} in {library_title}"
)
return watched
# Filter the list of shows to only include those that have been partially or fully watched # Filter the list of shows to only include those that have been partially or fully watched
watched_shows_filtered = [] watched_shows_filtered = []
for show in watched_shows: for show in all_shows.get("Items", []):
if not show.get("UserData"): if not show.get("UserData"):
continue continue
@@ -312,6 +322,7 @@ class JellyfinEmby:
# Retrieve the watched/partially watched list of episodes of each watched show # Retrieve the watched/partially watched list of episodes of each watched show
for show in watched_shows_filtered: for show in watched_shows_filtered:
show_name = show.get("Name")
show_guids = { show_guids = {
k.lower(): v for k, v in show.get("ProviderIds", {}).items() k.lower(): v for k, v in show.get("ProviderIds", {}).items()
} }
@@ -325,12 +336,18 @@ class JellyfinEmby:
f"/Shows/{show.get('Id')}/Episodes" f"/Shows/{show.get('Id')}/Episodes"
+ f"?userId={user_id}&isPlaceHolder=false&Fields=ProviderIds,MediaSources", + f"?userId={user_id}&isPlaceHolder=false&Fields=ProviderIds,MediaSources",
"get", "get",
).get("Items", []) )
if not show_episodes or not isinstance(show_episodes, dict):
logger.debug(
f"{self.server_type}: Failed to get episodes for {user_name} {library_title} {show_name}"
)
continue
# Iterate through the episodes # Iterate through the episodes
# Create a list to store the episodes # Create a list to store the episodes
episode_mediaitem = [] episode_mediaitem = []
for episode in show_episodes: for episode in show_episodes.get("Items", []):
if not episode.get("UserData"): if not episode.get("UserData"):
continue continue
@@ -381,35 +398,44 @@ class JellyfinEmby:
users_watched: dict[str, UserData] = {} users_watched: dict[str, UserData] = {}
for user_name, user_id in users.items(): for user_name, user_id in users.items():
libraries = [ libraries = []
self.query(
f"/Users/{user_id}/Items"
f"?ParentId={lib.get('Id')}&Filters=IsPlayed&Recursive=True&excludeItemTypes=Folder&limit=100",
"get",
identifiers={
"library_id": lib["Id"],
"library_title": lib["Name"],
},
)
for lib in self.query(f"/Users/{user_id}/Views", "get").get(
"Items", []
)
if lib.get("Name") in sync_libraries
]
for library in libraries: all_libraries = self.query(f"/Users/{user_id}/Views", "get")
if not library.get("Items"): for library in all_libraries["Items"]:
library_id = library["Id"]
library_title = library["Name"]
if library_title not in sync_libraries:
continue continue
library_id = library.get("Identifiers", {}).get("library_id") identifiers: dict[str, str] = {
library_title = library.get("Identifiers", {}).get("library_title") "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: str = library["Identifiers"]["library_id"]
library_title: str = library["Identifiers"]["library_title"]
# Get all library types excluding "Folder" # Get all library types excluding "Folder"
types = { types = set(
x["Type"] [
for x in library.get("Items", []) x["Type"]
if x.get("Type") in {"Movie", "Series", "Episode"} for x in library["Items"]
} if x["Type"] in ["Movie", "Series", "Episode"]
]
)
for library_type in types: for library_type in types:
# Get watched for user # Get watched for user
@@ -441,7 +467,7 @@ class JellyfinEmby:
library_name: str, library_name: str,
library_id: str, library_id: str,
dryrun: bool, dryrun: bool,
): ) -> None:
try: try:
# If there are no movies or shows to update, exit early. # If there are no movies or shows to update, exit early.
if not library_data.series and not library_data.movies: if not library_data.series and not library_data.movies:
@@ -458,9 +484,15 @@ class JellyfinEmby:
+ f"?SortBy=SortName&SortOrder=Ascending&Recursive=True&ParentId={library_id}" + f"?SortBy=SortName&SortOrder=Ascending&Recursive=True&ParentId={library_id}"
+ "&isPlayed=false&Fields=ItemCounts,ProviderIds,MediaSources&IncludeItemTypes=Movie", + "&isPlayed=false&Fields=ItemCounts,ProviderIds,MediaSources&IncludeItemTypes=Movie",
"get", "get",
).get("Items", []) )
for jellyfin_video in jellyfin_search: if not jellyfin_search or not isinstance(jellyfin_search, dict):
logger.debug(
f"{self.server_type}: Failed to get movies for {user_name} {library_name}"
)
return
for jellyfin_video in jellyfin_search.get("Items", []):
jelly_identifiers = extract_identifiers_from_item( jelly_identifiers = extract_identifiers_from_item(
self.server_type, jellyfin_video self.server_type, jellyfin_video
) )
@@ -522,6 +554,12 @@ class JellyfinEmby:
+ "&Fields=ItemCounts,ProviderIds,Path&IncludeItemTypes=Series", + "&Fields=ItemCounts,ProviderIds,Path&IncludeItemTypes=Series",
"get", "get",
) )
if not jellyfin_search or not isinstance(jellyfin_search, dict):
logger.debug(
f"{self.server_type}: Failed to get shows for {user_name} {library_name}"
)
return
jellyfin_shows = [x for x in jellyfin_search.get("Items", [])] jellyfin_shows = [x for x in jellyfin_search.get("Items", [])]
for jellyfin_show in jellyfin_shows: for jellyfin_show in jellyfin_shows:
@@ -543,9 +581,17 @@ class JellyfinEmby:
f"/Shows/{jellyfin_show_id}/Episodes" f"/Shows/{jellyfin_show_id}/Episodes"
+ f"?userId={user_id}&Fields=ItemCounts,ProviderIds,MediaSources", + f"?userId={user_id}&Fields=ItemCounts,ProviderIds,MediaSources",
"get", "get",
).get("Items", []) )
for jellyfin_episode in jellyfin_episodes: if not jellyfin_episodes or not isinstance(
jellyfin_episodes, dict
):
logger.debug(
f"{self.server_type}: Failed to get episodes for {user_name} {library_name} {jellyfin_show.get('Name')}"
)
return
for jellyfin_episode in jellyfin_episodes.get("Items", []):
jellyfin_episode_identifiers = ( jellyfin_episode_identifiers = (
extract_identifiers_from_item( extract_identifiers_from_item(
self.server_type, jellyfin_episode self.server_type, jellyfin_episode
@@ -629,10 +675,10 @@ class JellyfinEmby:
def update_watched( def update_watched(
self, self,
watched_list: dict[str, UserData], watched_list: dict[str, UserData],
user_mapping=None, user_mapping: dict[str, str] | None = None,
library_mapping=None, library_mapping: dict[str, str] | None = None,
dryrun=False, dryrun: bool = False,
): ) -> None:
try: try:
for user, user_data in watched_list.items(): for user, user_data in watched_list.items():
user_other = None user_other = None
@@ -662,6 +708,13 @@ class JellyfinEmby:
f"/Users/{user_id}/Views", f"/Users/{user_id}/Views",
"get", "get",
) )
if not jellyfin_libraries or not isinstance(jellyfin_libraries, dict):
logger.debug(
f"{self.server_type}: Failed to get libraries for {user_name}"
)
continue
jellyfin_libraries = [x for x in jellyfin_libraries.get("Items", [])] jellyfin_libraries = [x for x in jellyfin_libraries.get("Items", [])]
for library_name in user_data.libraries: for library_name in user_data.libraries:

View File

@@ -5,6 +5,10 @@ from src.functions import (
search_mapping, search_mapping,
) )
from src.emby import Emby
from src.jellyfin import Jellyfin
from src.plex import Plex
def check_skip_logic( def check_skip_logic(
library_title: str, library_title: str,
@@ -54,7 +58,7 @@ def check_blacklist_logic(
blacklist_library: list[str], blacklist_library: list[str],
blacklist_library_type: list[str], blacklist_library_type: list[str],
library_other: str | None = None, library_other: str | None = None,
): ) -> str | None:
skip_reason = None skip_reason = None
if isinstance(library_type, (list, tuple, set)): if isinstance(library_type, (list, tuple, set)):
for library_type_item in library_type: for library_type_item in library_type:
@@ -90,7 +94,7 @@ def check_whitelist_logic(
whitelist_library: list[str], whitelist_library: list[str],
whitelist_library_type: list[str], whitelist_library_type: list[str],
library_other: str | None = None, library_other: str | None = None,
): ) -> str | None:
skip_reason = None skip_reason = None
if len(whitelist_library_type) > 0: if len(whitelist_library_type) > 0:
if isinstance(library_type, (list, tuple, set)): if isinstance(library_type, (list, tuple, set)):
@@ -161,8 +165,8 @@ def filter_libaries(
def setup_libraries( def setup_libraries(
server_1, server_1: Plex | Jellyfin | Emby,
server_2, server_2: Plex | Jellyfin | Emby,
blacklist_library: list[str], blacklist_library: list[str],
blacklist_library_type: list[str], blacklist_library_type: list[str],
whitelist_library: list[str], whitelist_library: list[str],

View File

@@ -27,7 +27,7 @@ log_file = os.getenv("LOG_FILE", os.getenv("LOGFILE", "log.log"))
level = os.getenv("DEBUG_LEVEL", "INFO").upper() level = os.getenv("DEBUG_LEVEL", "INFO").upper()
def configure_logger(): def configure_logger() -> None:
# Remove default logger to configure our own # Remove default logger to configure our own
logger.remove() logger.remove()
@@ -111,18 +111,20 @@ def should_sync_server(
return True return True
def main_loop(): def main_loop() -> None:
dryrun = str_to_bool(os.getenv("DRYRUN", "False")) dryrun = str_to_bool(os.getenv("DRYRUN", "False"))
logger.info(f"Dryrun: {dryrun}") logger.info(f"Dryrun: {dryrun}")
user_mapping = os.getenv("USER_MAPPING", None) user_mapping_env = os.getenv("USER_MAPPING", None)
if user_mapping: user_mapping = None
user_mapping = json.loads(user_mapping.lower()) if user_mapping_env:
user_mapping = json.loads(user_mapping_env.lower())
logger.info(f"User Mapping: {user_mapping}") logger.info(f"User Mapping: {user_mapping}")
library_mapping = os.getenv("LIBRARY_MAPPING", None) library_mapping_env = os.getenv("LIBRARY_MAPPING", None)
if library_mapping: library_mapping = None
library_mapping = json.loads(library_mapping) if library_mapping_env:
library_mapping = json.loads(library_mapping_env)
logger.info(f"Library Mapping: {library_mapping}") logger.info(f"Library Mapping: {library_mapping}")
# Create (black/white)lists # Create (black/white)lists
@@ -241,7 +243,7 @@ def main_loop():
@logger.catch @logger.catch
def main(): def main() -> None:
run_only_once = str_to_bool(os.getenv("RUN_ONLY_ONCE", "False")) run_only_once = str_to_bool(os.getenv("RUN_ONLY_ONCE", "False"))
sleep_duration = float(os.getenv("SLEEP_DURATION", "3600")) sleep_duration = float(os.getenv("SLEEP_DURATION", "3600"))
times: list[float] = [] times: list[float] = []

View File

@@ -36,7 +36,9 @@ generate_locations = str_to_bool(os.getenv("GENERATE_LOCATIONS", "True"))
# Bypass hostname validation for ssl. Taken from https://github.com/pkkid/python-plexapi/issues/143#issuecomment-775485186 # Bypass hostname validation for ssl. Taken from https://github.com/pkkid/python-plexapi/issues/143#issuecomment-775485186
class HostNameIgnoringAdapter(RequestsHTTPAdapter): class HostNameIgnoringAdapter(RequestsHTTPAdapter):
def init_poolmanager(self, connections, maxsize, block=..., **pool_kwargs): def init_poolmanager(
self, connections: int, maxsize: int | None, block=..., **pool_kwargs
) -> None:
self.poolmanager = PoolManager( self.poolmanager = PoolManager(
num_pools=connections, num_pools=connections,
maxsize=maxsize, maxsize=maxsize,
@@ -89,7 +91,7 @@ def update_user_watched(
library_data: LibraryData, library_data: LibraryData,
library_name: str, library_name: str,
dryrun: bool, dryrun: bool,
): ) -> None:
try: try:
# If there are no movies or shows to update, exit early. # If there are no movies or shows to update, exit early.
if not library_data.series and not library_data.movies: if not library_data.series and not library_data.movies:
@@ -224,8 +226,8 @@ class Plex:
password: str | None = None, password: str | None = None,
server_name: str | None = None, server_name: str | None = None,
ssl_bypass: bool = False, ssl_bypass: bool = False,
session=None, session: requests.Session | None = None,
): ) -> None:
self.server_type: str = "Plex" self.server_type: str = "Plex"
self.ssl_bypass: bool = ssl_bypass self.ssl_bypass: bool = ssl_bypass
if ssl_bypass: if ssl_bypass:
@@ -426,10 +428,10 @@ class Plex:
def update_watched( def update_watched(
self, self,
watched_list: dict[str, UserData], watched_list: dict[str, UserData],
user_mapping=None, user_mapping: dict[str, str] | None = None,
library_mapping=None, library_mapping: dict[str, str] | None = None,
dryrun=False, dryrun: bool = False,
): ) -> None:
try: try:
for user, user_data in watched_list.items(): for user, user_data in watched_list.items():
user_other = None user_other = None

View File

@@ -1,4 +1,4 @@
from plexapi.myplex import MyPlexAccount from plexapi.myplex import MyPlexAccount, MyPlexUser
from loguru import logger from loguru import logger
from src.emby import Emby from src.emby import Emby
@@ -109,7 +109,10 @@ def setup_users(
blacklist_users: list[str], blacklist_users: list[str],
whitelist_users: list[str], whitelist_users: list[str],
user_mapping: dict[str, str] | None = None, user_mapping: dict[str, str] | None = None,
) -> tuple[list[MyPlexAccount] | dict[str, str], list[MyPlexAccount] | dict[str, str]]: ) -> tuple[
list[MyPlexAccount | MyPlexUser] | dict[str, str],
list[MyPlexAccount | MyPlexUser] | dict[str, str],
]:
server_1_users = generate_user_list(server_1) server_1_users = generate_user_list(server_1)
server_2_users = generate_user_list(server_2) server_2_users = generate_user_list(server_2)
logger.debug(f"Server 1 users: {server_1_users}") logger.debug(f"Server 1 users: {server_1_users}")

View File

@@ -1,6 +1,7 @@
import copy import copy
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from loguru import logger from loguru import logger
from typing import Any
from src.functions import search_mapping from src.functions import search_mapping
@@ -103,8 +104,8 @@ def check_remove_entry(item1: MediaItem, item2: MediaItem) -> bool:
def cleanup_watched( def cleanup_watched(
watched_list_1: dict[str, UserData], watched_list_1: dict[str, UserData],
watched_list_2: dict[str, UserData], watched_list_2: dict[str, UserData],
user_mapping=None, user_mapping: dict[str, str] | None = None,
library_mapping=None, library_mapping: dict[str, str] | None = None,
) -> dict[str, UserData]: ) -> dict[str, UserData]:
modified_watched_list_1 = copy.deepcopy(watched_list_1) modified_watched_list_1 = copy.deepcopy(watched_list_1)
@@ -199,11 +200,17 @@ def cleanup_watched(
return modified_watched_list_1 return modified_watched_list_1
def get_other(watched_list, object_1, object_2): def get_other(
watched_list: dict[str, Any], object_1: str, object_2: str | None
) -> str | None:
if object_1 in watched_list: if object_1 in watched_list:
return object_1 return object_1
elif object_2 in watched_list:
if object_2 and object_2 in watched_list:
return object_2 return object_2
else:
logger.info(f"{object_1} and {object_2} not found in watched list 2") logger.info(
return None f"{object_1}{' and ' + object_2 if object_2 else ''} not found in watched list 2"
)
return None