diff --git a/plexpy/__init__.py b/plexpy/__init__.py index 003259bc..873b46f0 100644 --- a/plexpy/__init__.py +++ b/plexpy/__init__.py @@ -754,19 +754,22 @@ def dbcheck(): 'agent_id INTEGER, agent_name TEXT, agent_label TEXT, friendly_name TEXT, notifier_config TEXT, ' 'on_play INTEGER DEFAULT 0, on_stop INTEGER DEFAULT 0, on_pause INTEGER DEFAULT 0, ' 'on_resume INTEGER DEFAULT 0, on_change INTEGER DEFAULT 0, on_buffer INTEGER DEFAULT 0, ' - 'on_error INTEGER DEFAULT 0, on_watched INTEGER DEFAULT 0, on_created INTEGER DEFAULT 0, ' + 'on_error INTEGER DEFAULT 0, on_intro INTEGER DEFAULT 0, on_credits INTEGER DEFAULT 0, ' + 'on_watched INTEGER DEFAULT 0, on_created INTEGER DEFAULT 0, ' 'on_extdown INTEGER DEFAULT 0, on_intdown INTEGER DEFAULT 0, ' 'on_extup INTEGER DEFAULT 0, on_intup INTEGER DEFAULT 0, on_pmsupdate INTEGER DEFAULT 0, ' 'on_concurrent INTEGER DEFAULT 0, on_newdevice INTEGER DEFAULT 0, on_plexpyupdate INTEGER DEFAULT 0, ' 'on_plexpydbcorrupt INTEGER DEFAULT 0, ' 'on_play_subject TEXT, on_stop_subject TEXT, on_pause_subject TEXT, ' 'on_resume_subject TEXT, on_change_subject TEXT, on_buffer_subject TEXT, on_error_subject TEXT, ' + 'on_intro_subject TEXT, on_credits_subject TEXT, ' 'on_watched_subject TEXT, on_created_subject TEXT, on_extdown_subject TEXT, on_intdown_subject TEXT, ' 'on_extup_subject TEXT, on_intup_subject TEXT, on_pmsupdate_subject TEXT, ' 'on_concurrent_subject TEXT, on_newdevice_subject TEXT, on_plexpyupdate_subject TEXT, ' 'on_plexpydbcorrupt_subject TEXT, ' 'on_play_body TEXT, on_stop_body TEXT, on_pause_body TEXT, ' 'on_resume_body TEXT, on_change_body TEXT, on_buffer_body TEXT, on_error_body TEXT, ' + 'on_intro_body TEXT, on_credits_body TEXT, ' 'on_watched_body TEXT, on_created_body TEXT, on_extdown_body TEXT, on_intdown_body TEXT, ' 'on_extup_body TEXT, on_intup_body TEXT, on_pmsupdate_body TEXT, ' 'on_concurrent_body TEXT, on_newdevice_body TEXT, on_plexpyupdate_body TEXT, ' @@ -2384,6 +2387,30 @@ def dbcheck(): 'ALTER TABLE notifiers ADD COLUMN on_error_body TEXT' ) + # Upgrade notifiers table from earlier versions + try: + c_db.execute('SELECT on_intro FROM notifiers') + except sqlite3.OperationalError: + logger.debug("Altering database. Updating database table notifiers.") + c_db.execute( + 'ALTER TABLE notifiers ADD COLUMN on_intro INTEGER DEFAULT 0' + ) + c_db.execute( + 'ALTER TABLE notifiers ADD COLUMN on_intro_subject TEXT' + ) + c_db.execute( + 'ALTER TABLE notifiers ADD COLUMN on_intro_body TEXT' + ) + c_db.execute( + 'ALTER TABLE notifiers ADD COLUMN on_credits INTEGER DEFAULT 0' + ) + c_db.execute( + 'ALTER TABLE notifiers ADD COLUMN on_credits_subject TEXT' + ) + c_db.execute( + 'ALTER TABLE notifiers ADD COLUMN on_credits_body TEXT' + ) + # Upgrade tvmaze_lookup table from earlier versions try: c_db.execute('SELECT rating_key FROM tvmaze_lookup') diff --git a/plexpy/common.py b/plexpy/common.py index ad91ee87..65de4810 100644 --- a/plexpy/common.py +++ b/plexpy/common.py @@ -416,6 +416,7 @@ NOTIFICATION_PARAMETERS = [ {'name': 'Progress Duration (sec)', 'type': 'int', 'value': 'progress_duration_sec', 'description': 'The last reported offset (in seconds) of the stream.'}, {'name': 'Progress Time', 'type': 'str', 'value': 'progress_time', 'description': 'The last reported offset (in time format) of the stream.'}, {'name': 'Progress Percent', 'type': 'int', 'value': 'progress_percent', 'description': 'The last reported progress percent of the stream.'}, + {'name': 'View Offset (ms)', 'type': 'int', 'value': 'view_offset', 'description': 'The current view offset (in milliseconds) for the stream.'}, {'name': 'Transcode Decision', 'type': 'str', 'value': 'transcode_decision', 'description': 'The transcode decision of the stream.'}, {'name': 'Container Decision', 'type': 'str', 'value': 'container_decision', 'description': 'The container transcode decision of the stream.'}, {'name': 'Video Decision', 'type': 'str', 'value': 'video_decision', 'description': 'The video transcode decision of the stream.'}, @@ -426,6 +427,12 @@ NOTIFICATION_PARAMETERS = [ {'name': 'Optimized Version Profile', 'type': 'str', 'value': 'optimized_version_profile', 'description': 'The optimized version profile of the stream.'}, {'name': 'Synced Version', 'type': 'int', 'value': 'synced_version', 'description': 'If the stream is an synced version.', 'example': '0 or 1'}, {'name': 'Live', 'type': 'int', 'value': 'live', 'description': 'If the stream is live TV.', 'example': '0 or 1'}, + {'name': 'Intro Marker Start Time', 'type': 'int', 'value': 'intro_marker_start', 'description': 'The intro marker start time offset in milliseconds.'}, + {'name': 'Intro Marker End Time', 'type': 'int', 'value': 'intro_marker_end', 'description': 'The intro marker end time offset in milliseconds.'}, + {'name': 'Credits Marker First', 'type': 'int', 'value': 'credits_marker_first', 'description': 'If the credits marker is the first marker.', 'example': '0 or 1'}, + {'name': 'Credits Marker Final', 'type': 'int', 'value': 'credits_marker_final', 'description': 'If the credits marker is the final marker.', 'example': '0 or 1'}, + {'name': 'Credits Marker Start Time', 'type': 'int', 'value': 'credits_marker_start', 'description': 'The credits marker start time offset in milliseconds.'}, + {'name': 'Credits Marker End Time', 'type': 'int', 'value': 'credits_marker_end', 'description': 'The credits marker end time offset in milliseconds.'}, {'name': 'Channel Call Sign', 'type': 'str', 'value': 'channel_call_sign', 'description': 'The Live TV channel call sign.'}, {'name': 'Channel Identifier', 'type': 'str', 'value': 'channel_identifier', 'description': 'The Live TV channel number.'}, {'name': 'Channel Thumb', 'type': 'str', 'value': 'channel_thumb', 'description': 'The URL for the Live TV channel logo.'}, @@ -540,6 +547,7 @@ NOTIFICATION_PARAMETERS = [ {'name': 'User Rating', 'type': 'float', 'value': 'user_rating', 'description': 'The user (star) rating (out of 10) for the item.'}, {'name': 'Duration', 'type': 'int', 'value': 'duration', 'description': 'The duration (in minutes) for the item.'}, {'name': 'Duration (sec)', 'type': 'int', 'value': 'duration_sec', 'description': 'The duration (in seconds) for the item.'}, + {'name': 'Duration (ms)', 'type': 'int', 'value': 'duration_ms', 'description': 'The duration (in milliseconds) for the item.'}, {'name': 'Poster URL', 'type': 'str', 'value': 'poster_url', 'description': 'A URL for the movie, TV show, or album poster.'}, {'name': 'Plex ID', 'type': 'str', 'value': 'plex_id', 'description': 'The Plex ID for the item.', 'example': 'e.g. 5d7769a9594b2b001e6a6b7e'}, {'name': 'Plex URL', 'type': 'str', 'value': 'plex_url', 'description': 'The Plex URL to your server for the item.'}, diff --git a/plexpy/notification_handler.py b/plexpy/notification_handler.py index 6b55c5b7..b9940b70 100644 --- a/plexpy/notification_handler.py +++ b/plexpy/notification_handler.py @@ -583,6 +583,8 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m notify_params.update(media_info) notify_params.update(media_part_info) + metadata = pmsconnect.PmsConnect().get_metadata_details(rating_key=rating_key) + child_metadata = grandchild_metadata = [] for key in kwargs.pop('child_keys', []): child = pmsconnect.PmsConnect().get_metadata_details(rating_key=key) @@ -938,6 +940,20 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m and audience_rating: audience_rating = helpers.get_percent(notify_params['audience_rating'], 10) + intro_markers, credits_markers = [], [] + for marker in metadata['markers']: + if marker['type'] == 'intro': + intro_markers.append(marker) + elif marker['type'] == 'credits': + credits_markers.append(marker) + + intro_marker = defaultdict(int) + credits_marker = defaultdict(int) + if notify_action == 'on_intro' and intro_markers and notify_params['intro'] < len(intro_markers): + intro_marker = intro_markers[notify_params['intro']] + if notify_action == 'on_credits' and credits_markers and notify_params['credits'] < len(credits_markers): + credits_marker = credits_markers[notify_params['credits']] + now = arrow.now() now_iso = now.isocalendar() @@ -1005,6 +1021,7 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m 'progress_duration_sec': view_offset_sec, 'progress_time': arrow.get(view_offset_sec).format(duration_format), 'progress_percent': helpers.get_percent(view_offset_sec, duration_sec), + 'view_offset': session.get('view_offset', 0), 'initial_stream': notify_params['initial_stream'], 'transcode_decision': transcode_decision, 'container_decision': notify_params['container_decision'], @@ -1016,6 +1033,12 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m 'optimized_version_profile': notify_params['optimized_version_profile'], 'synced_version': notify_params['synced_version'], 'live': notify_params['live'], + 'intro_marker_start': intro_marker['start_time_offset'], + 'intro_marker_end': intro_marker['end_time_offset'], + 'credits_marker_first': int(bool(credits_marker and notify_params['credits'] == 0)), + 'credits_marker_final': int(credits_marker['final']), + 'credits_marker_start': credits_marker['start_time_offset'], + 'credits_marker_end': credits_marker['end_time_offset'], 'channel_call_sign': notify_params['channel_call_sign'], 'channel_identifier': notify_params['channel_identifier'], 'channel_thumb': notify_params['channel_thumb'], @@ -1132,6 +1155,7 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m 'user_rating': notify_params['user_rating'], 'duration': duration, 'duration_sec': duration_sec, + 'duration_ms': notify_params['duration'], 'poster_title': notify_params['poster_title'], 'poster_url': notify_params['poster_url'], 'plex_id': notify_params['plex_id'], diff --git a/plexpy/notifiers.py b/plexpy/notifiers.py index e3ef6862..383f4908 100644 --- a/plexpy/notifiers.py +++ b/plexpy/notifiers.py @@ -340,6 +340,22 @@ def available_notification_actions(agent_id=None): 'icon': 'fa-exchange-alt', 'media_types': ('movie', 'episode', 'track') }, + {'label': 'Intro Marker', + 'name': 'on_intro', + 'description': 'Trigger a notification when a video stream reaches any intro marker.', + 'subject': 'Tautulli ({server_name})', + 'body': '{user} ({player}) has reached an intro marker for {title}.', + 'icon': 'fa-bookmark', + 'media_types': ('episode',) + }, + {'label': 'Credits Marker', + 'name': 'on_credits', + 'description': 'Trigger a notification when a video stream reaches any credits marker.', + 'subject': 'Tautulli ({server_name})', + 'body': '{user} ({player}) has reached a credits marker for {title}.', + 'icon': 'fa-bookmark', + 'media_types': ('movie', 'episode') + }, {'label': 'Watched', 'name': 'on_watched', 'description': 'Trigger a notification when a video stream reaches the specified watch percentage.',