Skip to content

Commit ab372ef

Browse files
committed
Add support for Common Sense Media
1 parent e8451cc commit ab372ef

2 files changed

Lines changed: 134 additions & 4 deletions

File tree

plexapi/media.py

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ class MediaTag(PlexObject):
741741
742742
Attributes:
743743
filter (str): The library filter for the tag.
744-
id (id): Tag ID (This seems meaningless except to use it as a unique id).
744+
id (int): Tag ID (This seems meaningless except to use it as a unique id).
745745
key (str): API URL (/library/section/<librarySectionID>/all?<filter>).
746746
role (str): The name of the character role for :class:`~plexapi.media.Role` only.
747747
tag (str): Name of the tag. This will be Animation, SciFi etc for Genres. The name of
@@ -1366,3 +1366,123 @@ class Level(PlexObject):
13661366
def _loadData(self, data):
13671367
""" Load attribute values from Plex XML response. """
13681368
self.loudness = utils.cast(float, data.attrib.get('v'))
1369+
1370+
1371+
@utils.registerPlexObject
1372+
class CommonSenseMedia(PlexObject):
1373+
""" Represents a single CommonSenseMedia media tag.
1374+
Note: This object is only loaded with partial data from a Plex Media Server.
1375+
Call `reload()` to load the full data from Plex Discover (Plex Pass required).
1376+
1377+
Attributes:
1378+
TAG (str): 'CommonSenseMedia'
1379+
ageRatings (List<:class:`~plexapi.media.AgeRating`>): List of AgeRating objects.
1380+
anyGood (str): A brief description of the media's quality.
1381+
id (int): The ID of the CommonSenseMedia tag.
1382+
key (str): The unique key for the CommonSenseMedia tag.
1383+
oneLiner (str): A brief description of the CommonSenseMedia tag.
1384+
parentalAdvisoryTopics (List<:class:`~plexapi.media.ParentalAdvisoryTopic`>):
1385+
List of ParentalAdvisoryTopic objects.
1386+
parentsNeedToKnow (str): A brief description of what parents need to know about the media.
1387+
talkingPoints (List<:class:`~plexapi.media.TalkingPoint`>): List of TalkingPoint objects.
1388+
1389+
Example:
1390+
1391+
.. code-block:: python
1392+
1393+
from plexapi.server import PlexServer
1394+
plex = PlexServer('http://localhost:32400', token='xxxxxxxxxxxxxxxxxxxx')
1395+
1396+
# Retrieve the Common Sense Media info for a movie
1397+
movie = plex.library.section('Movies').get('Cars')
1398+
commonSenseMedia = movie.commonSenseMedia[0]
1399+
ageRating = commonSenseMedia.ageRatings[0].age
1400+
1401+
# Load the Common Sense Media info from Plex Discover (Plex Pass required)
1402+
commonSenseMedia.reload()
1403+
parentalAdvisoryTopics = commonSenseMedia.parentalAdvisoryTopics
1404+
talkingPoints = commonSenseMedia.talkingPoints
1405+
1406+
"""
1407+
TAG = 'CommonSenseMedia'
1408+
1409+
def _loadData(self, data):
1410+
self.ageRatings = self.findItems(data, AgeRating)
1411+
self.anyGood = data.attrib.get('anyGood')
1412+
self.id = utils.cast(int, data.attrib.get('id'))
1413+
self.key = data.attrib.get('key')
1414+
self.oneLiner = data.attrib.get('oneLiner')
1415+
self.parentalAdvisoryTopics = self.findItems(data, ParentalAdvisoryTopic)
1416+
self.parentsNeedToKnow = data.attrib.get('parentsNeedToKnow')
1417+
self.talkingPoints = self.findItems(data, TalkingPoint)
1418+
1419+
def _reload(self, **kwargs):
1420+
""" Reload the data for the hub. """
1421+
guid = self._parent().guid
1422+
if not guid.startswith('plex://'):
1423+
return self
1424+
1425+
ratingKey = guid.rsplit('/', 1)[-1]
1426+
account = self._server.myPlexAccount()
1427+
key = f'{account.METADATA}/library/metadata/{ratingKey}/commonsensemedia'
1428+
data = account.query(key)
1429+
self._findAndLoadElem(data)
1430+
return self
1431+
1432+
1433+
@utils.registerPlexObject
1434+
class AgeRating(PlexObject):
1435+
""" Represents a single AgeRating for a Common Sense Media tag.
1436+
1437+
Attributes:
1438+
TAG (str): 'AgeRating'
1439+
age (float): The age rating (e.g. 13, 17).
1440+
ageGroup (str): The age group for the rating (e.g. Little Kids, Teens, etc.).
1441+
rating (float): The star rating (out of 5).
1442+
ratingCount (int): The number of ratings contributing to the star rating.
1443+
type (str): The type of rating (official, adult, child).
1444+
"""
1445+
TAG = 'AgeRating'
1446+
1447+
def _loadData(self, data):
1448+
self.age = utils.cast(float, data.attrib.get('age'))
1449+
self.ageGroup = data.attrib.get('ageGroup')
1450+
self.rating = utils.cast(float, data.attrib.get('rating'))
1451+
self.ratingCount = utils.cast(int, data.attrib.get('ratingCount'))
1452+
self.type = data.attrib.get('type')
1453+
1454+
1455+
@utils.registerPlexObject
1456+
class TalkingPoint(PlexObject):
1457+
""" Represents a single TalkingPoint for a Common Sense Media tag.
1458+
1459+
Attributes:
1460+
TAG (str): 'TalkingPoint'
1461+
tag (str): The description of the talking point.
1462+
"""
1463+
TAG = 'TalkingPoint'
1464+
1465+
def _loadData(self, data):
1466+
self.tag = data.attrib.get('tag')
1467+
1468+
1469+
@utils.registerPlexObject
1470+
class ParentalAdvisoryTopic(PlexObject):
1471+
""" Represents a single ParentalAdvisoryTopic for a Common Sense Media tag.
1472+
1473+
Attributes:
1474+
TAG (str): 'ParentalAdvisoryTopic'
1475+
id (str): The ID of the topic (e.g. violence, language, etc.).
1476+
label (str): The label for the topic (e.g. Violence & Scariness, Language, etc.).
1477+
positive (bool): Whether the topic is considered positive.
1478+
rating (float): The rating of the topic (out of 5).
1479+
tag (str): The description of the parental advisory topic.
1480+
"""
1481+
TAG = 'ParentalAdvisoryTopic'
1482+
1483+
def _loadData(self, data):
1484+
self.id = data.attrib.get('id')
1485+
self.label = data.attrib.get('label')
1486+
self.positive = utils.cast(bool, data.attrib.get('positive'))
1487+
self.rating = utils.cast(float, data.attrib.get('rating'))
1488+
self.tag = data.attrib.get('tag')

