mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-07 21:51:14 -07:00
Update plexapi==4.15.13
This commit is contained in:
parent
8419eee4b2
commit
8396a04ce8
10 changed files with 83 additions and 26 deletions
|
@ -181,6 +181,7 @@ class Artist(
|
||||||
TYPE (str): 'artist'
|
TYPE (str): 'artist'
|
||||||
albumSort (int): Setting that indicates how albums are sorted for the artist
|
albumSort (int): Setting that indicates how albums are sorted for the artist
|
||||||
(-1 = Library default, 0 = Newest first, 1 = Oldest first, 2 = By name).
|
(-1 = Library default, 0 = Newest first, 1 = Oldest first, 2 = By name).
|
||||||
|
audienceRating (float): Audience rating.
|
||||||
collections (List<:class:`~plexapi.media.Collection`>): List of collection objects.
|
collections (List<:class:`~plexapi.media.Collection`>): List of collection objects.
|
||||||
countries (List<:class:`~plexapi.media.Country`>): List country objects.
|
countries (List<:class:`~plexapi.media.Country`>): List country objects.
|
||||||
genres (List<:class:`~plexapi.media.Genre`>): List of genre objects.
|
genres (List<:class:`~plexapi.media.Genre`>): List of genre objects.
|
||||||
|
@ -188,6 +189,7 @@ class Artist(
|
||||||
key (str): API URL (/library/metadata/<ratingkey>).
|
key (str): API URL (/library/metadata/<ratingkey>).
|
||||||
labels (List<:class:`~plexapi.media.Label`>): List of label objects.
|
labels (List<:class:`~plexapi.media.Label`>): List of label objects.
|
||||||
locations (List<str>): List of folder paths where the artist is found on disk.
|
locations (List<str>): List of folder paths where the artist is found on disk.
|
||||||
|
rating (float): Artist rating (7.9; 9.8; 8.1).
|
||||||
similar (List<:class:`~plexapi.media.Similar`>): List of similar objects.
|
similar (List<:class:`~plexapi.media.Similar`>): List of similar objects.
|
||||||
styles (List<:class:`~plexapi.media.Style`>): List of style objects.
|
styles (List<:class:`~plexapi.media.Style`>): List of style objects.
|
||||||
theme (str): URL to theme resource (/library/metadata/<ratingkey>/theme/<themeid>).
|
theme (str): URL to theme resource (/library/metadata/<ratingkey>/theme/<themeid>).
|
||||||
|
@ -199,6 +201,7 @@ class Artist(
|
||||||
""" Load attribute values from Plex XML response. """
|
""" Load attribute values from Plex XML response. """
|
||||||
Audio._loadData(self, data)
|
Audio._loadData(self, data)
|
||||||
self.albumSort = utils.cast(int, data.attrib.get('albumSort', '-1'))
|
self.albumSort = utils.cast(int, data.attrib.get('albumSort', '-1'))
|
||||||
|
self.audienceRating = utils.cast(float, data.attrib.get('audienceRating'))
|
||||||
self.collections = self.findItems(data, media.Collection)
|
self.collections = self.findItems(data, media.Collection)
|
||||||
self.countries = self.findItems(data, media.Country)
|
self.countries = self.findItems(data, media.Country)
|
||||||
self.genres = self.findItems(data, media.Genre)
|
self.genres = self.findItems(data, media.Genre)
|
||||||
|
@ -206,6 +209,7 @@ class Artist(
|
||||||
self.key = self.key.replace('/children', '') # FIX_BUG_50
|
self.key = self.key.replace('/children', '') # FIX_BUG_50
|
||||||
self.labels = self.findItems(data, media.Label)
|
self.labels = self.findItems(data, media.Label)
|
||||||
self.locations = self.listAttrs(data, 'path', etag='Location')
|
self.locations = self.listAttrs(data, 'path', etag='Location')
|
||||||
|
self.rating = utils.cast(float, data.attrib.get('rating'))
|
||||||
self.similar = self.findItems(data, media.Similar)
|
self.similar = self.findItems(data, media.Similar)
|
||||||
self.styles = self.findItems(data, media.Style)
|
self.styles = self.findItems(data, media.Style)
|
||||||
self.theme = data.attrib.get('theme')
|
self.theme = data.attrib.get('theme')
|
||||||
|
@ -301,6 +305,7 @@ class Album(
|
||||||
Attributes:
|
Attributes:
|
||||||
TAG (str): 'Directory'
|
TAG (str): 'Directory'
|
||||||
TYPE (str): 'album'
|
TYPE (str): 'album'
|
||||||
|
audienceRating (float): Audience rating.
|
||||||
collections (List<:class:`~plexapi.media.Collection`>): List of collection objects.
|
collections (List<:class:`~plexapi.media.Collection`>): List of collection objects.
|
||||||
formats (List<:class:`~plexapi.media.Format`>): List of format objects.
|
formats (List<:class:`~plexapi.media.Format`>): List of format objects.
|
||||||
genres (List<:class:`~plexapi.media.Genre`>): List of genre objects.
|
genres (List<:class:`~plexapi.media.Genre`>): List of genre objects.
|
||||||
|
@ -329,6 +334,7 @@ class Album(
|
||||||
def _loadData(self, data):
|
def _loadData(self, data):
|
||||||
""" Load attribute values from Plex XML response. """
|
""" Load attribute values from Plex XML response. """
|
||||||
Audio._loadData(self, data)
|
Audio._loadData(self, data)
|
||||||
|
self.audienceRating = utils.cast(float, data.attrib.get('audienceRating'))
|
||||||
self.collections = self.findItems(data, media.Collection)
|
self.collections = self.findItems(data, media.Collection)
|
||||||
self.formats = self.findItems(data, media.Format)
|
self.formats = self.findItems(data, media.Format)
|
||||||
self.genres = self.findItems(data, media.Genre)
|
self.genres = self.findItems(data, media.Genre)
|
||||||
|
@ -426,6 +432,7 @@ class Track(
|
||||||
Attributes:
|
Attributes:
|
||||||
TAG (str): 'Directory'
|
TAG (str): 'Directory'
|
||||||
TYPE (str): 'track'
|
TYPE (str): 'track'
|
||||||
|
audienceRating (float): Audience rating.
|
||||||
chapters (List<:class:`~plexapi.media.Chapter`>): List of Chapter objects.
|
chapters (List<:class:`~plexapi.media.Chapter`>): List of Chapter objects.
|
||||||
chapterSource (str): Unknown
|
chapterSource (str): Unknown
|
||||||
collections (List<:class:`~plexapi.media.Collection`>): List of collection objects.
|
collections (List<:class:`~plexapi.media.Collection`>): List of collection objects.
|
||||||
|
@ -451,6 +458,7 @@ class Track(
|
||||||
parentThumb (str): URL to album thumbnail image (/library/metadata/<parentRatingKey>/thumb/<thumbid>).
|
parentThumb (str): URL to album thumbnail image (/library/metadata/<parentRatingKey>/thumb/<thumbid>).
|
||||||
parentTitle (str): Name of the album for the track.
|
parentTitle (str): Name of the album for the track.
|
||||||
primaryExtraKey (str) API URL for the primary extra for the track.
|
primaryExtraKey (str) API URL for the primary extra for the track.
|
||||||
|
rating (float): Track rating (7.9; 9.8; 8.1).
|
||||||
ratingCount (int): Number of listeners who have scrobbled this track, as reported by Last.fm.
|
ratingCount (int): Number of listeners who have scrobbled this track, as reported by Last.fm.
|
||||||
skipCount (int): Number of times the track has been skipped.
|
skipCount (int): Number of times the track has been skipped.
|
||||||
sourceURI (str): Remote server URI (server://<machineIdentifier>/com.plexapp.plugins.library)
|
sourceURI (str): Remote server URI (server://<machineIdentifier>/com.plexapp.plugins.library)
|
||||||
|
@ -465,6 +473,7 @@ class Track(
|
||||||
""" Load attribute values from Plex XML response. """
|
""" Load attribute values from Plex XML response. """
|
||||||
Audio._loadData(self, data)
|
Audio._loadData(self, data)
|
||||||
Playable._loadData(self, data)
|
Playable._loadData(self, data)
|
||||||
|
self.audienceRating = utils.cast(float, data.attrib.get('audienceRating'))
|
||||||
self.chapters = self.findItems(data, media.Chapter)
|
self.chapters = self.findItems(data, media.Chapter)
|
||||||
self.chapterSource = data.attrib.get('chapterSource')
|
self.chapterSource = data.attrib.get('chapterSource')
|
||||||
self.collections = self.findItems(data, media.Collection)
|
self.collections = self.findItems(data, media.Collection)
|
||||||
|
@ -488,6 +497,7 @@ class Track(
|
||||||
self.parentThumb = data.attrib.get('parentThumb')
|
self.parentThumb = data.attrib.get('parentThumb')
|
||||||
self.parentTitle = data.attrib.get('parentTitle')
|
self.parentTitle = data.attrib.get('parentTitle')
|
||||||
self.primaryExtraKey = data.attrib.get('primaryExtraKey')
|
self.primaryExtraKey = data.attrib.get('primaryExtraKey')
|
||||||
|
self.rating = utils.cast(float, data.attrib.get('rating'))
|
||||||
self.ratingCount = utils.cast(int, data.attrib.get('ratingCount'))
|
self.ratingCount = utils.cast(int, data.attrib.get('ratingCount'))
|
||||||
self.skipCount = utils.cast(int, data.attrib.get('skipCount'))
|
self.skipCount = utils.cast(int, data.attrib.get('skipCount'))
|
||||||
self.sourceURI = data.attrib.get('source') # remote playlist item
|
self.sourceURI = data.attrib.get('source') # remote playlist item
|
||||||
|
|
|
@ -253,7 +253,7 @@ class PlexObject:
|
||||||
|
|
||||||
fetchItem(ekey, viewCount__gte=0)
|
fetchItem(ekey, viewCount__gte=0)
|
||||||
fetchItem(ekey, Media__container__in=["mp4", "mkv"])
|
fetchItem(ekey, Media__container__in=["mp4", "mkv"])
|
||||||
fetchItem(ekey, guid__regex=r"com\\.plexapp\\.agents\\.(imdb|themoviedb)://|tt\d+")
|
fetchItem(ekey, guid__regex=r"com\\.plexapp\\.agents\\.(imdb|themoviedb)://|tt\\d+")
|
||||||
fetchItem(ekey, guid__id__regex=r"(imdb|tmdb|tvdb)://")
|
fetchItem(ekey, guid__id__regex=r"(imdb|tmdb|tvdb)://")
|
||||||
fetchItem(ekey, Media__Part__file__startswith="D:\\Movies")
|
fetchItem(ekey, Media__Part__file__startswith="D:\\Movies")
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ class Collection(
|
||||||
addedAt (datetime): Datetime the collection was added to the library.
|
addedAt (datetime): Datetime the collection was added to the library.
|
||||||
art (str): URL to artwork image (/library/metadata/<ratingKey>/art/<artid>).
|
art (str): URL to artwork image (/library/metadata/<ratingKey>/art/<artid>).
|
||||||
artBlurHash (str): BlurHash string for artwork image.
|
artBlurHash (str): BlurHash string for artwork image.
|
||||||
|
audienceRating (float): Audience rating.
|
||||||
childCount (int): Number of items in the collection.
|
childCount (int): Number of items in the collection.
|
||||||
collectionFilterBasedOnUser (int): Which user's activity is used for the collection filtering.
|
collectionFilterBasedOnUser (int): Which user's activity is used for the collection filtering.
|
||||||
collectionMode (int): How the items in the collection are displayed.
|
collectionMode (int): How the items in the collection are displayed.
|
||||||
|
@ -47,6 +48,7 @@ class Collection(
|
||||||
librarySectionTitle (str): :class:`~plexapi.library.LibrarySection` title.
|
librarySectionTitle (str): :class:`~plexapi.library.LibrarySection` title.
|
||||||
maxYear (int): Maximum year for the items in the collection.
|
maxYear (int): Maximum year for the items in the collection.
|
||||||
minYear (int): Minimum year for the items in the collection.
|
minYear (int): Minimum year for the items in the collection.
|
||||||
|
rating (float): Collection rating (7.9; 9.8; 8.1).
|
||||||
ratingCount (int): The number of ratings.
|
ratingCount (int): The number of ratings.
|
||||||
ratingKey (int): Unique key identifying the collection.
|
ratingKey (int): Unique key identifying the collection.
|
||||||
smart (bool): True if the collection is a smart collection.
|
smart (bool): True if the collection is a smart collection.
|
||||||
|
@ -69,6 +71,7 @@ class Collection(
|
||||||
self.addedAt = utils.toDatetime(data.attrib.get('addedAt'))
|
self.addedAt = utils.toDatetime(data.attrib.get('addedAt'))
|
||||||
self.art = data.attrib.get('art')
|
self.art = data.attrib.get('art')
|
||||||
self.artBlurHash = data.attrib.get('artBlurHash')
|
self.artBlurHash = data.attrib.get('artBlurHash')
|
||||||
|
self.audienceRating = utils.cast(float, data.attrib.get('audienceRating'))
|
||||||
self.childCount = utils.cast(int, data.attrib.get('childCount'))
|
self.childCount = utils.cast(int, data.attrib.get('childCount'))
|
||||||
self.collectionFilterBasedOnUser = utils.cast(int, data.attrib.get('collectionFilterBasedOnUser', '0'))
|
self.collectionFilterBasedOnUser = utils.cast(int, data.attrib.get('collectionFilterBasedOnUser', '0'))
|
||||||
self.collectionMode = utils.cast(int, data.attrib.get('collectionMode', '-1'))
|
self.collectionMode = utils.cast(int, data.attrib.get('collectionMode', '-1'))
|
||||||
|
@ -87,6 +90,7 @@ class Collection(
|
||||||
self.librarySectionTitle = data.attrib.get('librarySectionTitle')
|
self.librarySectionTitle = data.attrib.get('librarySectionTitle')
|
||||||
self.maxYear = utils.cast(int, data.attrib.get('maxYear'))
|
self.maxYear = utils.cast(int, data.attrib.get('maxYear'))
|
||||||
self.minYear = utils.cast(int, data.attrib.get('minYear'))
|
self.minYear = utils.cast(int, data.attrib.get('minYear'))
|
||||||
|
self.rating = utils.cast(float, data.attrib.get('rating'))
|
||||||
self.ratingCount = utils.cast(int, data.attrib.get('ratingCount'))
|
self.ratingCount = utils.cast(int, data.attrib.get('ratingCount'))
|
||||||
self.ratingKey = utils.cast(int, data.attrib.get('ratingKey'))
|
self.ratingKey = utils.cast(int, data.attrib.get('ratingKey'))
|
||||||
self.smart = utils.cast(bool, data.attrib.get('smart', '0'))
|
self.smart = utils.cast(bool, data.attrib.get('smart', '0'))
|
||||||
|
|
|
@ -4,6 +4,6 @@
|
||||||
# Library version
|
# Library version
|
||||||
MAJOR_VERSION = 4
|
MAJOR_VERSION = 4
|
||||||
MINOR_VERSION = 15
|
MINOR_VERSION = 15
|
||||||
PATCH_VERSION = 12
|
PATCH_VERSION = 13
|
||||||
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||||
__version__ = f"{__short_version__}.{PATCH_VERSION}"
|
__version__ = f"{__short_version__}.{PATCH_VERSION}"
|
||||||
|
|
|
@ -226,7 +226,7 @@ class Library(PlexObject):
|
||||||
section.deleteMediaPreviews()
|
section.deleteMediaPreviews()
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def add(self, name='', type='', agent='', scanner='', location='', language='en', *args, **kwargs):
|
def add(self, name='', type='', agent='', scanner='', location='', language='en-US', *args, **kwargs):
|
||||||
""" Simplified add for the most common options.
|
""" Simplified add for the most common options.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
|
@ -234,7 +234,7 @@ class Library(PlexObject):
|
||||||
agent (str): Example com.plexapp.agents.imdb
|
agent (str): Example com.plexapp.agents.imdb
|
||||||
type (str): movie, show, # check me
|
type (str): movie, show, # check me
|
||||||
location (str or list): /path/to/files, ["/path/to/files", "/path/to/morefiles"]
|
location (str or list): /path/to/files, ["/path/to/files", "/path/to/morefiles"]
|
||||||
language (str): Two letter language fx en
|
language (str): Four letter language code (e.g. en-US)
|
||||||
kwargs (dict): Advanced options should be passed as a dict. where the id is the key.
|
kwargs (dict): Advanced options should be passed as a dict. where the id is the key.
|
||||||
|
|
||||||
**Photo Preferences**
|
**Photo Preferences**
|
||||||
|
|
|
@ -567,6 +567,19 @@ class AddedAtMixin(EditFieldMixin):
|
||||||
return self.editField('addedAt', addedAt, locked=locked)
|
return self.editField('addedAt', addedAt, locked=locked)
|
||||||
|
|
||||||
|
|
||||||
|
class AudienceRatingMixin(EditFieldMixin):
|
||||||
|
""" Mixin for Plex objects that can have an audience rating. """
|
||||||
|
|
||||||
|
def editAudienceRating(self, audienceRating, locked=True):
|
||||||
|
""" Edit the audience rating.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
audienceRating (float): The new value.
|
||||||
|
locked (bool): True (default) to lock the field, False to unlock the field.
|
||||||
|
"""
|
||||||
|
return self.editField('audienceRating', audienceRating, locked=locked)
|
||||||
|
|
||||||
|
|
||||||
class ContentRatingMixin(EditFieldMixin):
|
class ContentRatingMixin(EditFieldMixin):
|
||||||
""" Mixin for Plex objects that can have a content rating. """
|
""" Mixin for Plex objects that can have a content rating. """
|
||||||
|
|
||||||
|
@ -580,6 +593,19 @@ class ContentRatingMixin(EditFieldMixin):
|
||||||
return self.editField('contentRating', contentRating, locked=locked)
|
return self.editField('contentRating', contentRating, locked=locked)
|
||||||
|
|
||||||
|
|
||||||
|
class CriticRatingMixin(EditFieldMixin):
|
||||||
|
""" Mixin for Plex objects that can have a critic rating. """
|
||||||
|
|
||||||
|
def editCriticRating(self, criticRating, locked=True):
|
||||||
|
""" Edit the critic rating.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
criticRating (float): The new value.
|
||||||
|
locked (bool): True (default) to lock the field, False to unlock the field.
|
||||||
|
"""
|
||||||
|
return self.editField('rating', criticRating, locked=locked)
|
||||||
|
|
||||||
|
|
||||||
class EditionTitleMixin(EditFieldMixin):
|
class EditionTitleMixin(EditFieldMixin):
|
||||||
""" Mixin for Plex objects that can have an edition title. """
|
""" Mixin for Plex objects that can have an edition title. """
|
||||||
|
|
||||||
|
@ -751,7 +777,7 @@ class UserRatingMixin(EditFieldMixin):
|
||||||
""" Edit the user rating.
|
""" Edit the user rating.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
userRating (int): The new value.
|
userRating (float): The new value.
|
||||||
locked (bool): True (default) to lock the field, False to unlock the field.
|
locked (bool): True (default) to lock the field, False to unlock the field.
|
||||||
"""
|
"""
|
||||||
return self.editField('userRating', userRating, locked=locked)
|
return self.editField('userRating', userRating, locked=locked)
|
||||||
|
@ -1145,7 +1171,8 @@ class WatchlistMixin:
|
||||||
|
|
||||||
class MovieEditMixins(
|
class MovieEditMixins(
|
||||||
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
|
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
|
||||||
AddedAtMixin, ContentRatingMixin, EditionTitleMixin, OriginallyAvailableMixin, OriginalTitleMixin, SortTitleMixin,
|
AddedAtMixin, AudienceRatingMixin, ContentRatingMixin, CriticRatingMixin, EditionTitleMixin,
|
||||||
|
OriginallyAvailableMixin, OriginalTitleMixin, SortTitleMixin,
|
||||||
StudioMixin, SummaryMixin, TaglineMixin, TitleMixin, UserRatingMixin,
|
StudioMixin, SummaryMixin, TaglineMixin, TitleMixin, UserRatingMixin,
|
||||||
CollectionMixin, CountryMixin, DirectorMixin, GenreMixin, LabelMixin, ProducerMixin, WriterMixin
|
CollectionMixin, CountryMixin, DirectorMixin, GenreMixin, LabelMixin, ProducerMixin, WriterMixin
|
||||||
):
|
):
|
||||||
|
@ -1154,7 +1181,8 @@ class MovieEditMixins(
|
||||||
|
|
||||||
class ShowEditMixins(
|
class ShowEditMixins(
|
||||||
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
|
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
|
||||||
AddedAtMixin, ContentRatingMixin, OriginallyAvailableMixin, OriginalTitleMixin, SortTitleMixin, StudioMixin,
|
AddedAtMixin, AudienceRatingMixin, ContentRatingMixin, CriticRatingMixin,
|
||||||
|
OriginallyAvailableMixin, OriginalTitleMixin, SortTitleMixin, StudioMixin,
|
||||||
SummaryMixin, TaglineMixin, TitleMixin, UserRatingMixin,
|
SummaryMixin, TaglineMixin, TitleMixin, UserRatingMixin,
|
||||||
CollectionMixin, GenreMixin, LabelMixin,
|
CollectionMixin, GenreMixin, LabelMixin,
|
||||||
):
|
):
|
||||||
|
@ -1163,7 +1191,8 @@ class ShowEditMixins(
|
||||||
|
|
||||||
class SeasonEditMixins(
|
class SeasonEditMixins(
|
||||||
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
|
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
|
||||||
AddedAtMixin, SummaryMixin, TitleMixin, UserRatingMixin,
|
AddedAtMixin, AudienceRatingMixin, CriticRatingMixin,
|
||||||
|
SummaryMixin, TitleMixin, UserRatingMixin,
|
||||||
CollectionMixin, LabelMixin
|
CollectionMixin, LabelMixin
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
@ -1171,7 +1200,8 @@ class SeasonEditMixins(
|
||||||
|
|
||||||
class EpisodeEditMixins(
|
class EpisodeEditMixins(
|
||||||
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
|
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
|
||||||
AddedAtMixin, ContentRatingMixin, OriginallyAvailableMixin, SortTitleMixin, SummaryMixin, TitleMixin, UserRatingMixin,
|
AddedAtMixin, AudienceRatingMixin, ContentRatingMixin, CriticRatingMixin,
|
||||||
|
OriginallyAvailableMixin, SortTitleMixin, SummaryMixin, TitleMixin, UserRatingMixin,
|
||||||
CollectionMixin, DirectorMixin, LabelMixin, WriterMixin
|
CollectionMixin, DirectorMixin, LabelMixin, WriterMixin
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
@ -1179,7 +1209,8 @@ class EpisodeEditMixins(
|
||||||
|
|
||||||
class ArtistEditMixins(
|
class ArtistEditMixins(
|
||||||
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
|
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
|
||||||
AddedAtMixin, SortTitleMixin, SummaryMixin, TitleMixin, UserRatingMixin,
|
AddedAtMixin, AudienceRatingMixin, CriticRatingMixin,
|
||||||
|
SortTitleMixin, SummaryMixin, TitleMixin, UserRatingMixin,
|
||||||
CollectionMixin, CountryMixin, GenreMixin, LabelMixin, MoodMixin, SimilarArtistMixin, StyleMixin
|
CollectionMixin, CountryMixin, GenreMixin, LabelMixin, MoodMixin, SimilarArtistMixin, StyleMixin
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
@ -1187,7 +1218,8 @@ class ArtistEditMixins(
|
||||||
|
|
||||||
class AlbumEditMixins(
|
class AlbumEditMixins(
|
||||||
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
|
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
|
||||||
AddedAtMixin, OriginallyAvailableMixin, SortTitleMixin, StudioMixin, SummaryMixin, TitleMixin, UserRatingMixin,
|
AddedAtMixin, AudienceRatingMixin, CriticRatingMixin,
|
||||||
|
OriginallyAvailableMixin, SortTitleMixin, StudioMixin, SummaryMixin, TitleMixin, UserRatingMixin,
|
||||||
CollectionMixin, GenreMixin, LabelMixin, MoodMixin, StyleMixin
|
CollectionMixin, GenreMixin, LabelMixin, MoodMixin, StyleMixin
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
@ -1195,7 +1227,8 @@ class AlbumEditMixins(
|
||||||
|
|
||||||
class TrackEditMixins(
|
class TrackEditMixins(
|
||||||
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
|
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
|
||||||
AddedAtMixin, TitleMixin, TrackArtistMixin, TrackNumberMixin, TrackDiscNumberMixin, UserRatingMixin,
|
AddedAtMixin, AudienceRatingMixin, CriticRatingMixin,
|
||||||
|
TitleMixin, TrackArtistMixin, TrackNumberMixin, TrackDiscNumberMixin, UserRatingMixin,
|
||||||
CollectionMixin, GenreMixin, LabelMixin, MoodMixin
|
CollectionMixin, GenreMixin, LabelMixin, MoodMixin
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
@ -1218,7 +1251,8 @@ class PhotoEditMixins(
|
||||||
|
|
||||||
class CollectionEditMixins(
|
class CollectionEditMixins(
|
||||||
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
|
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
|
||||||
AddedAtMixin, ContentRatingMixin, SortTitleMixin, SummaryMixin, TitleMixin, UserRatingMixin,
|
AddedAtMixin, AudienceRatingMixin, ContentRatingMixin, CriticRatingMixin,
|
||||||
|
SortTitleMixin, SummaryMixin, TitleMixin, UserRatingMixin,
|
||||||
LabelMixin
|
LabelMixin
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -99,7 +99,7 @@ class MyPlexAccount(PlexObject):
|
||||||
EXISTINGUSER = 'https://plex.tv/api/home/users?invitedEmail={username}' # post with data
|
EXISTINGUSER = 'https://plex.tv/api/home/users?invitedEmail={username}' # post with data
|
||||||
FRIENDSERVERS = 'https://plex.tv/api/servers/{machineId}/shared_servers/{serverId}' # put with data
|
FRIENDSERVERS = 'https://plex.tv/api/servers/{machineId}/shared_servers/{serverId}' # put with data
|
||||||
PLEXSERVERS = 'https://plex.tv/api/servers/{machineId}' # get
|
PLEXSERVERS = 'https://plex.tv/api/servers/{machineId}' # get
|
||||||
FRIENDUPDATE = 'https://plex.tv/api/friends/{userId}' # put with args, delete
|
FRIENDUPDATE = 'https://plex.tv/api/v2/sharings/{userId}' # put with args, delete
|
||||||
HOMEUSER = 'https://plex.tv/api/home/users/{userId}' # delete, put
|
HOMEUSER = 'https://plex.tv/api/home/users/{userId}' # delete, put
|
||||||
MANAGEDHOMEUSER = 'https://plex.tv/api/v2/home/users/restricted/{userId}' # put
|
MANAGEDHOMEUSER = 'https://plex.tv/api/v2/home/users/restricted/{userId}' # put
|
||||||
SIGNIN = 'https://plex.tv/api/v2/users/signin' # post with auth
|
SIGNIN = 'https://plex.tv/api/v2/users/signin' # post with auth
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import re
|
import re
|
||||||
|
from itertools import groupby
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from urllib.parse import quote_plus, unquote
|
from urllib.parse import quote_plus, unquote
|
||||||
|
|
||||||
|
@ -212,19 +213,23 @@ class Playlist(
|
||||||
if items and not isinstance(items, (list, tuple)):
|
if items and not isinstance(items, (list, tuple)):
|
||||||
items = [items]
|
items = [items]
|
||||||
|
|
||||||
ratingKeys = []
|
# Group items by server to maintain order when adding items from multiple servers
|
||||||
for item in items:
|
for server, _items in groupby(items, key=lambda item: item._server):
|
||||||
if item.listType != self.playlistType: # pragma: no cover
|
|
||||||
raise BadRequest(f'Can not mix media types when building a playlist: '
|
|
||||||
f'{self.playlistType} and {item.listType}')
|
|
||||||
ratingKeys.append(str(item.ratingKey))
|
|
||||||
|
|
||||||
ratingKeys = ','.join(ratingKeys)
|
ratingKeys = []
|
||||||
uri = f'{self._server._uriRoot()}/library/metadata/{ratingKeys}'
|
for item in _items:
|
||||||
|
if item.listType != self.playlistType: # pragma: no cover
|
||||||
|
raise BadRequest(f'Can not mix media types when building a playlist: '
|
||||||
|
f'{self.playlistType} and {item.listType}')
|
||||||
|
ratingKeys.append(str(item.ratingKey))
|
||||||
|
|
||||||
|
ratingKeys = ','.join(ratingKeys)
|
||||||
|
uri = f'{server._uriRoot()}/library/metadata/{ratingKeys}'
|
||||||
|
|
||||||
|
args = {'uri': uri}
|
||||||
|
key = f"{self.key}/items{utils.joinArgs(args)}"
|
||||||
|
self._server.query(key, method=self._server._session.put)
|
||||||
|
|
||||||
args = {'uri': uri}
|
|
||||||
key = f"{self.key}/items{utils.joinArgs(args)}"
|
|
||||||
self._server.query(key, method=self._server._session.put)
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@deprecated('use "removeItems" instead')
|
@deprecated('use "removeItems" instead')
|
||||||
|
|
|
@ -713,6 +713,7 @@ class Season(
|
||||||
Attributes:
|
Attributes:
|
||||||
TAG (str): 'Directory'
|
TAG (str): 'Directory'
|
||||||
TYPE (str): 'season'
|
TYPE (str): 'season'
|
||||||
|
audienceRating (float): Audience rating.
|
||||||
audioLanguage (str): Setting that indicates the preferred audio language.
|
audioLanguage (str): Setting that indicates the preferred audio language.
|
||||||
collections (List<:class:`~plexapi.media.Collection`>): List of collection objects.
|
collections (List<:class:`~plexapi.media.Collection`>): List of collection objects.
|
||||||
guids (List<:class:`~plexapi.media.Guid`>): List of guid objects.
|
guids (List<:class:`~plexapi.media.Guid`>): List of guid objects.
|
||||||
|
@ -729,6 +730,7 @@ class Season(
|
||||||
parentTheme (str): URL to show theme resource (/library/metadata/<parentRatingkey>/theme/<themeid>).
|
parentTheme (str): URL to show theme resource (/library/metadata/<parentRatingkey>/theme/<themeid>).
|
||||||
parentThumb (str): URL to show thumbnail image (/library/metadata/<parentRatingKey>/thumb/<thumbid>).
|
parentThumb (str): URL to show thumbnail image (/library/metadata/<parentRatingKey>/thumb/<thumbid>).
|
||||||
parentTitle (str): Name of the show for the season.
|
parentTitle (str): Name of the show for the season.
|
||||||
|
rating (float): Season rating (7.9; 9.8; 8.1).
|
||||||
ratings (List<:class:`~plexapi.media.Rating`>): List of rating objects.
|
ratings (List<:class:`~plexapi.media.Rating`>): List of rating objects.
|
||||||
subtitleLanguage (str): Setting that indicates the preferred subtitle language.
|
subtitleLanguage (str): Setting that indicates the preferred subtitle language.
|
||||||
subtitleMode (int): Setting that indicates the auto-select subtitle mode.
|
subtitleMode (int): Setting that indicates the auto-select subtitle mode.
|
||||||
|
@ -743,6 +745,7 @@ class Season(
|
||||||
def _loadData(self, data):
|
def _loadData(self, data):
|
||||||
""" Load attribute values from Plex XML response. """
|
""" Load attribute values from Plex XML response. """
|
||||||
Video._loadData(self, data)
|
Video._loadData(self, data)
|
||||||
|
self.audienceRating = utils.cast(float, data.attrib.get('audienceRating'))
|
||||||
self.audioLanguage = data.attrib.get('audioLanguage', '')
|
self.audioLanguage = data.attrib.get('audioLanguage', '')
|
||||||
self.collections = self.findItems(data, media.Collection)
|
self.collections = self.findItems(data, media.Collection)
|
||||||
self.guids = self.findItems(data, media.Guid)
|
self.guids = self.findItems(data, media.Guid)
|
||||||
|
@ -759,6 +762,7 @@ class Season(
|
||||||
self.parentTheme = data.attrib.get('parentTheme')
|
self.parentTheme = data.attrib.get('parentTheme')
|
||||||
self.parentThumb = data.attrib.get('parentThumb')
|
self.parentThumb = data.attrib.get('parentThumb')
|
||||||
self.parentTitle = data.attrib.get('parentTitle')
|
self.parentTitle = data.attrib.get('parentTitle')
|
||||||
|
self.rating = utils.cast(float, data.attrib.get('rating'))
|
||||||
self.ratings = self.findItems(data, media.Rating)
|
self.ratings = self.findItems(data, media.Rating)
|
||||||
self.subtitleLanguage = data.attrib.get('subtitleLanguage', '')
|
self.subtitleLanguage = data.attrib.get('subtitleLanguage', '')
|
||||||
self.subtitleMode = utils.cast(int, data.attrib.get('subtitleMode', '-1'))
|
self.subtitleMode = utils.cast(int, data.attrib.get('subtitleMode', '-1'))
|
||||||
|
|
|
@ -26,7 +26,7 @@ musicbrainzngs==0.7.1
|
||||||
packaging==24.0
|
packaging==24.0
|
||||||
paho-mqtt==2.1.0
|
paho-mqtt==2.1.0
|
||||||
platformdirs==4.2.2
|
platformdirs==4.2.2
|
||||||
plexapi==4.15.12
|
plexapi==4.15.13
|
||||||
portend==3.2.0
|
portend==3.2.0
|
||||||
profilehooks==1.12.0
|
profilehooks==1.12.0
|
||||||
PyJWT==2.8.0
|
PyJWT==2.8.0
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue