def build_server_notify_text(state=None): # Get the server name server_name = plexpy.CONFIG.PMS_NAME # Get the server uptime plex_tv = plextv.PlexTV() server_times = plex_tv.get_server_times() if server_times: updated_at = server_times[0]['updated_at'] server_uptime = helpers.human_duration(int(time.time() - helpers.cast_to_float(updated_at))) else: logger.error(u"PlexPy NotificationHandler :: Unable to retrieve server uptime.") server_uptime = 'N/A' on_extdown_subject = plexpy.CONFIG.NOTIFY_ON_EXTDOWN_SUBJECT_TEXT on_extdown_body = plexpy.CONFIG.NOTIFY_ON_EXTDOWN_BODY_TEXT on_intdown_subject = plexpy.CONFIG.NOTIFY_ON_INTDOWN_SUBJECT_TEXT on_intdown_body = plexpy.CONFIG.NOTIFY_ON_INTDOWN_BODY_TEXT on_extup_subject = plexpy.CONFIG.NOTIFY_ON_EXTUP_SUBJECT_TEXT on_extup_body = plexpy.CONFIG.NOTIFY_ON_EXTUP_BODY_TEXT on_intup_subject = plexpy.CONFIG.NOTIFY_ON_INTUP_SUBJECT_TEXT on_intup_body = plexpy.CONFIG.NOTIFY_ON_INTUP_BODY_TEXT script_args_text = plexpy.CONFIG.NOTIFY_SCRIPTS_ARGS_TEXT available_params = {'server_name': server_name, 'server_uptime': server_uptime, 'action': state, 'datestamp': arrow.now().format(plexpy.CONFIG.DATE_FORMAT.replace('Do','').replace('zz','')), 'timestamp': arrow.now().format(plexpy.CONFIG.TIME_FORMAT.replace('Do','').replace('zz',''))} # Default text subject_text = 'PlexPy (%s)' % server_name # Default scripts args script_args = [] # Regex to match {param} but not "{param}" params_to_quote = re.compile(r'(?<!\")([\{][^}]+[\}])(?!\"\})') script_args_text = re.sub(params_to_quote, r'"\g<0>"', script_args_text) if script_args_text: try: script_args = [unicode(arg).format(**available_params) for arg in script_args_text.split()] except LookupError as e: logger.error(u"PlexPy Notifier :: Unable to parse field %s in script argument. Using fallback." % e) except Exception as e: logger.error(u"PlexPy Notifier :: Unable to parse custom script arguments %s. Using fallback." % e) if state == 'extdown': # Default body text body_text = 'The Plex Media Server remote access is down.' if on_extdown_subject and on_extdown_body: try: subject_text = unicode(on_extdown_subject).format(**available_params) except LookupError, e: logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e) except:
def build_server_notify_text(state=None): # Get the server name server_name = plexpy.CONFIG.PMS_NAME # Get the server uptime plex_tv = plextv.PlexTV() server_times = plex_tv.get_server_times() if server_times: updated_at = server_times[0]['updated_at'] server_uptime = helpers.human_duration( int(time.time() - helpers.cast_to_float(updated_at))) else: logger.error(u"PlexPy Notifier :: Unable to retrieve server uptime.") server_uptime = 'N/A' on_extdown_subject = plexpy.CONFIG.NOTIFY_ON_EXTDOWN_SUBJECT_TEXT on_extdown_body = plexpy.CONFIG.NOTIFY_ON_EXTDOWN_BODY_TEXT on_intdown_subject = plexpy.CONFIG.NOTIFY_ON_INTDOWN_SUBJECT_TEXT on_intdown_body = plexpy.CONFIG.NOTIFY_ON_INTDOWN_BODY_TEXT on_extup_subject = plexpy.CONFIG.NOTIFY_ON_EXTUP_SUBJECT_TEXT on_extup_body = plexpy.CONFIG.NOTIFY_ON_EXTUP_BODY_TEXT on_intup_subject = plexpy.CONFIG.NOTIFY_ON_INTUP_SUBJECT_TEXT on_intup_body = plexpy.CONFIG.NOTIFY_ON_INTUP_BODY_TEXT available_params = { 'server_name': server_name, 'server_uptime': server_uptime } # Default text subject_text = 'PlexPy (%s)' % server_name if state == 'extdown': # Default body text body_text = 'The Plex Media Server remote access is down.' if on_extdown_subject and on_extdown_body: try: subject_text = unicode(on_extdown_subject).format( **available_params) except LookupError, e: logger.error( u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e) except:
def build_server_notify_text(state=None): # Get the server name server_name = plexpy.CONFIG.PMS_NAME # Get the server uptime plex_tv = plextv.PlexTV() server_times = plex_tv.get_server_times() if server_times: updated_at = server_times[0]['updated_at'] server_uptime = helpers.human_duration(int(time.time() - helpers.cast_to_float(updated_at))) else: logger.error(u"PlexPy Notifier :: Unable to retrieve server uptime.") server_uptime = 'N/A' on_extdown_subject = plexpy.CONFIG.NOTIFY_ON_EXTDOWN_SUBJECT_TEXT on_extdown_body = plexpy.CONFIG.NOTIFY_ON_EXTDOWN_BODY_TEXT on_intdown_subject = plexpy.CONFIG.NOTIFY_ON_INTDOWN_SUBJECT_TEXT on_intdown_body = plexpy.CONFIG.NOTIFY_ON_INTDOWN_BODY_TEXT on_extup_subject = plexpy.CONFIG.NOTIFY_ON_EXTUP_SUBJECT_TEXT on_extup_body = plexpy.CONFIG.NOTIFY_ON_EXTUP_BODY_TEXT on_intup_subject = plexpy.CONFIG.NOTIFY_ON_INTUP_SUBJECT_TEXT on_intup_body = plexpy.CONFIG.NOTIFY_ON_INTUP_BODY_TEXT available_params = {'server_name': server_name, 'server_uptime': server_uptime} # Default text subject_text = 'PlexPy (%s)' % server_name if state == 'extdown': # Default body text body_text = 'The Plex Media Server remote access is down.' if on_extdown_subject and on_extdown_body: try: subject_text = unicode(on_extdown_subject).format(**available_params) except LookupError, e: logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e) except:
def build_notify_text(session=None, timeline=None, state=None): import re # Get the server name server_name = plexpy.CONFIG.PMS_NAME # Get the server uptime plex_tv = plextv.PlexTV() server_times = plex_tv.get_server_times() if server_times: updated_at = server_times[0]['updated_at'] server_uptime = helpers.human_duration(int(time.time() - helpers.cast_to_float(updated_at))) else: logger.error(u"PlexPy Notifier :: Unable to retrieve server uptime.") server_uptime = 'N/A' # Get metadata feed for item if session: rating_key = session['rating_key'] elif timeline: rating_key = timeline['rating_key'] pms_connect = pmsconnect.PmsConnect() metadata_list = pms_connect.get_metadata_details(rating_key=rating_key) if metadata_list: metadata = metadata_list['metadata'] else: logger.error(u"PlexPy Notifier :: Unable to retrieve metadata for rating_key %s" % str(rating_key)) return [] # Check for exclusion tags if metadata['media_type'] == 'movie': # Regex pattern to remove the text in the tags we don't want pattern = re.compile('<tv>[^>]+.</tv>|<music>[^>]+.</music>', re.IGNORECASE) elif metadata['media_type'] == 'show' or metadata['media_type'] == 'episode': # Regex pattern to remove the text in the tags we don't want pattern = re.compile('<movie>[^>]+.</movie>|<music>[^>]+.</music>', re.IGNORECASE) elif metadata['media_type'] == 'artist' or metadata['media_type'] == 'track': # Regex pattern to remove the text in the tags we don't want pattern = re.compile('<tv>[^>]+.</tv>|<movie>[^>]+.</movie>', re.IGNORECASE) else: pattern = None if metadata['media_type'] == 'movie' \ or metadata['media_type'] == 'show' or metadata['media_type'] == 'episode' \ or metadata['media_type'] == 'artist' or metadata['media_type'] == 'track' \ and pattern: # Remove the unwanted tags and strip any unmatch tags too. on_start_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT)) on_start_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT)) on_stop_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT)) on_stop_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT)) on_pause_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_PAUSE_SUBJECT_TEXT)) on_pause_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_PAUSE_BODY_TEXT)) on_resume_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_RESUME_SUBJECT_TEXT)) on_resume_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_RESUME_BODY_TEXT)) on_buffer_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_BUFFER_SUBJECT_TEXT)) on_buffer_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_BUFFER_BODY_TEXT)) on_watched_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT)) on_watched_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT)) on_created_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_CREATED_SUBJECT_TEXT)) on_created_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_CREATED_BODY_TEXT)) else: on_start_subject = plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT on_start_body = plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT on_stop_subject = plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT on_stop_body = plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT on_pause_subject = plexpy.CONFIG.NOTIFY_ON_PAUSE_SUBJECT_TEXT on_pause_body = plexpy.CONFIG.NOTIFY_ON_PAUSE_BODY_TEXT on_resume_subject = plexpy.CONFIG.NOTIFY_ON_RESUME_SUBJECT_TEXT on_resume_body = plexpy.CONFIG.NOTIFY_ON_RESUME_BODY_TEXT on_buffer_subject = plexpy.CONFIG.NOTIFY_ON_BUFFER_SUBJECT_TEXT on_buffer_body = plexpy.CONFIG.NOTIFY_ON_BUFFER_BODY_TEXT on_watched_subject = plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT on_watched_body = plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT on_created_subject = plexpy.CONFIG.NOTIFY_ON_CREATED_SUBJECT_TEXT on_created_body = plexpy.CONFIG.NOTIFY_ON_CREATED_BODY_TEXT # Create a title if metadata['media_type'] == 'episode' or metadata['media_type'] == 'track': full_title = '%s - %s' % (metadata['grandparent_title'], metadata['title']) else: full_title = metadata['title'] duration = helpers.convert_milliseconds_to_minutes(metadata['duration']) # Default values video_decision = '' audio_decision = '' transcode_decision = '' stream_duration = 0 view_offset = 0 user = '' platform = '' player = '' ip_address = 'N/A' # Session values if session: # Generate a combined transcode decision value video_decision = session['video_decision'].title() audio_decision = session['audio_decision'].title() if session['video_decision'] == 'transcode' or session['audio_decision'] == 'transcode': transcode_decision = 'Transcode' elif session['video_decision'] == 'copy' or session['audio_decision'] == 'copy': transcode_decision = 'Direct Stream' else: transcode_decision = 'Direct Play' if state != 'play': if session['paused_counter']: stream_duration = int((time.time() - helpers.cast_to_float(session['started']) - helpers.cast_to_float(session['paused_counter'])) / 60) else: stream_duration = int((time.time() - helpers.cast_to_float(session['started'])) / 60) view_offset = helpers.convert_milliseconds_to_minutes(session['view_offset']) user = session['friendly_name'] platform = session['platform'] player = session['player'] ip_address = session['ip_address'] if session['ip_address'] else 'N/A' progress_percent = helpers.get_percent(view_offset, duration) available_params = {'server_name': server_name, 'server_uptime': server_uptime, 'user': user, 'platform': platform, 'player': player, 'ip_address': ip_address, 'media_type': metadata['media_type'], 'title': full_title, 'show_name': metadata['grandparent_title'], 'episode_name': metadata['title'], 'artist_name': metadata['grandparent_title'], 'album_name': metadata['parent_title'], 'track_name': metadata['title'], 'season_num': metadata['parent_index'].zfill(1), 'season_num00': metadata['parent_index'].zfill(2), 'episode_num': metadata['index'].zfill(1), 'episode_num00': metadata['index'].zfill(2), 'video_decision': video_decision, 'audio_decision': audio_decision, 'transcode_decision': transcode_decision, 'year': metadata['year'], 'studio': metadata['studio'], 'content_rating': metadata['content_rating'], 'directors': ', '.join(metadata['directors']), 'writers': ', '.join(metadata['writers']), 'actors': ', '.join(metadata['actors']), 'genres': ', '.join(metadata['genres']), 'summary': metadata['summary'], 'tagline': metadata['tagline'], 'rating': metadata['rating'], 'duration': duration, 'stream_duration': stream_duration, 'remaining_duration': duration - view_offset, 'progress': view_offset, 'progress_percent': progress_percent } # Default subject text subject_text = 'PlexPy (%s)' % server_name if state == 'play': # Default body text body_text = '%s (%s) is watching %s' % (session['friendly_name'], session['player'], full_title) if on_start_subject and on_start_body: try: subject_text = unicode(on_start_subject).format(**available_params) except LookupError, e: logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e) except:
def _getHistory(self, iDisplayStart=0, iDisplayLength=100, sSearch="", iSortCol_0='0', sSortDir_0='asc', **kwargs): iDisplayStart = int(iDisplayStart) iDisplayLength = int(iDisplayLength) filtered = [] totalcount = 0 myDB = db.DBConnection() db_table = db.DBConnection().get_history_table_name() sortcolumn = 'time' sortbyhavepercent = False if iSortCol_0 == '1': sortcolumn = 'user' if iSortCol_0 == '2': sortcolumn = 'platform' elif iSortCol_0 == '3': sortcolumn = 'ip_address' elif iSortCol_0 == '4': sortcolumn = 'title' elif iSortCol_0 == '5': sortcolumn = 'time' elif iSortCol_0 == '6': sortcolumn = 'paused_counter' elif iSortCol_0 == '7': sortcolumn = 'stopped' elif iSortCol_0 == '8': sortbyhavepercent = True if sSearch == "": query = 'SELECT * from %s order by %s COLLATE NOCASE %s' % ( db_table, sortcolumn, sSortDir_0) filtered = myDB.select(query) totalcount = len(filtered) else: query = 'SELECT * from ' + db_table + ' WHERE user LIKE "%' + sSearch + \ '%" OR title LIKE "%' + sSearch + '%"' + 'ORDER BY %s COLLATE NOCASE %s' % (sortcolumn, sSortDir_0) filtered = myDB.select(query) totalcount = myDB.select('SELECT COUNT(*) from processed')[0][0] history = filtered[iDisplayStart:(iDisplayStart + iDisplayLength)] rows = [] for item in history: row = { "date": item['time'], "user": item["user"], "platform": item["platform"], "ip_address": item["ip_address"], "title": item["title"], "started": item["time"], "paused": item["paused_counter"], "stopped": item["stopped"], "duration": "", "percent_complete": 0, } if item['paused_counter'] > 0: row['paused'] = item['paused_counter'] else: row['paused'] = 0 if item['time']: if item['stopped'] > 0: stopped = item['stopped'] else: stopped = 0 if item['paused_counter'] > 0: paused_counter = item['paused_counter'] else: paused_counter = 0 row['duration'] = stopped - item['time'] + paused_counter try: xml_parse = minidom.parseString( helpers.latinToAscii(item['xml'])) except IOError, e: logger.warn("Error parsing XML in PlexWatch db: %s" % e) xml_head = xml_parse.getElementsByTagName('opt') if not xml_head: logger.warn("Error parsing XML in PlexWatch db: %s" % e) for s in xml_head: if s.getAttribute('duration') and s.getAttribute('viewOffset'): view_offset = helpers.cast_to_float( s.getAttribute('viewOffset')) duration = helpers.cast_to_float( s.getAttribute('duration')) if duration > 0: row['percent_complete'] = (view_offset / duration) * 100 else: row['percent_complete'] = 0 rows.append(row)
def build_notify_text(session=None, timeline=None, state=None): import re # Get the server name server_name = plexpy.CONFIG.PMS_NAME # Get the server uptime plex_tv = plextv.PlexTV() server_times = plex_tv.get_server_times() if server_times: updated_at = server_times[0]['updated_at'] server_uptime = helpers.human_duration( int(time.time() - helpers.cast_to_float(updated_at))) else: logger.error(u"PlexPy Notifier :: Unable to retrieve server uptime.") server_uptime = 'N/A' # Get metadata feed for item if session: rating_key = session['rating_key'] elif timeline: rating_key = timeline['rating_key'] pms_connect = pmsconnect.PmsConnect() metadata_list = pms_connect.get_metadata_details(rating_key=rating_key) if metadata_list: metadata = metadata_list['metadata'] else: logger.error( u"PlexPy Notifier :: Unable to retrieve metadata for rating_key %s" % str(rating_key)) return [] # Check for exclusion tags if metadata['media_type'] == 'movie': # Regex pattern to remove the text in the tags we don't want pattern = re.compile('<tv>[^>]+.</tv>|<music>[^>]+.</music>', re.IGNORECASE) elif metadata['media_type'] == 'show' or metadata[ 'media_type'] == 'episode': # Regex pattern to remove the text in the tags we don't want pattern = re.compile('<movie>[^>]+.</movie>|<music>[^>]+.</music>', re.IGNORECASE) elif metadata['media_type'] == 'artist' or metadata[ 'media_type'] == 'track': # Regex pattern to remove the text in the tags we don't want pattern = re.compile('<tv>[^>]+.</tv>|<movie>[^>]+.</movie>', re.IGNORECASE) else: pattern = None if metadata['media_type'] == 'movie' \ or metadata['media_type'] == 'show' or metadata['media_type'] == 'episode' \ or metadata['media_type'] == 'artist' or metadata['media_type'] == 'track' \ and pattern: # Remove the unwanted tags and strip any unmatch tags too. on_start_subject = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT)) on_start_body = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT)) on_stop_subject = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT)) on_stop_body = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT)) on_pause_subject = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_PAUSE_SUBJECT_TEXT)) on_pause_body = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_PAUSE_BODY_TEXT)) on_resume_subject = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_RESUME_SUBJECT_TEXT)) on_resume_body = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_RESUME_BODY_TEXT)) on_buffer_subject = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_BUFFER_SUBJECT_TEXT)) on_buffer_body = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_BUFFER_BODY_TEXT)) on_watched_subject = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT)) on_watched_body = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT)) on_created_subject = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_CREATED_SUBJECT_TEXT)) on_created_body = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_CREATED_BODY_TEXT)) else: on_start_subject = plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT on_start_body = plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT on_stop_subject = plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT on_stop_body = plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT on_pause_subject = plexpy.CONFIG.NOTIFY_ON_PAUSE_SUBJECT_TEXT on_pause_body = plexpy.CONFIG.NOTIFY_ON_PAUSE_BODY_TEXT on_resume_subject = plexpy.CONFIG.NOTIFY_ON_RESUME_SUBJECT_TEXT on_resume_body = plexpy.CONFIG.NOTIFY_ON_RESUME_BODY_TEXT on_buffer_subject = plexpy.CONFIG.NOTIFY_ON_BUFFER_SUBJECT_TEXT on_buffer_body = plexpy.CONFIG.NOTIFY_ON_BUFFER_BODY_TEXT on_watched_subject = plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT on_watched_body = plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT on_created_subject = plexpy.CONFIG.NOTIFY_ON_CREATED_SUBJECT_TEXT on_created_body = plexpy.CONFIG.NOTIFY_ON_CREATED_BODY_TEXT # Create a title if metadata['media_type'] == 'episode' or metadata['media_type'] == 'track': full_title = '%s - %s' % (metadata['grandparent_title'], metadata['title']) else: full_title = metadata['title'] duration = helpers.convert_milliseconds_to_minutes(metadata['duration']) # Default values video_decision = '' audio_decision = '' transcode_decision = '' stream_duration = 0 view_offset = 0 user = '' platform = '' player = '' ip_address = 'N/A' # Session values if session: # Generate a combined transcode decision value video_decision = session['video_decision'].title() audio_decision = session['audio_decision'].title() if session['video_decision'] == 'transcode' or session[ 'audio_decision'] == 'transcode': transcode_decision = 'Transcode' elif session['video_decision'] == 'copy' or session[ 'audio_decision'] == 'copy': transcode_decision = 'Direct Stream' else: transcode_decision = 'Direct Play' if state != 'play': if session['paused_counter']: stream_duration = int( (time.time() - helpers.cast_to_float(session['started']) - helpers.cast_to_float(session['paused_counter'])) / 60) else: stream_duration = int( (time.time() - helpers.cast_to_float(session['started'])) / 60) view_offset = helpers.convert_milliseconds_to_minutes( session['view_offset']) user = session['friendly_name'] platform = session['platform'] player = session['player'] ip_address = session['ip_address'] if session['ip_address'] else 'N/A' progress_percent = helpers.get_percent(view_offset, duration) available_params = { 'server_name': server_name, 'server_uptime': server_uptime, 'user': user, 'platform': platform, 'player': player, 'ip_address': ip_address, 'media_type': metadata['media_type'], 'title': full_title, 'show_name': metadata['grandparent_title'], 'episode_name': metadata['title'], 'artist_name': metadata['grandparent_title'], 'album_name': metadata['parent_title'], 'track_name': metadata['title'], 'season_num': metadata['parent_index'].zfill(1), 'season_num00': metadata['parent_index'].zfill(2), 'episode_num': metadata['index'].zfill(1), 'episode_num00': metadata['index'].zfill(2), 'video_decision': video_decision, 'audio_decision': audio_decision, 'transcode_decision': transcode_decision, 'year': metadata['year'], 'studio': metadata['studio'], 'content_rating': metadata['content_rating'], 'directors': ', '.join(metadata['directors']), 'writers': ', '.join(metadata['writers']), 'actors': ', '.join(metadata['actors']), 'genres': ', '.join(metadata['genres']), 'summary': metadata['summary'], 'tagline': metadata['tagline'], 'rating': metadata['rating'], 'duration': duration, 'stream_duration': stream_duration, 'remaining_duration': duration - view_offset, 'progress': view_offset, 'progress_percent': progress_percent } # Default subject text subject_text = 'PlexPy (%s)' % server_name if state == 'play': # Default body text body_text = '%s (%s) is watching %s' % (session['friendly_name'], session['player'], full_title) if on_start_subject and on_start_body: try: subject_text = unicode(on_start_subject).format( **available_params) except LookupError, e: logger.error( u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e) except:
def build_notify_text(session=None, timeline=None, state=None): # Get the server name server_name = plexpy.CONFIG.PMS_NAME # Get the server uptime plex_tv = plextv.PlexTV() server_times = plex_tv.get_server_times() if server_times: updated_at = server_times[0]['updated_at'] server_uptime = helpers.human_duration(int(time.time() - helpers.cast_to_float(updated_at))) else: logger.error(u"PlexPy NotificationHandler :: Unable to retrieve server uptime.") server_uptime = 'N/A' # Get metadata feed for item if session: rating_key = session['rating_key'] elif timeline: rating_key = timeline['rating_key'] pms_connect = pmsconnect.PmsConnect() metadata_list = pms_connect.get_metadata_details(rating_key=rating_key) stream_count = pms_connect.get_current_activity().get('stream_count', '') if metadata_list: metadata = metadata_list['metadata'] else: logger.error(u"PlexPy NotificationHandler :: Unable to retrieve metadata for rating_key %s" % str(rating_key)) return [] # Check for exclusion tags if metadata['media_type'] == 'movie': # Regex pattern to remove the text in the tags we don't want pattern = re.compile('\n*<tv>[^>]+.</tv>\n*|\n*<music>[^>]+.</music>\n*', re.IGNORECASE | re.DOTALL) elif metadata['media_type'] == 'show' or metadata['media_type'] == 'episode': # Regex pattern to remove the text in the tags we don't want pattern = re.compile('\n*<movie>[^>]+.</movie>\n*|\n*?<music>[^>]+.</music>\n*', re.IGNORECASE | re.DOTALL) elif metadata['media_type'] == 'artist' or metadata['media_type'] == 'track': # Regex pattern to remove the text in the tags we don't want pattern = re.compile('\n*<tv>[^>]+.</tv>\n*|\n*<movie>[^>]+.</movie>\n*', re.IGNORECASE | re.DOTALL) else: pattern = None if metadata['media_type'] == 'movie' \ or metadata['media_type'] == 'show' or metadata['media_type'] == 'episode' \ or metadata['media_type'] == 'artist' or metadata['media_type'] == 'track' \ and pattern: # Remove the unwanted tags and strip any unmatch tags too. on_start_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT)) on_start_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT)) on_stop_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT)) on_stop_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT)) on_pause_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_PAUSE_SUBJECT_TEXT)) on_pause_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_PAUSE_BODY_TEXT)) on_resume_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_RESUME_SUBJECT_TEXT)) on_resume_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_RESUME_BODY_TEXT)) on_buffer_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_BUFFER_SUBJECT_TEXT)) on_buffer_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_BUFFER_BODY_TEXT)) on_watched_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT)) on_watched_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT)) on_created_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_CREATED_SUBJECT_TEXT)) on_created_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_CREATED_BODY_TEXT)) script_args_text = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_SCRIPTS_ARGS_TEXT)) else: on_start_subject = plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT on_start_body = plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT on_stop_subject = plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT on_stop_body = plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT on_pause_subject = plexpy.CONFIG.NOTIFY_ON_PAUSE_SUBJECT_TEXT on_pause_body = plexpy.CONFIG.NOTIFY_ON_PAUSE_BODY_TEXT on_resume_subject = plexpy.CONFIG.NOTIFY_ON_RESUME_SUBJECT_TEXT on_resume_body = plexpy.CONFIG.NOTIFY_ON_RESUME_BODY_TEXT on_buffer_subject = plexpy.CONFIG.NOTIFY_ON_BUFFER_SUBJECT_TEXT on_buffer_body = plexpy.CONFIG.NOTIFY_ON_BUFFER_BODY_TEXT on_watched_subject = plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT on_watched_body = plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT on_created_subject = plexpy.CONFIG.NOTIFY_ON_CREATED_SUBJECT_TEXT on_created_body = plexpy.CONFIG.NOTIFY_ON_CREATED_BODY_TEXT script_args_text = plexpy.CONFIG.NOTIFY_SCRIPTS_ARGS_TEXT # Create a title if metadata['media_type'] == 'episode' or metadata['media_type'] == 'track': full_title = '%s - %s' % (metadata['grandparent_title'], metadata['title']) else: full_title = metadata['title'] duration = helpers.convert_milliseconds_to_minutes(metadata['duration']) # Default values user = '' platform = '' player = '' ip_address = 'N/A' stream_duration = 0 view_offset = 0 container = '' video_codec = '' video_bitrate = '' video_width = '' video_height = '' video_resolution = '' video_framerate = '' aspect_ratio = '' audio_codec = '' audio_channels = '' transcode_decision = '' video_decision = '' audio_decision = '' transcode_container = '' transcode_video_codec = '' transcode_video_width = '' transcode_video_height = '' transcode_audio_codec = '' transcode_audio_channels = '' # Session values if session: # Generate a combined transcode decision value video_decision = session['video_decision'].title() audio_decision = session['audio_decision'].title() if session['video_decision'] == 'transcode' or session['audio_decision'] == 'transcode': transcode_decision = 'Transcode' elif session['video_decision'] == 'copy' or session['audio_decision'] == 'copy': transcode_decision = 'Direct Stream' else: transcode_decision = 'Direct Play' if state != 'play': if session['paused_counter']: stream_duration = int((time.time() - helpers.cast_to_float(session['started']) - helpers.cast_to_float(session['paused_counter'])) / 60) else: stream_duration = int((time.time() - helpers.cast_to_float(session['started'])) / 60) view_offset = helpers.convert_milliseconds_to_minutes(session['view_offset']) user = session['friendly_name'] platform = session['platform'] player = session['player'] ip_address = session['ip_address'] if session['ip_address'] else 'N/A' container = session['container'] video_codec = session['video_codec'] video_bitrate = session['bitrate'] video_width = session['width'] video_height = session['height'] video_resolution = session['video_resolution'] video_framerate = session['video_framerate'] aspect_ratio = session['aspect_ratio'] audio_codec = session['audio_codec'] audio_channels = session['audio_channels'] transcode_container = session['transcode_container'] transcode_video_codec = session['transcode_video_codec'] transcode_video_width = session['transcode_width'] transcode_video_height = session['transcode_height'] transcode_audio_codec = session['transcode_audio_codec'] transcode_audio_channels = session['transcode_audio_channels'] progress_percent = helpers.get_percent(view_offset, duration) # Fix metadata params for notify recently added grandparent if state == 'created' and plexpy.CONFIG.NOTIFY_RECENTLY_ADDED_GRANDPARENT: show_name = metadata['title'] episode_name = '' artist_name = metadata['title'] album_name = '' track_name = '' else: show_name = metadata['grandparent_title'] episode_name = metadata['title'] artist_name = metadata['grandparent_title'] album_name = metadata['parent_title'] track_name = metadata['title'] available_params = {'server_name': server_name, 'server_uptime': server_uptime, 'streams': stream_count, 'action': state, 'datestamp': arrow.now().format(plexpy.CONFIG.DATE_FORMAT.replace('Do','').replace('zz','')), 'timestamp': arrow.now().format(plexpy.CONFIG.TIME_FORMAT.replace('Do','').replace('zz','')), 'user': user, 'platform': platform, 'player': player, 'ip_address': ip_address, 'media_type': metadata['media_type'], 'stream_duration': stream_duration, 'remaining_duration': duration - view_offset, 'progress': view_offset, 'progress_percent': progress_percent, 'container': container, 'video_codec': video_codec, 'video_bitrate': video_bitrate, 'video_width': video_width, 'video_height': video_height, 'video_resolution': video_resolution, 'video_framerate': video_framerate, 'aspect_ratio': aspect_ratio, 'audio_codec': audio_codec, 'audio_channels': audio_channels, 'transcode_decision': transcode_decision, 'video_decision': video_decision, 'audio_decision': audio_decision, 'transcode_container': transcode_container, 'transcode_video_codec': transcode_video_codec, 'transcode_video_width': transcode_video_width, 'transcode_video_height': transcode_video_height, 'transcode_audio_codec': transcode_audio_codec, 'transcode_audio_channels': transcode_audio_channels, 'title': full_title, 'library_name': metadata['library_name'], 'show_name': show_name, 'episode_name': episode_name, 'artist_name': artist_name, 'album_name': album_name, 'track_name': track_name, 'season_num': metadata['parent_media_index'].zfill(1), 'season_num00': metadata['parent_media_index'].zfill(2), 'episode_num': metadata['media_index'].zfill(1), 'episode_num00': metadata['media_index'].zfill(2), 'year': metadata['year'], 'studio': metadata['studio'], 'content_rating': metadata['content_rating'], 'directors': ', '.join(metadata['directors']), 'writers': ', '.join(metadata['writers']), 'actors': ', '.join(metadata['actors']), 'genres': ', '.join(metadata['genres']), 'summary': metadata['summary'], 'tagline': metadata['tagline'], 'rating': metadata['rating'], 'duration': duration } # Default subject text subject_text = 'PlexPy (%s)' % server_name # Default scripts args script_args = [] # Regex to match {param} but not "{param}" params_to_quote = re.compile(r'(?<!\")([\{][^}]+[\}])(?!\"\})') script_args_text = re.sub(params_to_quote, r'"\g<0>"', script_args_text) if script_args_text: try: script_args = [unicode(arg).format(**available_params) for arg in script_args_text.split()] except LookupError as e: logger.error(u"PlexPy Notifier :: Unable to parse field %s in script argument. Using fallback." % e) except Exception as e: logger.error(u"PlexPy Notifier :: Unable to parse custom script arguments %s. Using fallback." % e) if state == 'play': # Default body text body_text = '%s (%s) is watching %s' % (session['friendly_name'], session['player'], full_title) if on_start_subject and on_start_body: try: subject_text = unicode(on_start_subject).format(**available_params) except LookupError, e: logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e) except:
def build_notify_text(session, state): from plexpy import pmsconnect, helpers import re # Get the server name pms_connect = pmsconnect.PmsConnect() server_name = pms_connect.get_server_pref(pref='FriendlyName') # Get metadata feed for item metadata = pms_connect.get_metadata_details(rating_key=session['rating_key']) if metadata: item_metadata = metadata['metadata'] else: logger.error(u"PlexPy Notifier :: Unable to retrieve metadata for rating_key %s" % str(session['rating_key'])) return [] # Check for exclusion tags if session['media_type'] == 'episode': # Regex pattern to remove the text in the tags we don't want pattern = re.compile('<movie>[^>]+.</movie>|<music>[^>]+.</music>', re.IGNORECASE) elif session['media_type'] == 'movie': # Regex pattern to remove the text in the tags we don't want pattern = re.compile('<tv>[^>]+.</tv>|<music>[^>]+.</music>', re.IGNORECASE) elif session['media_type'] == 'track': # Regex pattern to remove the text in the tags we don't want pattern = re.compile('<tv>[^>]+.</tv>|<movie>[^>]+.</movie>', re.IGNORECASE) else: pattern = None if session['media_type'] == 'episode' or session['media_type'] == 'movie' or session['media_type'] == 'track' \ and pattern: # Remove the unwanted tags and strip any unmatch tags too. on_start_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT)) on_start_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT)) on_stop_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT)) on_stop_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT)) on_pause_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_PAUSE_SUBJECT_TEXT)) on_pause_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_PAUSE_BODY_TEXT)) on_resume_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_RESUME_SUBJECT_TEXT)) on_resume_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_RESUME_BODY_TEXT)) on_buffer_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_BUFFER_SUBJECT_TEXT)) on_buffer_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_BUFFER_BODY_TEXT)) on_watched_subject = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT)) on_watched_body = strip_tag(re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT)) else: on_start_subject = plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT on_start_body = plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT on_stop_subject = plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT on_stop_body = plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT on_pause_subject = plexpy.CONFIG.NOTIFY_ON_PAUSE_SUBJECT_TEXT on_pause_body = plexpy.CONFIG.NOTIFY_ON_PAUSE_BODY_TEXT on_resume_subject = plexpy.CONFIG.NOTIFY_ON_RESUME_SUBJECT_TEXT on_resume_body = plexpy.CONFIG.NOTIFY_ON_RESUME_BODY_TEXT on_buffer_subject = plexpy.CONFIG.NOTIFY_ON_BUFFER_SUBJECT_TEXT on_buffer_body = plexpy.CONFIG.NOTIFY_ON_BUFFER_BODY_TEXT on_watched_subject = plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT on_watched_body = plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT # Create a title if session['media_type'] == 'episode': full_title = '%s - %s' % (session['grandparent_title'], session['title']) elif session['media_type'] == 'track': full_title = '%s - %s' % (session['grandparent_title'], session['title']) else: full_title = session['title'] # Generate a combined transcode decision value if session['video_decision']: if session['video_decision'] == 'transcode': transcode_decision = 'Transcode' elif session['video_decision'] == 'copy' or session['audio_decision'] == 'copy': transcode_decision = 'Direct Stream' else: transcode_decision = 'Direct Play' else: if session['audio_decision'] == 'transcode': transcode_decision = 'Transcode' else: transcode_decision = 'Direct Play' duration = helpers.convert_milliseconds_to_minutes(item_metadata['duration']) view_offset = helpers.convert_milliseconds_to_minutes(session['view_offset']) stream_duration = 0 if state != 'play': if session['paused_counter']: stream_duration = int((time.time() - helpers.cast_to_float(session['started']) - helpers.cast_to_float(session['paused_counter'])) / 60) else: stream_duration = int((time.time() - helpers.cast_to_float(session['started'])) / 60) progress_percent = helpers.get_percent(view_offset, duration) available_params = {'server_name': server_name, 'user': session['friendly_name'], 'player': session['player'], 'title': full_title, 'show_name': item_metadata['grandparent_title'], 'episode_name': item_metadata['title'], 'platform': session['platform'], 'media_type': session['media_type'], 'transcode_decision': transcode_decision, 'year': item_metadata['year'], 'studio': item_metadata['studio'], 'content_rating': item_metadata['content_rating'], 'summary': item_metadata['summary'], 'season_num': item_metadata['parent_index'], 'season_num00': item_metadata['parent_index'].zfill(2), 'episode_num': item_metadata['index'], 'episode_num00': item_metadata['index'].zfill(2), 'album_name': item_metadata['parent_title'], 'rating': item_metadata['rating'], 'duration': duration, 'stream_duration': stream_duration, 'progress': view_offset, 'progress_percent': progress_percent } # Default subject text subject_text = 'PlexPy (%s)' % server_name if state == 'play': # Default body text body_text = '%s (%s) is watching %s' % (session['friendly_name'], session['player'], full_title) if on_start_subject and on_start_body: try: subject_text = unicode(on_start_subject).format(**available_params) except LookupError, e: logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e) except:
def get_history(self, start='', length='', kwargs=None, custom_where=''): data_tables = datatables.DataTables() start = int(start) length = int(length) filtered = [] totalcount = 0 search_value = "" search_regex = "" order_column = 1 order_dir = "desc" if 'order[0][dir]' in kwargs: order_dir = kwargs.get('order[0][dir]', "desc") if 'order[0][column]' in kwargs: order_column = kwargs.get('order[0][column]', "1") if 'search[value]' in kwargs: search_value = kwargs.get('search[value]', "") if 'search[regex]' in kwargs: search_regex = kwargs.get('search[regex]', "") columns = ['id', 'time as date', 'user', 'platform', 'ip_address', 'title', 'time as started', 'paused_counter', 'stopped', 'ratingKey as rating_key', 'xml', 'round((julianday(datetime(stopped, "unixepoch", "localtime")) - \ julianday(datetime(time, "unixepoch", "localtime"))) * 86400) - \ (case when paused_counter is null then 0 else paused_counter end) as duration', 'grandparentRatingKey as grandparent_rating_key' ] try: query = data_tables.ssp_query(table_name=self.get_history_table_name(), columns=columns, start=start, length=length, order_column=int(order_column), order_dir=order_dir, search_value=search_value, search_regex=search_regex, custom_where=custom_where, group_by='', kwargs=kwargs) except: logger.warn("Unable to open PlexWatch database.") return {'recordsFiltered': 0, 'recordsTotal': 0, 'data': 'null'}, history = query['result'] rows = [] # NOTE: We are adding in a blank xml field in order enable the Datatables "searchable" parameter for item in history: row = {"id": item['id'], "date": item['date'], "user": item["user"], "platform": item["platform"], "ip_address": item["ip_address"], "title": item["title"], "started": item["started"], "paused_counter": item["paused_counter"], "stopped": item["stopped"], "rating_key": item["rating_key"], "duration": item["duration"], "percent_complete": 0, "xml": ""} if item['paused_counter'] > 0: row['paused_counter'] = item['paused_counter'] else: row['paused_counter'] = 0 if item['started']: if item['stopped'] > 0: stopped = item['stopped'] else: stopped = 0 if item['paused_counter'] > 0: paused_counter = item['paused_counter'] else: paused_counter = 0 try: xml_parse = minidom.parseString(helpers.latinToAscii(item['xml'])) except IOError, e: logger.warn("Error parsing XML in PlexWatch db: %s" % e) xml_head = xml_parse.getElementsByTagName('opt') if not xml_head: logger.warn("Error parsing XML in PlexWatch db: %s" % e) for s in xml_head: if s.getAttribute('duration') and s.getAttribute('viewOffset'): view_offset = helpers.cast_to_float(s.getAttribute('viewOffset')) duration = helpers.cast_to_float(s.getAttribute('duration')) if duration > 0: row['percent_complete'] = (view_offset / duration) * 100 else: row['percent_complete'] = 0 rows.append(row)
def build_notify_text(session, state): from plexpy import pmsconnect, helpers import re # Get the server name pms_connect = pmsconnect.PmsConnect() server_name = pms_connect.get_server_pref(pref="FriendlyName") # Get metadata feed for item metadata = pms_connect.get_metadata_details(rating_key=session["rating_key"]) if metadata: item_metadata = metadata["metadata"] else: logger.error(u"PlexPy Notifier :: Unable to retrieve metadata for rating_key %s" % str(session["rating_key"])) return [] # Check for exclusion tags if session["media_type"] == "episode": # Regex pattern to remove the text in the tags we don't want pattern = re.compile("<movie>[^>]+.</movie>|<music>[^>]+.</music>", re.IGNORECASE) elif session["media_type"] == "movie": # Regex pattern to remove the text in the tags we don't want pattern = re.compile("<tv>[^>]+.</tv>|<music>[^>]+.</music>", re.IGNORECASE) elif session["media_type"] == "track": # Regex pattern to remove the text in the tags we don't want pattern = re.compile("<tv>[^>]+.</tv>|<movie>[^>]+.</movie>", re.IGNORECASE) else: pattern = None if ( session["media_type"] == "episode" or session["media_type"] == "movie" or session["media_type"] == "track" and pattern ): # Remove the unwanted tags and strip any unmatch tags too. on_start_subject = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT)) on_start_body = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT)) on_stop_subject = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT)) on_stop_body = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT)) on_pause_subject = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_PAUSE_SUBJECT_TEXT)) on_pause_body = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_PAUSE_BODY_TEXT)) on_resume_subject = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_RESUME_SUBJECT_TEXT)) on_resume_body = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_RESUME_BODY_TEXT)) on_buffer_subject = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_BUFFER_SUBJECT_TEXT)) on_buffer_body = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_BUFFER_BODY_TEXT)) on_watched_subject = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT)) on_watched_body = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT)) else: on_start_subject = plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT on_start_body = plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT on_stop_subject = plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT on_stop_body = plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT on_pause_subject = plexpy.CONFIG.NOTIFY_ON_PAUSE_SUBJECT_TEXT on_pause_body = plexpy.CONFIG.NOTIFY_ON_PAUSE_BODY_TEXT on_resume_subject = plexpy.CONFIG.NOTIFY_ON_RESUME_SUBJECT_TEXT on_resume_body = plexpy.CONFIG.NOTIFY_ON_RESUME_BODY_TEXT on_buffer_subject = plexpy.CONFIG.NOTIFY_ON_BUFFER_SUBJECT_TEXT on_buffer_body = plexpy.CONFIG.NOTIFY_ON_BUFFER_BODY_TEXT on_watched_subject = plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT on_watched_body = plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT # Create a title if session["media_type"] == "episode": full_title = "%s - %s" % (session["grandparent_title"], session["title"]) elif session["media_type"] == "track": full_title = "%s - %s" % (session["grandparent_title"], session["title"]) else: full_title = session["title"] # Generate a combined transcode decision value if session["video_decision"]: if session["video_decision"] == "transcode": transcode_decision = "Transcode" elif session["video_decision"] == "copy" or session["audio_decision"] == "copy": transcode_decision = "Direct Stream" else: transcode_decision = "Direct Play" else: if session["audio_decision"] == "transcode": transcode_decision = "Transcode" else: transcode_decision = "Direct Play" duration = helpers.convert_milliseconds_to_minutes(item_metadata["duration"]) view_offset = helpers.convert_milliseconds_to_minutes(session["view_offset"]) stream_duration = 0 if state != "play": if session["paused_counter"]: stream_duration = int( ( time.time() - helpers.cast_to_float(session["started"]) - helpers.cast_to_float(session["paused_counter"]) ) / 60 ) else: stream_duration = int((time.time() - helpers.cast_to_float(session["started"])) / 60) progress_percent = helpers.get_percent(view_offset, duration) available_params = { "server_name": server_name, "user": session["friendly_name"], "platform": session["platform"], "player": session["player"], "media_type": session["media_type"], "title": full_title, "show_name": item_metadata["grandparent_title"], "episode_name": item_metadata["title"], "artist_name": item_metadata["grandparent_title"], "album_name": item_metadata["parent_title"], "season_num": item_metadata["parent_index"], "season_num00": item_metadata["parent_index"].zfill(2), "episode_num": item_metadata["index"], "episode_num00": item_metadata["index"].zfill(2), "transcode_decision": transcode_decision, "year": item_metadata["year"], "studio": item_metadata["studio"], "content_rating": item_metadata["content_rating"], "summary": item_metadata["summary"], "rating": item_metadata["rating"], "duration": duration, "stream_duration": stream_duration, "remaining_duration": duration - view_offset, "progress": view_offset, "progress_percent": progress_percent, } # Default subject text subject_text = "PlexPy (%s)" % server_name if state == "play": # Default body text body_text = "%s (%s) is watching %s" % (session["friendly_name"], session["player"], full_title) if on_start_subject and on_start_body: try: subject_text = unicode(on_start_subject).format(**available_params) except LookupError, e: logger.error( u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e ) except:
def build_notify_text(session, state): from plexpy import pmsconnect, helpers import re # Get the server name pms_connect = pmsconnect.PmsConnect() server_name = pms_connect.get_server_pref(pref='FriendlyName') # Get metadata feed for item metadata = pms_connect.get_metadata_details( rating_key=session['rating_key']) if metadata: item_metadata = metadata['metadata'] else: logger.error( u"PlexPy Notifier :: Unable to retrieve metadata for rating_key %s" % str(session['rating_key'])) return [] # Check for exclusion tags if session['media_type'] == 'episode': # Regex pattern to remove the text in the tags we don't want pattern = re.compile('<movie>[^>]+.</movie>|<music>[^>]+.</music>', re.IGNORECASE) elif session['media_type'] == 'movie': # Regex pattern to remove the text in the tags we don't want pattern = re.compile('<tv>[^>]+.</tv>|<music>[^>]+.</music>', re.IGNORECASE) elif session['media_type'] == 'track': # Regex pattern to remove the text in the tags we don't want pattern = re.compile('<tv>[^>]+.</tv>|<movie>[^>]+.</movie>', re.IGNORECASE) else: pattern = None if session['media_type'] == 'episode' or session['media_type'] == 'movie' or session['media_type'] == 'track' \ and pattern: # Remove the unwanted tags and strip any unmatch tags too. on_start_subject = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT)) on_start_body = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT)) on_stop_subject = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT)) on_stop_body = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT)) on_pause_subject = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_PAUSE_SUBJECT_TEXT)) on_pause_body = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_PAUSE_BODY_TEXT)) on_resume_subject = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_RESUME_SUBJECT_TEXT)) on_resume_body = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_RESUME_BODY_TEXT)) on_buffer_subject = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_BUFFER_SUBJECT_TEXT)) on_buffer_body = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_BUFFER_BODY_TEXT)) on_watched_subject = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT)) on_watched_body = strip_tag( re.sub(pattern, '', plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT)) else: on_start_subject = plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT on_start_body = plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT on_stop_subject = plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT on_stop_body = plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT on_pause_subject = plexpy.CONFIG.NOTIFY_ON_PAUSE_SUBJECT_TEXT on_pause_body = plexpy.CONFIG.NOTIFY_ON_PAUSE_BODY_TEXT on_resume_subject = plexpy.CONFIG.NOTIFY_ON_RESUME_SUBJECT_TEXT on_resume_body = plexpy.CONFIG.NOTIFY_ON_RESUME_BODY_TEXT on_buffer_subject = plexpy.CONFIG.NOTIFY_ON_BUFFER_SUBJECT_TEXT on_buffer_body = plexpy.CONFIG.NOTIFY_ON_BUFFER_BODY_TEXT on_watched_subject = plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT on_watched_body = plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT # Create a title if session['media_type'] == 'episode': full_title = '%s - %s' % (session['grandparent_title'], session['title']) elif session['media_type'] == 'track': full_title = '%s - %s' % (session['grandparent_title'], session['title']) else: full_title = session['title'] # Generate a combined transcode decision value if session['video_decision']: if session['video_decision'] == 'transcode': transcode_decision = 'Transcode' elif session['video_decision'] == 'copy' or session[ 'audio_decision'] == 'copy': transcode_decision = 'Direct Stream' else: transcode_decision = 'Direct Play' else: if session['audio_decision'] == 'transcode': transcode_decision = 'Transcode' else: transcode_decision = 'Direct Play' duration = helpers.convert_milliseconds_to_minutes( item_metadata['duration']) view_offset = helpers.convert_milliseconds_to_minutes( session['view_offset']) stream_duration = 0 if state != 'play': if session['paused_counter']: stream_duration = int( (time.time() - helpers.cast_to_float(session['started']) - helpers.cast_to_float(session['paused_counter'])) / 60) else: stream_duration = int( (time.time() - helpers.cast_to_float(session['started'])) / 60) progress_percent = helpers.get_percent(view_offset, duration) available_params = { 'server_name': server_name, 'user': session['friendly_name'], 'platform': session['platform'], 'player': session['player'], 'media_type': session['media_type'], 'title': full_title, 'show_name': item_metadata['grandparent_title'], 'episode_name': item_metadata['title'], 'artist_name': item_metadata['grandparent_title'], 'album_name': item_metadata['parent_title'], 'season_num': item_metadata['parent_index'], 'season_num00': item_metadata['parent_index'].zfill(2), 'episode_num': item_metadata['index'], 'episode_num00': item_metadata['index'].zfill(2), 'transcode_decision': transcode_decision, 'year': item_metadata['year'], 'studio': item_metadata['studio'], 'content_rating': item_metadata['content_rating'], 'summary': item_metadata['summary'], 'rating': item_metadata['rating'], 'duration': duration, 'stream_duration': stream_duration, 'remaining_duration': duration - view_offset, 'progress': view_offset, 'progress_percent': progress_percent } # Default subject text subject_text = 'PlexPy (%s)' % server_name if state == 'play': # Default body text body_text = '%s (%s) is watching %s' % (session['friendly_name'], session['player'], full_title) if on_start_subject and on_start_body: try: subject_text = unicode(on_start_subject).format( **available_params) except LookupError, e: logger.error( u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e) except:
def _getHistory(self, iDisplayStart=0, iDisplayLength=100, sSearch="", iSortCol_0='0', sSortDir_0='asc', **kwargs): iDisplayStart = int(iDisplayStart) iDisplayLength = int(iDisplayLength) filtered = [] totalcount = 0 myDB = db.DBConnection() db_table = db.DBConnection().get_history_table_name() sortcolumn = 'time' sortbyhavepercent = False if iSortCol_0 == '1': sortcolumn = 'user' if iSortCol_0 == '2': sortcolumn = 'platform' elif iSortCol_0 == '3': sortcolumn = 'ip_address' elif iSortCol_0 == '4': sortcolumn = 'title' elif iSortCol_0 == '5': sortcolumn = 'time' elif iSortCol_0 == '6': sortcolumn = 'paused_counter' elif iSortCol_0 == '7': sortcolumn = 'stopped' elif iSortCol_0 == '8': sortbyhavepercent = True if sSearch == "": query = 'SELECT * from %s order by %s COLLATE NOCASE %s' % (db_table, sortcolumn, sSortDir_0) filtered = myDB.select(query) totalcount = len(filtered) else: query = 'SELECT * from ' + db_table + ' WHERE user LIKE "%' + sSearch + \ '%" OR title LIKE "%' + sSearch + '%"' + 'ORDER BY %s COLLATE NOCASE %s' % (sortcolumn, sSortDir_0) filtered = myDB.select(query) totalcount = myDB.select('SELECT COUNT(*) from processed')[0][0] history = filtered[iDisplayStart:(iDisplayStart + iDisplayLength)] rows = [] for item in history: row = {"date": item['time'], "user": item["user"], "platform": item["platform"], "ip_address": item["ip_address"], "title": item["title"], "started": item["time"], "paused": item["paused_counter"], "stopped": item["stopped"], "duration": "", "percent_complete": 0, } if item['paused_counter'] > 0: row['paused'] = item['paused_counter'] else: row['paused'] = 0 if item['time']: if item['stopped'] > 0: stopped = item['stopped'] else: stopped = 0 if item['paused_counter'] > 0: paused_counter = item['paused_counter'] else: paused_counter = 0 row['duration'] = stopped - item['time'] + paused_counter try: xml_parse = minidom.parseString(helpers.latinToAscii(item['xml'])) except IOError, e: logger.warn("Error parsing XML in PlexWatch db: %s" % e) xml_head = xml_parse.getElementsByTagName('opt') if not xml_head: logger.warn("Error parsing XML in PlexWatch db: %s" % e) for s in xml_head: if s.getAttribute('duration') and s.getAttribute('viewOffset'): view_offset = helpers.cast_to_float(s.getAttribute('viewOffset')) duration = helpers.cast_to_float(s.getAttribute('duration')) if duration > 0: row['percent_complete'] = (view_offset / duration)*100 else: row['percent_complete'] = 0 rows.append(row)
def get_history(self, start='', length='', kwargs=None, custom_where=''): data_tables = datatables.DataTables() start = int(start) length = int(length) filtered = [] totalcount = 0 search_value = "" search_regex = "" order_column = 1 order_dir = "desc" t = self.get_history_table_name() if 'order[0][dir]' in kwargs: order_dir = kwargs.get('order[0][dir]', "desc") if 'order[0][column]' in kwargs: order_column = kwargs.get('order[0][column]', "1") if 'search[value]' in kwargs: search_value = kwargs.get('search[value]', "") if 'search[regex]' in kwargs: search_regex = kwargs.get('search[regex]', "") columns = [ t + '.id', t + '.time as date', '(case when plexpy_users.friendly_name is null then ' + t + '.user else plexpy_users.friendly_name end) as friendly_name', t + '.platform', t + '.ip_address', t + '.title', t + '.time as started', t + '.paused_counter', t + '.stopped', 'round((julianday(datetime(' + t + '.stopped, "unixepoch", "localtime")) - \ julianday(datetime(' + t + '.time, "unixepoch", "localtime"))) * 86400) - \ (case when ' + t + '.paused_counter is null then 0 else ' + t + '.paused_counter end) as duration', t + '.ratingKey as rating_key', t + '.xml', t + '.user', t + '.grandparentRatingKey as grandparent_rating_key' ] try: query = data_tables.ssp_query( table_name=t, columns=columns, start=start, length=length, order_column=int(order_column), order_dir=order_dir, search_value=search_value, search_regex=search_regex, custom_where=custom_where, group_by='', join_type='LEFT OUTER JOIN', join_table='plexpy_users', join_evals=[t + '.user', 'plexpy_users.username'], kwargs=kwargs) except: logger.warn("Unable to open PlexWatch database.") return {'recordsFiltered': 0, 'recordsTotal': 0, 'data': 'null'}, history = query['result'] rows = [] # NOTE: We are adding in a blank xml field in order enable the Datatables "searchable" parameter for item in history: row = { "id": item['id'], "date": item['date'], "friendly_name": item['friendly_name'], "platform": item["platform"], "ip_address": item["ip_address"], "title": item["title"], "started": item["started"], "paused_counter": item["paused_counter"], "stopped": item["stopped"], "rating_key": item["rating_key"], "duration": item["duration"], "percent_complete": 0, "xml": "", "user": item["user"] } if item['paused_counter'] > 0: row['paused_counter'] = item['paused_counter'] else: row['paused_counter'] = 0 if item['started']: if item['stopped'] > 0: stopped = item['stopped'] else: stopped = 0 if item['paused_counter'] > 0: paused_counter = item['paused_counter'] else: paused_counter = 0 try: xml_parse = minidom.parseString( helpers.latinToAscii(item['xml'])) except: logger.warn("Error parsing XML in PlexWatch db") xml_head = xml_parse.getElementsByTagName('opt') if not xml_head: logger.warn("Error parsing XML in PlexWatch db.") for s in xml_head: if s.getAttribute('duration') and s.getAttribute('viewOffset'): view_offset = helpers.cast_to_float( s.getAttribute('viewOffset')) duration = helpers.cast_to_float( s.getAttribute('duration')) if duration > 0: row['percent_complete'] = (view_offset / duration) * 100 else: row['percent_complete'] = 0 rows.append(row) dict = { 'recordsFiltered': query['filteredCount'], 'recordsTotal': query['totalCount'], 'data': rows, } return dict
def build_server_notify_text(state=None): # Get time formats date_format = plexpy.CONFIG.DATE_FORMAT.replace("Do", "").replace("zz", "") time_format = plexpy.CONFIG.TIME_FORMAT.replace("Do", "").replace("zz", "") # Get the server name server_name = plexpy.CONFIG.PMS_NAME # Get the server uptime plex_tv = plextv.PlexTV() server_times = plex_tv.get_server_times() if server_times: updated_at = server_times[0]["updated_at"] server_uptime = helpers.human_duration(int(time.time() - helpers.cast_to_float(updated_at))) else: logger.error(u"PlexPy NotificationHandler :: Unable to retrieve server uptime.") server_uptime = "N/A" on_extdown_subject = plexpy.CONFIG.NOTIFY_ON_EXTDOWN_SUBJECT_TEXT on_extdown_body = plexpy.CONFIG.NOTIFY_ON_EXTDOWN_BODY_TEXT on_intdown_subject = plexpy.CONFIG.NOTIFY_ON_INTDOWN_SUBJECT_TEXT on_intdown_body = plexpy.CONFIG.NOTIFY_ON_INTDOWN_BODY_TEXT on_extup_subject = plexpy.CONFIG.NOTIFY_ON_EXTUP_SUBJECT_TEXT on_extup_body = plexpy.CONFIG.NOTIFY_ON_EXTUP_BODY_TEXT on_intup_subject = plexpy.CONFIG.NOTIFY_ON_INTUP_SUBJECT_TEXT on_intup_body = plexpy.CONFIG.NOTIFY_ON_INTUP_BODY_TEXT script_args_text = plexpy.CONFIG.NOTIFY_SCRIPTS_ARGS_TEXT available_params = { # Global paramaters "server_name": server_name, "server_uptime": server_uptime, "action": state.title(), "datestamp": arrow.now().format(date_format), "timestamp": arrow.now().format(time_format), } # Default text subject_text = "PlexPy (%s)" % server_name # Default scripts args script_args = [] if script_args_text: try: script_args = [unicode(arg).format(**available_params) for arg in script_args_text.split()] except LookupError as e: logger.error(u"PlexPy Notifier :: Unable to parse field %s in script argument. Using fallback." % e) except Exception as e: logger.error(u"PlexPy Notifier :: Unable to parse custom script arguments %s. Using fallback." % e) if state == "extdown": # Default body text body_text = "The Plex Media Server remote access is down." if on_extdown_subject and on_extdown_body: try: subject_text = unicode(on_extdown_subject).format(**available_params) except LookupError, e: logger.error( u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e ) except:
def build_notify_text(session=None, timeline=None, state=None): # Get time formats date_format = plexpy.CONFIG.DATE_FORMAT.replace("Do", "").replace("zz", "") time_format = plexpy.CONFIG.TIME_FORMAT.replace("Do", "").replace("zz", "") duration_format = plexpy.CONFIG.TIME_FORMAT.replace("Do", "").replace("zz", "").replace("a", "").replace("A", "") # Get the server name server_name = plexpy.CONFIG.PMS_NAME # Get the server uptime plex_tv = plextv.PlexTV() server_times = plex_tv.get_server_times() if server_times: updated_at = server_times[0]["updated_at"] server_uptime = helpers.human_duration(int(time.time() - helpers.cast_to_float(updated_at))) else: logger.error(u"PlexPy NotificationHandler :: Unable to retrieve server uptime.") server_uptime = "N/A" # Get metadata feed for item if session: rating_key = session["rating_key"] elif timeline: rating_key = timeline["rating_key"] pms_connect = pmsconnect.PmsConnect() metadata_list = pms_connect.get_metadata_details(rating_key=rating_key) stream_count = pms_connect.get_current_activity().get("stream_count", "") if metadata_list: metadata = metadata_list["metadata"] else: logger.error(u"PlexPy NotificationHandler :: Unable to retrieve metadata for rating_key %s" % str(rating_key)) return [] # Check for exclusion tags if metadata["media_type"] == "movie": # Regex pattern to remove the text in the tags we don't want pattern = re.compile("\n*<tv>[^>]+.</tv>\n*|\n*<music>[^>]+.</music>\n*", re.IGNORECASE | re.DOTALL) elif metadata["media_type"] == "show" or metadata["media_type"] == "episode": # Regex pattern to remove the text in the tags we don't want pattern = re.compile("\n*<movie>[^>]+.</movie>\n*|\n*?<music>[^>]+.</music>\n*", re.IGNORECASE | re.DOTALL) elif metadata["media_type"] == "artist" or metadata["media_type"] == "track": # Regex pattern to remove the text in the tags we don't want pattern = re.compile("\n*<tv>[^>]+.</tv>\n*|\n*<movie>[^>]+.</movie>\n*", re.IGNORECASE | re.DOTALL) else: pattern = None if ( metadata["media_type"] == "movie" or metadata["media_type"] == "show" or metadata["media_type"] == "episode" or metadata["media_type"] == "artist" or metadata["media_type"] == "track" and pattern ): # Remove the unwanted tags and strip any unmatch tags too. on_start_subject = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT)) on_start_body = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT)) on_stop_subject = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT)) on_stop_body = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT)) on_pause_subject = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_PAUSE_SUBJECT_TEXT)) on_pause_body = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_PAUSE_BODY_TEXT)) on_resume_subject = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_RESUME_SUBJECT_TEXT)) on_resume_body = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_RESUME_BODY_TEXT)) on_buffer_subject = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_BUFFER_SUBJECT_TEXT)) on_buffer_body = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_BUFFER_BODY_TEXT)) on_watched_subject = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT)) on_watched_body = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT)) on_created_subject = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_CREATED_SUBJECT_TEXT)) on_created_body = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_ON_CREATED_BODY_TEXT)) script_args_text = strip_tag(re.sub(pattern, "", plexpy.CONFIG.NOTIFY_SCRIPTS_ARGS_TEXT)) else: on_start_subject = plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT on_start_body = plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT on_stop_subject = plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT on_stop_body = plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT on_pause_subject = plexpy.CONFIG.NOTIFY_ON_PAUSE_SUBJECT_TEXT on_pause_body = plexpy.CONFIG.NOTIFY_ON_PAUSE_BODY_TEXT on_resume_subject = plexpy.CONFIG.NOTIFY_ON_RESUME_SUBJECT_TEXT on_resume_body = plexpy.CONFIG.NOTIFY_ON_RESUME_BODY_TEXT on_buffer_subject = plexpy.CONFIG.NOTIFY_ON_BUFFER_SUBJECT_TEXT on_buffer_body = plexpy.CONFIG.NOTIFY_ON_BUFFER_BODY_TEXT on_watched_subject = plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT on_watched_body = plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT on_created_subject = plexpy.CONFIG.NOTIFY_ON_CREATED_SUBJECT_TEXT on_created_body = plexpy.CONFIG.NOTIFY_ON_CREATED_BODY_TEXT script_args_text = plexpy.CONFIG.NOTIFY_SCRIPTS_ARGS_TEXT # Create a title if metadata["media_type"] == "episode" or metadata["media_type"] == "track": full_title = "%s - %s" % (metadata["grandparent_title"], metadata["title"]) else: full_title = metadata["title"] # Session values if session is None: session = {} # Generate a combined transcode decision value if session.get("video_decision", "") == "transcode" or session.get("audio_decision", "") == "transcode": transcode_decision = "Transcode" elif session.get("video_decision", "") == "copy" or session.get("audio_decision", "") == "copy": transcode_decision = "Direct Stream" else: transcode_decision = "Direct Play" if state != "play": stream_duration = helpers.convert_seconds_to_minutes( time.time() - helpers.cast_to_float(session.get("started", 0)) - helpers.cast_to_float(session.get("paused_counter", 0)) ) else: stream_duration = 0 view_offset = helpers.convert_milliseconds_to_minutes(session.get("view_offset", 0)) duration = helpers.convert_milliseconds_to_minutes(metadata["duration"]) progress_percent = helpers.get_percent(view_offset, duration) remaining_duration = duration - view_offset # Fix metadata params for notify recently added grandparent if state == "created" and plexpy.CONFIG.NOTIFY_RECENTLY_ADDED_GRANDPARENT: show_name = metadata["title"] episode_name = "" artist_name = metadata["title"] album_name = "" track_name = "" else: show_name = metadata["grandparent_title"] episode_name = metadata["title"] artist_name = metadata["grandparent_title"] album_name = metadata["parent_title"] track_name = metadata["title"] available_params = { # Global paramaters "server_name": server_name, "server_uptime": server_uptime, "action": state.title(), "datestamp": arrow.now().format(date_format), "timestamp": arrow.now().format(time_format), # Stream parameters "streams": stream_count, "user": session.get("friendly_name", ""), "platform": session.get("platform", ""), "player": session.get("player", ""), "ip_address": session.get("ip_address", "N/A"), "stream_duration": stream_duration, "stream_time": arrow.get(stream_duration * 60).format(duration_format), "remaining_duration": remaining_duration, "remaining_time": arrow.get(remaining_duration * 60).format(duration_format), "progress_duration": view_offset, "progress_time": arrow.get(view_offset * 60).format(duration_format), "progress_percent": progress_percent, "container": session.get("container", ""), "video_codec": session.get("video_codec", ""), "video_bitrate": session.get("bitrate", ""), "video_width": session.get("width", ""), "video_height": session.get("height", ""), "video_resolution": session.get("video_resolution", ""), "video_framerate": session.get("video_framerate", ""), "aspect_ratio": session.get("aspect_ratio", ""), "audio_codec": session.get("audio_codec", ""), "audio_channels": session.get("audio_channels", ""), "transcode_decision": transcode_decision, "video_decision": session.get("video_decision", "").title(), "audio_decision": session.get("audio_decision", "").title(), "transcode_container": session.get("transcode_container", ""), "transcode_video_codec": session.get("transcode_video_codec", ""), "transcode_video_width": session.get("transcode_width", ""), "transcode_video_height": session.get("transcode_height", ""), "transcode_audio_codec": session.get("transcode_audio_codec", ""), "transcode_audio_channels": session.get("transcode_audio_channels", ""), "session_key": session.get("session_key", ""), "user_id": session.get("user_id", ""), # Metadata parameters "media_type": metadata["media_type"], "title": full_title, "library_name": metadata["library_name"], "show_name": show_name, "episode_name": episode_name, "artist_name": artist_name, "album_name": album_name, "track_name": track_name, "season_num": metadata["parent_media_index"].zfill(1), "season_num00": metadata["parent_media_index"].zfill(2), "episode_num": metadata["media_index"].zfill(1), "episode_num00": metadata["media_index"].zfill(2), "track_num": metadata["media_index"].zfill(1), "track_num00": metadata["media_index"].zfill(2), "year": metadata["year"], "studio": metadata["studio"], "content_rating": metadata["content_rating"], "directors": ", ".join(metadata["directors"]), "writers": ", ".join(metadata["writers"]), "actors": ", ".join(metadata["actors"]), "genres": ", ".join(metadata["genres"]), "summary": metadata["summary"], "tagline": metadata["tagline"], "rating": metadata["rating"], "duration": metadata["duration"], "section_id": metadata["section_id"], "rating_key": metadata["rating_key"], "parent_rating_key": metadata["parent_rating_key"], "grandparent_rating_key": metadata["grandparent_rating_key"], } # Default subject text subject_text = "PlexPy (%s)" % server_name # Default scripts args script_args = [] if script_args_text: try: script_args = [unicode(arg).format(**available_params) for arg in script_args_text.split()] except LookupError as e: logger.error(u"PlexPy Notifier :: Unable to parse field %s in script argument. Using fallback." % e) except Exception as e: logger.error(u"PlexPy Notifier :: Unable to parse custom script arguments %s. Using fallback." % e) if state == "play": # Default body text body_text = "%s (%s) started playing %s" % (session["friendly_name"], session["player"], full_title) if on_start_subject and on_start_body: try: subject_text = unicode(on_start_subject).format(**available_params) except LookupError, e: logger.error( u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e ) except: