|
|
@ -496,7 +496,7 @@ class Plex(Library):
|
|
|
|
args = f"{args}&label={label_id}"
|
|
|
|
args = f"{args}&label={label_id}"
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
return []
|
|
|
|
return []
|
|
|
|
return self.get_filter_items(args)
|
|
|
|
return self.fetchItems(args)
|
|
|
|
|
|
|
|
|
|
|
|
@retry(stop_max_attempt_number=6, wait_fixed=10000, retry_on_exception=util.retry_if_not_plex)
|
|
|
|
@retry(stop_max_attempt_number=6, wait_fixed=10000, retry_on_exception=util.retry_if_not_plex)
|
|
|
|
def search(self, title=None, sort=None, maxresults=None, libtype=None, **kwargs):
|
|
|
|
def search(self, title=None, sort=None, maxresults=None, libtype=None, **kwargs):
|
|
|
@ -527,6 +527,10 @@ class Plex(Library):
|
|
|
|
def fetchItem(self, data):
|
|
|
|
def fetchItem(self, data):
|
|
|
|
return self.PlexServer.fetchItem(data)
|
|
|
|
return self.PlexServer.fetchItem(data)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@retry(stop_max_attempt_number=6, wait_fixed=10000, retry_on_exception=util.retry_if_not_plex)
|
|
|
|
|
|
|
|
def fetchItems(self, uri_args):
|
|
|
|
|
|
|
|
return self.Plex.fetchItems(f"/library/sections/{self.Plex.key}/all{uri_args}")
|
|
|
|
|
|
|
|
|
|
|
|
def get_all(self, builder_level=None, load=False):
|
|
|
|
def get_all(self, builder_level=None, load=False):
|
|
|
|
if load and builder_level in [None, "show", "artist", "movie"]:
|
|
|
|
if load and builder_level in [None, "show", "artist", "movie"]:
|
|
|
|
self._all_items = []
|
|
|
|
self._all_items = []
|
|
|
@ -540,11 +544,22 @@ class Plex(Library):
|
|
|
|
container_start = 0
|
|
|
|
container_start = 0
|
|
|
|
container_size = plexapi.X_PLEX_CONTAINER_SIZE
|
|
|
|
container_size = plexapi.X_PLEX_CONTAINER_SIZE
|
|
|
|
results = []
|
|
|
|
results = []
|
|
|
|
while self.Plex._totalViewSize is None or container_start <= self.Plex._totalViewSize:
|
|
|
|
total_size = 1
|
|
|
|
results.extend(self.fetchItems(key, container_start, container_size))
|
|
|
|
while total_size > len(results) and container_start <= total_size:
|
|
|
|
logger.ghost(f"Loaded: {container_start}/{self.Plex._totalViewSize}")
|
|
|
|
data = self.Plex._server.query(key, headers={"X-Plex-Container-Start": str(container_start), "X-Plex-Container-Size": str(container_size)})
|
|
|
|
|
|
|
|
subresults = self.Plex.findItems(data, initpath=key)
|
|
|
|
|
|
|
|
total_size = utils.cast(int, data.attrib.get('totalSize') or data.attrib.get('size')) or len(subresults)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
librarySectionID = utils.cast(int, data.attrib.get('librarySectionID'))
|
|
|
|
|
|
|
|
if librarySectionID:
|
|
|
|
|
|
|
|
for item in subresults:
|
|
|
|
|
|
|
|
item.librarySectionID = librarySectionID
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
results.extend(subresults)
|
|
|
|
container_start += container_size
|
|
|
|
container_start += container_size
|
|
|
|
logger.info(f"Loaded {self.Plex._totalViewSize} {builder_level.capitalize()}s")
|
|
|
|
logger.ghost(f"Loaded: {total_size if container_start > total_size else container_start}/{total_size}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
logger.info(f"Loaded {total_size} {builder_level.capitalize()}s")
|
|
|
|
if builder_level in [None, "show", "artist", "movie"]:
|
|
|
|
if builder_level in [None, "show", "artist", "movie"]:
|
|
|
|
self._all_items = results
|
|
|
|
self._all_items = results
|
|
|
|
return results
|
|
|
|
return results
|
|
|
@ -560,10 +575,6 @@ class Plex(Library):
|
|
|
|
def create_playlist(self, name, items):
|
|
|
|
def create_playlist(self, name, items):
|
|
|
|
return self.PlexServer.createPlaylist(name, items=items)
|
|
|
|
return self.PlexServer.createPlaylist(name, items=items)
|
|
|
|
|
|
|
|
|
|
|
|
@retry(stop_max_attempt_number=6, wait_fixed=10000, retry_on_exception=util.retry_if_not_plex)
|
|
|
|
|
|
|
|
def fetchItems(self, key, container_start, container_size):
|
|
|
|
|
|
|
|
return self.Plex.fetchItems(key, container_start=container_start, container_size=container_size)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@retry(stop_max_attempt_number=6, wait_fixed=10000, retry_on_exception=util.retry_if_not_plex)
|
|
|
|
@retry(stop_max_attempt_number=6, wait_fixed=10000, retry_on_exception=util.retry_if_not_plex)
|
|
|
|
def moveItem(self, obj, item, after):
|
|
|
|
def moveItem(self, obj, item, after):
|
|
|
|
try:
|
|
|
|
try:
|
|
|
@ -858,7 +869,7 @@ class Plex(Library):
|
|
|
|
|
|
|
|
|
|
|
|
def test_smart_filter(self, uri_args):
|
|
|
|
def test_smart_filter(self, uri_args):
|
|
|
|
logger.debug(f"Smart Collection Test: {uri_args}")
|
|
|
|
logger.debug(f"Smart Collection Test: {uri_args}")
|
|
|
|
test_items = self.get_filter_items(uri_args)
|
|
|
|
test_items = self.fetchItems(uri_args)
|
|
|
|
if len(test_items) < 1:
|
|
|
|
if len(test_items) < 1:
|
|
|
|
raise Failed(f"Plex Error: No items for smart filter: {uri_args}")
|
|
|
|
raise Failed(f"Plex Error: No items for smart filter: {uri_args}")
|
|
|
|
|
|
|
|
|
|
|
@ -1028,7 +1039,7 @@ class Plex(Library):
|
|
|
|
elif method == "plex_search":
|
|
|
|
elif method == "plex_search":
|
|
|
|
logger.info(f"Processing {data[1]}")
|
|
|
|
logger.info(f"Processing {data[1]}")
|
|
|
|
logger.trace(data[2])
|
|
|
|
logger.trace(data[2])
|
|
|
|
items = self.get_filter_items(data[2])
|
|
|
|
items = self.fetchItems(data[2])
|
|
|
|
elif method == "plex_collectionless":
|
|
|
|
elif method == "plex_collectionless":
|
|
|
|
good_collections = []
|
|
|
|
good_collections = []
|
|
|
|
logger.info(f"Processing Plex Collectionless")
|
|
|
|
logger.info(f"Processing Plex Collectionless")
|
|
|
@ -1077,16 +1088,12 @@ class Plex(Library):
|
|
|
|
return self.search(label=collection.title if isinstance(collection, Collection) else str(collection))
|
|
|
|
return self.search(label=collection.title if isinstance(collection, Collection) else str(collection))
|
|
|
|
elif isinstance(collection, (Collection, Playlist)):
|
|
|
|
elif isinstance(collection, (Collection, Playlist)):
|
|
|
|
if collection.smart:
|
|
|
|
if collection.smart:
|
|
|
|
return self.get_filter_items(self.smart_filter(collection))
|
|
|
|
return self.fetchItems(self.smart_filter(collection))
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
return self.query(collection.items)
|
|
|
|
return self.query(collection.items)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
return []
|
|
|
|
return []
|
|
|
|
|
|
|
|
|
|
|
|
def get_filter_items(self, uri_args):
|
|
|
|
|
|
|
|
key = f"/library/sections/{self.Plex.key}/all{uri_args}"
|
|
|
|
|
|
|
|
return self.Plex._search(key, None, 0, plexapi.X_PLEX_CONTAINER_SIZE)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_collection_name_and_items(self, collection, smart_label_collection):
|
|
|
|
def get_collection_name_and_items(self, collection, smart_label_collection):
|
|
|
|
name = collection.title if isinstance(collection, (Collection, Playlist)) else str(collection)
|
|
|
|
name = collection.title if isinstance(collection, (Collection, Playlist)) else str(collection)
|
|
|
|
return name, self.get_collection_items(collection, smart_label_collection)
|
|
|
|
return name, self.get_collection_items(collection, smart_label_collection)
|
|
|
|