From c0439bd173763a36d4d096e674db6de7317c0533 Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Sat, 26 Nov 2016 13:41:10 +1300 Subject: [PATCH 1/3] Updated plex.activity.py #372 --- .../Shared/plex_activity/__init__.py | 2 +- .../plex_activity/sources/s_websocket/main.py | 141 +++++++++++++----- 2 files changed, 105 insertions(+), 38 deletions(-) diff --git a/Trakttv.bundle/Contents/Libraries/Shared/plex_activity/__init__.py b/Trakttv.bundle/Contents/Libraries/Shared/plex_activity/__init__.py index 2346478e7..4da218f59 100644 --- a/Trakttv.bundle/Contents/Libraries/Shared/plex_activity/__init__.py +++ b/Trakttv.bundle/Contents/Libraries/Shared/plex_activity/__init__.py @@ -3,7 +3,7 @@ log = logging.getLogger(__name__) -__version__ = '0.7.0' +__version__ = '0.7.1' try: diff --git a/Trakttv.bundle/Contents/Libraries/Shared/plex_activity/sources/s_websocket/main.py b/Trakttv.bundle/Contents/Libraries/Shared/plex_activity/sources/s_websocket/main.py index 64ebfadc9..429498fc3 100644 --- a/Trakttv.bundle/Contents/Libraries/Shared/plex_activity/sources/s_websocket/main.py +++ b/Trakttv.bundle/Contents/Libraries/Shared/plex_activity/sources/s_websocket/main.py @@ -139,72 +139,102 @@ def process(self, opcode, data): log.debug(data) return False - type = info.get('type') + # Handle modern messages (PMS 1.3.0+) + if type(info.get('NotificationContainer')) is dict: + info = info['NotificationContainer'] - if not type: + # Process message + m_type = info.get('type') + + if not m_type: + log.debug('Received message with no "type" parameter: %r', info) return False # Pre-process message (if function exists) - process_func = getattr(self, 'process_%s' % type, None) + process_func = getattr(self, 'process_%s' % m_type, None) if process_func and process_func(info): return True # Emit raw message - self.emit_notification('%s.notification.%s' % (self.name, type), info) - return True + return self.emit_notification('%s.notification.%s' % (self.name, m_type), info) def process_playing(self, info): - self.emit_notification('%s.playing' % self.name, info) - return True + children = info.get('_children') or info.get('PlaySessionStateNotification') + + if not children: + log.debug('Received "playing" message with no children: %r', info) + return False + + return self.emit_notification('%s.playing' % self.name, children) def process_progress(self, info): - if not info.get('_children'): + children = info.get('_children') or info.get('ProgressNotification') + + if not children: + log.debug('Received "progress" message with no children: %r', info) return False - notification = info['_children'][0] + for notification in children: + self.emit('%s.scanner.progress' % self.name, { + 'message': notification.get('message') + }) - self.emit_notification('%s.scanner.progress' % self.name, { - 'message': notification.get('message') - }) return True def process_status(self, info): - if not info.get('_children'): + children = info.get('_children') or info.get('StatusNotification') + + if not children: + log.debug('Received "status" message with no children: %r', info) return False - notification = info['_children'][0] + # Process children + count = 0 - title = notification.get('title') + for notification in children: + title = notification.get('title') - if not title: - return False + if not title: + continue - # Scan complete message - if SCAN_COMPLETE_REGEX.match(title): - self.emit_notification('%s.scanner.finished' % self.name) - return True + # Scan complete message + if SCAN_COMPLETE_REGEX.match(title): + self.emit('%s.scanner.finished' % self.name) + count += 1 + continue + + # Scanning message + match = SCANNING_REGEX.match(title) - # Scanning message - match = SCANNING_REGEX.match(title) + if not match: + continue - if match: section = match.group('section') - if section: - self.emit_notification('%s.scanner.started' % self.name, { - 'section': section - }) - return True + if not section: + continue + + self.emit('%s.scanner.started' % self.name, {'section': section}) + count += 1 - return False + # Validate result + if count < 1: + log.debug('Received "status" message with no valid children: %r', info) + return False + + return True def process_timeline(self, info): - children = info.get('_children', []) + children = info.get('_children') or info.get('TimelineEntry') if not children: + log.debug('Received "timeline" message with no children: %r', info) return False + # Process children + count = 0 + for entry in children: state = TIMELINE_STATES.get(entry.get('state')) @@ -212,20 +242,57 @@ def process_timeline(self, info): continue self.emit('%s.timeline.%s' % (self.name, state), entry) + count += 1 + + # Validate result + if count < 1: + log.debug('Received "timeline" message with no valid children: %r', info) + return False return True + # + # Helpers + # + def emit_notification(self, name, info=None): if info is None: info = {} - children = info.get('_children', []) + # Emit children + children = self._get_children(info) - if len(children) > 1: - self.emit(name, children) - elif len(children) == 1: - self.emit(name, children[0]) - elif info: + if children: + for child in children: + self.emit(name, child) + + return True + + # Emit objects + if info: self.emit(name, info) else: self.emit(name) + + return True + + @staticmethod + def _get_children(info): + if type(info) is list: + return info + + if type(info) is not dict: + return None + + # Return legacy children + if info.get('_children'): + return info['_children'] + + # Search for modern children container + for key, value in info.items(): + key = key.lower() + + if (key.endswith('entry') or key.endswith('notification')) and type(value) is list: + return value + + return None From 1e691da3ac3abd7aef1ea7592187159fce21ad54 Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Sat, 26 Nov 2016 14:40:59 +1300 Subject: [PATCH 2/3] Updated plex.py --- .../Contents/Libraries/Shared/plex/objects/detail.py | 2 ++ .../Libraries/Shared/plex/objects/library/section.py | 5 +++-- .../Contents/Libraries/Shared/plex/objects/library/stream.py | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Trakttv.bundle/Contents/Libraries/Shared/plex/objects/detail.py b/Trakttv.bundle/Contents/Libraries/Shared/plex/objects/detail.py index 44fc324ea..39ba43b82 100644 --- a/Trakttv.bundle/Contents/Libraries/Shared/plex/objects/detail.py +++ b/Trakttv.bundle/Contents/Libraries/Shared/plex/objects/detail.py @@ -29,9 +29,11 @@ class Detail(Container): event_stream = Property('eventStream', (int, bool)) hub_search = Property('hubSearch', (int, bool)) media_providers = Property('mediaProviders', (int, bool)) + photo_auto_tag = Property('photoAutoTag', (int, bool)) plugin_host = Property('pluginHost', (int, bool)) read_only_libraries = Property('readOnlyLibraries', (int, bool)) updater = Property('updater', (int, bool)) + voice_search = Property('voiceSearch', (int, bool)) certificate = Property(type=(int, bool)) multiuser = Property(type=(int, bool)) diff --git a/Trakttv.bundle/Contents/Libraries/Shared/plex/objects/library/section.py b/Trakttv.bundle/Contents/Libraries/Shared/plex/objects/library/section.py index e016ffa15..a98a9c994 100644 --- a/Trakttv.bundle/Contents/Libraries/Shared/plex/objects/library/section.py +++ b/Trakttv.bundle/Contents/Libraries/Shared/plex/objects/library/section.py @@ -8,8 +8,9 @@ class Section(Directory): uuid = Property path = Property('key') - filters = Property(type=bool) - refreshing = Property(type=bool) + auto_photo_tags = Property('enableAutoPhotoTags', type=(int, bool)) + filters = Property(type=(int, bool)) + refreshing = Property(type=(int, bool)) agent = Property scanner = Property diff --git a/Trakttv.bundle/Contents/Libraries/Shared/plex/objects/library/stream.py b/Trakttv.bundle/Contents/Libraries/Shared/plex/objects/library/stream.py index 9a3a8d2dc..122727c05 100644 --- a/Trakttv.bundle/Contents/Libraries/Shared/plex/objects/library/stream.py +++ b/Trakttv.bundle/Contents/Libraries/Shared/plex/objects/library/stream.py @@ -9,7 +9,7 @@ class Stream(Descriptor): selected = Property(type=bool) title = Property - duration = Property(type=int) + duration = Property(type=(float, int)) language = Property language_code = Property('languageCode') From 420a0314d931dc249d0f9610b0cf459246b97008 Mon Sep 17 00:00:00 2001 From: Dean Gardiner Date: Sat, 26 Nov 2016 17:22:13 +1300 Subject: [PATCH 3/3] Bumped version to 1.1.0.7 --- .../Contents/Libraries/Shared/plugin/core/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Trakttv.bundle/Contents/Libraries/Shared/plugin/core/constants.py b/Trakttv.bundle/Contents/Libraries/Shared/plugin/core/constants.py index a26deafa6..115648673 100644 --- a/Trakttv.bundle/Contents/Libraries/Shared/plugin/core/constants.py +++ b/Trakttv.bundle/Contents/Libraries/Shared/plugin/core/constants.py @@ -7,7 +7,7 @@ PLUGIN_IDENTIFIER = 'com.plexapp.plugins.trakttv' PLUGIN_PREFIX = '/video/trakt' -PLUGIN_VERSION_BASE = (1, 1, 0, 6) +PLUGIN_VERSION_BASE = (1, 1, 0, 7) PLUGIN_VERSION_BRANCH = 'master' PLUGIN_VERSION = ''.join([