Skip to content

Commit

Permalink
Stage three of notification rewrite. Page cache refresh required.
Browse files Browse the repository at this point in the history
Watched notifications added with configurable cutoff percent.
Styling fixes.
Add information back to settings page for required restart on web interface changes.
Use user_id on user link in activity pane.
Added channels option to Pushbullet.
Possible fix for text encoding issues in Plexwatch importer.
Thread the notifications.
Move most of the notification logic to the notification handler.
  • Loading branch information
drzoidberg33 committed Jul 23, 2015
1 parent 8a16fcf commit b394ebc
Show file tree
Hide file tree
Showing 10 changed files with 194 additions and 65 deletions.
17 changes: 8 additions & 9 deletions data/interfaces/default/css/plexwatch.css
Original file line number Diff line number Diff line change
Expand Up @@ -8416,26 +8416,25 @@ ol.test >li {
background-color: #2f2f2f;
}

.stacked-configs > li > span > a {
.stacked-configs > li > span > a.toggle-right {
float: right;
color: #999;
padding-left: 10px;
}

.stacked-configs > li > span > a:hover {
color: #eee;
}

.stacked-configs > li > span > i {
cursor: pointer;
padding-right: 2px;
.stacked-configs > li > span > a.toggle-left {
color: #444;
padding-right: 2px;
}

.stacked-configs > li > span > i:hover {
.stacked-configs > li > span > a:hover {
color: #eee;
}

.stacked-configs > li > span > a.active {
color: #eb8600;
}

.stacked-configs > li > span > input[type='checkbox'] {

}
4 changes: 4 additions & 0 deletions data/interfaces/default/current_activity.html
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,11 @@
<div class="dashboard-activity-metadata-platform" id="platform-${a['session_key']}">
</div>
<div class="dashboard-activity-metadata-user">
% if a['user_id']:
<a href="user?user_id=${a['user_id']}">${a['friendly_name']}</a> is ${a['state']}
% else:
<a href="user?user=${a['user']}">${a['friendly_name']}</a> is ${a['state']}
% endif
</div>
<div class="dashboard-activity-metadata-title">
% if a['type'] == 'episode':
Expand Down
27 changes: 17 additions & 10 deletions data/interfaces/default/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ <h3>Display Settings</h3>
<div class="wellheader">
<h3>Web Interface</h3>
</div>
<p class="help-block">Web interface changes require a restart.</p>
<div class="form-group">
<label for="http_host">HTTP Host</label>
<input type="text" id="http_host" name="http_host" value="${config['http_host']}" size="30" data-parsley-trigger="change" required>
Expand Down Expand Up @@ -116,6 +117,7 @@ <h3>Web Interface</h3>
<div class="wellheader">
<h3>Authentication</h3>
</div>
<p class="help-block">Authentication changes require a restart.</p>
<div class="form-group">
<label for="http_username">HTTP Username</label>
<input type="text" id="http_username" name="http_username" value="${config['http_username']}" size="30">
Expand Down Expand Up @@ -273,7 +275,7 @@ <h3>IP Logging</h3>
<div role="tabpanel" class="tab-pane" id="tabs-8">
<fieldset>
<div class="wellheader">
<h3>Global Notifications</h3>
<h3>Global Notification Toggles</h3>
</div>
<div class="checkbox">
<input type="checkbox" name="movie_notify_enable" id="movie_notify_enable" value="1" ${config['movie_notify_enable']}> Enable Movie and TV Notifications
Expand All @@ -282,6 +284,16 @@ <h3>Global Notifications</h3>
<input type="checkbox" name="music_notify_enable" id="music_notify_enable" value="1" ${config['music_notify_enable']}> Enable Music Notifications
</div>
</fieldset>
<div class="wellheader">
<h3>Notification Tuning</h3>
</div>
<fieldset>
<div class="form-group">
<label for="notify_watched_percent">Watched Percent</label>
<input type="text" data-parsley-type="integer" id="notify_watched_percent" name="notify_watched_percent" value="${config['notify_watched_percent']}" size="5" data-parsley-range="[50,95]" data-parsley-trigger="change" required>
<p class="help-block">Set the progress percentage of when a watched notification should be triggered. Minimum 50, Maximum 95.</p>
</div>
</fieldset>
<input type="button" class="rounded rounded-primary save-button" value="Save" data-success="Changes saved successfully">
</div>
<div role="tabpanel" class="tab-pane" id="tabs-9">
Expand All @@ -299,12 +311,12 @@ <h3>Notification Agents</h3>
<li>
<span>
<!--<input type="checkbox" name="${agent['config_prefix']}_enabled" id="${agent['config_prefix']}" value="1" ${agent['state']}> ${agent['name']}-->
<i class="fa fa-play notify-toggle-icon" data-toggle="tooltip" data-placement="top" title data-title="Notify on playback start" data-id="${agent['id']}" data-config-name="${agent['config_prefix']}_on_play" data-config-value="${agent['on_play']}"></i>
<i class="fa fa-stop notify-toggle-icon" data-toggle="tooltip" data-placement="top" title data-title="Notify on stop" data-id="${agent['id']}" data-config-name="${agent['config_prefix']}_on_stop" data-config-value="${agent['on_stop']}"></i>
<!--<i class="fa fa-eye notify-toggle-icon" data-toggle="tooltip" data-placement="top" title data-title="Notify on watched" data-id="${agent['id']}" data-config-name="${agent['config_prefix']}_on_watched" data-config-value="${agent['on_watched']}"></i>-->
<a class="toggle-left notify-toggle-icon" href="javascript:void(0)" data-toggle="tooltip" data-placement="top" title data-title="Notify on playback start" data-id="${agent['id']}" data-config-name="${agent['config_prefix']}_on_play" data-config-value="${agent['on_play']}"><i class="fa fa-play"></i></a>
<a class="toggle-left notify-toggle-icon" href="javascript:void(0)" data-toggle="tooltip" data-placement="top" title data-title="Notify on stop" data-id="${agent['id']}" data-config-name="${agent['config_prefix']}_on_stop" data-config-value="${agent['on_stop']}"><i class="fa fa-stop"></i></a>
<a class="toggle-left notify-toggle-icon" href="javascript:void(0)" data-toggle="tooltip" data-placement="top" title data-title="Notify on watched" data-id="${agent['id']}" data-config-name="${agent['config_prefix']}_on_watched" data-config-value="${agent['on_watched']}"><i class="fa fa-eye"></i></a>
${agent['name']}
% if agent['has_config']:
<a href="#notification-config-modal" rel="tooltip" data-placement="top" title data-title="Open configuration" data-id="${agent['id']}" class="toggle-notification-config-modal" data-toggle="modal"><i class="fa fa-lg fa-cog"></i></a>
<a href="#notification-config-modal" rel="tooltip" data-placement="top" title data-title="Open configuration" data-id="${agent['id']}" class="toggle-notification-config-modal toggle-right" data-toggle="modal"><i class="fa fa-lg fa-cog"></i></a>
% endif
</span>
</li>
Expand Down Expand Up @@ -661,10 +673,7 @@ <h3 id="PMSAuthModal">Fetch Plex.tv Token</h3>

$('.notify-toggle-icon').each(function() {
if ($(this).data('config-value') == 1) {
$(this).css("color", "#eb8600");
$(this).addClass("active");
} else {
$(this).css("color", "#444");
}
});

Expand All @@ -679,7 +688,6 @@ <h3 id="PMSAuthModal">Fetch Plex.tv Token</h3>
data: data,
async: true,
success: function(data) {
toggle.css("color", "#444");
toggle.removeClass("active");
}
});
Expand All @@ -691,7 +699,6 @@ <h3 id="PMSAuthModal">Fetch Plex.tv Token</h3>
data: data,
async: true,
success: function(data) {
toggle.css("color", "#eb8600");
toggle.addClass("active");
}
});
Expand Down
7 changes: 7 additions & 0 deletions plexpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,13 @@ def dbcheck():
'ALTER TABLE session_history_metadata ADD COLUMN full_title TEXT'
)

# notify_log table :: This is a table which logs notifications sent
c_db.execute(
'CREATE TABLE IF NOT EXISTS notify_log (id INTEGER PRIMARY KEY AUTOINCREMENT, '
'session_key INTEGER, rating_key INTEGER, user_id INTEGER, user TEXT, '
'agent_id INTEGER, agent_name TEXT, on_play INTEGER, on_stop INTEGER, on_watched INTEGER)'
)

conn_db.commit()
c_db.close()

Expand Down
2 changes: 2 additions & 0 deletions plexpy/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ def bool_int(value):
'NMA_ON_PLAY': (int, 'NMA', 0),
'NMA_ON_STOP': (int, 'NMA', 0),
'NMA_ON_WATCHED': (int, 'NMA', 0),
'NOTIFY_WATCHED_PERCENT': (int, 'Monitoring', 85),
'OSX_NOTIFY_APP': (str, 'OSX_Notify', '/Applications/PlexPy'),
'OSX_NOTIFY_ENABLED': (int, 'OSX_Notify', 0),
'OSX_NOTIFY_ON_PLAY': (int, 'OSX_Notify', 0),
Expand All @@ -128,6 +129,7 @@ def bool_int(value):
'PUSHALOT_ON_WATCHED': (int, 'Pushalot', 0),
'PUSHBULLET_APIKEY': (str, 'PushBullet', ''),
'PUSHBULLET_DEVICEID': (str, 'PushBullet', ''),
'PUSHBULLET_CHANNEL_TAG': (str, 'PushBullet', ''),
'PUSHBULLET_ENABLED': (int, 'PushBullet', 0),
'PUSHBULLET_ON_PLAY': (int, 'PushBullet', 0),
'PUSHBULLET_ON_STOP': (int, 'PushBullet', 0),
Expand Down
4 changes: 2 additions & 2 deletions plexpy/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def latinToAscii(unicrap):
pass
else:
r += str(i)
return r
return r.encode('utf-8')


