diff --git a/data/interfaces/default/css/plexwatch.css b/data/interfaces/default/css/plexwatch.css
index a11331a6..e80e73e2 100644
--- a/data/interfaces/default/css/plexwatch.css
+++ b/data/interfaces/default/css/plexwatch.css
@@ -8438,3 +8438,89 @@ ol.test >li {
.stacked-configs > li > span > input[type='checkbox'] {
}
+
+.accordion {
+ width: 100%;
+ max-width: 900px;
+ margin: 0px 0px 20px 0px;
+ background: #282828;
+ list-style: none;
+}
+
+.accordion .link {
+ cursor: pointer;
+ display: block;
+ padding: 8px 20px 8px 30px;
+ color: #999;
+ border-bottom: 1px solid #2d2d2d;
+ position: relative;
+ -webkit-transition: all 0.4s ease;
+ -o-transition: all 0.4s ease;
+ transition: all 0.4s ease;
+}
+
+.accordion li:last-child .link { border-bottom: 0; }
+
+.accordion li i {
+ position: absolute;
+ top: 10px;
+ left: 10px;
+ color: #999;
+ -webkit-transition: all 0.4s ease;
+ -o-transition: all 0.4s ease;
+ transition: all 0.4s ease;
+}
+
+.accordion li i.fa-chevron-down {
+ right: 12px;
+ left: auto;
+ font-size: 16px;
+}
+
+.accordion li .link:hover {
+ color: #FFF;
+ background: #2f2f2f;
+}
+
+.accordion li.open .link { color: #eb8600; }
+
+.accordion li.open i { color: #eb8600; }
+
+.accordion li.open i.fa-chevron-down {
+ -webkit-transform: rotate(180deg);
+ -ms-transform: rotate(180deg);
+ -o-transform: rotate(180deg);
+ transform: rotate(180deg);
+}
+
+/**
+ * Submenu
+ -----------------------------*/
+
+
+.submenu {
+ display: none;
+ background: #2d2d2d;
+ list-style: none;
+ margin: 0px;
+ padding: 20px;
+}
+
+.submenu li {
+ border-bottom: 1px solid #2f2f2f;
+}
+
+.submenu a {
+ display: block;
+ text-decoration: none;
+ color: #d9d9d9;
+ padding: 12px;
+ -webkit-transition: all 0.25s ease;
+ -o-transition: all 0.25s ease;
+ transition: all 0.25s ease;
+}
+
+.submenu a:hover {
+ background: #eb8600;
+ color: #FFF;
+}
\ No newline at end of file
diff --git a/data/interfaces/default/edit_user.html b/data/interfaces/default/edit_user.html
index aafca93b..f699d525 100644
--- a/data/interfaces/default/edit_user.html
+++ b/data/interfaces/default/edit_user.html
@@ -24,7 +24,7 @@ DOCUMENTATION :: END
Edit user ${data['user']}
+
+
@@ -493,6 +558,51 @@
+
+
+
+
+
+
+
+ {user} |
+ The username of the person streaming. |
+
+
+ {server_name} |
+ The name of your Plex Server. |
+
+
+ {player} |
+ The name of the device being used for playback. |
+
+
+ {platform} |
+ The type of client being used for playback. |
+
+
+ {title} |
+ The title of the item being played back. |
+
+
+ {transcode_decision} |
+ Returns the transcode decisions for the media item. |
+
+
+ More options will be added soon. |
+
+
+
+
+
+
+
@@ -502,7 +612,7 @@
<%def name="javascriptIncludes()">
%def>
\ No newline at end of file
diff --git a/plexpy/config.py b/plexpy/config.py
index bcd3ed81..96aacc3b 100644
--- a/plexpy/config.py
+++ b/plexpy/config.py
@@ -104,6 +104,12 @@ _CONFIG_DEFINITIONS = {
'NMA_ON_STOP': (int, 'NMA', 0),
'NMA_ON_WATCHED': (int, 'NMA', 0),
'NOTIFY_WATCHED_PERCENT': (int, 'Monitoring', 85),
+ 'NOTIFY_ON_START_SUBJECT_TEXT': (str, 'Monitoring', 'PlexPy ({server_name})'),
+ 'NOTIFY_ON_START_BODY_TEXT': (str, 'Monitoring', '{user} ({player}) started playing {title}.'),
+ 'NOTIFY_ON_STOP_SUBJECT_TEXT': (str, 'Monitoring', 'PlexPy ({server_name})'),
+ 'NOTIFY_ON_STOP_BODY_TEXT': (str, 'Monitoring', '{user} ({player}) has stopped {title}.'),
+ 'NOTIFY_ON_WATCHED_SUBJECT_TEXT': (str, 'Monitoring', 'PlexPy ({server_name})'),
+ 'NOTIFY_ON_WATCHED_BODY_TEXT': (str, 'Monitoring', '{user} ({player}) has watched {title}.'),
'OSX_NOTIFY_APP': (str, 'OSX_Notify', '/Applications/PlexPy'),
'OSX_NOTIFY_ENABLED': (int, 'OSX_Notify', 0),
'OSX_NOTIFY_ON_PLAY': (int, 'OSX_Notify', 0),
diff --git a/plexpy/datafactory.py b/plexpy/datafactory.py
index 872f461e..f2bfb0a3 100644
--- a/plexpy/datafactory.py
+++ b/plexpy/datafactory.py
@@ -607,19 +607,19 @@ class DataFactory(object):
'thumb, parent_thumb, media_index, parent_media_index, year, started, user ' \
'FROM session_history_metadata ' \
'JOIN session_history ON session_history_metadata.id = session_history.id ' \
- 'WHERE user_id = ? ORDER BY started DESC LIMIT ?'
+ 'WHERE user_id = ? AND session_history.media_type != "track" ORDER BY started DESC LIMIT ?'
result = monitor_db.select(query, args=[user_id, limit])
elif user:
query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, title, ' \
'thumb, parent_thumb, media_index, parent_media_index, year, started, user ' \
'FROM session_history_metadata ' \
'JOIN session_history ON session_history_metadata.id = session_history.id ' \
- 'WHERE user = ? ORDER BY started DESC LIMIT ?'
+ 'WHERE user = ? AND session_history.media_type != "track" ORDER BY started DESC LIMIT ?'
result = monitor_db.select(query, args=[user, limit])
else:
query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, title, ' \
'thumb, parent_thumb, media_index, parent_media_index, year, started, user ' \
- 'FROM session_history_metadata ' \
+ 'FROM session_history_metadata WHERE session_history.media_type != "track"' \
'JOIN session_history ON session_history_metadata.id = session_history.id ' \
'ORDER BY started DESC LIMIT ?'
result = monitor_db.select(query, args=[limit])
diff --git a/plexpy/notification_handler.py b/plexpy/notification_handler.py
index 3f7ff149..ffcbe37d 100644
--- a/plexpy/notification_handler.py
+++ b/plexpy/notification_handler.py
@@ -19,28 +19,9 @@ import plexpy
import time
def notify(stream_data=None, notify_action=None):
- from plexpy import pmsconnect, common, datafactory
+ from plexpy import datafactory
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))
-
# Check if notifications enabled for user
data_factory = datafactory.DataFactory()
user_details = data_factory.get_user_friendly_name(user=stream_data['user'])
@@ -53,34 +34,47 @@ def notify(stream_data=None, notify_action=None):
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)
+ # 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':
- 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)
+ # 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):
- 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)
+ # 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']):
- 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)
+ # 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':
@@ -88,16 +82,21 @@ def notify(stream_data=None, notify_action=None):
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)
+ # 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':
- 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)
+ # 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':
@@ -151,3 +150,100 @@ def set_notify_state(session, state, agent_info):
monitor_db.upsert(table_name='notify_log', key_dict=keys, value_dict=values)
else:
logger.error('PlexPy Notifier :: Unable to set notify state.')
+
+def build_notify_text(session, state):
+ from plexpy import pmsconnect
+
+ # Get the server name
+ pms_connect = pmsconnect.PmsConnect()
+ server_name = pms_connect.get_server_pref(pref='FriendlyName')
+
+ # 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']:
+ transcode_decision = 'V:%s/A:%s' % (session['video_decision'], session['audio_decision'])
+ else:
+ transcode_decision = 'A:%s' % session['audio_decision']
+
+ available_params = {'server_name': server_name,
+ 'user': session['friendly_name'],
+ 'player': session['player'],
+ 'title': full_title,
+ 'platform': session['platform'],
+ 'media_type': session['media_type'],
+ 'transcode_decision': transcode_decision}
+
+ # 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 plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT and plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT:
+ try:
+ subject_text = plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT.format(**available_params)
+ except:
+ logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using default.")
+
+ try:
+ body_text = plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT.format(**available_params)
+ except:
+ logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using default.")
+
+ return [subject_text, body_text]
+ else:
+ return [subject_text, body_text]
+ elif state == 'stop':
+ # Default body text
+ body_text = '%s (%s) has stopped %s' % (session['friendly_name'],
+ session['player'],
+ full_title)
+
+ if plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT and plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT:
+ try:
+ subject_text = plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT.format(**available_params)
+ except:
+ logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using default.")
+
+ try:
+ body_text = plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT.format(**available_params)
+ except:
+ logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using default.")
+
+ return [subject_text, body_text]
+ else:
+ return [subject_text, body_text]
+ elif state == 'watched':
+ # Default body text
+ body_text = '%s (%s) has watched %s' % (session['friendly_name'],
+ session['player'],
+ full_title)
+
+ if plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT and plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT:
+ try:
+ subject_text = plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT.format(**available_params)
+ except:
+ logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using default.")
+
+ try:
+ body_text = plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT.format(**available_params)
+ except:
+ logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using default.")
+
+ return [subject_text, body_text]
+ else:
+ return [subject_text, body_text]
+ else:
+ return None
diff --git a/plexpy/webserve.py b/plexpy/webserve.py
index 6277991a..289938ec 100644
--- a/plexpy/webserve.py
+++ b/plexpy/webserve.py
@@ -407,7 +407,13 @@ class WebInterface(object):
"music_logging_enable": checked(plexpy.CONFIG.MUSIC_LOGGING_ENABLE),
"logging_ignore_interval": plexpy.CONFIG.LOGGING_IGNORE_INTERVAL,
"pms_is_remote": checked(plexpy.CONFIG.PMS_IS_REMOTE),
- "notify_watched_percent": plexpy.CONFIG.NOTIFY_WATCHED_PERCENT
+ "notify_watched_percent": plexpy.CONFIG.NOTIFY_WATCHED_PERCENT,
+ "notify_on_start_subject_text": plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT,
+ "notify_on_start_body_text": plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT,
+ "notify_on_stop_subject_text": plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT,
+ "notify_on_stop_body_text": plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT,
+ "notify_on_watched_subject_text": plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT,
+ "notify_on_watched_body_text": plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT
}
return serve_template(templatename="settings.html", title="Settings", config=config)
@@ -1075,7 +1081,9 @@ class WebInterface(object):
'I LIED!',
'See you at the party, Richter!',
'Are you Sarah Conner?',
- 'I\'m a cop you idiot!'
+ 'I\'m a cop you idiot!',
+ 'Come with me if you want to live.',
+ 'Who is your daddy and what does he do?'
]
random_number = randint(0, len(quote_list) - 1)