Skip to content

Commit 7bdc9ed

Browse files
authored
Add support for the new Plex TV agent (#679)
* Add new Plex TV agent to library doc string * Update new Plex TV agent show/season/episode attributes * Update tests for new Plex TV agent show/season/episode attributes * Fix test for show attributes * Add network attribute to show * Add show network to tests
1 parent a78126e commit 7bdc9ed

3 files changed

Lines changed: 65 additions & 2 deletions

File tree

plexapi/library.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,12 +216,13 @@ def add(self, name='', type='', agent='', scanner='', location='', language='en'
216216
217217
**Show Preferences**
218218
219-
* **agent** (str): com.plexapp.agents.none, com.plexapp.agents.thetvdb, com.plexapp.agents.themoviedb
219+
* **agent** (str): com.plexapp.agents.none, com.plexapp.agents.thetvdb, com.plexapp.agents.themoviedb,
220+
tv.plex.agent.series
220221
* **enableBIFGeneration** (bool): Enable video preview thumbnails. Default value true.
221222
* **episodeSort** (int): Episode order. Default -1 Possible options: 0:Oldest first, 1:Newest first.
222223
* **flattenSeasons** (int): Seasons. Default value 0 Possible options: 0:Show,1:Hide.
223224
* **includeInGlobal** (bool): Include in dashboard. Default value true.
224-
* **scanner** (str): Plex Series Scanner
225+
* **scanner** (str): Plex TV Series, Plex Series Scanner
225226
226227
**TheTVDB Show Options** (com.plexapp.agents.thetvdb)
227228

plexapi/video.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,25 +382,47 @@ class Show(Video, ArtMixin, BannerMixin, PosterMixin, SplitMergeMixin, UnmatchMa
382382
Attributes:
383383
TAG (str): 'Directory'
384384
TYPE (str): 'show'
385+
audienceRating (float): Audience rating (TMDB or TVDB).
386+
audienceRatingImage (str): Key to audience rating image (tmdb://image.rating).
387+
autoDeletionItemPolicyUnwatchedLibrary (int): Setting that indicates the number of unplayed
388+
episodes to keep for the show (0 = All episodes, 5 = 5 latest episodes, 3 = 3 latest episodes,
389+
1 = 1 latest episode, -3 = Episodes added in the past 3 days, -7 = Episodes added in the
390+
past 7 days, -30 = Episodes added in the past 30 days).
391+
autoDeletionItemPolicyWatchedLibrary (int): Setting that indicates if episodes are deleted
392+
after being watched for the show (0 = Never, 1 = After a day, 7 = After a week,
393+
100 = On next refresh).
385394
banner (str): Key to banner artwork (/library/metadata/<ratingkey>/banner/<bannerid>).
386395
childCount (int): Number of seasons in the show.
387396
collections (List<:class:`~plexapi.media.Collection`>): List of collection objects.
388397
contentRating (str) Content rating (PG-13; NR; TV-G).
389398
duration (int): Typical duration of the show episodes in milliseconds.
399+
episodeSort (int): Setting that indicates how episodes are sorted for the show
400+
(-1 = Library default, 0 = Oldest first, 1 = Newest first).
401+
flattenSeasons (int): Setting that indicates if seasons are set to hidden for the show
402+
(-1 = Library default, 0 = Hide, 1 = Show).
390403
genres (List<:class:`~plexapi.media.Genre`>): List of genre objects.
404+
guids (List<:class:`~plexapi.media.Guid`>): List of guid objects.
391405
index (int): Plex index number for the show.
392406
key (str): API URL (/library/metadata/<ratingkey>).
393407
labels (List<:class:`~plexapi.media.Label`>): List of label objects.
408+
languageOverride (str): Setting that indicates if a languge is used to override metadata
409+
(eg. en-CA, None = Library default).
394410
leafCount (int): Number of items in the show view.
395411
locations (List<str>): List of folder paths where the show is found on disk.
412+
network (str): The network that distributed the show.
396413
originallyAvailableAt (datetime): Datetime the show was released.
397414
originalTitle (str): The original title of the show.
398415
rating (float): Show rating (7.9; 9.8; 8.1).
399416
roles (List<:class:`~plexapi.media.Role`>): List of role objects.
417+
showOrdering (str): Setting that indicates the episode ordering for the show
418+
(None = Library default).
400419
similar (List<:class:`~plexapi.media.Similar`>): List of Similar objects.
401420
studio (str): Studio that created show (Di Bonaventura Pictures; 21 Laps Entertainment).
402421
tagline (str): Show tag line.
403422
theme (str): URL to theme resource (/library/metadata/<ratingkey>/theme/<themeid>).
423+
useOriginalTitle (int): Setting that indicates if the original title is used for the show
424+
(-1 = Library default, 0 = No, 1 = Yes).
425+
userRating (float): User rating (2.0; 8.0).
404426
viewedLeafCount (int): Number of items marked as played in the show view.
405427
year (int): Year the show was released.
406428
"""
@@ -411,25 +433,39 @@ class Show(Video, ArtMixin, BannerMixin, PosterMixin, SplitMergeMixin, UnmatchMa
411433
def _loadData(self, data):
412434
""" Load attribute values from Plex XML response. """
413435
Video._loadData(self, data)
436+
self.audienceRating = utils.cast(float, data.attrib.get('audienceRating'))
437+
self.audienceRatingImage = data.attrib.get('audienceRatingImage')
438+
self.autoDeletionItemPolicyUnwatchedLibrary = utils.cast(
439+
int, data.attrib.get('autoDeletionItemPolicyUnwatchedLibrary', '0'))
440+
self.autoDeletionItemPolicyWatchedLibrary = utils.cast(
441+
int, data.attrib.get('autoDeletionItemPolicyWatchedLibrary', '0'))
414442
self.banner = data.attrib.get('banner')
415443
self.childCount = utils.cast(int, data.attrib.get('childCount'))
416444
self.collections = self.findItems(data, media.Collection)
417445
self.contentRating = data.attrib.get('contentRating')
418446
self.duration = utils.cast(int, data.attrib.get('duration'))
447+
self.episodeSort = utils.cast(int, data.attrib.get('episodeSort', '-1'))
448+
self.flattenSeasons = utils.cast(int, data.attrib.get('flattenSeasons', '-1'))
419449
self.genres = self.findItems(data, media.Genre)
450+
self.guids = self.findItems(data, media.Guid)
420451
self.index = utils.cast(int, data.attrib.get('index'))
421452
self.key = self.key.replace('/children', '') # FIX_BUG_50
422453
self.labels = self.findItems(data, media.Label)
454+
self.languageOverride = data.attrib.get('languageOverride')
423455
self.leafCount = utils.cast(int, data.attrib.get('leafCount'))
424456
self.locations = self.listAttrs(data, 'path', etag='Location')
457+
self.network = data.attrib.get('network')
425458
self.originallyAvailableAt = utils.toDatetime(data.attrib.get('originallyAvailableAt'), '%Y-%m-%d')
426459
self.originalTitle = data.attrib.get('originalTitle')
427460
self.rating = utils.cast(float, data.attrib.get('rating'))
428461
self.roles = self.findItems(data, media.Role)
462+
self.showOrdering = data.attrib.get('showOrdering')
429463
self.similar = self.findItems(data, media.Similar)
430464
self.studio = data.attrib.get('studio')
431465
self.tagline = data.attrib.get('tagline')
432466
self.theme = data.attrib.get('theme')
467+
self.useOriginalTitle = utils.cast(int, data.attrib.get('useOriginalTitle', '-1'))
468+
self.userRating = utils.cast(float, data.attrib.get('userRating'))
433469
self.viewedLeafCount = utils.cast(int, data.attrib.get('viewedLeafCount'))
434470
self.year = utils.cast(int, data.attrib.get('year'))
435471

@@ -584,6 +620,7 @@ class Season(Video, ArtMixin, PosterMixin):
584620
Attributes:
585621
TAG (str): 'Directory'
586622
TYPE (str): 'season'
623+
guids (List<:class:`~plexapi.media.Guid`>): List of guid objects.
587624
index (int): Season number.
588625
key (str): API URL (/library/metadata/<ratingkey>).
589626
leafCount (int): Number of items in the season view.
@@ -603,6 +640,7 @@ class Season(Video, ArtMixin, PosterMixin):
603640
def _loadData(self, data):
604641
""" Load attribute values from Plex XML response. """
605642
Video._loadData(self, data)
643+
self.guids = self.findItems(data, media.Guid)
606644
self.index = utils.cast(int, data.attrib.get('index'))
607645
self.key = self.key.replace('/children', '') # FIX_BUG_50
608646
self.leafCount = utils.cast(int, data.attrib.get('leafCount'))
@@ -711,6 +749,8 @@ class Episode(Video, Playable, ArtMixin, PosterMixin,
711749
Attributes:
712750
TAG (str): 'Video'
713751
TYPE (str): 'episode'
752+
audienceRating (float): Audience rating (TMDB or TVDB).
753+
audienceRatingImage (str): Key to audience rating image (tmdb://image.rating).
714754
chapters (List<:class:`~plexapi.media.Chapter`>): List of Chapter objects.
715755
chapterSource (str): Chapter source (agent; media; mixed).
716756
contentRating (str) Content rating (PG-13; NR; TV-G).
@@ -723,6 +763,7 @@ class Episode(Video, Playable, ArtMixin, PosterMixin,
723763
grandparentTheme (str): URL to show theme resource (/library/metadata/<grandparentRatingkey>/theme/<themeid>).
724764
grandparentThumb (str): URL to show thumbnail image (/library/metadata/<grandparentRatingKey>/thumb/<thumbid>).
725765
grandparentTitle (str): Name of the show for the episode.
766+
guids (List<:class:`~plexapi.media.Guid`>): List of guid objects.
726767
index (int): Episode number.
727768
markers (List<:class:`~plexapi.media.Marker`>): List of marker objects.
728769
media (List<:class:`~plexapi.media.Media`>): List of media objects.
@@ -735,6 +776,7 @@ class Episode(Video, Playable, ArtMixin, PosterMixin,
735776
parentTitle (str): Name of the season for the episode.
736777
rating (float): Episode rating (7.9; 9.8; 8.1).
737778
skipParent (bool): True if the show's seasons are set to hidden.
779+
userRating (float): User rating (2.0; 8.0).
738780
viewOffset (int): View offset in milliseconds.
739781
writers (List<:class:`~plexapi.media.Writer`>): List of writers objects.
740782
year (int): Year episode was released.
@@ -748,6 +790,8 @@ def _loadData(self, data):
748790
Video._loadData(self, data)
749791
Playable._loadData(self, data)
750792
self._seasonNumber = None # cached season number
793+
self.audienceRating = utils.cast(float, data.attrib.get('audienceRating'))
794+
self.audienceRatingImage = data.attrib.get('audienceRatingImage')
751795
self.chapters = self.findItems(data, media.Chapter)
752796
self.chapterSource = data.attrib.get('chapterSource')
753797
self.contentRating = data.attrib.get('contentRating')
@@ -760,6 +804,7 @@ def _loadData(self, data):
760804
self.grandparentTheme = data.attrib.get('grandparentTheme')
761805
self.grandparentThumb = data.attrib.get('grandparentThumb')
762806
self.grandparentTitle = data.attrib.get('grandparentTitle')
807+
self.guids = self.findItems(data, media.Guid)
763808
self.index = utils.cast(int, data.attrib.get('index'))
764809
self.markers = self.findItems(data, media.Marker)
765810
self.media = self.findItems(data, media.Media)
@@ -772,6 +817,7 @@ def _loadData(self, data):
772817
self.parentTitle = data.attrib.get('parentTitle')
773818
self.rating = utils.cast(float, data.attrib.get('rating'))
774819
self.skipParent = utils.cast(bool, data.attrib.get('skipParent', '0'))
820+
self.userRating = utils.cast(float, data.attrib.get('userRating'))
775821
self.viewOffset = utils.cast(int, data.attrib.get('viewOffset', 0))
776822
self.writers = self.findItems(data, media.Writer)
777823
self.year = utils.cast(int, data.attrib.get('year'))

tests/test_video.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,16 +559,25 @@ def test_video_Show_attrs(show):
559559
# Check reloading the show loads the full list of genres
560560
assert not {"Adventure", "Drama"} - {i.tag for i in show.genres}
561561
show.reload()
562+
assert show.audienceRating is None # TODO: Change when updating test to the Plex TV agent
563+
assert show.audienceRatingImage is None # TODO: Change when updating test to the Plex TV agent
564+
assert show.autoDeletionItemPolicyUnwatchedLibrary == 0
565+
assert show.autoDeletionItemPolicyWatchedLibrary == 0
566+
assert show.episodeSort == -1
567+
assert show.flattenSeasons == -1
562568
assert sorted([i.tag for i in show.genres]) == ["Adventure", "Drama", "Fantasy"]
569+
assert show.guids == [] # TODO: Change when updating test to the Plex TV agent
563570
# So the initkey should have changed because of the reload
564571
assert utils.is_metadata(show._initpath)
565572
assert utils.is_int(show.index)
566573
assert utils.is_metadata(show.key)
574+
assert show.languageOverride is None
567575
assert utils.is_datetime(show.lastViewedAt)
568576
assert utils.is_int(show.leafCount)
569577
assert show.listType == "video"
570578
assert len(show.locations) == 1
571579
assert len(show.locations[0]) >= 10
580+
assert show.network is None
572581
assert utils.is_datetime(show.originallyAvailableAt)
573582
assert show.originalTitle is None
574583
assert show.rating >= 8.0
@@ -586,6 +595,7 @@ def test_video_Show_attrs(show):
586595
"Alfie Allen",
587596
] # noqa
588597
assert show._server._baseurl == utils.SERVER_BASEURL
598+
assert show.showOrdering in (None, 'aired')
589599
assert show.studio == "HBO"
590600
assert utils.is_string(show.summary, gte=100)
591601
assert show.tagline is None
@@ -595,6 +605,8 @@ def test_video_Show_attrs(show):
595605
assert show.title == "Game of Thrones"
596606
assert show.titleSort == "Game of Thrones"
597607
assert show.type == "show"
608+
assert show.useOriginalTitle == -1
609+
assert show.userRating is None
598610
assert utils.is_datetime(show.updatedAt)
599611
assert utils.is_int(show.viewCount, gte=0)
600612
assert utils.is_int(show.viewedLeafCount, gte=0)
@@ -790,6 +802,8 @@ def test_video_Episode_attrs(episode):
790802
assert utils.is_datetime(episode.addedAt)
791803
if episode.art:
792804
assert utils.is_art(episode.art)
805+
assert episode.audienceRating is None # TODO: Change when updating test to the Plex TV agent
806+
assert episode.audienceRatingImage is None # TODO: Change when updating test to the Plex TV agent
793807
assert episode.contentRating in utils.CONTENTRATINGS
794808
if len(episode.directors):
795809
assert [i.tag for i in episode.directors] == ["Tim Van Patten"]
@@ -799,6 +813,7 @@ def test_video_Episode_attrs(episode):
799813
if episode.grandparentThumb:
800814
assert utils.is_thumb(episode.grandparentThumb)
801815
assert episode.grandparentTitle == "Game of Thrones"
816+
assert episode.guids == [] # TODO: Change when updating test to the Plex TV agent
802817
assert episode.index == 1
803818
assert utils.is_metadata(episode._initpath)
804819
assert utils.is_metadata(episode.key)
@@ -913,6 +928,7 @@ def test_video_Season_attrs(show):
913928
assert utils.is_datetime(season.addedAt)
914929
if season.art:
915930
assert utils.is_art(season.art)
931+
assert season.guids == [] # TODO: Change when updating test to the Plex TV agent
916932
assert season.index == 1
917933
assert utils.is_metadata(season._initpath)
918934
assert utils.is_metadata(season.key)

0 commit comments

Comments
 (0)