def convert_milliseconds(ms):
Expand Down Expand Up @@ -352,7 +352,7 @@ def convert_xml_to_dict(xml):

def get_percent(value1, value2):

if value1.isdigit() and value2.isdigit():
if str(value1).isdigit() and str(value2).isdigit():
value1 = cast_to_float(value1)
value2 = cast_to_float(value2)
else:
Expand Down
40 changes: 32 additions & 8 deletions plexpy/monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# You should have received a copy of the GNU General Public License
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.

from plexpy import logger, pmsconnect, notification_handler, log_reader, common, database
from plexpy import logger, pmsconnect, notification_handler, log_reader, common, database, helpers

import threading
import plexpy
Expand Down Expand Up @@ -97,8 +97,10 @@ def check_active_sessions():
# Here we can check the play states
if session['state'] != stream['state']:
if session['state'] == 'paused':
# Push any notifications
notification_handler.notify(stream_data=stream, notify_action='pause')
# 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 stream['state'] == 'paused':
# 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
Expand All @@ -107,14 +109,33 @@ def check_active_sessions():
monitor_db.action('UPDATE sessions SET paused_counter = ? '
'WHERE session_key = ? AND rating_key = ?',
[paused_counter, stream['session_key'], stream['rating_key']])
# Check if the user has reached the offset in the media we defined as the "watched" percent
if session['progress'] and session['duration']:
if helpers.get_percent(session['progress'], session['duration']) > plexpy.CONFIG.NOTIFY_WATCHED_PERCENT:
# 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
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']])
# Push any notifications
notification_handler.notify(stream_data=stream, notify_action='stop')

# 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:
# 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()

# 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
monitor_process.write_session_history(session=stream)

Expand All @@ -132,7 +153,8 @@ def __init__(self):

def write_session(self, session=None):

values = {'rating_key': session['rating_key'],
values = {'session_key': session['session_key'],
'rating_key': session['rating_key'],
'media_type': session['type'],
'state': session['state'],
'user_id': session['user_id'],
Expand Down Expand Up @@ -175,8 +197,10 @@ def write_session(self, session=None):
result = self.db.upsert('sessions', values, keys)

if result == 'insert':
# Push any notifications
notification_handler.notify(stream_data=values, notify_action='play')
# 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()

started = int(time.time())

# Try and grab IP address from logs
Expand Down

0 comments on commit b394ebc

Please sign in to comment.