@@ -238,9 +276,14 @@
@@ -253,9 +296,14 @@
@@ -268,7 +316,13 @@
diff --git a/plexpy/__init__.py b/plexpy/__init__.py
index 3d9f5a51..530aca1a 100644
--- a/plexpy/__init__.py
+++ b/plexpy/__init__.py
@@ -163,7 +163,7 @@ def initialize(config_file):
LATEST_VERSION = CURRENT_VERSION
# Refresh the users list on startup
- if CONFIG.PMS_TOKEN:
+ if CONFIG.PMS_TOKEN and CONFIG.REFRESH_USERS_ON_STARTUP:
plextv.refresh_users()
# Store the original umask
@@ -261,12 +261,26 @@ def initialize_scheduler():
schedule_job(versioncheck.checkGithub, 'Check GitHub for updates', hours=0, minutes=minutes)
# Start checking for new sessions every minute
- if CONFIG.PMS_IP:
- schedule_job(monitor.check_active_sessions, 'Check for active sessions', hours=0, minutes=0, seconds=60)
+ if CONFIG.MONITORING_INTERVAL:
+ # Our interval should never be less than 30 seconds
+ if CONFIG.MONITORING_INTERVAL > 30:
+ seconds = CONFIG.MONITORING_INTERVAL
+ else:
+ seconds = 30
+ else:
+ seconds = 0
+
+ if CONFIG.PMS_IP:
+ schedule_job(monitor.check_active_sessions, 'Check for active sessions', hours=0, minutes=0, seconds=seconds)
+
+ # Refresh the users list
+ if CONFIG.REFRESH_USERS_INTERVAL:
+ hours = CONFIG.REFRESH_USERS_INTERVAL
+ else:
+ hours = 0
- # Refresh the users list every 12 hours (we will make this configurable later)
if CONFIG.PMS_TOKEN:
- schedule_job(plextv.refresh_users, 'Refresh users list', hours=12, minutes=0, seconds=0)
+ schedule_job(plextv.refresh_users, 'Refresh users list', hours=hours, minutes=0, seconds=0)
# Start scheduler
if start_jobs and len(SCHED.get_jobs()):
@@ -356,7 +370,8 @@ def dbcheck():
c_db.execute(
'CREATE TABLE IF NOT EXISTS sessions (id INTEGER PRIMARY KEY AUTOINCREMENT, '
'session_key INTEGER, rating_key INTEGER, media_type TEXT, started INTEGER, '
- 'paused_counter INTEGER, state TEXT, user TEXT, machine_id TEXT)'
+ 'paused_counter INTEGER, state TEXT, user_id INTEGER, user TEXT, friendly_name TEXT, '
+ 'machine_id TEXT, player TEXT, title TEXT, parent_title TEXT, grandparent_title TEXT)'
)
# Upgrade sessions table from earlier versions
@@ -380,6 +395,30 @@ def dbcheck():
'ALTER TABLE sessions ADD COLUMN machine_id TEXT'
)
+ # Upgrade sessions table from earlier versions
+ try:
+ c_db.execute('SELECT title from sessions')
+ except sqlite3.OperationalError:
+ logger.debug(u"Altering database. Updating database table sessions.")
+ c_db.execute(
+ 'ALTER TABLE sessions ADD COLUMN title TEXT'
+ )
+ c_db.execute(
+ 'ALTER TABLE sessions ADD COLUMN parent_title TEXT'
+ )
+ c_db.execute(
+ 'ALTER TABLE sessions ADD COLUMN grandparent_title TEXT'
+ )
+ c_db.execute(
+ 'ALTER TABLE sessions ADD COLUMN friendly_name TEXT'
+ )
+ c_db.execute(
+ 'ALTER TABLE sessions ADD COLUMN player TEXT'
+ )
+ c_db.execute(
+ 'ALTER TABLE sessions ADD COLUMN user_id INTEGER'
+ )
+
conn_db.commit()
c_db.close()
diff --git a/plexpy/config.py b/plexpy/config.py
index b04834ba..7120a2e8 100644
--- a/plexpy/config.py
+++ b/plexpy/config.py
@@ -69,13 +69,19 @@ _CONFIG_DEFINITIONS = {
'HTTP_ROOT': (str, 'General', '/'),
'HTTP_USERNAME': (str, 'General', ''),
'INTERFACE': (str, 'General', 'default'),
+ 'IP_LOGGING_ENABLE': (int, 'General', 0),
'JOURNAL_MODE': (str, 'Advanced', 'wal'),
'LAUNCH_BROWSER': (int, 'General', 1),
'LOG_DIR': (str, 'General', ''),
'MOVIE_NOTIFY_ENABLE': (int, 'Monitoring', 0),
'MOVIE_NOTIFY_ON_START': (int, 'Monitoring', 1),
+ 'MOVIE_NOTIFY_ON_STOP': (int, 'Monitoring', 0),
+ 'MOVIE_NOTIFY_ON_PAUSE': (int, 'Monitoring', 0),
'MUSIC_NOTIFY_ENABLE': (int, 'Monitoring', 0),
'MUSIC_NOTIFY_ON_START': (int, 'Monitoring', 1),
+ 'MUSIC_NOTIFY_ON_STOP': (int, 'Monitoring', 0),
+ 'MUSIC_NOTIFY_ON_PAUSE': (int, 'Monitoring', 0),
+ 'MONITORING_INTERVAL': (int, 'Monitoring', 60),
'NMA_APIKEY': (str, 'NMA', ''),
'NMA_ENABLED': (int, 'NMA', 0),
'NMA_PRIORITY': (int, 'NMA', 0),
@@ -97,8 +103,12 @@ _CONFIG_DEFINITIONS = {
'PUSHOVER_ENABLED': (int, 'Pushover', 0),
'PUSHOVER_KEYS': (str, 'Pushover', ''),
'PUSHOVER_PRIORITY': (int, 'Pushover', 0),
+ 'REFRESH_USERS_INTERVAL': (int, 'Monitoring', 12),
+ 'REFRESH_USERS_ON_STARTUP': (int, 'Monitoring', 1),
'TV_NOTIFY_ENABLE': (int, 'Monitoring', 0),
'TV_NOTIFY_ON_START': (int, 'Monitoring', 1),
+ 'TV_NOTIFY_ON_STOP': (int, 'Monitoring', 0),
+ 'TV_NOTIFY_ON_PAUSE': (int, 'Monitoring', 0),
'TWITTER_ENABLED': (int, 'Twitter', 0),
'TWITTER_PASSWORD': (str, 'Twitter', ''),
'TWITTER_PREFIX': (str, 'Twitter', 'Headphones'),
diff --git a/plexpy/monitor.py b/plexpy/monitor.py
index 1c0060f0..261f93a1 100644
--- a/plexpy/monitor.py
+++ b/plexpy/monitor.py
@@ -41,24 +41,44 @@ def check_active_sessions():
media_container = session_list['sessions']
# Check our temp table for what we must do with the new streams
- db_streams = monitor_db.select('SELECT session_key, rating_key, media_type FROM sessions')
+ db_streams = monitor_db.select('SELECT session_key, rating_key, media_type, title, parent_title, '
+ 'grandparent_title, user, friendly_name, player, state '
+ 'FROM sessions')
for result in db_streams:
- if any(d['session_key'] == str(result[0]) for d in media_container):
+ # Build a result dictionary for easier referencing
+ stream = {'session_key': result[0],
+ 'rating_key': result[1],
+ 'media_type': result[2],
+ 'title': result[3],
+ 'parent_title': result[4],
+ 'grandparent_title': result[5],
+ 'user': result[6],
+ 'friendly_name': result[7],
+ 'player': result[8],
+ 'state': result[9]
+ }
+
+ if any(d['session_key'] == str(stream['session_key']) for d in media_container):
# The user's session is still active
- pass
- if any(d['rating_key'] == str(result[1]) for d in media_container):
- # The user is still playing the same media item
- # Here we can check the play states
- # logger.debug(u"PlexPy Monitor :: Session key %s :: Rating key %s is still active." % (result[0], result[1]))
- pass
- else:
- # The user has stopped playing a stream
- monitor_db.action('DELETE FROM sessions WHERE session_key = ? AND rating_key = ?', [result[0], result[1]])
- # logger.debug(u"PlexPy Monitor :: Session key %s :: Rating key %s has been stopped." % (result[0], result[1]))
+ for session in media_container:
+ if session['rating_key'] == str(stream['rating_key']):
+ # The user is still playing the same media item
+ # Here we can check the play states
+ if session['state'] != stream['state']:
+ if session['state'] == 'paused':
+ # Push any notifications
+ notify(stream_data=stream, notify_action='pause')
+ else:
+ # The user has stopped playing a stream
+ monitor_db.action('DELETE FROM sessions WHERE session_key = ? AND rating_key = ?',
+ [stream['session_key'], stream['rating_key']])
+ # Push any notifications
+ notify(stream_data=stream, notify_action='stop')
else:
# The user's session is no longer active
- monitor_db.action('DELETE FROM sessions WHERE session_key = ?', [result[0]])
- # logger.debug(u"PlexPy Monitor :: Session key %s :: Rating key %s has been stopped." % (result[0], result[1]))
+ monitor_db.action('DELETE FROM sessions WHERE session_key = ?', [stream['session_key']])
+ # Push any notifications
+ notify(stream_data=stream, notify_action='stop')
# Process the newly received session data
for session in media_container:
@@ -169,7 +189,13 @@ class MonitorProcessing(object):
'media_type': session['type'],
'state': session['state'],
'user': session['user'],
- 'machine_id': session['machine_id']}
+ 'machine_id': session['machine_id'],
+ 'title': session['title'],
+ 'parent_title': session['parent_title'],
+ 'grandparent_title': session['grandparent_title'],
+ 'friendly_name': session['friendly_name'],
+ 'player': session['player']
+ }
timestamp = {'started': int(time.time())}
@@ -182,23 +208,11 @@ class MonitorProcessing(object):
# If it's our first write then time stamp it.
self.db.upsert('sessions', timestamp, keys)
- # User started playing a stream :: We notify here
- if session['type'] == 'track' or session['type'] == 'episode':
- item_title = session['grandparent_title'] + ' - ' + session['title']
- elif session['type'] == 'movie':
- item_title = session['title']
- else:
- item_title = session['title']
-
- logger.info('%s (%s) starting playing %s' % (session['friendly_name'], session['platform'], item_title))
- pushmessage = '%s (%s) starting playing %s' % (session['friendly_name'], session['platform'], item_title)
-
# Push any notifications
- monitor_notifications = MonitorNotifications(media_type=session['type'], user=session['user'])
- monitor_notifications.notify(pushmessage)
+ notify(stream_data=values, notify_action='play')
# Try and grab IP address from logs
- if plexpy.CONFIG.PMS_LOGS_FOLDER:
+ if plexpy.CONFIG.IP_LOGGING_ENABLE and plexpy.CONFIG.PMS_LOGS_FOLDER:
ip_address = self.find_session_ip(rating_key=session['rating_key'],
machine_id=session['machine_id'])
@@ -247,31 +261,78 @@ class MonitorProcessing(object):
return None
+def notify(stream_data=None, notify_action=None):
-class MonitorNotifications(object):
-
- def __init__(self, media_type, user=None):
- self.media_type = media_type
- self.user = user
- self.tv_notify_enabled = plexpy.CONFIG.TV_NOTIFY_ENABLE
- self.movie_notify_enabled = plexpy.CONFIG.MOVIE_NOTIFY_ENABLE
- self.music_notify_enabled = plexpy.CONFIG.MUSIC_NOTIFY_ENABLE
-
- def notify(self, message=None):
- if message:
- if self.media_type == 'movie':
- if self.movie_notify_enabled:
- notification_handler.push_nofitications(message, 'PlexPy', common.notify_strings[1])
- elif self.media_type == 'episode':
- if self.tv_notify_enabled:
- notification_handler.push_nofitications(message, 'PlexPy', common.notify_strings[1])
- elif self.media_type == 'track':
- if self.music_notify_enabled:
- notification_handler.push_nofitications(message, 'PlexPy', common.notify_strings[1])
- elif self.media_type == 'clip':
- pass
- else:
- logger.debug(u"Notify called with unsupported media type.")
- pass
+ if stream_data and notify_action:
+ # 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:
- logger.debug(u"Notify called without a message.")
+ item_title = stream_data['title']
+
+ if notify_action == 'play':
+ logger.info('%s (%s) started playing %s.' % (stream_data['friendly_name'], stream_data['player'], item_title))
+
+ if stream_data['media_type'] == 'movie':
+ if plexpy.CONFIG.MOVIE_NOTIFY_ENABLE:
+
+ if plexpy.CONFIG.MOVIE_NOTIFY_ON_START and notify_action == 'play':
+ message = '%s (%s) started playing %s.' % \
+ (stream_data['friendly_name'], stream_data['player'], item_title)
+ notification_handler.push_nofitications(message, 'PlexPy', common.notify_strings[1])
+
+ elif plexpy.CONFIG.MOVIE_NOTIFY_ON_PAUSE and notify_action == 'pause':
+ message = '%s (%s) has paused %s.' % \
+ (stream_data['friendly_name'], stream_data['player'], item_title)
+ notification_handler.push_nofitications(message, 'PlexPy', common.notify_strings[1])
+
+ elif plexpy.CONFIG.MOVIE_NOTIFY_ON_STOP and notify_action == 'stop':
+ message = '%s (%s) stopped playing %s.' % \
+ (stream_data['friendly_name'], stream_data['player'], item_title)
+ notification_handler.push_nofitications(message, 'PlexPy', common.notify_strings[1])
+
+ elif stream_data['media_type'] == 'episode':
+ if plexpy.CONFIG.TV_NOTIFY_ENABLE:
+
+ if plexpy.CONFIG.TV_NOTIFY_ON_START and notify_action == 'play':
+ message = '%s (%s) started playing %s.' % \
+ (stream_data['friendly_name'], stream_data['player'], item_title)
+ notification_handler.push_nofitications(message, 'PlexPy', common.notify_strings[1])
+
+ elif plexpy.CONFIG.TV_NOTIFY_ON_PAUSE and notify_action == 'pause':
+ message = '%s (%s) has paused %s.' % \
+ (stream_data['friendly_name'], stream_data['player'], item_title)
+ notification_handler.push_nofitications(message, 'PlexPy', common.notify_strings[1])
+
+ elif plexpy.CONFIG.TV_NOTIFY_ON_STOP and notify_action == 'stop':
+ message = '%s (%s) stopped playing %s.' % \
+ (stream_data['friendly_name'], stream_data['player'], item_title)
+ notification_handler.push_nofitications(message, 'PlexPy', common.notify_strings[1])
+
+ elif stream_data['media_type'] == 'track':
+ if plexpy.CONFIG.MUSIC_NOTIFY_ENABLE:
+
+ if plexpy.CONFIG.MUSIC_NOTIFY_ON_START and notify_action == 'play':
+ message = '%s (%s) started playing %s.' % \
+ (stream_data['friendly_name'], stream_data['player'], item_title)
+ notification_handler.push_nofitications(message, 'PlexPy', common.notify_strings[1])
+
+ elif plexpy.CONFIG.MUSIC_NOTIFY_ON_PAUSE and notify_action == 'pause':
+ message = '%s (%s) has paused %s.' % \
+ (stream_data['friendly_name'], stream_data['player'], item_title)
+ notification_handler.push_nofitications(message, 'PlexPy', common.notify_strings[1])
+
+ elif plexpy.CONFIG.MUSIC_NOTIFY_ON_STOP and notify_action == 'stop':
+ message = '%s (%s) stopped playing %s.' % \
+ (stream_data['friendly_name'], stream_data['player'], item_title)
+ notification_handler.push_nofitications(message, 'PlexPy', common.notify_strings[1])
+
+ elif stream_data['media_type'] == 'clip':
+ pass
+ else:
+ logger.debug(u"Notify called with unsupported media type.")
+ pass
+ else:
+ logger.debug(u"Notify called but incomplete data received.")
diff --git a/plexpy/webserve.py b/plexpy/webserve.py
index e298aa3d..961c3c09 100644
--- a/plexpy/webserve.py
+++ b/plexpy/webserve.py
@@ -335,7 +335,17 @@ class WebInterface(object):
"music_notify_enable": checked(plexpy.CONFIG.MUSIC_NOTIFY_ENABLE),
"tv_notify_on_start": checked(plexpy.CONFIG.TV_NOTIFY_ON_START),
"movie_notify_on_start": checked(plexpy.CONFIG.MOVIE_NOTIFY_ON_START),
- "music_notify_on_start": checked(plexpy.CONFIG.MUSIC_NOTIFY_ON_START)
+ "music_notify_on_start": checked(plexpy.CONFIG.MUSIC_NOTIFY_ON_START),
+ "tv_notify_on_stop": checked(plexpy.CONFIG.TV_NOTIFY_ON_STOP),
+ "movie_notify_on_stop": checked(plexpy.CONFIG.MOVIE_NOTIFY_ON_STOP),
+ "music_notify_on_stop": checked(plexpy.CONFIG.MUSIC_NOTIFY_ON_STOP),
+ "tv_notify_on_pause": checked(plexpy.CONFIG.TV_NOTIFY_ON_PAUSE),
+ "movie_notify_on_pause": checked(plexpy.CONFIG.MOVIE_NOTIFY_ON_PAUSE),
+ "music_notify_on_pause": checked(plexpy.CONFIG.MUSIC_NOTIFY_ON_PAUSE),
+ "monitoring_interval": plexpy.CONFIG.MONITORING_INTERVAL,
+ "refresh_users_interval": plexpy.CONFIG.REFRESH_USERS_INTERVAL,
+ "refresh_users_on_startup": checked(plexpy.CONFIG.REFRESH_USERS_ON_STARTUP),
+ "ip_logging_enable": checked(plexpy.CONFIG.IP_LOGGING_ENABLE)
}
return serve_template(templatename="config.html", title="Settings", config=config)
@@ -353,7 +363,10 @@ class WebInterface(object):
"boxcar_enabled", "email_enabled", "email_tls",
"grouping_global_history", "grouping_user_history", "grouping_charts", "pms_use_bif",
"tv_notify_enable", "movie_notify_enable", "music_notify_enable",
- "tv_notify_on_start", "movie_notify_on_start", "music_notify_on_start"
+ "tv_notify_on_start", "movie_notify_on_start", "music_notify_on_start",
+ "tv_notify_on_stop", "movie_notify_on_stop", "music_notify_on_stop",
+ "tv_notify_on_pause", "movie_notify_on_pause", "music_notify_on_pause", "refresh_users_on_startup",
+ "ip_logging_enable"
]
for checked_config in checked_configs:
if checked_config not in kwargs: