Conversation
…ne` and refine ID assignment conditions.
There was a problem hiding this comment.
Pull request overview
This PR improves robustness of the scrobbling flow when Kodi’s JSON-RPC returns empty/invalid media details by explicitly setting curVideoInfo to None and tightening conditions around assigning Kodi library IDs into Trakt result payloads.
Changes:
- Guard
getEpisodeDetailsFromKodi/getMovieDetailsFromKodiresults before converting to Trakt media objects; setcurVideoInfo = Nonewhen empty. - Avoid indexing into missing episode details by gating
traktShowSummary/curVideoInfosetup on a non-empty response. - Refine Kodi ID assignment to Trakt scrobble results by checking
resultand expected keys (movie/episode) first.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "movie", movieDetailsKodi | ||
| ) | ||
| else: | ||
| self.curVideoInfo = None |
There was a problem hiding this comment.
When movieDetailsKodi is empty, self.curVideoInfo is set to None but playback continues. Later in this method there are conditions like "ids" in self.curVideoInfo that will raise TypeError when self.curVideoInfo is None (e.g., when scrobbling is disabled but rating is enabled). Consider aborting the playbackStarted flow (similar to the episode invalid-ID path) or ensure subsequent checks are guarded with self.curVideoInfo being a dict before using membership tests.
| self.curVideoInfo = None | |
| # Ensure curVideoInfo remains a dict so membership tests like | |
| # `"ids" in self.curVideoInfo` do not raise TypeError. | |
| self.curVideoInfo = {} |
| "episode", episode_details | ||
| ) | ||
| else: | ||
| self.curVideoInfo = None |
There was a problem hiding this comment.
If episode_details is empty, self.curVideoInfo becomes None but the multi-episode transition continues. playbackEnded() later unconditionally appends self.curVideoInfo to videosToRate, which can introduce None entries and crash the rating flow (it expects dicts). Consider aborting scrobbling/rating for the remainder of this multi-part item when details are empty, or ensure videosToRate never contains None values.
| self.curVideoInfo = None | |
| logger.warning( | |
| "Failed to get episode details for multi-part " | |
| "episode index %s; keeping existing curVideoInfo.", | |
| self.curMPEpisode, | |
| ) |
| if result and "id" in self.curVideo: | ||
| if utilities.isMovie(self.curVideo["type"]) and "movie" in result: | ||
| result["movie"]["movieid"] = self.curVideo["id"] | ||
| elif utilities.isEpisode(self.curVideo["type"]): | ||
| elif utilities.isEpisode(self.curVideo["type"]) and "episode" in result: | ||
| result["episode"]["episodeid"] = self.curVideo["id"] |
There was a problem hiding this comment.
result can be None here (e.g., self.__scrobble("start") returns None when self.curVideoInfo is missing), but it is passed to __preFetchUserRatings which is annotated as result: Dict. Consider normalizing result to {} (or updating the type hints to Optional[Dict]) to keep the types consistent and avoid future misuse of result as a dict in this block.
…ne` and refine ID assignment conditions.