-
Notifications
You must be signed in to change notification settings - Fork 113
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1475 from glensc/refactor-pl
Refactor: Playlists refactoring
- Loading branch information
Showing
9 changed files
with
249 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
from __future__ import annotations | ||
|
||
from collections import UserDict | ||
from typing import TYPE_CHECKING | ||
|
||
from plextraktsync.plex.PlexPlaylist import PlexPlaylist | ||
|
||
if TYPE_CHECKING: | ||
from plexapi.server import PlexServer | ||
|
||
|
||
class PlexPlaylistCollection(UserDict): | ||
def __init__(self, server: PlexServer): | ||
super().__init__() | ||
self.server = server | ||
|
||
def __missing__(self, name: str): | ||
playlist = PlexPlaylist(self.server, name) | ||
self[name] = playlist | ||
|
||
return playlist |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
from __future__ import annotations | ||
|
||
from functools import cached_property | ||
from itertools import count | ||
from typing import TYPE_CHECKING | ||
|
||
from plextraktsync.factory import factory, logging | ||
|
||
if TYPE_CHECKING: | ||
from trakt.movies import Movie | ||
from trakt.tv import TVEpisode | ||
|
||
from plextraktsync.media import Media | ||
from plextraktsync.plex.PlexLibraryItem import PlexLibraryItem | ||
|
||
|
||
class TraktUserList: | ||
plex_items: list[tuple[int, PlexLibraryItem]] | ||
|
||
def __init__(self, | ||
trakt_id: int = None, | ||
name: str = None, | ||
items=None, | ||
): | ||
if items is None: | ||
items = [] | ||
self.trakt_id = trakt_id | ||
self.name = name | ||
self._items = items | ||
self.description = None | ||
self.plex_items = [] | ||
self.logger = logging.getLogger("PlexTraktSync.TraktUserList") | ||
|
||
def __iter__(self): | ||
return iter(self.items) | ||
|
||
def __len__(self): | ||
return len(self.items) | ||
|
||
def __contains__(self, m: Media): | ||
rank = self.items.get((m.media_type, m.trakt_id)) | ||
|
||
return rank is not None | ||
|
||
@property | ||
def items(self): | ||
if not self._items: | ||
self.description, self._items = self.load_items() | ||
return self._items | ||
|
||
def load_items(self): | ||
from plextraktsync.trakt_list_util import LazyUserList | ||
|
||
userlist = LazyUserList._get(self.name, self.trakt_id) | ||
list_items = userlist._items | ||
prelist = [ | ||
(elem[0], elem[1]) | ||
for elem in list_items | ||
if elem[0] in ["movies", "episodes"] | ||
] | ||
self.logger.info(f"Downloaded Trakt list '{self.name}' https://trakt.tv/lists/{self.trakt_id}") | ||
|
||
return userlist.description, dict(zip(prelist, count(1))) | ||
|
||
@classmethod | ||
def from_trakt_list(cls, name: str, items: list[Movie, TVEpisode]): | ||
items = zip([(item.media_type, item.trakt) for item in items], count(1)) | ||
|
||
return cls(name=name, items=dict(items)) | ||
|
||
@classmethod | ||
def from_watchlist(cls, items: list[Movie, TVEpisode]): | ||
trakt_items = dict( | ||
zip([(elem.media_type, elem.trakt) for elem in items], count(1)) | ||
) | ||
return cls(name="Trakt Watchlist", items=trakt_items) | ||
|
||
@cached_property | ||
def plex_lists(self): | ||
return factory.plex_lists | ||
|
||
@cached_property | ||
def plex_list(self): | ||
if not self.name: | ||
raise RuntimeError("Name is required") | ||
|
||
return self.plex_lists[self.name] | ||
|
||
def add(self, m: Media): | ||
rank = self.items.get((m.media_type, m.trakt_id)) | ||
if rank is None: | ||
# Item is not in this trakt list | ||
return | ||
|
||
# TODO: add with rank | ||
self.plex_items.append((rank, m.plex)) | ||
|
||
if m in self.plex_list: | ||
# Already in the list | ||
return | ||
|
||
self.logger.info(f'Adding {m.title_link} ({m.plex_key}) to Plex list {self.title_link}', extra={"markup": True}) | ||
|
||
@property | ||
def title_link(self): | ||
return self.plex_list.title_link | ||
|
||
@property | ||
def plex_items_sorted(self): | ||
""" | ||
Returns items sorted by trakt rank | ||
https://github.com/Taxel/PlexTraktSync/pull/58 | ||
""" | ||
if len(self.plex_items) == 0: | ||
return [] | ||
|
||
plex_items = [(r, p.item) for (r, p) in self.plex_items] | ||
_, items = zip(*sorted(dict(reversed(plex_items)).items())) | ||
|
||
return items |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
from __future__ import annotations | ||
|
||
from collections import UserList | ||
from typing import TYPE_CHECKING | ||
|
||
from plextraktsync.factory import logging | ||
from plextraktsync.trakt.TraktUserList import TraktUserList | ||
|
||
if TYPE_CHECKING: | ||
from trakt.movies import Movie | ||
from trakt.tv import TVEpisode | ||
|
||
from plextraktsync.media import Media | ||
from plextraktsync.trakt.types import TraktLikedList | ||
|
||
|
||
class TraktUserListCollection(UserList): | ||
def __init__(self): | ||
super().__init__() | ||
self.logger = logging.getLogger("PlexTraktSync.TraktUserListCollection") | ||
|
||
def add_to_lists(self, m: Media): | ||
for tl in self: | ||
tl.add(m) | ||
|
||
def load_lists(self, liked_lists: list[TraktLikedList]): | ||
for liked_list in liked_lists: | ||
self.add_list(liked_list["listid"], liked_list["listname"]) | ||
|
||
def add_watchlist(self, items: list[Movie, TVEpisode]): | ||
tl = TraktUserList.from_watchlist(items) | ||
self.append(tl) | ||
return tl | ||
|
||
def add_list(self, list_id: int, list_name: str): | ||
tl = TraktUserList(list_id, list_name) | ||
self.append(tl) | ||
return tl | ||
|
||
def sync(self): | ||
for tl in self: | ||
updated = tl.plex_list.update(tl.plex_items_sorted) | ||
if not updated: | ||
continue | ||
self.logger.info(f"Plex list {tl.title_link} ({len(tl.plex_items)} items) updated", extra={"markup": True}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,11 @@ | ||
from typing import Union | ||
from typing import TypedDict, Union | ||
|
||
from trakt.movies import Movie | ||
from trakt.tv import TVEpisode, TVSeason, TVShow | ||
|
||
TraktMedia = Union[Movie, TVShow, TVSeason, TVEpisode] | ||
|
||
|
||
class TraktLikedList(TypedDict): | ||
listid: int | ||
listname: str |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters