From 2c540f69c83fff3e4b574848e129c516b062109c Mon Sep 17 00:00:00 2001 From: JonnyWong16 <9099342+JonnyWong16@users.noreply.github.com> Date: Mon, 26 Jul 2021 18:36:54 -0700 Subject: [PATCH] Add producers, roles, and hasCommercialMarker to Episode objects (#797) * Add producers and roles to Episode * Add producers and roles to episode test * Add hasCommercialMarker to Episode --- plexapi/media.py | 4 +++- plexapi/video.py | 14 ++++++++++++++ tests/test_video.py | 5 +++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/plexapi/media.py b/plexapi/media.py index 3ca69978..addc3fdf 100644 --- a/plexapi/media.py +++ b/plexapi/media.py @@ -964,10 +964,12 @@ class Marker(PlexObject): name = self._clean(self.firstAttr('type')) start = utils.millisecondToHumanstr(self._clean(self.firstAttr('start'))) end = utils.millisecondToHumanstr(self._clean(self.firstAttr('end'))) - return '<%s:%s %s - %s>' % (self.__class__.__name__, name, start, end) + offsets = '%s-%s' % (start, end) + return '<%s>' % ':'.join([self.__class__.__name__, name, offsets]) def _loadData(self, data): self._data = data + self.id = utils.cast(int, data.attrib.get('id')) self.type = data.attrib.get('type') self.start = utils.cast(int, data.attrib.get('startTimeOffset')) self.end = utils.cast(int, data.attrib.get('endTimeOffset')) diff --git a/plexapi/video.py b/plexapi/video.py index 609eaffc..090d9502 100644 --- a/plexapi/video.py +++ b/plexapi/video.py @@ -767,7 +767,9 @@ class Episode(Video, Playable, ArtMixin, PosterMixin, RatingMixin, parentThumb (str): URL to season thumbnail image (/library/metadata//thumb/). parentTitle (str): Name of the season for the episode. parentYear (int): Year the season was released. + producers (List<:class:`~plexapi.media.Producer`>): List of producers objects. rating (float): Episode rating (7.9; 9.8; 8.1). + roles (List<:class:`~plexapi.media.Role`>): List of role objects. skipParent (bool): True if the show's seasons are set to hidden. viewOffset (int): View offset in milliseconds. writers (List<:class:`~plexapi.media.Writer`>): List of writers objects. @@ -809,7 +811,9 @@ class Episode(Video, Playable, ArtMixin, PosterMixin, RatingMixin, self.parentThumb = data.attrib.get('parentThumb') self.parentTitle = data.attrib.get('parentTitle') self.parentYear = utils.cast(int, data.attrib.get('parentYear')) + self.producers = self.findItems(data, media.Producer) self.rating = utils.cast(float, data.attrib.get('rating')) + self.roles = self.findItems(data, media.Role) self.skipParent = utils.cast(bool, data.attrib.get('skipParent', '0')) self.viewOffset = utils.cast(int, data.attrib.get('viewOffset', 0)) self.writers = self.findItems(data, media.Writer) @@ -838,6 +842,11 @@ class Episode(Video, Playable, ArtMixin, PosterMixin, RatingMixin, """ Returns a human friendly filename. """ return '%s.%s' % (self.grandparentTitle.replace(' ', '.'), self.seasonEpisode) + @property + def actors(self): + """ Alias to self.roles. """ + return self.roles + @property def locations(self): """ This does not exist in plex xml response but is added to have a common @@ -865,6 +874,11 @@ class Episode(Video, Playable, ArtMixin, PosterMixin, RatingMixin, """ Returns the s00e00 string containing the season and episode numbers. """ return 's%se%s' % (str(self.seasonNumber).zfill(2), str(self.episodeNumber).zfill(2)) + @property + def hasCommercialMarker(self): + """ Returns True if the episode has a commercial marker in the xml. """ + return any(marker.type == 'commercial' for marker in self.markers) + @property def hasIntroMarker(self): """ Returns True if the episode has an intro marker in the xml. """ diff --git a/tests/test_video.py b/tests/test_video.py index 3d7d925e..d919b6b1 100644 --- a/tests/test_video.py +++ b/tests/test_video.py @@ -1016,8 +1016,13 @@ def test_video_Episode_attrs(episode): assert utils.is_thumb(episode.parentThumb) assert episode.parentTitle == "Season 1" assert episode.parentYear is None + if episode.producers: + assert episode.producers # Test episode doesn't have producers assert episode.rating is None assert utils.is_int(episode.ratingKey) + if episode.roles: + assert "Jason Momoa" in [i.tag for i in episode.roles] + assert episode.actors == episode.roles assert episode._server._baseurl == utils.SERVER_BASEURL assert episode.skipParent is False assert utils.is_string(episode.summary, gte=100)