def notify_timeline(timeline_data=None, notify_action=None): if timeline_data and notify_action: if (timeline_data['media_type'] == 'movie' and plexpy.CONFIG.MOVIE_NOTIFY_ENABLE) \ or ((timeline_data['media_type'] == 'show' or timeline_data['media_type'] == 'episode') \ and plexpy.CONFIG.TV_NOTIFY_ENABLE) \ or ((timeline_data['media_type'] == 'artist' or timeline_data['media_type'] == 'track') \ and plexpy.CONFIG.MUSIC_NOTIFY_ENABLE): for agent in notifiers.available_notification_agents(): if agent['on_created'] and notify_action == 'created': # Build and send notification notify_strings = build_notify_text(timeline=timeline_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=timeline_data, state=notify_action, agent_info=agent) elif not timeline_data and notify_action: for agent in notifiers.available_notification_agents(): if agent['on_extdown'] and notify_action == 'extdown': # Build and send notification notify_strings = build_server_notify_text(state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) if agent['on_intdown'] and notify_action == 'intdown': # Build and send notification notify_strings = build_server_notify_text(state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) else: logger.debug(u"PlexPy Notifier :: Notify timeline called but incomplete data received.")
def notify_timeline(timeline_data=None, notify_action=None): if timeline_data and notify_action: for agent in notifiers.available_notification_agents(): if agent["on_created"] and notify_action == "created": # Build and send notification notify_strings = build_notify_text(timeline=timeline_data, state=notify_action) notifiers.send_notification( config_id=agent["id"], subject=notify_strings[0], body=notify_strings[1], notify_action=notify_action, script_args=notify_strings[2], ) # Set the notification state in the db set_notify_state(session=timeline_data, state=notify_action, agent_info=agent) elif not timeline_data and notify_action: for agent in notifiers.available_notification_agents(): if agent["on_extdown"] and notify_action == "extdown": # Build and send notification notify_strings = build_server_notify_text(state=notify_action) notifiers.send_notification( config_id=agent["id"], subject=notify_strings[0], body=notify_strings[1], notify_action=notify_action, script_args=notify_strings[2], ) if agent["on_intdown"] and notify_action == "intdown": # Build and send notification notify_strings = build_server_notify_text(state=notify_action) notifiers.send_notification( config_id=agent["id"], subject=notify_strings[0], body=notify_strings[1], notify_action=notify_action, script_args=notify_strings[2], ) if agent["on_extup"] and notify_action == "extup": # Build and send notification notify_strings = build_server_notify_text(state=notify_action) notifiers.send_notification( config_id=agent["id"], subject=notify_strings[0], body=notify_strings[1], notify_action=notify_action, script_args=notify_strings[2], ) if agent["on_intup"] and notify_action == "intup": # Build and send notification notify_strings = build_server_notify_text(state=notify_action) notifiers.send_notification( config_id=agent["id"], subject=notify_strings[0], body=notify_strings[1], notify_action=notify_action, script_args=notify_strings[2], ) else: logger.debug(u"PlexPy NotificationHandler :: Notify timeline called but incomplete data received.")
def notify_timeline(timeline_data=None, notify_action=None): if timeline_data and notify_action: if (timeline_data['media_type'] == 'movie' and plexpy.CONFIG.MOVIE_NOTIFY_ENABLE) \ or ((timeline_data['media_type'] == 'show' or timeline_data['media_type'] == 'episode') \ and plexpy.CONFIG.TV_NOTIFY_ENABLE) \ or ((timeline_data['media_type'] == 'artist' or timeline_data['media_type'] == 'track') \ and plexpy.CONFIG.MUSIC_NOTIFY_ENABLE): for agent in notifiers.available_notification_agents(): if agent['on_created'] and notify_action == 'created': # Build and send notification notify_strings = build_notify_text(timeline=timeline_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=timeline_data, state=notify_action, agent_info=agent) elif not timeline_data and notify_action: for agent in notifiers.available_notification_agents(): if agent['on_extdown'] and notify_action == 'extdown': # Build and send notification notify_strings = build_server_notify_text(state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) if agent['on_intdown'] and notify_action == 'intdown': # Build and send notification notify_strings = build_server_notify_text(state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) if agent['on_extup'] and notify_action == 'extup': # Build and send notification notify_strings = build_server_notify_text(state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) if agent['on_intup'] and notify_action == 'intup': # Build and send notification notify_strings = build_server_notify_text(state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) else: logger.debug( u"PlexPy Notifier :: Notify timeline called but incomplete data received." )
def on_buffer(self): if self.is_valid_session(): logger.debug(u"PlexPy ActivityHandler :: Session %s is buffering." % self.get_session_key()) ap = activity_processor.ActivityProcessor() db_stream = ap.get_session_by_key(session_key=self.get_session_key()) # Increment our buffer count ap.increment_session_buffer_count(session_key=self.get_session_key()) # Get our current buffer count current_buffer_count = ap.get_session_buffer_count(self.get_session_key()) logger.debug(u"PlexPy ActivityHandler :: Session %s buffer count is %s." % (self.get_session_key(), current_buffer_count)) # Get our last triggered time buffer_last_triggered = ap.get_session_buffer_trigger_time(self.get_session_key()) time_since_last_trigger = 0 if buffer_last_triggered: logger.debug(u"PlexPy ActivityHandler :: Session %s buffer last triggered at %s." % (self.get_session_key(), buffer_last_triggered)) time_since_last_trigger = int(time.time()) - int(buffer_last_triggered) if plexpy.CONFIG.BUFFER_THRESHOLD > 0 and (current_buffer_count >= plexpy.CONFIG.BUFFER_THRESHOLD and \ time_since_last_trigger == 0 or time_since_last_trigger >= plexpy.CONFIG.BUFFER_WAIT): ap.set_session_buffer_trigger_time(session_key=self.get_session_key()) # Check if any notification agents have notifications enabled if any(d['on_buffer'] for d in notifiers.available_notification_agents()): threading.Thread(target=notification_handler.notify, kwargs=dict(stream_data=db_stream, notify_action='buffer')).start()
def check_server_updates(): with monitor_lock: logger.info(u"PlexPy Monitor :: Checking for PMS updates...") pms_connect = pmsconnect.PmsConnect() server_identity = pms_connect.get_server_identity() update_status = pms_connect.get_update_staus() if server_identity and update_status: version = server_identity['version'] logger.info(u"PlexPy Monitor :: Current PMS version: %s", version) if update_status['state'] == 'available': update_version = update_status['version'] logger.info( u"PlexPy Monitor :: PMS update available version: %s", update_version) # Check if any notification agents have notifications enabled if any(d['on_pmsupdate'] for d in notifiers.available_notification_agents()): # Fire off notifications threading.Thread( target=notification_handler.notify_timeline, kwargs=dict(notify_action='pmsupdate')).start() else: logger.info(u"PlexPy Monitor :: No PMS update available.")
def on_stop(self, force_stop=False): if self.is_valid_session(): logger.debug(u"PlexPy ActivityHandler :: Session %s has stopped." % str(self.get_session_key())) # Set the session last_paused timestamp ap = activity_processor.ActivityProcessor() ap.set_session_last_paused(session_key=self.get_session_key(), timestamp=None) # Update the session state and viewOffset # Set force_stop to true to disable the state set if not force_stop: ap.set_session_state(session_key=self.get_session_key(), state=self.timeline['state'], view_offset=self.timeline['viewOffset'], stopped=int(time.time())) # Retrieve the session data from our temp table db_session = ap.get_session_by_key(session_key=self.get_session_key()) # Check if any notification agents have notifications enabled if any(d['on_stop'] for d in notifiers.available_notification_agents()): # Fire off notifications threading.Thread(target=notification_handler.notify, kwargs=dict(stream_data=db_session, notify_action='stop')).start() # Write it to the history table monitor_proc = activity_processor.ActivityProcessor() monitor_proc.write_session_history(session=db_session) # Remove the session from our temp session table logger.debug(u"PlexPy ActivityHandler :: Removing session %s from session queue" % str(self.get_session_key())) ap.delete_session(session_key=self.get_session_key())
def check_server_updates(): with monitor_lock: logger.info(u"PlexPy Monitor :: Checking for PMS updates...") pms_connect = pmsconnect.PmsConnect() server_identity = pms_connect.get_server_identity() update_status = pms_connect.get_update_staus() if server_identity and update_status: version = server_identity['version'] logger.info(u"PlexPy Monitor :: Current PMS version: %s", version) if update_status['state'] == 'available': update_version = update_status['version'] logger.info(u"PlexPy Monitor :: PMS update available version: %s", update_version) # Check if any notification agents have notifications enabled if any(d['on_pmsupdate'] for d in notifiers.available_notification_agents()): # Fire off notifications threading.Thread(target=notification_handler.notify_timeline, kwargs=dict(notify_action='pmsupdate')).start() else: logger.info(u"PlexPy Monitor :: No PMS update available.")
def check_server_response(): with monitor_lock: pms_connect = pmsconnect.PmsConnect() server_response = pms_connect.get_server_response() global ext_ping_count # Check for remote access if server_response: mapping_state = server_response['mapping_state'] mapping_error = server_response['mapping_error'] # Check if the port is mapped if not mapping_state == 'mapped': ext_ping_count += 1 logger.warn(u"PlexPy Monitor :: Plex remote access port not mapped, ping attempt %s." \ % str(ext_ping_count)) # Check if the port is open elif mapping_error == 'unreachable': ext_ping_count += 1 logger.warn(u"PlexPy Monitor :: Plex remote access port mapped, but mapping failed, ping attempt %s." \ % str(ext_ping_count)) # Reset external ping counter else: if ext_ping_count >= 3: logger.info( u"PlexPy Monitor :: Plex remote access is back up.") # Check if any notification agents have notifications enabled if any(d['on_extup'] for d in notifiers.available_notification_agents()): # Fire off notifications threading.Thread( target=notification_handler.notify_timeline, kwargs=dict(notify_action='extup')).start() ext_ping_count = 0 if ext_ping_count == 3: # Check if any notification agents have notifications enabled if any(d['on_extdown'] for d in notifiers.available_notification_agents()): # Fire off notifications threading.Thread(target=notification_handler.notify_timeline, kwargs=dict(notify_action='extdown')).start()
def process(self): if self.is_valid_session(): ap = activity_processor.ActivityProcessor() db_session = ap.get_session_by_key(session_key=self.get_session_key()) this_state = self.timeline['state'] this_key = str(self.timeline['ratingKey']) # If we already have this session in the temp table, check for state changes if db_session: last_state = db_session['state'] last_key = str(db_session['rating_key']) # Make sure the same item is being played if this_key == last_key: # Update the session state and viewOffset if this_state == 'playing': ap.set_session_state(session_key=self.get_session_key(), state=this_state, view_offset=self.timeline['viewOffset']) # Start our state checks if this_state != last_state: if this_state == 'paused': self.on_pause() elif last_state == 'paused' and this_state == 'playing': self.on_resume() elif this_state == 'stopped': self.on_stop() elif this_state == 'buffering': self.on_buffer() # If a client doesn't register stop events (I'm looking at you PHT!) check if the ratingKey has changed else: # Manually stop and start # Set force_stop so that we don't overwrite our last viewOffset self.on_stop(force_stop=True) self.on_start() # Monitor if the stream has reached the watch percentage for notifications # The only purpose of this is for notifications # Check if any notification agents have notifications enabled notify_agents = [d['id'] for d in notifiers.available_notification_agents() if d['on_watched']] # Get the current states for notifications from our db notified_agents = [d['agent_id'] for d in notification_handler.get_notify_state(session=db_session) if d['notify_action'] == 'watched'] if notify_agents else [] if any(a not in notified_agents for a in notify_agents): progress_percent = helpers.get_percent(self.timeline['viewOffset'], db_session['duration']) if progress_percent >= plexpy.CONFIG.NOTIFY_WATCHED_PERCENT and this_state != 'buffering': # Rather not put this on it's own thread so we know it completes before our next event. notification_handler.notify(stream_data=db_session, notify_action='watched') else: # We don't have this session in our table yet, start a new one. if this_state != 'buffering': self.on_start()
def check_server_response(): with monitor_lock: pms_connect = pmsconnect.PmsConnect() server_response = pms_connect.get_server_response() global ext_ping_count # Check for remote access if server_response: mapping_state = server_response['mapping_state'] mapping_error = server_response['mapping_error'] # Check if the port is mapped if not mapping_state == 'mapped': ext_ping_count += 1 logger.warn(u"PlexPy Monitor :: Plex remote access port not mapped, ping attempt %s." \ % str(ext_ping_count)) # Check if the port is open elif mapping_error == 'unreachable': ext_ping_count += 1 logger.warn(u"PlexPy Monitor :: Plex remote access port mapped, but mapping failed, ping attempt %s." \ % str(ext_ping_count)) # Reset external ping counter else: if ext_ping_count >= 3: logger.info(u"PlexPy Monitor :: Plex remote access is back up.") # Check if any notification agents have notifications enabled if any(d['on_extup'] for d in notifiers.available_notification_agents()): # Fire off notifications threading.Thread(target=notification_handler.notify_timeline, kwargs=dict(notify_action='extup')).start() ext_ping_count = 0 if ext_ping_count == 3: # Check if any notification agents have notifications enabled if any(d['on_extdown'] for d in notifiers.available_notification_agents()): # Fire off notifications threading.Thread(target=notification_handler.notify_timeline, kwargs=dict(notify_action='extdown')).start()
def on_start(self): if self.is_valid_session() and self.get_live_session(): logger.debug(u"PlexPy ActivityHandler :: Session %s has started." % str(self.get_session_key())) # Check if any notification agents have notifications enabled if any(d['on_play'] for d in notifiers.available_notification_agents()): # Fire off notifications threading.Thread(target=notification_handler.notify, kwargs=dict(stream_data=self.get_live_session(), notify_action='play')).start() # Write the new session to our temp session table self.update_db_session()
def get_notification_agent_triggers(self, config_id, **kwargs): if config_id.isdigit(): agents = notifiers.available_notification_agents() for agent in agents: if int(config_id) == agent['id']: this_agent = agent break else: this_agent = None else: return None return serve_template(templatename="notification_triggers_modal.html", title="Notification Triggers", data=this_agent)
def on_resume(self): if self.is_valid_session(): logger.debug(u"PlexPy ActivityHandler :: Session %s has been resumed." % str(self.get_session_key())) # Set the session last_paused timestamp ap = activity_processor.ActivityProcessor() ap.set_session_last_paused(session_key=self.get_session_key(), timestamp=None) # Update the session state and viewOffset ap.set_session_state(session_key=self.get_session_key(), state=self.timeline['state'], view_offset=self.timeline['viewOffset']) # Retrieve the session data from our temp table db_session = ap.get_session_by_key(session_key=self.get_session_key()) # Check if any notification agents have notifications enabled if any(d['on_resume'] for d in notifiers.available_notification_agents()): # Fire off notifications threading.Thread(target=notification_handler.notify, kwargs=dict(stream_data=db_session, notify_action='resume')).start()
def notify(stream_data=None, notify_action=None): from plexpy import pmsconnect, common if stream_data and notify_action: # Get the server name pms_connect = pmsconnect.PmsConnect() server_name = pms_connect.get_server_pref(pref='FriendlyName') # Build the notification heading notify_header = 'PlexPy (%s)' % server_name # Build media item title if stream_data['media_type'] == 'episode' or stream_data['media_type'] == 'track': item_title = '%s - %s' % (stream_data['grandparent_title'], stream_data['title']) elif stream_data['media_type'] == 'movie': item_title = stream_data['title'] else: item_title = stream_data['title'] if notify_action == 'play': logger.info('PlexPy Notifier :: %s (%s) started playing %s.' % (stream_data['friendly_name'], stream_data['player'], item_title)) if stream_data['media_type'] == 'movie' or stream_data['media_type'] == 'episode': if plexpy.CONFIG.MOVIE_NOTIFY_ENABLE or plexpy.CONFIG.TV_NOTIFY_ENABLE: for agent in notifiers.available_notification_agents(): if agent['on_play'] and notify_action == 'play': logger.debug("PlexPy Notifier :: %s agent is configured to notify on playback start." % agent['name']) message = '%s (%s) started playing %s.' % \ (stream_data['friendly_name'], stream_data['player'], item_title) notifiers.send_notification(config_id=agent['id'], subject=notify_header, body=message) set_notify_state(session=stream_data, state='play', agent_info=agent) elif agent['on_stop'] and notify_action == 'stop': logger.debug("PlexPy Notifier :: %s agent is configured to notify on playback stop." % agent['name']) message = '%s (%s) has stopped %s.' % \ (stream_data['friendly_name'], stream_data['player'], item_title) notifiers.send_notification(config_id=agent['id'], subject=notify_header, body=message) set_notify_state(session=stream_data, state='stop', agent_info=agent) elif agent['on_watched'] and notify_action == 'watched': notify_states = get_notify_state(session=stream_data) # If there is nothing in the notify_log for our agent id but it is enabled we should notify if not any(d['agent_id'] == agent['id'] for d in notify_states): logger.debug("PlexPy Notifier :: %s agent is configured to notify on watched." % agent['name']) message = '%s (%s) has watched %s.' % \ (stream_data['friendly_name'], stream_data['player'], item_title) notifiers.send_notification(config_id=agent['id'], subject=notify_header, body=message) set_notify_state(session=stream_data, state='watched', agent_info=agent) else: # Check in our notify log if the notification has already been sent for notify_state in notify_states: if not notify_state['on_watched'] and (notify_state['agent_id'] == agent['id']): logger.debug("PlexPy Notifier :: %s agent is configured to notify on watched." % agent['name']) message = '%s (%s) has watched %s.' % \ (stream_data['friendly_name'], stream_data['player'], item_title) notifiers.send_notification(config_id=agent['id'], subject=notify_header, body=message) set_notify_state(session=stream_data, state='watched', agent_info=agent) elif stream_data['media_type'] == 'track': if plexpy.CONFIG.MUSIC_NOTIFY_ENABLE: for agent in notifiers.available_notification_agents(): if agent['on_play'] and notify_action == 'play': logger.debug("PlexPy Notifier :: %s agent is configured to notify on playback start." % agent['name']) message = '%s (%s) started playing %s.' % \ (stream_data['friendly_name'], stream_data['player'], item_title) notifiers.send_notification(config_id=agent['id'], subject=notify_header, body=message) set_notify_state(session=stream_data, state='play', agent_info=agent) elif agent['on_stop'] and notify_action == 'stop': logger.debug("PlexPy Notifier :: %s agent is configured to notify on playback stop." % agent['name']) message = '%s (%s) has stopped %s.' % \ (stream_data['friendly_name'], stream_data['player'], item_title) notifiers.send_notification(config_id=agent['id'], subject=notify_header, body=message) set_notify_state(session=stream_data, state='stop', agent_info=agent) elif stream_data['media_type'] == 'clip': pass else: logger.debug(u"PlexPy Notifier :: Notify called with unsupported media type.") pass else: logger.debug(u"PlexPy Notifier :: Notify called but incomplete data received.")
def notify(stream_data=None, notify_action=None): from plexpy import users if stream_data and notify_action: # Check if notifications enabled for user user_data = users.Users() user_details = user_data.get_user_friendly_name( user=stream_data['user']) if not user_details['do_notify']: return if (stream_data['media_type'] == 'movie' and plexpy.CONFIG.MOVIE_NOTIFY_ENABLE) \ or (stream_data['media_type'] == 'episode' and plexpy.CONFIG.TV_NOTIFY_ENABLE): progress_percent = helpers.get_percent(stream_data['view_offset'], stream_data['duration']) for agent in notifiers.available_notification_agents(): if agent['on_play'] and notify_action == 'play': # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=stream_data, state=notify_action, agent_info=agent) elif agent['on_stop'] and notify_action == 'stop' \ and (plexpy.CONFIG.NOTIFY_CONSECUTIVE or progress_percent < plexpy.CONFIG.NOTIFY_WATCHED_PERCENT): # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) set_notify_state(session=stream_data, state=notify_action, agent_info=agent) elif agent['on_pause'] and notify_action == 'pause' \ and (plexpy.CONFIG.NOTIFY_CONSECUTIVE or progress_percent < 99): # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) set_notify_state(session=stream_data, state=notify_action, agent_info=agent) elif agent['on_resume'] and notify_action == 'resume' \ and (plexpy.CONFIG.NOTIFY_CONSECUTIVE or progress_percent < 99): # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) set_notify_state(session=stream_data, state=notify_action, agent_info=agent) elif agent['on_buffer'] and notify_action == 'buffer': # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) set_notify_state(session=stream_data, state=notify_action, agent_info=agent) elif agent['on_watched'] and notify_action == 'watched': # Get the current states for notifications from our db notify_states = get_notify_state(session=stream_data) # If there is nothing in the notify_log for our agent id but it is enabled we should notify if not any(d['agent_id'] == agent['id'] for d in notify_states): # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=stream_data, state=notify_action, agent_info=agent) else: # Check in our notify log if the notification has already been sent for notify_state in notify_states: if not notify_state['on_watched'] and ( notify_state['agent_id'] == agent['id']): # Build and send notification notify_strings = build_notify_text( session=stream_data, state=notify_action) notifiers.send_notification( config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=stream_data, state=notify_action, agent_info=agent) elif (stream_data['media_type'] == 'track' and plexpy.CONFIG.MUSIC_NOTIFY_ENABLE): for agent in notifiers.available_notification_agents(): if agent['on_play'] and notify_action == 'play': # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=stream_data, state=notify_action, agent_info=agent) elif agent['on_stop'] and notify_action == 'stop': # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=stream_data, state=notify_action, agent_info=agent) elif agent['on_pause'] and notify_action == 'pause': # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=stream_data, state=notify_action, agent_info=agent) elif agent['on_resume'] and notify_action == 'resume': # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=stream_data, state=notify_action, agent_info=agent) elif agent['on_buffer'] and notify_action == 'buffer': # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=stream_data, state=notify_action, agent_info=agent) elif stream_data['media_type'] == 'clip': pass else: #logger.debug(u"PlexPy Notifier :: Notify called with unsupported media type.") pass else: logger.debug( u"PlexPy Notifier :: Notify called but incomplete data received.")
def notify(stream_data=None, notify_action=None): from plexpy import datafactory if stream_data and notify_action: # Check if notifications enabled for user data_factory = datafactory.DataFactory() user_details = data_factory.get_user_friendly_name(user=stream_data['user']) if not user_details['do_notify']: return if stream_data['media_type'] == 'movie' or stream_data['media_type'] == 'episode': if plexpy.CONFIG.MOVIE_NOTIFY_ENABLE or plexpy.CONFIG.TV_NOTIFY_ENABLE: for agent in notifiers.available_notification_agents(): if agent['on_play'] and notify_action == 'play': # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=stream_data, state='play', agent_info=agent) elif agent['on_stop'] and notify_action == 'stop': # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) set_notify_state(session=stream_data, state='stop', agent_info=agent) elif agent['on_watched'] and notify_action == 'watched': # Get the current states for notifications from our db notify_states = get_notify_state(session=stream_data) # If there is nothing in the notify_log for our agent id but it is enabled we should notify if not any(d['agent_id'] == agent['id'] for d in notify_states): # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=stream_data, state='watched', agent_info=agent) else: # Check in our notify log if the notification has already been sent for notify_state in notify_states: if not notify_state['on_watched'] and (notify_state['agent_id'] == agent['id']): # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=stream_data, state='watched', agent_info=agent) elif stream_data['media_type'] == 'track': if plexpy.CONFIG.MUSIC_NOTIFY_ENABLE: for agent in notifiers.available_notification_agents(): if agent['on_play'] and notify_action == 'play': # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=stream_data, state='play', agent_info=agent) elif agent['on_stop'] and notify_action == 'stop': # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=stream_data, state='stop', agent_info=agent) elif stream_data['media_type'] == 'clip': pass else: logger.debug(u"PlexPy Notifier :: Notify called with unsupported media type.") pass else: logger.debug(u"PlexPy Notifier :: Notify called but incomplete data received.")
def check_active_sessions(ws_request=False): with monitor_lock: pms_connect = pmsconnect.PmsConnect() session_list = pms_connect.get_current_activity() monitor_db = database.MonitorDatabase() monitor_process = activity_processor.ActivityProcessor() # logger.debug(u"PlexPy Monitor :: Checking for active streams.") global int_ping_count if session_list: if int_ping_count >= 3: logger.info( u"PlexPy Monitor :: The Plex Media Server is back up.") # Check if any notification agents have notifications enabled if any(d['on_intup'] for d in notifiers.available_notification_agents()): # Fire off notifications threading.Thread( target=notification_handler.notify_timeline, kwargs=dict(notify_action='intup')).start() int_ping_count = 0 media_container = session_list['sessions'] # Check our temp table for what we must do with the new streams db_streams = monitor_db.select('SELECT * FROM sessions') for stream in db_streams: if any(d['session_key'] == str(stream['session_key']) and d['rating_key'] == str(stream['rating_key']) for d in media_container): # The user's session is still active for session in media_container: if session['session_key'] == str(stream['session_key']) and \ session['rating_key'] == str(stream['rating_key']): # The user is still playing the same media item # Here we can check the play states if session['state'] != stream['state']: if session['state'] == 'paused': logger.debug( u"PlexPy Monitor :: Session %s has been paused." % stream['session_key']) # Check if any notification agents have notifications enabled if any(d['on_pause'] for d in notifiers. available_notification_agents()): # Push any notifications - # Push it on it's own thread so we don't hold up our db actions threading.Thread( target=notification_handler.notify, kwargs=dict(stream_data=stream, notify_action='pause' )).start() if session['state'] == 'playing' and stream[ 'state'] == 'paused': logger.debug( u"PlexPy Monitor :: Session %s has been resumed." % stream['session_key']) # Check if any notification agents have notifications enabled if any(d['on_resume'] for d in notifiers. available_notification_agents()): # Push any notifications - # Push it on it's own thread so we don't hold up our db actions threading.Thread( target=notification_handler.notify, kwargs=dict(stream_data=stream, notify_action='resume' )).start() if stream['state'] == 'paused' and not ws_request: # The stream is still paused so we need to increment the paused_counter # Using the set config parameter as the interval, probably not the most accurate but # it will have to do for now. If it's a websocket request don't use this method. paused_counter = int( stream['paused_counter'] ) + plexpy.CONFIG.MONITORING_INTERVAL monitor_db.action( 'UPDATE sessions SET paused_counter = ? ' 'WHERE session_key = ? AND rating_key = ?', [ paused_counter, stream['session_key'], stream['rating_key'] ]) if session[ 'state'] == 'buffering' and plexpy.CONFIG.BUFFER_THRESHOLD > 0: # The stream is buffering so we need to increment the buffer_count # We're going just increment on every monitor ping, # would be difficult to keep track otherwise monitor_db.action( 'UPDATE sessions SET buffer_count = buffer_count + 1 ' 'WHERE session_key = ? AND rating_key = ?', [ stream['session_key'], stream['rating_key'] ]) # Check the current buffer count and last buffer to determine if we should notify buffer_values = monitor_db.select( 'SELECT buffer_count, buffer_last_triggered ' 'FROM sessions ' 'WHERE session_key = ? AND rating_key = ?', [ stream['session_key'], stream['rating_key'] ]) if buffer_values[0][ 'buffer_count'] >= plexpy.CONFIG.BUFFER_THRESHOLD: # Push any notifications - # Push it on it's own thread so we don't hold up our db actions # Our first buffer notification if buffer_values[0][ 'buffer_count'] == plexpy.CONFIG.BUFFER_THRESHOLD: logger.info( u"PlexPy Monitor :: User '%s' has triggered a buffer warning." % stream['user']) # Set the buffer trigger time monitor_db.action( 'UPDATE sessions ' 'SET buffer_last_triggered = strftime("%s","now") ' 'WHERE session_key = ? AND rating_key = ?', [ stream['session_key'], stream['rating_key'] ]) # Check if any notification agents have notifications enabled if any(d['on_buffer'] for d in notifiers. available_notification_agents( )): # Push any notifications - # Push it on it's own thread so we don't hold up our db actions threading.Thread( target=notification_handler. notify, kwargs=dict( stream_data=stream, notify_action='buffer' )).start() else: # Subsequent buffer notifications after wait time if int(time.time()) > buffer_values[0]['buffer_last_triggered'] + \ plexpy.CONFIG.BUFFER_WAIT: logger.info( u"PlexPy Monitor :: User '%s' has triggered multiple buffer warnings." % stream['user']) # Set the buffer trigger time monitor_db.action( 'UPDATE sessions ' 'SET buffer_last_triggered = strftime("%s","now") ' 'WHERE session_key = ? AND rating_key = ?', [ stream['session_key'], stream['rating_key'] ]) # Check if any notification agents have notifications enabled if any(d['on_buffer'] for d in notifiers. available_notification_agents( )): # Push any notifications - # Push it on it's own thread so we don't hold up our db actions threading.Thread( target=notification_handler .notify, kwargs=dict( stream_data=stream, notify_action='buffer' )).start() logger.debug( u"PlexPy Monitor :: Session %s is buffering. Count is now %s. Last triggered %s." % (stream['session_key'], buffer_values[0]['buffer_count'], buffer_values[0]['buffer_last_triggered']) ) # Check if the user has reached the offset in the media we defined as the "watched" percent # Don't trigger if state is buffer as some clients push the progress to the end when # buffering on start. if session['view_offset'] and session[ 'duration'] and session[ 'state'] != 'buffering': if helpers.get_percent( session['view_offset'], session['duration'] ) > plexpy.CONFIG.NOTIFY_WATCHED_PERCENT: # Check if any notification agents have notifications enabled if any(d['on_watched'] for d in notifiers. available_notification_agents()): # Push any notifications - # Push it on it's own thread so we don't hold up our db actions threading.Thread( target=notification_handler.notify, kwargs=dict(stream_data=stream, notify_action='watched' )).start() else: # The user has stopped playing a stream if stream['state'] != 'stopped': logger.debug( u"PlexPy Monitor :: Session %s has stopped." % stream['session_key']) # Set the stream stop time stream['stopped'] = int(time.time()) monitor_db.action( 'UPDATE sessions SET stopped = ?, state = ? ' 'WHERE session_key = ? AND rating_key = ?', [ stream['stopped'], 'stopped', stream['session_key'], stream['rating_key'] ]) # Check if the user has reached the offset in the media we defined as the "watched" percent if stream['view_offset'] and stream['duration']: if helpers.get_percent( stream['view_offset'], stream['duration'] ) > plexpy.CONFIG.NOTIFY_WATCHED_PERCENT: # Check if any notification agents have notifications enabled if any(d['on_watched'] for d in notifiers. available_notification_agents()): # Push any notifications - # Push it on it's own thread so we don't hold up our db actions threading.Thread( target=notification_handler.notify, kwargs=dict( stream_data=stream, notify_action='watched')).start() # Check if any notification agents have notifications enabled if any(d['on_stop'] for d in notifiers.available_notification_agents()): # Push any notifications - Push it on it's own thread so we don't hold up our db actions threading.Thread( target=notification_handler.notify, kwargs=dict(stream_data=stream, notify_action='stop')).start() # Write the item history on playback stop success = monitor_process.write_session_history( session=stream) if success: # If session is written to the databaase successfully, remove the session from the session table logger.debug( u"PlexPy Monitor :: Removing sessionKey %s ratingKey %s from session queue" % (stream['session_key'], stream['rating_key'])) monitor_db.action( 'DELETE FROM sessions WHERE session_key = ? AND rating_key = ?', [stream['session_key'], stream['rating_key']]) else: logger.warn(u"PlexPy Monitor :: Failed to write sessionKey %s ratingKey %s to the database. " \ "Will try again on the next pass." % (stream['session_key'], stream['rating_key'])) # Process the newly received session data for session in media_container: new_session = monitor_process.write_session(session) if new_session: logger.debug(u"PlexPy Monitor :: Session %s has started." % session['session_key']) else: logger.debug(u"PlexPy Monitor :: Unable to read session list.") int_ping_count += 1 logger.warn(u"PlexPy Monitor :: Unable to get an internal response from the server, ping attempt %s." \ % str(int_ping_count)) if int_ping_count == 3: # Check if any notification agents have notifications enabled if any(d['on_intdown'] for d in notifiers.available_notification_agents()): # Fire off notifications threading.Thread(target=notification_handler.notify_timeline, kwargs=dict(notify_action='intdown')).start()
def check_recently_added(): with monitor_lock: # add delay to allow for metadata processing delay = plexpy.CONFIG.NOTIFY_RECENTLY_ADDED_DELAY time_threshold = int(time.time()) - delay time_interval = plexpy.CONFIG.MONITORING_INTERVAL pms_connect = pmsconnect.PmsConnect() recently_added_list = pms_connect.get_recently_added_details( count='10') library_data = libraries.Libraries() if recently_added_list: recently_added = recently_added_list['recently_added'] for item in recently_added: library_details = library_data.get_details( section_id=item['section_id']) if not library_details['do_notify_created']: continue metadata = [] if 0 < time_threshold - int(item['added_at']) <= time_interval: if item['media_type'] == 'movie': metadata_list = pms_connect.get_metadata_details( item['rating_key']) if metadata_list: metadata = [metadata_list['metadata']] else: logger.error(u"PlexPy Monitor :: Unable to retrieve metadata for rating_key %s" \ % str(item['rating_key'])) else: metadata_list = pms_connect.get_metadata_children_details( item['rating_key']) if metadata_list: metadata = metadata_list['metadata'] else: logger.error(u"PlexPy Monitor :: Unable to retrieve children metadata for rating_key %s" \ % str(item['rating_key'])) if metadata: if not plexpy.CONFIG.NOTIFY_RECENTLY_ADDED_GRANDPARENT: for item in metadata: library_details = library_data.get_details( section_id=item['section_id']) if 0 < time_threshold - int( item['added_at']) <= time_interval: logger.debug( u"PlexPy Monitor :: Library item %s has been added to Plex." % str(item['rating_key'])) # Check if any notification agents have notifications enabled if any(d['on_created'] for d in notifiers. available_notification_agents()): # Fire off notifications threading.Thread( target=notification_handler. notify_timeline, kwargs=dict( timeline_data=item, notify_action='created')).start() else: item = max(metadata, key=lambda x: x['added_at']) if 0 < time_threshold - int( item['added_at']) <= time_interval: if item['media_type'] == 'episode' or item[ 'media_type'] == 'track': metadata_list = pms_connect.get_metadata_details( item['grandparent_rating_key']) if metadata_list: item = metadata_list['metadata'] else: logger.error(u"PlexPy Monitor :: Unable to retrieve grandparent metadata for grandparent_rating_key %s" \ % str(item['rating_key'])) logger.debug( u"PlexPy Monitor :: Library item %s has been added to Plex." % str(item['rating_key'])) # Check if any notification agents have notifications enabled if any(d['on_created'] for d in notifiers.available_notification_agents()): # Fire off notifications threading.Thread( target=notification_handler. notify_timeline, kwargs=dict( timeline_data=item, notify_action='created')).start()
def write_session(self, session=None, notify=True): if session: values = {'session_key': session['session_key'], 'section_id': session['section_id'], 'rating_key': session['rating_key'], 'media_type': session['media_type'], 'state': session['state'], 'user_id': session['user_id'], 'user': session['user'], 'machine_id': session['machine_id'], 'title': session['title'], 'parent_title': session['parent_title'], 'grandparent_title': session['grandparent_title'], 'friendly_name': session['friendly_name'], #'ip_address': session['ip_address'], 'player': session['player'], 'platform': session['platform'], 'parent_rating_key': session['parent_rating_key'], 'grandparent_rating_key': session['grandparent_rating_key'], 'view_offset': session['view_offset'], 'duration': session['duration'], 'video_decision': session['video_decision'], 'audio_decision': session['audio_decision'], 'width': session['width'], 'height': session['height'], 'container': session['container'], 'video_codec': session['video_codec'], 'audio_codec': session['audio_codec'], 'bitrate': session['bitrate'], 'video_resolution': session['video_resolution'], 'video_framerate': session['video_framerate'], 'aspect_ratio': session['aspect_ratio'], 'audio_channels': session['audio_channels'], 'transcode_protocol': session['transcode_protocol'], 'transcode_container': session['transcode_container'], 'transcode_video_codec': session['transcode_video_codec'], 'transcode_audio_codec': session['transcode_audio_codec'], 'transcode_audio_channels': session['transcode_audio_channels'], 'transcode_width': session['transcode_width'], 'transcode_height': session['transcode_height'] } # Add ip_address back into values if session['ip_address']: values.update({'ip_address': session['ip_address']}) keys = {'session_key': session['session_key'], 'rating_key': session['rating_key']} result = self.db.upsert('sessions', values, keys) if result == 'insert': # Check if any notification agents have notifications enabled if notify and any(d['on_play'] for d in notifiers.available_notification_agents()): values.update({'ip_address': session['ip_address']}) # Push any notifications - Push it on it's own thread so we don't hold up our db actions threading.Thread(target=notification_handler.notify, kwargs=dict(stream_data=values, notify_action='play')).start() # If it's our first write then time stamp it. started = int(time.time()) timestamp = {'started': started} self.db.upsert('sessions', timestamp, keys) # Try and grab IP address from logs (fallback if not on PMS 0.9.14 and above) if not session['ip_address']: if plexpy.CONFIG.IP_LOGGING_ENABLE and plexpy.CONFIG.PMS_LOGS_FOLDER: ip_address = self.find_session_ip(rating_key=session['rating_key'], machine_id=session['machine_id']) ip_address = {'ip_address': ip_address} self.db.upsert('sessions', ip_address, keys) return True
def write_session(self, session=None, notify=True): if session: values = { 'session_key': session['session_key'], 'transcode_key': session['transcode_key'], 'section_id': session['section_id'], 'rating_key': session['rating_key'], 'media_type': session['media_type'], 'state': session['state'], 'user_id': session['user_id'], 'user': session['user'], 'machine_id': session['machine_id'], 'title': session['title'], 'parent_title': session['parent_title'], 'grandparent_title': session['grandparent_title'], 'friendly_name': session['friendly_name'], #'ip_address': session['ip_address'], 'player': session['player'], 'platform': session['platform'], 'parent_rating_key': session['parent_rating_key'], 'grandparent_rating_key': session['grandparent_rating_key'], 'view_offset': session['view_offset'], 'duration': session['duration'], 'video_decision': session['video_decision'], 'audio_decision': session['audio_decision'], 'width': session['width'], 'height': session['height'], 'container': session['container'], 'video_codec': session['video_codec'], 'audio_codec': session['audio_codec'], 'bitrate': session['bitrate'], 'video_resolution': session['video_resolution'], 'video_framerate': session['video_framerate'], 'aspect_ratio': session['aspect_ratio'], 'audio_channels': session['audio_channels'], 'transcode_protocol': session['transcode_protocol'], 'transcode_container': session['transcode_container'], 'transcode_video_codec': session['transcode_video_codec'], 'transcode_audio_codec': session['transcode_audio_codec'], 'transcode_audio_channels': session['transcode_audio_channels'], 'transcode_width': session['transcode_width'], 'transcode_height': session['transcode_height'] } # Add ip_address back into values if session['ip_address']: values.update({'ip_address': session['ip_address']}) keys = { 'session_key': session['session_key'], 'rating_key': session['rating_key'] } result = self.db.upsert('sessions', values, keys) if result == 'insert': # Check if any notification agents have notifications enabled if notify and any( d['on_play'] for d in notifiers.available_notification_agents()): values.update({'ip_address': session['ip_address']}) # Push any notifications - Push it on it's own thread so we don't hold up our db actions threading.Thread(target=notification_handler.notify, kwargs=dict( stream_data=values, notify_action='play')).start() # If it's our first write then time stamp it. started = int(time.time()) timestamp = {'started': started} self.db.upsert('sessions', timestamp, keys) # Try and grab IP address from logs (fallback if not on PMS 0.9.14 and above) if not session['ip_address']: if plexpy.CONFIG.IP_LOGGING_ENABLE and plexpy.CONFIG.PMS_LOGS_FOLDER: ip_address = self.find_session_ip( rating_key=session['rating_key'], machine_id=session['machine_id']) ip_address = {'ip_address': ip_address} self.db.upsert('sessions', ip_address, keys) return True
def notify(stream_data=None, notify_action=None): from plexpy import users if stream_data and notify_action: # Check if notifications enabled for user user_data = users.Users() user_details = user_data.get_user_friendly_name(user=stream_data["user"]) if not user_details["do_notify"]: return if stream_data["media_type"] == "movie" or stream_data["media_type"] == "episode": if plexpy.CONFIG.MOVIE_NOTIFY_ENABLE or plexpy.CONFIG.TV_NOTIFY_ENABLE: progress_percent = helpers.get_percent(stream_data["view_offset"], stream_data["duration"]) for agent in notifiers.available_notification_agents(): if agent["on_play"] and notify_action == "play": # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification( config_id=agent["id"], subject=notify_strings[0], body=notify_strings[1] ) # Set the notification state in the db set_notify_state(session=stream_data, state="play", agent_info=agent) elif ( agent["on_stop"] and notify_action == "stop" and ( plexpy.CONFIG.NOTIFY_CONSECUTIVE or progress_percent < plexpy.CONFIG.NOTIFY_WATCHED_PERCENT ) ): # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification( config_id=agent["id"], subject=notify_strings[0], body=notify_strings[1] ) set_notify_state(session=stream_data, state="stop", agent_info=agent) elif ( agent["on_pause"] and notify_action == "pause" and (plexpy.CONFIG.NOTIFY_CONSECUTIVE or progress_percent < 99) ): # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification( config_id=agent["id"], subject=notify_strings[0], body=notify_strings[1] ) set_notify_state(session=stream_data, state="pause", agent_info=agent) elif ( agent["on_resume"] and notify_action == "resume" and (plexpy.CONFIG.NOTIFY_CONSECUTIVE or progress_percent < 99) ): # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification( config_id=agent["id"], subject=notify_strings[0], body=notify_strings[1] ) set_notify_state(session=stream_data, state="resume", agent_info=agent) elif agent["on_buffer"] and notify_action == "buffer": # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification( config_id=agent["id"], subject=notify_strings[0], body=notify_strings[1] ) set_notify_state(session=stream_data, state="buffer", agent_info=agent) elif agent["on_watched"] and notify_action == "watched": # Get the current states for notifications from our db notify_states = get_notify_state(session=stream_data) # If there is nothing in the notify_log for our agent id but it is enabled we should notify if not any(d["agent_id"] == agent["id"] for d in notify_states): # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification( config_id=agent["id"], subject=notify_strings[0], body=notify_strings[1] ) # Set the notification state in the db set_notify_state(session=stream_data, state="watched", agent_info=agent) else: # Check in our notify log if the notification has already been sent for notify_state in notify_states: if not notify_state["on_watched"] and (notify_state["agent_id"] == agent["id"]): # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification( config_id=agent["id"], subject=notify_strings[0], body=notify_strings[1] ) # Set the notification state in the db set_notify_state(session=stream_data, state="watched", agent_info=agent) elif stream_data["media_type"] == "track": if plexpy.CONFIG.MUSIC_NOTIFY_ENABLE: for agent in notifiers.available_notification_agents(): if agent["on_play"] and notify_action == "play": # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification( config_id=agent["id"], subject=notify_strings[0], body=notify_strings[1] ) # Set the notification state in the db set_notify_state(session=stream_data, state="play", agent_info=agent) elif agent["on_stop"] and notify_action == "stop": # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification( config_id=agent["id"], subject=notify_strings[0], body=notify_strings[1] ) # Set the notification state in the db set_notify_state(session=stream_data, state="stop", agent_info=agent) elif agent["on_pause"] and notify_action == "pause": # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification( config_id=agent["id"], subject=notify_strings[0], body=notify_strings[1] ) # Set the notification state in the db set_notify_state(session=stream_data, state="pause", agent_info=agent) elif agent["on_resume"] and notify_action == "resume": # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification( config_id=agent["id"], subject=notify_strings[0], body=notify_strings[1] ) # Set the notification state in the db set_notify_state(session=stream_data, state="resume", agent_info=agent) elif agent["on_buffer"] and notify_action == "buffer": # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification( config_id=agent["id"], subject=notify_strings[0], body=notify_strings[1] ) # Set the notification state in the db set_notify_state(session=stream_data, state="buffer", agent_info=agent) elif stream_data["media_type"] == "clip": pass else: logger.debug(u"PlexPy Notifier :: Notify called with unsupported media type.") pass else: logger.debug(u"PlexPy Notifier :: Notify called but incomplete data received.")
def check_recently_added(): with monitor_lock: # add delay to allow for metadata processing delay = plexpy.CONFIG.NOTIFY_RECENTLY_ADDED_DELAY time_threshold = int(time.time()) - delay time_interval = plexpy.CONFIG.MONITORING_INTERVAL pms_connect = pmsconnect.PmsConnect() recently_added_list = pms_connect.get_recently_added_details(count='10') library_data = libraries.Libraries() if recently_added_list: recently_added = recently_added_list['recently_added'] for item in recently_added: library_details = library_data.get_details(section_id=item['section_id']) if not library_details['do_notify_created']: continue metadata = [] if 0 < time_threshold - int(item['added_at']) <= time_interval: if item['media_type'] == 'movie': metadata_list = pms_connect.get_metadata_details(item['rating_key']) if metadata_list: metadata = [metadata_list['metadata']] else: logger.error(u"PlexPy Monitor :: Unable to retrieve metadata for rating_key %s" \ % str(item['rating_key'])) else: metadata_list = pms_connect.get_metadata_children_details(item['rating_key']) if metadata_list: metadata = metadata_list['metadata'] else: logger.error(u"PlexPy Monitor :: Unable to retrieve children metadata for rating_key %s" \ % str(item['rating_key'])) if metadata: if not plexpy.CONFIG.NOTIFY_RECENTLY_ADDED_GRANDPARENT: for item in metadata: library_details = library_data.get_details(section_id=item['section_id']) if 0 < time_threshold - int(item['added_at']) <= time_interval: logger.debug(u"PlexPy Monitor :: Library item %s has been added to Plex." % str(item['rating_key'])) # Check if any notification agents have notifications enabled if any(d['on_created'] for d in notifiers.available_notification_agents()): # Fire off notifications threading.Thread(target=notification_handler.notify_timeline, kwargs=dict(timeline_data=item, notify_action='created')).start() else: item = max(metadata, key=lambda x:x['added_at']) if 0 < time_threshold - int(item['added_at']) <= time_interval: if item['media_type'] == 'episode' or item['media_type'] == 'track': metadata_list = pms_connect.get_metadata_details(item['grandparent_rating_key']) if metadata_list: item = metadata_list['metadata'] else: logger.error(u"PlexPy Monitor :: Unable to retrieve grandparent metadata for grandparent_rating_key %s" \ % str(item['rating_key'])) logger.debug(u"PlexPy Monitor :: Library item %s has been added to Plex." % str(item['rating_key'])) # Check if any notification agents have notifications enabled if any(d['on_created'] for d in notifiers.available_notification_agents()): # Fire off notifications threading.Thread(target=notification_handler.notify_timeline, kwargs=dict(timeline_data=item, notify_action='created')).start()
def check_active_sessions(ws_request=False): with monitor_lock: pms_connect = pmsconnect.PmsConnect() session_list = pms_connect.get_current_activity() monitor_db = database.MonitorDatabase() monitor_process = activity_processor.ActivityProcessor() # logger.debug(u"PlexPy Monitor :: Checking for active streams.") global int_ping_count if session_list: if int_ping_count >= 3: logger.info(u"PlexPy Monitor :: The Plex Media Server is back up.") # Check if any notification agents have notifications enabled if any(d['on_intup'] for d in notifiers.available_notification_agents()): # Fire off notifications threading.Thread(target=notification_handler.notify_timeline, kwargs=dict(notify_action='intup')).start() int_ping_count = 0 media_container = session_list['sessions'] # Check our temp table for what we must do with the new streams db_streams = monitor_db.select('SELECT * FROM sessions') for stream in db_streams: if any(d['session_key'] == str(stream['session_key']) and d['rating_key'] == str(stream['rating_key']) for d in media_container): # The user's session is still active for session in media_container: if session['session_key'] == str(stream['session_key']) and \ session['rating_key'] == str(stream['rating_key']): # The user is still playing the same media item # Here we can check the play states if session['state'] != stream['state']: if session['state'] == 'paused': logger.debug(u"PlexPy Monitor :: Session %s has been paused." % stream['session_key']) # Check if any notification agents have notifications enabled if any(d['on_pause'] for d in notifiers.available_notification_agents()): # Push any notifications - # Push it on it's own thread so we don't hold up our db actions threading.Thread(target=notification_handler.notify, kwargs=dict(stream_data=stream, notify_action='pause')).start() if session['state'] == 'playing' and stream['state'] == 'paused': logger.debug(u"PlexPy Monitor :: Session %s has been resumed." % stream['session_key']) # Check if any notification agents have notifications enabled if any(d['on_resume'] for d in notifiers.available_notification_agents()): # Push any notifications - # Push it on it's own thread so we don't hold up our db actions threading.Thread(target=notification_handler.notify, kwargs=dict(stream_data=stream, notify_action='resume')).start() if stream['state'] == 'paused' and not ws_request: # The stream is still paused so we need to increment the paused_counter # Using the set config parameter as the interval, probably not the most accurate but # it will have to do for now. If it's a websocket request don't use this method. paused_counter = int(stream['paused_counter']) + plexpy.CONFIG.MONITORING_INTERVAL monitor_db.action('UPDATE sessions SET paused_counter = ? ' 'WHERE session_key = ? AND rating_key = ?', [paused_counter, stream['session_key'], stream['rating_key']]) if session['state'] == 'buffering' and plexpy.CONFIG.BUFFER_THRESHOLD > 0: # The stream is buffering so we need to increment the buffer_count # We're going just increment on every monitor ping, # would be difficult to keep track otherwise monitor_db.action('UPDATE sessions SET buffer_count = buffer_count + 1 ' 'WHERE session_key = ? AND rating_key = ?', [stream['session_key'], stream['rating_key']]) # Check the current buffer count and last buffer to determine if we should notify buffer_values = monitor_db.select('SELECT buffer_count, buffer_last_triggered ' 'FROM sessions ' 'WHERE session_key = ? AND rating_key = ?', [stream['session_key'], stream['rating_key']]) if buffer_values[0]['buffer_count'] >= plexpy.CONFIG.BUFFER_THRESHOLD: # Push any notifications - # Push it on it's own thread so we don't hold up our db actions # Our first buffer notification if buffer_values[0]['buffer_count'] == plexpy.CONFIG.BUFFER_THRESHOLD: logger.info(u"PlexPy Monitor :: User '%s' has triggered a buffer warning." % stream['user']) # Set the buffer trigger time monitor_db.action('UPDATE sessions ' 'SET buffer_last_triggered = strftime("%s","now") ' 'WHERE session_key = ? AND rating_key = ?', [stream['session_key'], stream['rating_key']]) # Check if any notification agents have notifications enabled if any(d['on_buffer'] for d in notifiers.available_notification_agents()): # Push any notifications - # Push it on it's own thread so we don't hold up our db actions threading.Thread(target=notification_handler.notify, kwargs=dict(stream_data=stream, notify_action='buffer')).start() else: # Subsequent buffer notifications after wait time if int(time.time()) > buffer_values[0]['buffer_last_triggered'] + \ plexpy.CONFIG.BUFFER_WAIT: logger.info(u"PlexPy Monitor :: User '%s' has triggered multiple buffer warnings." % stream['user']) # Set the buffer trigger time monitor_db.action('UPDATE sessions ' 'SET buffer_last_triggered = strftime("%s","now") ' 'WHERE session_key = ? AND rating_key = ?', [stream['session_key'], stream['rating_key']]) # Check if any notification agents have notifications enabled if any(d['on_buffer'] for d in notifiers.available_notification_agents()): # Push any notifications - # Push it on it's own thread so we don't hold up our db actions threading.Thread(target=notification_handler.notify, kwargs=dict(stream_data=stream, notify_action='buffer')).start() logger.debug(u"PlexPy Monitor :: Session %s is buffering. Count is now %s. Last triggered %s." % (stream['session_key'], buffer_values[0]['buffer_count'], buffer_values[0]['buffer_last_triggered'])) # Check if the user has reached the offset in the media we defined as the "watched" percent # Don't trigger if state is buffer as some clients push the progress to the end when # buffering on start. if session['view_offset'] and session['duration'] and session['state'] != 'buffering': if helpers.get_percent(session['view_offset'], session['duration']) > plexpy.CONFIG.NOTIFY_WATCHED_PERCENT: # Check if any notification agents have notifications enabled if any(d['on_watched'] for d in notifiers.available_notification_agents()): # Push any notifications - # Push it on it's own thread so we don't hold up our db actions threading.Thread(target=notification_handler.notify, kwargs=dict(stream_data=stream, notify_action='watched')).start() else: # The user has stopped playing a stream if stream['state'] != 'stopped': logger.debug(u"PlexPy Monitor :: Session %s has stopped." % stream['session_key']) # Set the stream stop time stream['stopped'] = int(time.time()) monitor_db.action('UPDATE sessions SET stopped = ?, state = ? ' 'WHERE session_key = ? AND rating_key = ?', [stream['stopped'], 'stopped', stream['session_key'], stream['rating_key']]) # Check if the user has reached the offset in the media we defined as the "watched" percent if stream['view_offset'] and stream['duration']: if helpers.get_percent(stream['view_offset'], stream['duration']) > plexpy.CONFIG.NOTIFY_WATCHED_PERCENT: # Check if any notification agents have notifications enabled if any(d['on_watched'] for d in notifiers.available_notification_agents()): # Push any notifications - # Push it on it's own thread so we don't hold up our db actions threading.Thread(target=notification_handler.notify, kwargs=dict(stream_data=stream, notify_action='watched')).start() # Check if any notification agents have notifications enabled if any(d['on_stop'] for d in notifiers.available_notification_agents()): # Push any notifications - Push it on it's own thread so we don't hold up our db actions threading.Thread(target=notification_handler.notify, kwargs=dict(stream_data=stream, notify_action='stop')).start() # Write the item history on playback stop success = monitor_process.write_session_history(session=stream) if success: # If session is written to the databaase successfully, remove the session from the session table logger.debug(u"PlexPy Monitor :: Removing sessionKey %s ratingKey %s from session queue" % (stream['session_key'], stream['rating_key'])) monitor_db.action('DELETE FROM sessions WHERE session_key = ? AND rating_key = ?', [stream['session_key'], stream['rating_key']]) else: logger.warn(u"PlexPy Monitor :: Failed to write sessionKey %s ratingKey %s to the database. " \ "Will try again on the next pass." % (stream['session_key'], stream['rating_key'])) # Process the newly received session data for session in media_container: new_session = monitor_process.write_session(session) if new_session: logger.debug(u"PlexPy Monitor :: Session %s has started." % session['session_key']) else: logger.debug(u"PlexPy Monitor :: Unable to read session list.") int_ping_count += 1 logger.warn(u"PlexPy Monitor :: Unable to get an internal response from the server, ping attempt %s." \ % str(int_ping_count)) if int_ping_count == 3: # Check if any notification agents have notifications enabled if any(d['on_intdown'] for d in notifiers.available_notification_agents()): # Fire off notifications threading.Thread(target=notification_handler.notify_timeline, kwargs=dict(notify_action='intdown')).start()
def notify(stream_data=None, notify_action=None): from plexpy import users if stream_data and notify_action: # Check if notifications enabled for user user_data = users.Users() user_details = user_data.get_user_friendly_name(user=stream_data['user']) if not user_details['do_notify']: return if (stream_data['media_type'] == 'movie' and plexpy.CONFIG.MOVIE_NOTIFY_ENABLE) \ or (stream_data['media_type'] == 'episode' and plexpy.CONFIG.TV_NOTIFY_ENABLE): progress_percent = helpers.get_percent(stream_data['view_offset'], stream_data['duration']) for agent in notifiers.available_notification_agents(): if agent['on_play'] and notify_action == 'play': # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=stream_data, state=notify_action, agent_info=agent) elif agent['on_stop'] and notify_action == 'stop' \ and (plexpy.CONFIG.NOTIFY_CONSECUTIVE or progress_percent < plexpy.CONFIG.NOTIFY_WATCHED_PERCENT): # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) set_notify_state(session=stream_data, state=notify_action, agent_info=agent) elif agent['on_pause'] and notify_action == 'pause' \ and (plexpy.CONFIG.NOTIFY_CONSECUTIVE or progress_percent < 99): # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) set_notify_state(session=stream_data, state=notify_action, agent_info=agent) elif agent['on_resume'] and notify_action == 'resume' \ and (plexpy.CONFIG.NOTIFY_CONSECUTIVE or progress_percent < 99): # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) set_notify_state(session=stream_data, state=notify_action, agent_info=agent) elif agent['on_buffer'] and notify_action == 'buffer': # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) set_notify_state(session=stream_data, state=notify_action, agent_info=agent) elif agent['on_watched'] and notify_action == 'watched': # Get the current states for notifications from our db notify_states = get_notify_state(session=stream_data) # If there is nothing in the notify_log for our agent id but it is enabled we should notify if not any(d['agent_id'] == agent['id'] for d in notify_states): # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=stream_data, state=notify_action, agent_info=agent) else: # Check in our notify log if the notification has already been sent for notify_state in notify_states: if not notify_state['on_watched'] and (notify_state['agent_id'] == agent['id']): # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=stream_data, state=notify_action, agent_info=agent) elif (stream_data['media_type'] == 'track' and plexpy.CONFIG.MUSIC_NOTIFY_ENABLE): for agent in notifiers.available_notification_agents(): if agent['on_play'] and notify_action == 'play': # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=stream_data, state=notify_action, agent_info=agent) elif agent['on_stop'] and notify_action == 'stop': # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=stream_data, state=notify_action, agent_info=agent) elif agent['on_pause'] and notify_action == 'pause': # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=stream_data, state=notify_action, agent_info=agent) elif agent['on_resume'] and notify_action == 'resume': # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=stream_data, state=notify_action, agent_info=agent) elif agent['on_buffer'] and notify_action == 'buffer': # Build and send notification notify_strings = build_notify_text(session=stream_data, state=notify_action) notifiers.send_notification(config_id=agent['id'], subject=notify_strings[0], body=notify_strings[1]) # Set the notification state in the db set_notify_state(session=stream_data, state=notify_action, agent_info=agent) elif stream_data['media_type'] == 'clip': pass else: #logger.debug(u"PlexPy Notifier :: Notify called with unsupported media type.") pass else: logger.debug(u"PlexPy Notifier :: Notify called but incomplete data received.")
def notify_timeline(timeline_data=None, notify_action=None): if timeline_data and notify_action: if ( (timeline_data["media_type"] == "movie" and plexpy.CONFIG.MOVIE_NOTIFY_ENABLE) or ( (timeline_data["media_type"] == "show" or timeline_data["media_type"] == "episode") and plexpy.CONFIG.TV_NOTIFY_ENABLE ) or ( (timeline_data["media_type"] == "artist" or timeline_data["media_type"] == "track") and plexpy.CONFIG.MUSIC_NOTIFY_ENABLE ) ): for agent in notifiers.available_notification_agents(): if agent["on_created"] and notify_action == "created": # Build and send notification notify_strings = build_notify_text(timeline=timeline_data, state=notify_action) notifiers.send_notification( config_id=agent["id"], subject=notify_strings[0], body=notify_strings[1], notify_action=notify_action, script_args=notify_strings[2], ) # Set the notification state in the db set_notify_state(session=timeline_data, state=notify_action, agent_info=agent) elif not timeline_data and notify_action: for agent in notifiers.available_notification_agents(): if agent["on_extdown"] and notify_action == "extdown": # Build and send notification notify_strings = build_server_notify_text(state=notify_action) notifiers.send_notification( config_id=agent["id"], subject=notify_strings[0], body=notify_strings[1], notify_action=notify_action, script_args=notify_strings[2], ) if agent["on_intdown"] and notify_action == "intdown": # Build and send notification notify_strings = build_server_notify_text(state=notify_action) notifiers.send_notification( config_id=agent["id"], subject=notify_strings[0], body=notify_strings[1], notify_action=notify_action, script_args=notify_strings[2], ) if agent["on_extup"] and notify_action == "extup": # Build and send notification notify_strings = build_server_notify_text(state=notify_action) notifiers.send_notification( config_id=agent["id"], subject=notify_strings[0], body=notify_strings[1], notify_action=notify_action, script_args=notify_strings[2], ) if agent["on_intup"] and notify_action == "intup": # Build and send notification notify_strings = build_server_notify_text(state=notify_action) notifiers.send_notification( config_id=agent["id"], subject=notify_strings[0], body=notify_strings[1], notify_action=notify_action, script_args=notify_strings[2], ) else: logger.debug(u"PlexPy NotificationHandler :: Notify timeline called but incomplete data received.")