diff --git a/backend/program/content/base.py b/backend/program/content/base.py index bb702382..6e1bc7a9 100644 --- a/backend/program/content/base.py +++ b/backend/program/content/base.py @@ -1,3 +1,4 @@ +from program.media.item import MediaItem from program.media.container import MediaItemContainer from program.updaters.trakt import Updater as Trakt @@ -19,7 +20,7 @@ def run(self): """Fetch new media from the content provider.""" raise NotImplementedError("The 'run' method must be implemented by subclasses.") - def process_items(self, items, requested_by): + def process_items(self, items: MediaItemContainer, requested_by: str) -> MediaItemContainer: """Process fetched media items and log the results.""" new_items = [item for item in items if self.is_valid_item(item)] if not new_items: @@ -31,7 +32,7 @@ def process_items(self, items, requested_by): item.set("requested_by", requested_by) return added_items - def is_valid_item(self, item) -> bool: - """Check if the item is valid for processing and not already in media_items""" - is_unique = item not in self.media_items - return item is not None and is_unique + def is_valid_item(self, item: MediaItem) -> bool: + """Check if an imdb_id is valid for processing and not already in media_items""" + is_unique = not any(existing_item.imdb_id == item for existing_item in self.media_items.items) + return item is not None and is_unique \ No newline at end of file diff --git a/backend/program/content/plex_watchlist.py b/backend/program/content/plex_watchlist.py index 001aec36..37f9fb78 100644 --- a/backend/program/content/plex_watchlist.py +++ b/backend/program/content/plex_watchlist.py @@ -56,7 +56,11 @@ def run(self): length = len(added_items) if length >= 1 and length <= 5: for item in added_items: - logger.info("Added %s", item.log_string) + if not hasattr(item, "log_string"): + logger.error("Removing invalid item added from Plex Watchlist") + self.media_items.remove(item) + else: + logger.info("Added %s", item.log_string) elif length > 5: logger.info("Added %s items", length) if self.not_found_ids: diff --git a/backend/program/media/container.py b/backend/program/media/container.py index 448b73d6..1a2d075e 100644 --- a/backend/program/media/container.py +++ b/backend/program/media/container.py @@ -3,6 +3,7 @@ import dill from pickle import UnpicklingError from typing import List, Optional +from utils.logger import logger from program.media.item import MediaItem @@ -82,6 +83,10 @@ def remove(self, item): if item in self.items: self.items.remove(item) + def remove_by_imdb_id(self, imdb_id: str): + with self.lock: + self.items = [item for item in self.items if item.imdb_id != imdb_id] + def count(self, state) -> int: """Count items with given state in container""" return len(self.get_items_with_state(state)) diff --git a/backend/program/plex.py b/backend/program/plex.py index 5b2f9cdc..7de8eedc 100644 --- a/backend/program/plex.py +++ b/backend/program/plex.py @@ -70,7 +70,7 @@ def _get_last_fetch_time(self, section): return self.last_fetch_times.get(section.key, datetime(1800, 1, 1)) def _update_items(self, init=False): - items = [] + items = MediaItemContainer() sections = self.plex.library.sections() processed_sections = set() max_workers = os.cpu_count() / 2 @@ -90,13 +90,18 @@ def _update_items(self, init=False): items.append(media_item) self.last_fetch_times[section.key] = datetime.now() processed_sections.add(section.key) - - length = len(items) - if length >= 1 and length <= 5: - for item in items: - logger.info("Found %s from plex", item.log_string) - elif length > 5: - logger.info("Found %s items from plex", length) + + added_count = 0 + for item in items: + if item is not None and item not in self.media_items: + self.media_items.append(item) + added_count += 1 + + if added_count > 0: + if added_count <= 5: + logger.info("Found %d from Plex", item.log_string) + else: + logger.info("Found %d items from Plex", added_count) def update_item_section(self, item): """Update plex library section for a single item""" @@ -169,28 +174,6 @@ def _update_item(self, item, library_item): def _is_wanted_section(self, section): return any(self.library_path in location for location in section.locations) and section.type in ["movie", "show"] - def _oauth(self): - random_uuid = uuid.uuid4() - response = get( - url="https://plex.tv/api/v2/user", - additional_headers={ - "X-Plex-Product": "Iceberg", - "X-Plex-Client-Identifier": random_uuid, - "X-Plex-Token": settings_manager.settings.plex.token, - }, - ) - if not response.ok: - data = post( - url="https://plex.tv/api/v2/pins", - additional_headers={ - "strong": "true", - "X-Plex-Product": "Iceberg", - "X-Plex-Client-Identifier": random_uuid, - }, - ) - if data.ok: - pin = data.id - def _map_item_from_data(item): """Map Plex API data to MediaItemContainer.""" @@ -216,18 +199,6 @@ def _map_item_from_data(item): ) aired_at = getattr(item, "originallyAvailableAt", None) - # Attempt to get the imdb id from the tvdb id if we don't have it. - # Uses Trakt to get the imdb id from the tvdb id. - # if not imdb_id: - # tvdb_id = next( - # (guid.id.split("://")[-1] for guid in guids if "tvdb" in guid.id), None - # ) - # if tvdb_id: - # imdb_id = get_imdbid_from_tvdb(tvdb_id) - # if imdb_id: - # logger.debug("%s was missing IMDb ID, found IMDb ID from TVdb ID: %s", title, imdb_id) - # If we still don't have an imdb id, we could check TMdb or use external services like cinemeta. - media_item_data = { "title": title, "imdb_id": imdb_id, diff --git a/backend/program/settings/models.py b/backend/program/settings/models.py index ed5cb0bc..3dca569f 100644 --- a/backend/program/settings/models.py +++ b/backend/program/settings/models.py @@ -54,10 +54,12 @@ class OverseerrModel(ContentNotifyingBaseModel): enabled: bool = False url: str = "http://localhost:5055" api_key: str = "" + update_interval: int = 60 class PlexWatchlistModel(ContentNotifyingBaseModel): enabled: bool = False rss: str = "" + update_interval: int = 60 class ContentModel(NotifyingBaseModel): listrr: ListrrModel = ListrrModel() diff --git a/backend/program/updaters/trakt.py b/backend/program/updaters/trakt.py index e3bbe34c..ecacd673 100644 --- a/backend/program/updaters/trakt.py +++ b/backend/program/updaters/trakt.py @@ -62,7 +62,8 @@ def create_items(self, imdb_ids): def _create_item(self, imdb_id): item = create_item_from_imdb_id(imdb_id) if item is None: - pass + logger.info(f"Removed request with IMDb ID {imdb_id}, unable to create item.") + self.trakt_data.remove_by_imdb_id(imdb_id) if item and item.type == "show": seasons = get_show(imdb_id) for season in seasons: @@ -162,7 +163,7 @@ def create_item_from_imdb_id(imdb_id: str): if data: return _map_item_from_data(data, media_type) except UnboundLocalError: - logger.error("Unknown item %s with response %s", imdb_id, response) + logger.error("Unknown item %s with response %s", imdb_id, response.content) return None logger.error("Unable to create item from IMDb ID %s, skipping..", imdb_id) return None