plexapi/video.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -349,11 +349,12 @@ class Movie(
349349
TYPE (str): 'movie'
350350
audienceRating (float): Audience rating (usually from Rotten Tomatoes).
351351
audienceRatingImage (str): Key to audience rating image (rottentomatoes://image.rating.spilled).
352-
chapters (List<:class:`~plexapi.media.Chapter`>): List of Chapter objects.
352+
chapters (List<:class:`~plexapi.media.Chapter`>): List of chapter objects.
353353
chapterSource (str): Chapter source (agent; media; mixed).
354354
collections (List<:class:`~plexapi.media.Collection`>): List of collection objects.
355+
commonSenseMedia (List<:class:`~plexapi.media.CommonSenseMedia`>): List of Common Sense Media objects.
355356
contentRating (str) Content rating (PG-13; NR; TV-G).
356-
countries (List<:class:`~plexapi.media.Country`>): List of countries objects.
357+
countries (List<:class:`~plexapi.media.Country`>): List of country objects.
357358
directors (List<:class:`~plexapi.media.Director`>): List of director objects.
358359
duration (int): Duration of the movie in milliseconds.
359360
editionTitle (str): The edition title of the movie (e.g. Director's Cut, Extended Edition, etc.).
@@ -426,6 +427,10 @@ def chapters(self):
426427
def collections(self):
427428
return self.findItems(self._data, media.Collection)
428429

430+
@cached_data_property
431+
def commonSenseMedia(self):
432+
return self.findItems(self._data, media.CommonSenseMedia)
433+
429434
@cached_data_property
430435
def countries(self):
431436
return self.findItems(self._data, media.Country)
@@ -566,6 +571,7 @@ class Show(
566571
100 = On next refresh).
567572
childCount (int): Number of seasons (including Specials) in the show.
568573
collections (List<:class:`~plexapi.media.Collection`>): List of collection objects.
574+
commonSenseMedia (List<:class:`~plexapi.media.CommonSenseMedia`>): List of Common Sense Media objects.
569575
contentRating (str) Content rating (PG-13; NR; TV-G).
570576
duration (int): Typical duration of the show episodes in milliseconds.
571577
enableCreditsMarkerGeneration (int): Setting that indicates if credits markers detection is enabled.
@@ -651,6 +657,10 @@ def _loadData(self, data):
651657
def collections(self):
652658
return self.findItems(self._data, media.Collection)
653659

660+
@cached_data_property
661+
def commonSenseMedia(self):
662+
return self.findItems(self._data, media.CommonSenseMedia)
663+
654664
@cached_data_property
655665
def genres(self):
656666
return self.findItems(self._data, media.Genre)
@@ -984,7 +994,7 @@ class Episode(
984994
TYPE (str): 'episode'
985995
audienceRating (float): Audience rating (TMDB or TVDB).
986996
audienceRatingImage (str): Key to audience rating image (tmdb://image.rating).
987-
chapters (List<:class:`~plexapi.media.Chapter`>): List of Chapter objects.
997+
chapters (List<:class:`~plexapi.media.Chapter`>): List of chapter objects.
988998
chapterSource (str): Chapter source (agent; media; mixed).
989999
collections (List<:class:`~plexapi.media.Collection`>): List of collection objects.
9901000
contentRating (str) Content rating (PG-13; NR; TV-G).

0 commit comments

Comments
 (0)