Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: Fetch Plex userRatings in a separate call #668

Merged
merged 7 commits into from
Dec 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions plextraktsync/commands/inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ def inspect_media(id):
m.show = ms

print(f"Trakt: {m.trakt_url}")
print(f"Plex Rating: {m.plex_rating}")
print(f"Trakt Rating: {m.trakt_rating}")
print(f"Watched on Plex: {m.watched_on_plex}")
print(f"Watched on Trakt: {m.watched_on_trakt}")

Expand Down
58 changes: 50 additions & 8 deletions plextraktsync/plex_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import datetime
import re
from typing import List, Optional, Union
from typing import List, Optional, Union, Dict

from plexapi import X_PLEX_CONTAINER_SIZE
from plexapi.exceptions import BadRequest, NotFound, Unauthorized
Expand Down Expand Up @@ -121,9 +121,29 @@ def __str__(self):
return self.guid


class PlexRatingCollection(dict):
def __init__(self, plex: PlexApi):
super(dict, self).__init__()
self.plex = plex

def __missing__(self, section_id: int):
section = self.plex.library_sections[section_id]
ratings = self.ratings(section)
self[section_id] = ratings

return ratings

@flatten_dict
def ratings(self, section: PlexLibrarySection):
ratings = section.find_with_rating()
for item in ratings:
yield item.ratingKey, item.userRating


class PlexLibraryItem:
def __init__(self, item: Union[Movie, Show, Episode]):
def __init__(self, item: Union[Movie, Show, Episode], plex: PlexApi = None):
self.item = item
self.plex = plex

@property
def is_legacy_agent(self):
Expand Down Expand Up @@ -169,13 +189,20 @@ def type(self):
return self.item.type

@property
@memoize
@nocache
@rate_limit(retries=1)
def rating(self):
if self.item.userRating is None:
if self.plex is not None:
ratings = self.plex.ratings[self.item.librarySectionID]
user_rating = ratings[self.item.ratingKey] if self.item.ratingKey in ratings else None
else:
user_rating = self.item.userRating

if user_rating is None:
return None

return int(self.item.userRating)
return int(user_rating)

@property
def seen_date(self):
Expand Down Expand Up @@ -362,8 +389,9 @@ def to_json(self):


class PlexLibrarySection:
def __init__(self, section: LibrarySection):
def __init__(self, section: LibrarySection, plex=None):
self.section = section
self.plex = plex

@nocache
def __len__(self):
Expand All @@ -384,6 +412,15 @@ def find_by_title(self, name: str):
except NotFound:
return None

def find_with_rating(self):
filters = {
'and': [
{'userRating>>': -1},
]
}

return self.section.search(filters=filters)

@nocache
def find_by_id(self, id: Union[str, int]) -> Optional[Union[Movie, Show, Episode]]:
try:
Expand Down Expand Up @@ -414,7 +451,7 @@ def fetch_items(self, key: str, size: int, start: int):

def items(self, max_items: int):
for item in self.all(max_items):
yield PlexLibraryItem(item)
yield PlexLibraryItem(item, plex=self.plex)

def __repr__(self):
return f"<PlexLibrarySection:{self.type}:{self.title}>"
Expand Down Expand Up @@ -489,12 +526,12 @@ def updated_at(self):
@memoize
@flatten_dict
@nocache
def library_sections(self) -> dict[PlexLibrarySection[MovieSection, ShowSection]]:
def library_sections(self) -> Dict[int, PlexLibrarySection]:
CONFIG = factory.config()
for section in self.plex.library.sections():
if section.title in CONFIG["excluded-libraries"]:
continue
yield section.key, PlexLibrarySection(section)
yield section.key, PlexLibrarySection(section, plex=self)

@property
def library_section_names(self):
Expand All @@ -510,6 +547,11 @@ def system_device(self, device_id: int) -> SystemDevice:
def system_account(self, account_id: int) -> SystemAccount:
return self.plex.systemAccount(account_id)

@property
@memoize
def ratings(self):
return PlexRatingCollection(self)

@nocache
def rate(self, m, rating):
m.rate(rating)
Expand Down