Update plexapi==4.15.13

This commit is contained in:
JonnyWong16 2024-05-18 13:52:52 -07:00
parent 8419eee4b2
commit 8396a04ce8
No known key found for this signature in database
GPG key ID: B1F1F9807184697A
10 changed files with 83 additions and 26 deletions

View file

@ -181,6 +181,7 @@ class Artist(
TYPE (str): '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).
audienceRating (float): Audience rating.
collections (List<:class:`~plexapi.media.Collection`>): List of collection objects.
countries (List<:class:`~plexapi.media.Country`>): List country objects.
genres (List<:class:`~plexapi.media.Genre`>): List of genre objects.
@ -188,6 +189,7 @@ class Artist(
key (str): API URL (/library/metadata/<ratingkey>).
labels (List<:class:`~plexapi.media.Label`>): List of label objects.
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.
styles (List<:class:`~plexapi.media.Style`>): List of style objects.
theme (str): URL to theme resource (/library/metadata/<ratingkey>/theme/<themeid>).
@ -199,6 +201,7 @@ class Artist(
""" Load attribute values from Plex XML response. """
Audio._loadData(self, data)
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.countries = self.findItems(data, media.Country)
self.genres = self.findItems(data, media.Genre)
@ -206,6 +209,7 @@ class Artist(
self.key = self.key.replace('/children', '') # FIX_BUG_50
self.labels = self.findItems(data, media.Label)
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.styles = self.findItems(data, media.Style)
self.theme = data.attrib.get('theme')
@ -301,6 +305,7 @@ class Album(
Attributes:
TAG (str): 'Directory'
TYPE (str): 'album'
audienceRating (float): Audience rating.
collections (List<:class:`~plexapi.media.Collection`>): List of collection objects.
formats (List<:class:`~plexapi.media.Format`>): List of format objects.
genres (List<:class:`~plexapi.media.Genre`>): List of genre objects.
@ -329,6 +334,7 @@ class Album(
def _loadData(self, data):
""" Load attribute values from Plex XML response. """
Audio._loadData(self, data)
self.audienceRating = utils.cast(float, data.attrib.get('audienceRating'))
self.collections = self.findItems(data, media.Collection)
self.formats = self.findItems(data, media.Format)
self.genres = self.findItems(data, media.Genre)
@ -426,6 +432,7 @@ class Track(
Attributes:
TAG (str): 'Directory'
TYPE (str): 'track'
audienceRating (float): Audience rating.
chapters (List<:class:`~plexapi.media.Chapter`>): List of Chapter objects.
chapterSource (str): Unknown
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>).
parentTitle (str): Name of the album 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.
skipCount (int): Number of times the track has been skipped.
sourceURI (str): Remote server URI (server://<machineIdentifier>/com.plexapp.plugins.library)
@ -465,6 +473,7 @@ class Track(
""" Load attribute values from Plex XML response. """
Audio._loadData(self, data)
Playable._loadData(self, data)
self.audienceRating = utils.cast(float, data.attrib.get('audienceRating'))
self.chapters = self.findItems(data, media.Chapter)
self.chapterSource = data.attrib.get('chapterSource')
self.collections = self.findItems(data, media.Collection)
@ -488,6 +497,7 @@ class Track(
self.parentThumb = data.attrib.get('parentThumb')
self.parentTitle = data.attrib.get('parentTitle')
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.skipCount = utils.cast(int, data.attrib.get('skipCount'))
self.sourceURI = data.attrib.get('source') # remote playlist item

View file

@ -253,7 +253,7 @@ class PlexObject:
fetchItem(ekey, viewCount__gte=0)
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, Media__Part__file__startswith="D:\\Movies")

View file

@ -29,6 +29,7 @@ class Collection(
addedAt (datetime): Datetime the collection was added to the library.
art (str): URL to artwork image (/library/metadata/<ratingKey>/art/<artid>).
artBlurHash (str): BlurHash string for artwork image.
audienceRating (float): Audience rating.
childCount (int): Number of items in the collection.
collectionFilterBasedOnUser (int): Which user's activity is used for the collection filtering.
collectionMode (int): How the items in the collection are displayed.
@ -47,6 +48,7 @@ class Collection(
librarySectionTitle (str): :class:`~plexapi.library.LibrarySection` title.
maxYear (int): Maximum 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.
ratingKey (int): Unique key identifying the 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.art = data.attrib.get('art')
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.collectionFilterBasedOnUser = utils.cast(int, data.attrib.get('collectionFilterBasedOnUser', '0'))
self.collectionMode = utils.cast(int, data.attrib.get('collectionMode', '-1'))
@ -87,6 +90,7 @@ class Collection(
self.librarySectionTitle = data.attrib.get('librarySectionTitle')
self.maxYear = utils.cast(int, data.attrib.get('maxYear'))
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.ratingKey = utils.cast(int, data.attrib.get('ratingKey'))
self.smart = utils.cast(bool, data.attrib.get('smart', '0'))

View file

@ -4,6 +4,6 @@
# Library version
MAJOR_VERSION = 4
MINOR_VERSION = 15
PATCH_VERSION = 12
PATCH_VERSION = 13
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
__version__ = f"{__short_version__}.{PATCH_VERSION}"

View file

@ -226,7 +226,7 @@ class Library(PlexObject):
section.deleteMediaPreviews()
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.
Parameters:
@ -234,7 +234,7 @@ class Library(PlexObject):
agent (str): Example com.plexapp.agents.imdb
type (str): movie, show, # check me
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.
**Photo Preferences**

View file

@ -567,6 +567,19 @@ class AddedAtMixin(EditFieldMixin):
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):
""" Mixin for Plex objects that can have a content rating. """
@ -580,6 +593,19 @@ class ContentRatingMixin(EditFieldMixin):
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):
""" Mixin for Plex objects that can have an edition title. """
@ -751,7 +777,7 @@ class UserRatingMixin(EditFieldMixin):
""" Edit the user rating.
Parameters:
userRating (int): The new value.
userRating (float): The new value.
locked (bool): True (default) to lock the field, False to unlock the field.
"""
return self.editField('userRating', userRating, locked=locked)
@ -1145,7 +1171,8 @@ class WatchlistMixin:
class MovieEditMixins(
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
AddedAtMixin, ContentRatingMixin, EditionTitleMixin, OriginallyAvailableMixin, OriginalTitleMixin, SortTitleMixin,
AddedAtMixin, AudienceRatingMixin, ContentRatingMixin, CriticRatingMixin, EditionTitleMixin,
OriginallyAvailableMixin, OriginalTitleMixin, SortTitleMixin,
StudioMixin, SummaryMixin, TaglineMixin, TitleMixin, UserRatingMixin,
CollectionMixin, CountryMixin, DirectorMixin, GenreMixin, LabelMixin, ProducerMixin, WriterMixin
):
@ -1154,7 +1181,8 @@ class MovieEditMixins(
class ShowEditMixins(
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
AddedAtMixin, ContentRatingMixin, OriginallyAvailableMixin, OriginalTitleMixin, SortTitleMixin, StudioMixin,
AddedAtMixin, AudienceRatingMixin, ContentRatingMixin, CriticRatingMixin,
OriginallyAvailableMixin, OriginalTitleMixin, SortTitleMixin, StudioMixin,
SummaryMixin, TaglineMixin, TitleMixin, UserRatingMixin,
CollectionMixin, GenreMixin, LabelMixin,
):
@ -1163,7 +1191,8 @@ class ShowEditMixins(
class SeasonEditMixins(
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
AddedAtMixin, SummaryMixin, TitleMixin, UserRatingMixin,
AddedAtMixin, AudienceRatingMixin, CriticRatingMixin,
SummaryMixin, TitleMixin, UserRatingMixin,
CollectionMixin, LabelMixin
):
pass
@ -1171,7 +1200,8 @@ class SeasonEditMixins(
class EpisodeEditMixins(
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
AddedAtMixin, ContentRatingMixin, OriginallyAvailableMixin, SortTitleMixin, SummaryMixin, TitleMixin, UserRatingMixin,
AddedAtMixin, AudienceRatingMixin, ContentRatingMixin, CriticRatingMixin,
OriginallyAvailableMixin, SortTitleMixin, SummaryMixin, TitleMixin, UserRatingMixin,
CollectionMixin, DirectorMixin, LabelMixin, WriterMixin
):
pass
@ -1179,7 +1209,8 @@ class EpisodeEditMixins(
class ArtistEditMixins(
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
AddedAtMixin, SortTitleMixin, SummaryMixin, TitleMixin, UserRatingMixin,
AddedAtMixin, AudienceRatingMixin, CriticRatingMixin,
SortTitleMixin, SummaryMixin, TitleMixin, UserRatingMixin,
CollectionMixin, CountryMixin, GenreMixin, LabelMixin, MoodMixin, SimilarArtistMixin, StyleMixin
):
pass
@ -1187,7 +1218,8 @@ class ArtistEditMixins(
class AlbumEditMixins(
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
AddedAtMixin, OriginallyAvailableMixin, SortTitleMixin, StudioMixin, SummaryMixin, TitleMixin, UserRatingMixin,
AddedAtMixin, AudienceRatingMixin, CriticRatingMixin,
OriginallyAvailableMixin, SortTitleMixin, StudioMixin, SummaryMixin, TitleMixin, UserRatingMixin,
CollectionMixin, GenreMixin, LabelMixin, MoodMixin, StyleMixin
):
pass
@ -1195,7 +1227,8 @@ class AlbumEditMixins(
class TrackEditMixins(
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
AddedAtMixin, TitleMixin, TrackArtistMixin, TrackNumberMixin, TrackDiscNumberMixin, UserRatingMixin,
AddedAtMixin, AudienceRatingMixin, CriticRatingMixin,
TitleMixin, TrackArtistMixin, TrackNumberMixin, TrackDiscNumberMixin, UserRatingMixin,
CollectionMixin, GenreMixin, LabelMixin, MoodMixin
):
pass
@ -1218,7 +1251,8 @@ class PhotoEditMixins(
class CollectionEditMixins(
ArtLockMixin, PosterLockMixin, ThemeLockMixin,
AddedAtMixin, ContentRatingMixin, SortTitleMixin, SummaryMixin, TitleMixin, UserRatingMixin,
AddedAtMixin, AudienceRatingMixin, ContentRatingMixin, CriticRatingMixin,
SortTitleMixin, SummaryMixin, TitleMixin, UserRatingMixin,
LabelMixin
):
pass

View file

@ -99,7 +99,7 @@ class MyPlexAccount(PlexObject):
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
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
MANAGEDHOMEUSER = 'https://plex.tv/api/v2/home/users/restricted/{userId}' # put
SIGNIN = 'https://plex.tv/api/v2/users/signin' # post with auth

View file

@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
import re
from itertools import groupby
from pathlib import Path
from urllib.parse import quote_plus, unquote
@ -212,19 +213,23 @@ class Playlist(
if items and not isinstance(items, (list, tuple)):
items = [items]
# Group items by server to maintain order when adding items from multiple servers
for server, _items in groupby(items, key=lambda item: item._server):
ratingKeys = []
for item in items:
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'{self._server._uriRoot()}/library/metadata/{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)
return self
@deprecated('use "removeItems" instead')

View file

@ -713,6 +713,7 @@ class Season(
Attributes:
TAG (str): 'Directory'
TYPE (str): 'season'
audienceRating (float): Audience rating.
audioLanguage (str): Setting that indicates the preferred audio language.
collections (List<:class:`~plexapi.media.Collection`>): List of collection 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>).
parentThumb (str): URL to show thumbnail image (/library/metadata/<parentRatingKey>/thumb/<thumbid>).
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.
subtitleLanguage (str): Setting that indicates the preferred subtitle language.
subtitleMode (int): Setting that indicates the auto-select subtitle mode.
@ -743,6 +745,7 @@ class Season(
def _loadData(self, data):
""" Load attribute values from Plex XML response. """
Video._loadData(self, data)
self.audienceRating = utils.cast(float, data.attrib.get('audienceRating'))
self.audioLanguage = data.attrib.get('audioLanguage', '')
self.collections = self.findItems(data, media.Collection)
self.guids = self.findItems(data, media.Guid)
@ -759,6 +762,7 @@ class Season(
self.parentTheme = data.attrib.get('parentTheme')
self.parentThumb = data.attrib.get('parentThumb')
self.parentTitle = data.attrib.get('parentTitle')
self.rating = utils.cast(float, data.attrib.get('rating'))
self.ratings = self.findItems(data, media.Rating)
self.subtitleLanguage = data.attrib.get('subtitleLanguage', '')
self.subtitleMode = utils.cast(int, data.attrib.get('subtitleMode', '-1'))

View file

@ -26,7 +26,7 @@ musicbrainzngs==0.7.1
packaging==24.0
paho-mqtt==2.1.0
platformdirs==4.2.2
plexapi==4.15.12
plexapi==4.15.13
portend==3.2.0
profilehooks==1.12.0
PyJWT==2.8.0