Unable to retrieve data from database. Please check your
settings.
+
Unable to retrieve data from database.
% endif
\ No newline at end of file
diff --git a/data/interfaces/default/users.html b/data/interfaces/default/users.html
index 928ec94b..9302625a 100644
--- a/data/interfaces/default/users.html
+++ b/data/interfaces/default/users.html
@@ -177,13 +177,13 @@
cache: false,
async: true,
success: function(data) {
- showMsg('
 Users list refresh started...',false,true,2000,false)
+ showMsg('
 Users list refresh started...', false, true, 2000, false);
},
complete: function (data) {
- showMsg('
 Users list refreshed.', false, true, 2000, false)
+ showMsg('
 Users list refreshed.', false, true, 2000, false);
},
error: function (jqXHR, textStatus, errorThrown) {
- showMsg('
 Unable to refresh users list.',false,true,2000,true)
+ showMsg('
 Unable to refresh users list.', false, true, 2000, true);
}
});
});
diff --git a/plexpy/__init__.py b/plexpy/__init__.py
index 59d05688..83557695 100644
--- a/plexpy/__init__.py
+++ b/plexpy/__init__.py
@@ -377,7 +377,7 @@ def dbcheck():
# sessions table :: This is a temp table that logs currently active sessions
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, '
+ 'session_key INTEGER, rating_key INTEGER, library_id INTEGER, media_type TEXT, started INTEGER, '
'paused_counter INTEGER DEFAULT 0, state TEXT, user_id INTEGER, user TEXT, friendly_name TEXT, '
'ip_address TEXT, machine_id TEXT, player TEXT, platform TEXT, title TEXT, parent_title TEXT, '
'grandparent_title TEXT, parent_rating_key INTEGER, grandparent_rating_key INTEGER, '
@@ -441,7 +441,8 @@ def dbcheck():
'CREATE TABLE IF NOT EXISTS library_sections (id INTEGER PRIMARY KEY AUTOINCREMENT, '
'server_id TEXT, section_id INTEGER UNIQUE, section_name TEXT, section_type TEXT, '
'thumb TEXT, custom_thumb_url TEXT, art TEXT, count INTEGER, parent_count INTEGER, child_count INTEGER, '
- 'do_notify INTEGER DEFAULT 1, keep_history INTEGER DEFAULT 1)'
+ 'do_notify INTEGER DEFAULT 1, do_notify_created INTEGER DEFAULT 1, keep_history INTEGER DEFAULT 1, '
+ 'deleted_section INTEGER DEFAULT 0)'
)
# Upgrade sessions table from earlier versions
@@ -591,6 +592,15 @@ def dbcheck():
'ALTER TABLE sessions ADD COLUMN last_paused INTEGER'
)
+ # Upgrade sessions table from earlier versions
+ try:
+ c_db.execute('SELECT library_id from sessions')
+ except sqlite3.OperationalError:
+ logger.debug(u"Altering database. Updating database table sessions.")
+ c_db.execute(
+ 'ALTER TABLE sessions ADD COLUMN library_id INTEGER'
+ )
+
# Upgrade session_history table from earlier versions
try:
c_db.execute('SELECT reference_id from session_history')
diff --git a/plexpy/activity_handler.py b/plexpy/activity_handler.py
index 967a2e21..b3e264a3 100644
--- a/plexpy/activity_handler.py
+++ b/plexpy/activity_handler.py
@@ -16,7 +16,7 @@
import time
import plexpy
-from plexpy import logger, pmsconnect, activity_processor, threading, notification_handler
+from plexpy import logger, pmsconnect, activity_processor, threading, notification_handler, helpers
class ActivityHandler(object):
@@ -165,8 +165,6 @@ class ActivityHandler(object):
# This function receives events from our websocket connection
def process(self):
if self.is_valid_session():
- from plexpy import helpers
-
ap = activity_processor.ActivityProcessor()
db_session = ap.get_session_by_key(session_key=self.get_session_key())
diff --git a/plexpy/activity_pinger.py b/plexpy/activity_pinger.py
index ee0479d3..b2998ca1 100644
--- a/plexpy/activity_pinger.py
+++ b/plexpy/activity_pinger.py
@@ -13,7 +13,7 @@
# You should have received a copy of the GNU General Public License
# along with PlexPy. If not, see
.
-from plexpy import logger, pmsconnect, plextv, notification_handler, database, helpers, activity_processor
+from plexpy import logger, pmsconnect, plextv, notification_handler, database, helpers, activity_processor, libraries
import threading
import plexpy
@@ -46,16 +46,7 @@ def check_active_sessions(ws_request=False):
media_container = session_list['sessions']
# Check our temp table for what we must do with the new streams
- db_streams = monitor_db.select('SELECT started, session_key, rating_key, media_type, title, parent_title, '
- 'grandparent_title, user_id, user, friendly_name, ip_address, player, '
- 'platform, machine_id, parent_rating_key, grandparent_rating_key, state, '
- 'view_offset, duration, video_decision, audio_decision, width, height, '
- 'container, video_codec, audio_codec, bitrate, video_resolution, '
- 'video_framerate, aspect_ratio, audio_channels, transcode_protocol, '
- 'transcode_container, transcode_video_codec, transcode_audio_codec, '
- 'transcode_audio_channels, transcode_width, transcode_height, '
- 'paused_counter, last_paused '
- 'FROM sessions')
+ db_streams = monitor_db.select('SELECT * FROM sessions')
for stream in db_streams:
if any(d['session_key'] == str(stream['session_key']) and d['rating_key'] == str(stream['rating_key'])
for d in media_container):
@@ -182,7 +173,7 @@ def check_active_sessions(ws_request=False):
if int_ping_count == 3:
# Fire off notifications
threading.Thread(target=notification_handler.notify_timeline,
- kwargs=dict(notify_action='intdown')).start()
+ kwargs=dict(notify_action='intdown')).start()
def check_recently_added():
@@ -196,10 +187,16 @@ def check_recently_added():
pms_connect = pmsconnect.PmsConnect()
recently_added_list = pms_connect.get_recently_added_details(count='10')
+ library_data = libraries.Libraries()
if recently_added_list:
recently_added = recently_added_list['recently_added']
for item in recently_added:
+ library_details = library_data.get_details(section_id=item['library_id'])
+
+ if not library_details['do_notify_created']:
+ continue
+
metadata = []
if 0 < time_threshold - int(item['added_at']) <= time_interval:
@@ -220,8 +217,12 @@ def check_recently_added():
% str(item['rating_key']))
if metadata:
+
if not plexpy.CONFIG.NOTIFY_RECENTLY_ADDED_GRANDPARENT:
for item in metadata:
+
+ library_details = library_data.get_details(section_id=item['library_id'])
+
if 0 < time_threshold - int(item['added_at']) <= time_interval:
logger.debug(u"PlexPy Monitor :: Library item %s has been added to Plex." % str(item['rating_key']))
# Fire off notifications
diff --git a/plexpy/activity_processor.py b/plexpy/activity_processor.py
index cc3f6448..433219cc 100644
--- a/plexpy/activity_processor.py
+++ b/plexpy/activity_processor.py
@@ -29,6 +29,7 @@ class ActivityProcessor(object):
def write_session(self, session=None, notify=True):
if session:
values = {'session_key': session['session_key'],
+ 'library_id': session['library_id'],
'rating_key': session['rating_key'],
'media_type': session['media_type'],
'state': session['state'],
@@ -97,10 +98,13 @@ class ActivityProcessor(object):
self.db.upsert('sessions', ip_address, keys)
def write_session_history(self, session=None, import_metadata=None, is_import=False, import_ignore_interval=0):
- from plexpy import users
+ from plexpy import users, libraries
user_data = users.Users()
- user_details = user_data.get_user_friendly_name(user=session['user'])
+ user_details = user_data.get_details(user_id=session['user_id'])
+
+ library_data = libraries.Libraries()
+ library_details = library_data.get_details(section_id=session['library_id'])
if session:
logging_enabled = False
@@ -155,7 +159,10 @@ class ActivityProcessor(object):
if not user_details['keep_history'] and not is_import:
logging_enabled = False
- logger.debug(u"PlexPy ActivityProcessor :: History logging for user '%s' is disabled." % session['user'])
+ logger.debug(u"PlexPy ActivityProcessor :: History logging for user '%s' is disabled." % user_details['username'])
+ elif not library_details['keep_history'] and not is_import:
+ logging_enabled = False
+ logger.debug(u"PlexPy ActivityProcessor :: History logging for library '%s' is disabled." % library_details['section_name'])
if logging_enabled:
# logger.debug(u"PlexPy ActivityProcessor :: Attempting to write to session_history table...")
@@ -331,15 +338,7 @@ class ActivityProcessor(object):
def get_session_by_key(self, session_key=None):
if str(session_key).isdigit():
- result = self.db.select('SELECT started, session_key, rating_key, media_type, title, parent_title, '
- 'grandparent_title, user_id, user, friendly_name, ip_address, player, '
- 'platform, machine_id, parent_rating_key, grandparent_rating_key, state, '
- 'view_offset, duration, video_decision, audio_decision, width, height, '
- 'container, video_codec, audio_codec, bitrate, video_resolution, '
- 'video_framerate, aspect_ratio, audio_channels, transcode_protocol, '
- 'transcode_container, transcode_video_codec, transcode_audio_codec, '
- 'transcode_audio_channels, transcode_width, transcode_height, '
- 'paused_counter, last_paused '
+ result = self.db.select('SELECT * '
'FROM sessions WHERE session_key = ? LIMIT 1', args=[session_key])
for session in result:
if session:
diff --git a/plexpy/api.py b/plexpy/api.py
index d2d0d432..6f5c2882 100644
--- a/plexpy/api.py
+++ b/plexpy/api.py
@@ -323,7 +323,7 @@ class Api(object):
custom_where = [['strftime("%Y-%m-%d", datetime(date, "unixepoch", "localtime"))', start_date]]
data_factory = datafactory.DataFactory()
- history = data_factory.get_history(kwargs=kwargs, custom_where=custom_where)
+ history = data_factory.get_datatables_history(kwargs=kwargs, custom_where=custom_where)
self.data = history
return self.data
diff --git a/plexpy/datafactory.py b/plexpy/datafactory.py
index 298b33dd..2120c603 100644
--- a/plexpy/datafactory.py
+++ b/plexpy/datafactory.py
@@ -26,7 +26,7 @@ class DataFactory(object):
def __init__(self):
pass
- def get_history(self, kwargs=None, custom_where=None, grouping=0, watched_percent=85):
+ def get_datatables_history(self, kwargs=None, custom_where=None, grouping=0, watched_percent=85):
data_tables = datatables.DataTables()
group_by = ['session_history.reference_id'] if grouping else ['session_history.id']
@@ -81,8 +81,8 @@ class DataFactory(object):
['session_history.id', 'session_history_metadata.id'],
['session_history.id', 'session_history_media_info.id']],
kwargs=kwargs)
- except:
- logger.warn("Unable to execute database query for get_history.")
+ except Exception as e:
+ logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_history: %s." % e)
return {'recordsFiltered': 0,
'recordsTotal': 0,
'draw': 0,
@@ -185,8 +185,8 @@ class DataFactory(object):
'ORDER BY %s DESC ' \
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query)
- except:
- logger.warn("Unable to execute database query for get_home_stats: top_tv.")
+ except Exception as e:
+ logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: top_tv: %s." % e)
return None
for item in result:
@@ -229,8 +229,8 @@ class DataFactory(object):
'ORDER BY users_watched DESC, %s DESC ' \
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query)
- except:
- logger.warn("Unable to execute database query for get_home_stats: popular_tv.")
+ except Exception as e:
+ logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: popular_tv: %s." % e)
return None
for item in result:
@@ -270,8 +270,8 @@ class DataFactory(object):
'ORDER BY %s DESC ' \
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query)
- except:
- logger.warn("Unable to execute database query for get_home_stats: top_movies.")
+ except Exception as e:
+ logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: top_movies: %s." % e)
return None
for item in result:
@@ -313,8 +313,8 @@ class DataFactory(object):
'ORDER BY users_watched DESC, %s DESC ' \
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query)
- except:
- logger.warn("Unable to execute database query for get_home_stats: popular_movies.")
+ except Exception as e:
+ logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: popular_movies: %s." % e)
return None
for item in result:
@@ -354,8 +354,8 @@ class DataFactory(object):
'ORDER BY %s DESC ' \
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query)
- except:
- logger.warn("Unable to execute database query for get_home_stats: top_music.")
+ except Exception as e:
+ logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: top_music: %s." % e)
return None
for item in result:
@@ -398,8 +398,8 @@ class DataFactory(object):
'ORDER BY users_watched DESC, %s DESC ' \
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query)
- except:
- logger.warn("Unable to execute database query for get_home_stats: popular_music.")
+ except Exception as e:
+ logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: popular_music: %s." % e)
return None
for item in result:
@@ -424,13 +424,13 @@ class DataFactory(object):
elif stat == 'top_users':
top_users = []
try:
- query = 'SELECT t.user, t.user_id, t.custom_avatar_url as thumb, ' \
+ query = 'SELECT t.user, t.user_id, t.user_thumb, t.custom_thumb, ' \
'(CASE WHEN t.friendly_name IS NULL THEN t.username ELSE t.friendly_name END) ' \
' AS friendly_name, ' \
'MAX(t.started) AS last_watch, COUNT(t.id) AS total_plays, SUM(t.d) AS total_duration ' \
'FROM (SELECT *, SUM(CASE WHEN stopped > 0 THEN (stopped - started) - ' \
' (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) ' \
- ' AS d ' \
+ ' AS d, users.thumb AS user_thumb, users.custom_avatar_url AS custom_thumb ' \
' FROM session_history ' \
' JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
' LEFT OUTER JOIN users ON session_history.user_id = users.user_id ' \
@@ -441,15 +441,17 @@ class DataFactory(object):
'ORDER BY %s DESC ' \
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query)
- except:
- logger.warn("Unable to execute database query for get_home_stats: top_users.")
+ except Exception as e:
+ logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: top_users: %s." % e)
return None
for item in result:
- if not item['thumb'] or item['thumb'] == '':
- user_thumb = common.DEFAULT_USER_THUMB
+ if item['custom_thumb'] and item['custom_thumb'] != item['user_thumb']:
+ user_thumb = item['custom_thumb']
+ elif item['user_thumb']:
+ user_thumb = item['user_thumb']
else:
- user_thumb = item['thumb']
+ user_thumb = common.DEFAULT_USER_THUMB
row = {'user': item['user'],
'user_id': item['user_id'],
@@ -490,8 +492,8 @@ class DataFactory(object):
'ORDER BY %s DESC ' \
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query)
- except:
- logger.warn("Unable to execute database query for get_home_stats: top_platforms.")
+ except Exception as e:
+ logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: top_platforms: %s." % e)
return None
for item in result:
@@ -542,8 +544,8 @@ class DataFactory(object):
'ORDER BY last_watch DESC ' \
'LIMIT %s' % (time_range, group_by, notify_watched_percent, stats_count)
result = monitor_db.select(query)
- except:
- logger.warn("Unable to execute database query for get_home_stats: last_watched.")
+ except Exception as e:
+ logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: last_watched: %s." % e)
return None
for item in result:
@@ -645,8 +647,8 @@ class DataFactory(object):
result = monitor_db.select(query)
if result:
most_concurrent.append(calc_most_concurrent(title, result))
- except:
- logger.warn("Unable to execute database query for get_home_stats: most_concurrent.")
+ except Exception as e:
+ logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: most_concurrent: %s." % e)
return None
home_stats.append({'stat_id': stat,
@@ -664,10 +666,10 @@ class DataFactory(object):
try:
query = 'SELECT section_id, section_name, section_type, thumb, count, parent_count, child_count ' \
'FROM library_sections ' \
- 'WHERE section_id = %s' % id
+ 'WHERE section_id = %s ' % id
result = monitor_db.select(query)
- except:
- logger.warn("Unable to execute database query for get_library_stats.")
+ except Exception as e:
+ logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_library_stats: %s." % e)
return None
for item in result:
@@ -725,86 +727,6 @@ class DataFactory(object):
return stream_output
- def get_recently_watched(self, user=None, user_id=None, library_id=None, limit='10'):
- monitor_db = database.MonitorDatabase()
- recently_watched = []
-
- if not limit.isdigit():
- limit = '10'
-
- try:
- if user_id:
- query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, session_history.parent_rating_key, ' \
- 'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_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 = ? ' \
- 'GROUP BY (CASE WHEN session_history.media_type = "track" THEN session_history.parent_rating_key ' \
- ' ELSE session_history.rating_key END) ' \
- '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, session_history.parent_rating_key, ' \
- 'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_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 = ? ' \
- 'GROUP BY (CASE WHEN session_history.media_type = "track" THEN session_history.parent_rating_key ' \
- ' ELSE session_history.rating_key END) ' \
- 'ORDER BY started DESC LIMIT ?'
- result = monitor_db.select(query, args=[user, limit])
- elif library_id:
- query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, session_history.parent_rating_key, ' \
- 'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_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 library_id = ? ' \
- 'GROUP BY (CASE WHEN session_history.media_type = "track" THEN session_history.parent_rating_key ' \
- ' ELSE session_history.rating_key END) ' \
- 'ORDER BY started DESC LIMIT ?'
- result = monitor_db.select(query, args=[library_id, limit])
- else:
- query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, session_history.parent_rating_key, ' \
- 'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_thumb, media_index, parent_media_index, ' \
- 'year, started, user ' \
- 'FROM session_history_metadata ' \
- 'JOIN session_history ON session_history_metadata.id = session_history.id ' \
- 'GROUP BY (CASE WHEN session_history.media_type = "track" THEN session_history.parent_rating_key ' \
- ' ELSE session_history.rating_key END) ' \
- 'ORDER BY started DESC LIMIT ?'
- result = monitor_db.select(query, args=[limit])
- except:
- logger.warn("Unable to execute database query for get_recently_watched.")
- return None
-
- for row in result:
- if row['media_type'] == 'episode' and row['parent_thumb']:
- thumb = row['parent_thumb']
- elif row['media_type'] == 'episode':
- thumb = row['grandparent_thumb']
- else:
- thumb = row['thumb']
-
- recent_output = {'row_id': row['id'],
- 'type': row['media_type'],
- 'rating_key': row['rating_key'],
- 'title': row['title'],
- 'parent_title': row['parent_title'],
- 'grandparent_title': row['grandparent_title'],
- 'thumb': thumb,
- 'media_index': row['media_index'],
- 'parent_media_index': row['parent_media_index'],
- 'year': row['year'],
- 'time': row['started'],
- 'user': row['user']
- }
- recently_watched.append(recent_output)
-
- return recently_watched
-
def get_metadata_details(self, rating_key):
monitor_db = database.MonitorDatabase()
@@ -866,89 +788,52 @@ class DataFactory(object):
'directors': directors,
'genres': genres,
'actors': actors,
- 'library_title': item['section_name'],
+ 'library_name': item['section_name'],
'library_id': item['library_id']
}
return metadata
- def delete_session_history_rows(self, row_id=None):
+ def get_total_duration(self, custom_where=None):
monitor_db = database.MonitorDatabase()
- if row_id.isdigit():
- logger.info(u"PlexPy DataFactory :: Deleting row id %s from the session history database." % row_id)
- session_history_del = \
- monitor_db.action('DELETE FROM session_history WHERE id = ?', [row_id])
- session_history_media_info_del = \
- monitor_db.action('DELETE FROM session_history_media_info WHERE id = ?', [row_id])
- session_history_metadata_del = \
- monitor_db.action('DELETE FROM session_history_metadata WHERE id = ?', [row_id])
-
- return 'Deleted rows %s.' % row_id
+ # Split up custom wheres
+ if custom_where:
+ where = 'WHERE ' + ' AND '.join([w[0] + ' = "' + w[1] + '"' for w in custom_where])
else:
- return 'Unable to delete rows. Input row not valid.'
+ where = ''
+
+ try:
+ query = 'SELECT SUM(CASE WHEN stopped > 0 THEN (stopped - started) ELSE 0 END) - ' \
+ 'SUM(CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) AS total_duration ' \
+ 'FROM session_history ' \
+ 'JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
+ '%s ' % where
+ result = monitor_db.select(query)
+ except Exception as e:
+ logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_total_duration: %s." % e)
+ return None
- def delete_all_user_history(self, user_id=None):
+ for item in result:
+ total_duration = item['total_duration']
+
+ return total_duration
+
+ def get_session_ip(self, session_key=''):
monitor_db = database.MonitorDatabase()
- if user_id.isdigit():
- logger.info(u"PlexPy DataFactory :: Deleting all history for user id %s from database." % user_id)
- session_history_media_info_del = \
- monitor_db.action('DELETE FROM '
- 'session_history_media_info '
- 'WHERE session_history_media_info.id IN (SELECT session_history_media_info.id '
- 'FROM session_history_media_info '
- 'JOIN session_history ON session_history_media_info.id = session_history.id '
- 'WHERE session_history.user_id = ?)', [user_id])
- session_history_metadata_del = \
- monitor_db.action('DELETE FROM '
- 'session_history_metadata '
- 'WHERE session_history_metadata.id IN (SELECT session_history_metadata.id '
- 'FROM session_history_metadata '
- 'JOIN session_history ON session_history_metadata.id = session_history.id '
- 'WHERE session_history.user_id = ?)', [user_id])
- session_history_del = \
- monitor_db.action('DELETE FROM '
- 'session_history '
- 'WHERE session_history.user_id = ?', [user_id])
-
- return 'Deleted all items for user_id %s.' % user_id
+ if session_key:
+ query = 'SELECT ip_address FROM sessions WHERE session_key = %d' % int(session_key)
+ result = monitor_db.select(query)
else:
- return 'Unable to delete items. Input user_id not valid.'
+ return None
- def delete_user(self, user_id=None):
- monitor_db = database.MonitorDatabase()
+ ip_address = 'N/A'
- if user_id.isdigit():
- self.delete_all_user_history(user_id)
- logger.info(u"PlexPy DataFactory :: Deleting user with id %s from database." % user_id)
- monitor_db.action('UPDATE users SET deleted_user = 1 WHERE user_id = ?', [user_id])
- monitor_db.action('UPDATE users SET keep_history = 0 WHERE user_id = ?', [user_id])
- monitor_db.action('UPDATE users SET do_notify = 0 WHERE user_id = ?', [user_id])
+ for item in result:
+ ip_address = item['ip_address']
- return 'Deleted user with id %s.' % user_id
- else:
- return 'Unable to delete user. Input user_id not valid.'
-
- def undelete_user(self, user_id=None, username=None):
- monitor_db = database.MonitorDatabase()
-
- if user_id and user_id.isdigit():
- logger.info(u"PlexPy DataFactory :: Re-adding user with id %s to database." % user_id)
- monitor_db.action('UPDATE users SET deleted_user = 0 WHERE user_id = ?', [user_id])
- monitor_db.action('UPDATE users SET keep_history = 1 WHERE user_id = ?', [user_id])
- monitor_db.action('UPDATE users SET do_notify = 1 WHERE user_id = ?', [user_id])
-
- return 'Re-added user with id %s.' % user_id
- elif username:
- logger.info(u"PlexPy DataFactory :: Re-adding user with username %s to database." % username)
- monitor_db.action('UPDATE users SET deleted_user = 0 WHERE username = ?', [username])
- monitor_db.action('UPDATE users SET keep_history = 1 WHERE username = ?', [username])
- monitor_db.action('UPDATE users SET do_notify = 1 WHERE username = ?', [username])
-
- return 'Re-added user with username %s.' % username
- else:
- return 'Unable to re-add user. Input user_id or username not valid.'
+ return ip_address
def get_search_query(self, rating_key=''):
monitor_db = database.MonitorDatabase()
@@ -1037,8 +922,8 @@ class DataFactory(object):
grandparent_rating_key = result[0]['grandparent_rating_key']
- except:
- logger.warn("Unable to execute database query for get_rating_keys_list.")
+ except Exception as e:
+ logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_rating_keys_list: %s." % e)
return {}
query = 'SELECT rating_key, parent_rating_key, grandparent_rating_key, title, parent_title, grandparent_title, ' \
@@ -1081,6 +966,22 @@ class DataFactory(object):
return key_list
+ def delete_session_history_rows(self, row_id=None):
+ monitor_db = database.MonitorDatabase()
+
+ if row_id.isdigit():
+ logger.info(u"PlexPy DataFactory :: Deleting row id %s from the session history database." % row_id)
+ session_history_del = \
+ monitor_db.action('DELETE FROM session_history WHERE id = ?', [row_id])
+ session_history_media_info_del = \
+ monitor_db.action('DELETE FROM session_history_media_info WHERE id = ?', [row_id])
+ session_history_metadata_del = \
+ monitor_db.action('DELETE FROM session_history_metadata WHERE id = ?', [row_id])
+
+ return 'Deleted rows %s.' % row_id
+ else:
+ return 'Unable to delete rows. Input row not valid.'
+
def update_metadata(self, old_key_list='', new_key_list='', media_type=''):
from plexpy import pmsconnect
pms_connect = pmsconnect.PmsConnect()
@@ -1134,8 +1035,6 @@ class DataFactory(object):
return 'Updated metadata in database.'
else:
return 'Unable to update metadata in database. No changes were made.'
- # for debugging
- #return mapping
def update_metadata_details(self, old_rating_key='', new_rating_key='', metadata=None):
@@ -1176,31 +1075,6 @@ class DataFactory(object):
monitor_db.action(query=query, args=args)
- def get_total_duration(self, custom_where=None):
- monitor_db = database.MonitorDatabase()
-
- # Split up custom wheres
- if custom_where:
- where = 'WHERE ' + ' AND '.join([w[0] + ' = "' + w[1] + '"' for w in custom_where])
- else:
- where = ''
-
- try:
- query = 'SELECT SUM(CASE WHEN stopped > 0 THEN (stopped - started) ELSE 0 END) - ' \
- 'SUM(CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) AS total_duration ' \
- 'FROM session_history ' \
- 'JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
- '%s ' % where
- result = monitor_db.select(query)
- except:
- logger.warn("Unable to execute database query for get_total_duration.")
- return None
-
- for item in result:
- total_duration = item['total_duration']
-
- return total_duration
-
def update_library_ids(self):
from plexpy import pmsconnect
@@ -1210,8 +1084,8 @@ class DataFactory(object):
try:
query = 'SELECT id, rating_key FROM session_history_metadata WHERE library_id IS NULL'
result = monitor_db.select(query=query)
- except:
- logger.warn("Unable to execute database query for update_library_id.")
+ except Exception as e:
+ logger.warn(u"PlexPy DataFactory :: Unable to execute database query for update_library_id: %s." % e)
return None
for item in result:
@@ -1230,60 +1104,4 @@ class DataFactory(object):
else:
continue
- return True
-
- def get_library_sections(self):
- monitor_db = database.MonitorDatabase()
-
- try:
- query = 'SELECT section_id, section_name FROM library_sections'
- result = monitor_db.select(query=query)
- except:
- logger.warn("Unable to execute database query for get_library_sections.")
- return None
-
- libraries = []
- for item in result:
- library = {'section_id': item['section_id'],
- 'section_name': item['section_name']
- }
- libraries.append(library)
-
- return libraries
-
-
- def update_library_sections(self):
- from plexpy import pmsconnect
-
- pms_connect = pmsconnect.PmsConnect()
- library_sections = pms_connect.get_server_children()
-
- if library_sections:
- if library_sections['libraries_count'] != '0':
- monitor_db = database.MonitorDatabase()
-
- for section in library_sections['libraries_list']:
- section_keys = {'section_id': section['key']}
- section_values = {'section_id': section['key'],
- 'section_name': section['title'],
- 'section_type': section['type']}
-
- monitor_db.upsert('library_sections', key_dict=section_keys, value_dict=section_values)
-
- return True
-
- def get_session_ip(self, session_key=''):
- monitor_db = database.MonitorDatabase()
-
- if session_key:
- query = 'SELECT ip_address FROM sessions WHERE session_key = %d' % int(session_key)
- result = monitor_db.select(query)
- else:
- return None
-
- ip_address = 'N/A'
-
- for item in result:
- ip_address = item['ip_address']
-
- return ip_address
\ No newline at end of file
+ return True
\ No newline at end of file
diff --git a/plexpy/libraries.py b/plexpy/libraries.py
index 13202724..4af69ced 100644
--- a/plexpy/libraries.py
+++ b/plexpy/libraries.py
@@ -14,6 +14,7 @@
# along with PlexPy. If not, see
.
from plexpy import logger, datatables, common, database, helpers
+import plexpy
class Libraries(object):
@@ -21,22 +22,23 @@ class Libraries(object):
def __init__(self):
pass
- def get_library_list(self, kwargs=None):
+ def get_datatables_list(self, kwargs=None):
data_tables = datatables.DataTables()
+ custom_where = ['library_sections.deleted_section', 0]
+
columns = ['library_sections.section_id',
'library_sections.section_name',
'library_sections.section_type',
- 'library_sections.count as count',
+ 'library_sections.count',
'library_sections.parent_count',
'library_sections.child_count',
'library_sections.thumb AS library_thumb',
- '(CASE WHEN library_sections.custom_thumb_url == library_sections.thumb \
- THEN NULL ELSE custom_thumb_url END) AS custom_thumb',
+ 'library_sections.custom_thumb_url AS custom_thumb',
'library_sections.art',
- 'COUNT(session_history.id) as plays',
- 'MAX(session_history.started) as last_accessed',
- 'session_history_metadata.full_title as last_watched',
+ 'COUNT(session_history.id) AS plays',
+ 'MAX(session_history.started) AS last_accessed',
+ 'session_history_metadata.full_title AS last_watched',
'session_history_metadata.thumb',
'session_history_metadata.parent_thumb',
'session_history_metadata.grandparent_thumb',
@@ -44,12 +46,13 @@ class Libraries(object):
'session_history.rating_key',
'session_history_media_info.video_decision',
'library_sections.do_notify',
+ 'library_sections.do_notify_created',
'library_sections.keep_history'
]
try:
query = data_tables.ssp_query(table_name='library_sections',
columns=columns,
- custom_where=[],
+ custom_where=[custom_where],
group_by=['library_sections.section_id'],
join_types=['LEFT OUTER JOIN',
'LEFT OUTER JOIN',
@@ -61,8 +64,8 @@ class Libraries(object):
['session_history_metadata.id', 'session_history.id'],
['session_history_metadata.id', 'session_history_media_info.id']],
kwargs=kwargs)
- except:
- logger.warn("Unable to execute database query for get_library_list.")
+ except Exception as e:
+ logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_list: %s." % e)
return {'recordsFiltered': 0,
'recordsTotal': 0,
'draw': 0,
@@ -80,23 +83,30 @@ class Libraries(object):
else:
thumb = item['thumb']
- row = {'plays': item['plays'],
+ if item['custom_thumb'] and item['custom_thumb'] != item['library_thumb']:
+ library_thumb = item['custom_thumb']
+ elif item['library_thumb']:
+ library_thumb = item['library_thumb']
+ else:
+ library_thumb = common.DEFAULT_COVER_THUMB
+
+ row = {'section_id': item['section_id'],
+ 'section_name': item['section_name'],
+ 'section_type': item['section_type'].capitalize(),
+ 'count': item['count'],
+ 'parent_count': item['parent_count'],
+ 'child_count': item['child_count'],
+ 'library_thumb': library_thumb,
+ 'library_art': item['art'],
+ 'plays': item['plays'],
'last_accessed': item['last_accessed'],
'last_watched': item['last_watched'],
'thumb': thumb,
'media_type': item['media_type'],
'rating_key': item['rating_key'],
'video_decision': item['video_decision'],
- 'section_id': item['section_id'],
- 'section_name': item['section_name'],
- 'section_type': item['section_type'].capitalize(),
- 'count': item['count'],
- 'parent_count': item['parent_count'],
- 'library_thumb': item['library_thumb'],
- 'custom_thumb': item['custom_thumb'],
- 'library_art': item['art'],
- 'child_count': item['child_count'],
'do_notify': helpers.checked(item['do_notify']),
+ 'do_notify_created': helpers.checked(item['do_notify_created']),
'keep_history': helpers.checked(item['keep_history'])
}
@@ -110,123 +120,154 @@ class Libraries(object):
return dict
- def set_library_config(self, section_id=None, do_notify=1, keep_history=1, custom_thumb=''):
+ def set_config(self, section_id=None, custom_thumb='', do_notify=1, keep_history=1, do_notify_created=1):
if section_id:
monitor_db = database.MonitorDatabase()
key_dict = {'section_id': section_id}
- value_dict = {'do_notify': do_notify,
- 'keep_history': keep_history,
- 'custom_thumb_url': custom_thumb}
+ value_dict = {'custom_thumb_url': custom_thumb,
+ 'do_notify': do_notify,
+ 'do_notify_created': do_notify_created,
+ 'keep_history': keep_history}
try:
monitor_db.upsert('library_sections', value_dict, key_dict)
except:
- logger.warn("Unable to execute database query for set_user_friendly_name.")
+ logger.warn(u"PlexPy Libraries :: Unable to execute database query for set_config: %s." % e)
- def get_library_details(self, section_id=None):
+ def get_details(self, section_id=None):
from plexpy import pmsconnect
monitor_db = database.MonitorDatabase()
- if section_id:
- query = 'SELECT section_id, section_name, section_type, count, parent_count, child_count, ' \
- 'thumb AS library_thumb, (CASE WHEN library_sections.custom_thumb_url == library_sections.thumb ' \
- ' THEN NULL ELSE custom_thumb_url END) AS custom_thumb, art, do_notify, keep_history ' \
- 'FROM library_sections ' \
- 'WHERE section_id = ? '
- result = monitor_db.select(query, args=[section_id])
- else:
- result = None
+ try:
+ if section_id:
+ query = 'SELECT section_id, section_name, section_type, count, parent_count, child_count, ' \
+ 'thumb AS library_thumb, custom_thumb_url AS custom_thumb, art, ' \
+ 'do_notify, do_notify_created, keep_history ' \
+ 'FROM library_sections ' \
+ 'WHERE section_id = ? '
+ result = monitor_db.select(query, args=[section_id])
+ else:
+ result = []
+ except Exception as e:
+ logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_details: %s." % e)
+ result = []
if result:
library_details = {}
for item in result:
+ if item['custom_thumb'] and item['custom_thumb'] != item['library_thumb']:
+ library_thumb = item['custom_thumb']
+ elif item['library_thumb']:
+ library_thumb = item['library_thumb']
+ else:
+ library_thumb = common.DEFAULT_COVER_THUMB
+
library_details = {'section_id': item['section_id'],
'section_name': item['section_name'],
'section_type': item['section_type'],
- 'library_thumb': item['library_thumb'],
- 'custom_thumb': item['custom_thumb'],
+ 'library_thumb': library_thumb,
'library_art': item['art'],
'count': item['count'],
'parent_count': item['parent_count'],
'child_count': item['child_count'],
'do_notify': item['do_notify'],
+ 'do_notify_created': item['do_notify_created'],
'keep_history': item['keep_history']
}
return library_details
else:
- logger.warn(u"PlexPy :: Unable to retrieve library from local database. Requesting library list refresh.")
+ logger.warn(u"PlexPy Libraries :: Unable to retrieve library from local database. Requesting library list refresh.")
# Let's first refresh the user list to make sure the user isn't newly added and not in the db yet
- if section_id:
- # Refresh libraries
- pmsconnect.refresh_libraries()
- query = 'SELECT section_id, section_name, section_type, count, parent_count, child_count, ' \
- 'thumb AS library_thumb, (CASE WHEN library_sections.custom_thumb_url == library_sections.thumb ' \
- ' THEN NULL ELSE custom_thumb_url END) AS custom_thumb, art, do_notify, keep_history ' \
- 'FROM library_sections ' \
- 'WHERE section_id = ? '
- result = monitor_db.select(query, args=[section_id])
- else:
- result = None
+ try:
+ if section_id:
+ # Refresh libraries
+ pmsconnect.refresh_libraries()
+ query = 'SELECT section_id, section_name, section_type, count, parent_count, child_count, ' \
+ 'thumb AS library_thumb, custom_thumb_url AS custom_thumb, art, ' \
+ 'do_notify, do_notify_created, keep_history ' \
+ 'FROM library_sections ' \
+ 'WHERE section_id = ? '
+ result = monitor_db.select(query, args=[section_id])
+ else:
+ result = []
+ except:
+ logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_details: %s." % e)
+ result = []
if result:
library_details = {}
for item in result:
+ if item['custom_thumb'] and item['custom_thumb'] != item['library_thumb']:
+ library_thumb = item['custom_thumb']
+ elif item['library_thumb']:
+ library_thumb = item['library_thumb']
+ else:
+ library_thumb = common.DEFAULT_COVER_THUMB
library_details = {'section_id': item['section_id'],
'section_name': item['section_name'],
'section_type': item['section_type'],
- 'library_thumb': item['library_thumb'],
- 'custom_thumb': item['custom_thumb'],
+ 'library_thumb': library_thumb,
'library_art': item['art'],
'count': item['count'],
'parent_count': item['parent_count'],
'child_count': item['child_count'],
'do_notify': item['do_notify'],
+ 'do_notify_created': item['do_notify_created'],
'keep_history': item['keep_history']
}
- return user_details
+ return library_details
else:
# If there is no library data we must return something
# Use "Local" user to retain compatibility with PlexWatch database value
return {'section_id': None,
- 'section_name': '',
+ 'section_name': 'Local',
'section_type': '',
- 'library_thumb': '',
- 'custom_thumb': '',
+ 'library_thumb': common.DEFAULT_COVER_THUMB,
'library_art': '',
'count': 0,
'parent_count': 0,
'child_count': 0,
'do_notify': 0,
+ 'do_notify_created': 0,
'keep_history': 0
}
- def get_library_watch_time_stats(self, library_id=None):
+ def get_watch_time_stats(self, library_id=None):
monitor_db = database.MonitorDatabase()
time_queries = [1, 7, 30, 0]
library_watch_time_stats = []
for days in time_queries:
- if days > 0:
- if library_id:
- query = 'SELECT (SUM(stopped - started) - ' \
- 'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
- 'COUNT(session_history.id) AS total_plays ' \
- 'FROM session_history ' \
- 'JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
- 'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
- 'AND library_id = ?' % days
- result = monitor_db.select(query, args=[library_id])
- else:
- query = 'SELECT (SUM(stopped - started) - ' \
- 'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
- 'COUNT(session_history.id) AS total_plays ' \
- 'FROM session_history ' \
- 'JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
- 'WHERE library_id = ?'
- result = monitor_db.select(query, args=[library_id])
+ try:
+ if days > 0:
+ if str(library_id).isdigit():
+ query = 'SELECT (SUM(stopped - started) - ' \
+ 'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
+ 'COUNT(session_history.id) AS total_plays ' \
+ 'FROM session_history ' \
+ 'JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
+ 'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
+ 'AND library_id = ?' % days
+ result = monitor_db.select(query, args=[library_id])
+ else:
+ result = []
+ else:
+ if str(library_id).isdigit():
+ query = 'SELECT (SUM(stopped - started) - ' \
+ 'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
+ 'COUNT(session_history.id) AS total_plays ' \
+ 'FROM session_history ' \
+ 'JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
+ 'WHERE library_id = ?'
+ result = monitor_db.select(query, args=[library_id])
+ else:
+ result = []
+ except Exception as e:
+ logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_watch_time_stats: %s." % e)
+ result = []
for item in result:
if item['total_time']:
@@ -245,13 +286,13 @@ class Libraries(object):
return library_watch_time_stats
- def get_library_user_stats(self, library_id=None):
+ def get_user_stats(self, library_id=None):
monitor_db = database.MonitorDatabase()
user_stats = []
try:
- if library_id:
+ if str(library_id).isdigit():
query = 'SELECT (CASE WHEN users.friendly_name IS NULL THEN users.username ' \
'ELSE users.friendly_name END) AS user, users.user_id, users.thumb, COUNT(user) AS user_count ' \
'FROM session_history ' \
@@ -261,9 +302,11 @@ class Libraries(object):
'GROUP BY user ' \
'ORDER BY user_count DESC'
result = monitor_db.select(query, args=[library_id])
- except:
- logger.warn("Unable to execute database query for get_library_user_stats.")
- return None
+ else:
+ result = []
+ except Exception as e:
+ logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_user_stats: %s." % e)
+ result = []
for item in result:
row = {'user': item['user'],
@@ -275,30 +318,151 @@ class Libraries(object):
return user_stats
- def delete_all_library_history(self, section_id=None):
+ def get_recently_watched(self, library_id=None, limit='10'):
+ monitor_db = database.MonitorDatabase()
+ recently_watched = []
+
+ if not limit.isdigit():
+ limit = '10'
+
+ try:
+ if str(library_id).isdigit():
+ query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, session_history.parent_rating_key, ' \
+ 'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_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 library_id = ? ' \
+ 'GROUP BY (CASE WHEN session_history.media_type = "track" THEN session_history.parent_rating_key ' \
+ ' ELSE session_history.rating_key END) ' \
+ 'ORDER BY started DESC LIMIT ?'
+ result = monitor_db.select(query, args=[library_id, limit])
+ else:
+ result = []
+ except Exception as e:
+ logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_recently_watched: %s." % e)
+ result = []
+
+ for row in result:
+ if row['media_type'] == 'episode' and row['parent_thumb']:
+ thumb = row['parent_thumb']
+ elif row['media_type'] == 'episode':
+ thumb = row['grandparent_thumb']
+ else:
+ thumb = row['thumb']
+
+ recent_output = {'row_id': row['id'],
+ 'type': row['media_type'],
+ 'rating_key': row['rating_key'],
+ 'title': row['title'],
+ 'parent_title': row['parent_title'],
+ 'grandparent_title': row['grandparent_title'],
+ 'thumb': thumb,
+ 'media_index': row['media_index'],
+ 'parent_media_index': row['parent_media_index'],
+ 'year': row['year'],
+ 'time': row['started'],
+ 'user': row['user']
+ }
+ recently_watched.append(recent_output)
+
+ return recently_watched
+
+ def get_sections(self):
monitor_db = database.MonitorDatabase()
- if section_id.isdigit():
- logger.info(u"PlexPy Libraries :: Deleting all history for library id %s from database." % section_id)
- session_history_media_info_del = \
- monitor_db.action('DELETE FROM '
- 'session_history_media_info '
- 'WHERE session_history_media_info.id IN (SELECT session_history_media_info.id '
- 'FROM session_history_media_info '
- 'JOIN session_history_metadata ON session_history_media_info.id = session_history_metadata.id '
- 'WHERE session_history_metadata.library_id = ?)', [section_id])
- session_history_del = \
- monitor_db.action('DELETE FROM '
- 'session_history '
- 'WHERE session_history.id IN (SELECT session_history.id '
- 'FROM session_history '
- 'JOIN session_history_metadata ON session_history.id = session_history_metadata.id '
- 'WHERE session_history_metadata.library_id = ?)', [section_id])
- session_history_metadata_del = \
- monitor_db.action('DELETE FROM '
- 'session_history_metadata '
- 'WHERE session_history_metadata.library_id = ?', [section_id])
+ try:
+ query = 'SELECT section_id, section_name FROM library_sections WHERE deleted_section = 0'
+ result = monitor_db.select(query=query)
+ except Exception as e:
+ logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_sections: %s." % e)
+ return None
- return 'Deleted all items for library_id %s.' % section_id
- else:
- return 'Unable to delete items. Input library_id not valid.'
\ No newline at end of file
+ libraries = []
+ for item in result:
+ library = {'section_id': item['section_id'],
+ 'section_name': item['section_name']
+ }
+ libraries.append(library)
+
+ return libraries
+
+ def delete_all_history(self, section_id=None):
+ monitor_db = database.MonitorDatabase()
+
+ try:
+ if section_id.isdigit():
+ logger.info(u"PlexPy Libraries :: Deleting all history for library id %s from database." % section_id)
+ session_history_media_info_del = \
+ monitor_db.action('DELETE FROM '
+ 'session_history_media_info '
+ 'WHERE session_history_media_info.id IN (SELECT session_history_media_info.id '
+ 'FROM session_history_media_info '
+ 'JOIN session_history_metadata ON session_history_media_info.id = session_history_metadata.id '
+ 'WHERE session_history_metadata.library_id = ?)', [section_id])
+ session_history_del = \
+ monitor_db.action('DELETE FROM '
+ 'session_history '
+ 'WHERE session_history.id IN (SELECT session_history.id '
+ 'FROM session_history '
+ 'JOIN session_history_metadata ON session_history.id = session_history_metadata.id '
+ 'WHERE session_history_metadata.library_id = ?)', [section_id])
+ session_history_metadata_del = \
+ monitor_db.action('DELETE FROM '
+ 'session_history_metadata '
+ 'WHERE session_history_metadata.library_id = ?', [section_id])
+
+ return 'Deleted all items for section_id %s.' % section_id
+ else:
+ return 'Unable to delete items, section_id not valid.'
+ except Exception as e:
+ logger.warn(u"PlexPy Libraries :: Unable to execute database query for delete_all_history: %s." % e)
+
+ def delete(self, section_id=None):
+ monitor_db = database.MonitorDatabase()
+
+ try:
+ if section_id.isdigit():
+ self.delete_all_history(section_id)
+ logger.info(u"PlexPy Libraries :: Deleting library with id %s from database." % section_id)
+ monitor_db.action('UPDATE library_sections SET deleted_section = 1 WHERE section_id = ?', [section_id])
+ monitor_db.action('UPDATE library_sections SET keep_history = 0 WHERE section_id = ?', [section_id])
+ monitor_db.action('UPDATE library_sections SET do_notify = 0 WHERE section_id = ?', [section_id])
+ monitor_db.action('UPDATE library_sections SET do_notify_created = 0 WHERE section_id = ?', [section_id])
+
+ library_cards = plexpy.CONFIG.HOME_LIBRARY_CARDS
+ if section_id in library_cards:
+ library_cards.remove(section_id)
+ plexpy.CONFIG.__setattr__('HOME_LIBRARY_CARDS', library_cards)
+ plexpy.CONFIG.write()
+
+ return 'Deleted library with id %s.' % section_id
+ else:
+ return 'Unable to delete library, section_id not valid.'
+ except Exception as e:
+ logger.warn(u"PlexPy Libraries :: Unable to execute database query for delete: %s." % e)
+
+ def undelete(self, section_id=None, section_name=None):
+ monitor_db = database.MonitorDatabase()
+
+ try:
+ if section_id and section_id.isdigit():
+ logger.info(u"PlexPy Libraries :: Re-adding library with id %s to database." % section_id)
+ monitor_db.action('UPDATE library_sections SET deleted_section = 0 WHERE section_id = ?', [section_id])
+ monitor_db.action('UPDATE library_sections SET keep_history = 1 WHERE section_id = ?', [section_id])
+ monitor_db.action('UPDATE library_sections SET do_notify = 1 WHERE section_id = ?', [section_id])
+ monitor_db.action('UPDATE library_sections SET do_notify_created = 1 WHERE section_id = ?', [section_id])
+
+ return 'Re-added library with id %s.' % section_id
+ elif section_name:
+ logger.info(u"PlexPy Libraries :: Re-adding library with name %s to database." % section_name)
+ monitor_db.action('UPDATE library_sections SET deleted_section = 0 WHERE section_name = ?', [section_name])
+ monitor_db.action('UPDATE library_sections SET keep_history = 1 WHERE section_name = ?', [section_name])
+ monitor_db.action('UPDATE library_sections SET do_notify = 1 WHERE section_name = ?', [section_name])
+ monitor_db.action('UPDATE library_sections SET do_notify_created = 1 WHERE section_name = ?', [section_name])
+
+ return 'Re-added library with section_name %s.' % section_name
+ else:
+ return 'Unable to re-add library, section_id or section_name not valid.'
+ except Exception as e:
+ logger.warn(u"PlexPy Libraries :: Unable to execute database query for undelete: %s." % e)
\ No newline at end of file
diff --git a/plexpy/notification_handler.py b/plexpy/notification_handler.py
index ae722368..5c54b430 100644
--- a/plexpy/notification_handler.py
+++ b/plexpy/notification_handler.py
@@ -16,20 +16,28 @@
import re
import time
+import re
from plexpy import logger, config, notifiers, database, helpers, plextv, pmsconnect
import plexpy
def notify(stream_data=None, notify_action=None):
- from plexpy import users
-
+ from plexpy import users, libraries
+
if stream_data and notify_action:
- # Check if notifications enabled for user
+ # Check if notifications enabled for user and library
user_data = users.Users()
- user_details = user_data.get_user_friendly_name(user=stream_data['user'])
+ user_details = user_data.get_details(user_id=stream_data['user_id'])
+
+ library_data = libraries.Libraries()
+ library_details = library_data.get_details(section_id=stream_data['library_id'])
if not user_details['do_notify']:
+ # logger.debug(u"PlexPy NotificationHandler :: Notifications for user '%s' is disabled." % user_details['username'])
+ return
+ elif not library_details['do_notify']:
+ # logger.debug(u"PlexPy NotificationHandler :: Notifications for library '%s' is disabled." % library_details['section_name'])
return
if (stream_data['media_type'] == 'movie' and plexpy.CONFIG.MOVIE_NOTIFY_ENABLE) \
@@ -195,10 +203,10 @@ def notify(stream_data=None, notify_action=None):
elif stream_data['media_type'] == 'clip':
pass
else:
- #logger.debug(u"PlexPy Notifier :: Notify called with unsupported media type.")
+ #logger.debug(u"PlexPy NotificationHandler :: Notify called with unsupported media type.")
pass
else:
- logger.debug(u"PlexPy Notifier :: Notify called but incomplete data received.")
+ logger.debug(u"PlexPy NotificationHandler :: Notify called but incomplete data received.")
def notify_timeline(timeline_data=None, notify_action=None):
@@ -256,7 +264,7 @@ def notify_timeline(timeline_data=None, notify_action=None):
notify_action=notify_action,
script_args=notify_strings[2])
else:
- logger.debug(u"PlexPy Notifier :: Notify timeline called but incomplete data received.")
+ logger.debug(u"PlexPy NotificationHandler :: Notify timeline called but incomplete data received.")
def get_notify_state(session):
@@ -334,11 +342,10 @@ 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.')
+ logger.error(u"PlexPy NotificationHandler :: Unable to set notify state.")
def build_notify_text(session=None, timeline=None, state=None):
-
# Get the server name
server_name = plexpy.CONFIG.PMS_NAME
@@ -350,7 +357,7 @@ def build_notify_text(session=None, timeline=None, state=None):
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.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to retrieve server uptime.")
server_uptime = 'N/A'
# Get metadata feed for item
@@ -367,7 +374,7 @@ def build_notify_text(session=None, timeline=None, state=None):
if metadata_list:
metadata = metadata_list['metadata']
else:
- logger.error(u"PlexPy Notifier :: Unable to retrieve metadata for rating_key %s" % str(rating_key))
+ logger.error(u"PlexPy NotificationHandler :: Unable to retrieve metadata for rating_key %s" % str(rating_key))
return []
# Check for exclusion tags
@@ -547,15 +554,16 @@ def build_notify_text(session=None, timeline=None, state=None):
'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_index'].zfill(1),
- 'season_num00': metadata['parent_index'].zfill(2),
- 'episode_num': metadata['index'].zfill(1),
- 'episode_num00': metadata['index'].zfill(2),
+ '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'],
@@ -597,16 +605,16 @@ def build_notify_text(session=None, timeline=None, state=None):
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)
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
- logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = unicode(on_start_body).format(**available_params)
except LookupError, e:
- logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
except:
- logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text, script_args]
else:
@@ -621,16 +629,16 @@ def build_notify_text(session=None, timeline=None, state=None):
try:
subject_text = unicode(on_stop_subject).format(**available_params)
except LookupError, e:
- logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
- logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = unicode(on_stop_body).format(**available_params)
except LookupError, e:
- logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
except:
- logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text, script_args]
else:
@@ -645,16 +653,16 @@ def build_notify_text(session=None, timeline=None, state=None):
try:
subject_text = unicode(on_pause_subject).format(**available_params)
except LookupError, e:
- logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
- logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = unicode(on_pause_body).format(**available_params)
except LookupError, e:
- logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
except:
- logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text, script_args]
else:
@@ -669,16 +677,16 @@ def build_notify_text(session=None, timeline=None, state=None):
try:
subject_text = unicode(on_resume_subject).format(**available_params)
except LookupError, e:
- logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
- logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = unicode(on_resume_body).format(**available_params)
except LookupError, e:
- logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
except:
- logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text, script_args]
else:
@@ -693,16 +701,16 @@ def build_notify_text(session=None, timeline=None, state=None):
try:
subject_text = unicode(on_buffer_subject).format(**available_params)
except LookupError, e:
- logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
- logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = unicode(on_buffer_body).format(**available_params)
except LookupError, e:
- logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
except:
- logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text, script_args]
else:
@@ -717,16 +725,16 @@ def build_notify_text(session=None, timeline=None, state=None):
try:
subject_text = unicode(on_watched_subject).format(**available_params)
except LookupError, e:
- logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
- logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = unicode(on_watched_body).format(**available_params)
except LookupError, e:
- logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
except:
- logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text, script_args]
else:
@@ -739,16 +747,16 @@ def build_notify_text(session=None, timeline=None, state=None):
try:
subject_text = unicode(on_created_subject).format(**available_params)
except LookupError, e:
- logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
- logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = unicode(on_created_body).format(**available_params)
except LookupError, e:
- logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
except:
- logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text, script_args]
else:
@@ -769,7 +777,7 @@ def build_server_notify_text(state=None):
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.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to retrieve server uptime.")
server_uptime = 'N/A'
on_extdown_subject = plexpy.CONFIG.NOTIFY_ON_EXTDOWN_SUBJECT_TEXT
@@ -812,14 +820,14 @@ def build_server_notify_text(state=None):
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)
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
- logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = unicode(on_extdown_body).format(**available_params)
except LookupError, e:
- logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
@@ -835,16 +843,16 @@ def build_server_notify_text(state=None):
try:
subject_text = unicode(on_intdown_subject).format(**available_params)
except LookupError, e:
- logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
- logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = unicode(on_intdown_body).format(**available_params)
except LookupError, e:
- logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
except:
- logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text, script_args]
else:
@@ -857,16 +865,16 @@ def build_server_notify_text(state=None):
try:
subject_text = unicode(on_extup_subject).format(**available_params)
except LookupError, e:
- logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
- logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = unicode(on_extup_body).format(**available_params)
except LookupError, e:
- logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
except:
- logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text, script_args]
else:
@@ -879,16 +887,16 @@ def build_server_notify_text(state=None):
try:
subject_text = unicode(on_intup_subject).format(**available_params)
except LookupError, e:
- logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
- logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = unicode(on_intup_body).format(**available_params)
except LookupError, e:
- logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
except:
- logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
+ logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text, script_args]
else:
@@ -899,7 +907,5 @@ def build_server_notify_text(state=None):
def strip_tag(data):
- import re
-
p = re.compile(r'<.*?>')
return p.sub('', data)
diff --git a/plexpy/notifiers.py b/plexpy/notifiers.py
index f9c89903..d9dd7b83 100644
--- a/plexpy/notifiers.py
+++ b/plexpy/notifiers.py
@@ -525,10 +525,10 @@ class GROWL(object):
try:
growl.register()
except gntp.notifier.errors.NetworkError:
- logger.warning(u'Growl notification failed: network error')
+ logger.warn(u"PlexPy Notifier :: Growl notification failed: network error")
return
except gntp.notifier.errors.AuthError:
- logger.warning(u'Growl notification failed: authentication error')
+ logger.warn(u"PlexPy Notifier :: Growl notification failed: authentication error")
return
# Fix message
@@ -548,11 +548,11 @@ class GROWL(object):
description=message,
icon=image
)
+ logger.info(u"PlexPy Notifier :: Growl notification sent.")
except gntp.notifier.errors.NetworkError:
- logger.warning(u'Growl notification failed: network error')
+ logger.warn(u"PlexPy Notifier :: Growl notification failed: network error")
return
- logger.info(u"Growl notifications sent.")
def updateLibrary(self):
# For uniformity reasons not removed
@@ -617,14 +617,14 @@ class PROWL(object):
request_status = response.status
if request_status == 200:
- logger.info(u"Prowl notifications sent.")
- return True
+ logger.info(u"PlexPy Notifier :: Prowl notification sent.")
+ return True
elif request_status == 401:
- logger.info(u"Prowl auth failed: %s" % response.reason)
- return False
+ logger.warn(u"PlexPy Notifier :: Prowl notification failed: %s" % response.reason)
+ return False
else:
- logger.info(u"Prowl notification failed.")
- return False
+ logger.warn(u"PlexPy Notifier :: Prowl notification failed.")
+ return False
def updateLibrary(self):
# For uniformity reasons not removed
@@ -698,7 +698,7 @@ class XBMC(object):
time = "3000" # in ms
for host in hosts:
- logger.info('Sending notification command to XMBC @ ' + host)
+ logger.info(u"PlexPy Notifier :: Sending notification command to XMBC @ " + host)
try:
version = self._sendjson(host, 'Application.GetProperties', {'properties': ['version']})['version']['major']
@@ -713,15 +713,17 @@ class XBMC(object):
if not request:
raise Exception
+ else:
+ logger.info(u"PlexPy Notifier :: XBMC notification sent.")
except Exception:
- logger.error('Error sending notification request to XBMC')
+ logger.warn(u"PlexPy Notifier :: XBMC notification filed.")
def return_config_options(self):
config_option = [{'label': 'XBMC Host:Port',
'value': self.hosts,
'name': 'xbmc_host',
- 'description': 'Host running XBMC (e.g. http://localhost:8080). Separate multiple hosts with commas.',
+ 'description': 'Host running XBMC (e.g. http://localhost:8080). Separate multiple hosts with commas (,).',
'input_type': 'text'
},
{'label': 'XBMC Username',
@@ -763,12 +765,12 @@ class Plex(object):
base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '')
req.add_header("Authorization", "Basic %s" % base64string)
- logger.info('Plex url: %s' % url)
+ # logger.info(u"PlexPy Notifier :: Plex url: %s" % url)
try:
handle = urllib2.urlopen(req)
except Exception as e:
- logger.warn('Error opening Plex url: %s' % e)
+ logger.error(u"PlexPy Notifier :: Error opening Plex url: %s" % e)
return
response = handle.read().decode(plexpy.SYS_ENCODING)
@@ -784,7 +786,7 @@ class Plex(object):
time = "3000" # in ms
for host in hosts:
- logger.info('Sending notification command to Plex Media Server @ ' + host)
+ logger.info(u"PlexPy Notifier :: Sending notification command to Plex Media Server @ " + host)
try:
notification = header + "," + message + "," + time
notifycommand = {'command': 'ExecBuiltIn', 'parameter': 'Notification(' + notification + ')'}
@@ -792,9 +794,11 @@ class Plex(object):
if not request:
raise Exception
+ else:
+ logger.info(u"PlexPy Notifier :: Plex notification sent.")
except:
- logger.warn('Error sending notification request to Plex Media Server')
+ logger.warn(u"PlexPy Notifier :: Plex notification failed.")
def return_config_options(self):
config_option = [{'label': 'Plex Client Host:Port',
@@ -855,9 +859,10 @@ class NMA(object):
response = p.push(title, event, message, priority=nma_priority, batch_mode=batch)
if not response[api][u'code'] == u'200':
- logger.error(u'Could not send notification to NotifyMyAndroid')
+ logger.warn(u"PlexPy Notifier :: NotifyMyAndroid notification failed.")
return False
else:
+ logger.info(u"PlexPy Notifier :: NotifyMyAndroid notification sent.")
return True
def return_config_options(self):
@@ -918,14 +923,14 @@ class PUSHBULLET(object):
# logger.debug(u"PushBullet response body: %r" % response.read())
if request_status == 200:
- logger.info(u"PushBullet notifications sent.")
- return True
+ logger.info(u"PlexPy Notifier :: PushBullet notification sent.")
+ return True
elif request_status >= 400 and request_status < 500:
- logger.info(u"PushBullet request failed: %s" % response.reason)
- return False
+ logger.warn(u"PlexPy Notifier :: PushBullet notification failed: %s" % response.reason)
+ return False
else:
- logger.info(u"PushBullet notification failed serverside.")
- return False
+ logger.warn(u"PlexPy Notifier :: PushBullet notification failed.")
+ return False
def test(self, apikey, deviceid):
@@ -952,10 +957,10 @@ class PUSHBULLET(object):
devices.update({'': ''})
return devices
elif request_status >= 400 and request_status < 500:
- logger.info(u"Unable to retrieve Pushbullet devices list: %s" % response.reason)
+ logger.warn(u"PlexPy Notifier :: Unable to retrieve Pushbullet devices list: %s" % response.reason)
return {'': ''}
else:
- logger.info(u"Unable to retrieve Pushbullet devices list.")
+ logger.warn(u"PlexPy Notifier :: Unable to retrieve Pushbullet devices list.")
return {'': ''}
else:
@@ -1020,14 +1025,14 @@ class PUSHALOT(object):
# logger.debug(u"Pushalot response body: %r" % response.read())
if request_status == 200:
- logger.info(u"Pushalot notifications sent.")
- return True
+ logger.info(u"PlexPy Notifier :: Pushalot notification sent.")
+ return True
elif request_status == 410:
- logger.info(u"Pushalot auth failed: %s" % response.reason)
- return False
+ logger.warn(u"PlexPy Notifier :: Pushalot notification failed: %s" % response.reason)
+ return False
else:
- logger.info(u"Pushalot notification failed.")
- return False
+ logger.warn(u"PlexPy Notifier :: Pushalot notification failed.")
+ return False
def return_config_options(self):
config_option = [{'label': 'Pushalot API Key',
@@ -1077,14 +1082,14 @@ class PUSHOVER(object):
# logger.debug(u"Pushover response body: %r" % response.read())
if request_status == 200:
- logger.info(u"Pushover notifications sent.")
- return True
+ logger.info(u"PlexPy Notifier :: Pushover notification sent.")
+ return True
elif request_status >= 400 and request_status < 500:
- logger.info(u"Pushover request failed: %s" % response.reason)
- return False
+ logger.warn(u"PlexPy Notifier :: Pushover notification failed: %s" % response.reason)
+ return False
else:
- logger.info(u"Pushover notification failed.")
- return False
+ logger.warn(u"PlexPy Notifier :: Pushover notification failed.")
+ return False
def updateLibrary(self):
# For uniformity reasons not removed
@@ -1111,10 +1116,10 @@ class PUSHOVER(object):
sounds.update({'': ''})
return sounds
elif request_status >= 400 and request_status < 500:
- logger.info(u"Unable to retrieve Pushover notification sounds list: %s" % response.reason)
+ logger.warn(u"PlexPy Notifier :: Unable to retrieve Pushover notification sounds list: %s" % response.reason)
return {'': ''}
else:
- logger.info(u"Unable to retrieve Pushover notification sounds list.")
+ logger.warn(u"PlexPy Notifier :: Unable to retrieve Pushover notification sounds list.")
return {'': ''}
else:
@@ -1177,12 +1182,12 @@ class TwitterNotifier(object):
oauth_consumer = oauth.Consumer(key=self.consumer_key, secret=self.consumer_secret)
oauth_client = oauth.Client(oauth_consumer)
- logger.info('Requesting temp token from Twitter')
+ logger.info("PlexPy Notifier :: Requesting temp token from Twitter")
resp, content = oauth_client.request(self.REQUEST_TOKEN_URL, 'GET')
if resp['status'] != '200':
- logger.info('Invalid respond from Twitter requesting temp token: %s' % resp['status'])
+ logger.warn("PlexPy Notifier :: Invalid respond from Twitter requesting temp token: %s" % resp['status'])
else:
request_token = dict(parse_qsl(content))
@@ -1201,25 +1206,25 @@ class TwitterNotifier(object):
token = oauth.Token(request_token['oauth_token'], request_token['oauth_token_secret'])
token.set_verifier(key)
- logger.info('Generating and signing request for an access token using key ' + key)
+ # logger.debug(u"Generating and signing request for an access token using key " + key)
oauth_consumer = oauth.Consumer(key=self.consumer_key, secret=self.consumer_secret)
- # logger.debug('oauth_consumer: ' + str(oauth_consumer))
+ # logger.debug(u"oauth_consumer: " + str(oauth_consumer))
oauth_client = oauth.Client(oauth_consumer, token)
- # logger.info('oauth_client: ' + str(oauth_client))
+ # logger.debug(u"oauth_client: " + str(oauth_client))
resp, content = oauth_client.request(self.ACCESS_TOKEN_URL, method='POST', body='oauth_verifier=%s' % key)
- # logger.info('resp, content: ' + str(resp) + ',' + str(content))
+ # logger.debug(u"resp, content: " + str(resp) + ',' + str(content))
access_token = dict(parse_qsl(content))
- # logger.info('access_token: ' + str(access_token))
+ # logger.debug(u"access_token: " + str(access_token))
- # logger.info('resp[status] = ' + str(resp['status']))
+ # logger.debug(u"resp[status] = " + str(resp['status']))
if resp['status'] != '200':
- logger.info('The request for a token with did not succeed: ' + str(resp['status']), logger.ERROR)
+ logger.error(u"PlexPy Notifier :: The request for a Twitter token did not succeed: " + str(resp['status']), logger.ERROR)
return False
else:
- logger.info('Your Twitter Access Token key: %s' % access_token['oauth_token'])
- logger.info('Access Token secret: %s' % access_token['oauth_token_secret'])
+ # logger.info(u"PlexPy Notifier :: Your Twitter Access Token key: %s" % access_token['oauth_token'])
+ # logger.info(u"PlexPy Notifier :: Access Token secret: %s" % access_token['oauth_token_secret'])
plexpy.CONFIG.TWITTER_USERNAME = access_token['oauth_token']
plexpy.CONFIG.TWITTER_PASSWORD = access_token['oauth_token_secret']
plexpy.CONFIG.write()
@@ -1231,15 +1236,15 @@ class TwitterNotifier(object):
access_token_key = plexpy.CONFIG.TWITTER_USERNAME
access_token_secret = plexpy.CONFIG.TWITTER_PASSWORD
- # logger.info(u"Sending tweet: " + message)
+ # logger.info(u"PlexPy Notifier :: Sending tweet: " + message)
api = twitter.Api(username, password, access_token_key, access_token_secret)
try:
api.PostUpdate(message)
- logger.info(u"Twitter notifications sent.")
+ logger.info(u"PlexPy Notifier :: Twitter notification sent")
except Exception as e:
- logger.info(u"Error sending Tweet: %s" % e)
+ logger.warn(u"PlexPy Notifier :: Twitter notification failed: %s" % e)
return False
return True
@@ -1335,13 +1340,13 @@ class OSX_NOTIFY(object):
notification_center = NSUserNotificationCenter.defaultUserNotificationCenter()
notification_center.deliverNotification_(notification)
- logger.info(u"OSX Notify notifications sent.")
+ logger.info(u"PlexPy Notifier :: OSX Notify notification sent.")
del pool
return True
except Exception as e:
- logger.warn('Error sending OS X Notification: %s' % e)
+ logger.warn(u"PlexPy Notifier :: OSX notification failed: %s" % e)
return False
def swizzled_bundleIdentifier(self, original, swizzled):
@@ -1382,13 +1387,47 @@ class BOXCAR(object):
req = urllib2.Request(self.url)
handle = urllib2.urlopen(req, data)
handle.close()
- logger.info(u"Boxcar2 notifications sent.")
+ logger.info(u"PlexPy Notifier :: Boxcar2 notification sent.")
return True
except urllib2.URLError as e:
- logger.warn('Error sending Boxcar2 Notification: %s' % e)
+ logger.warn(u"PlexPy Notifier :: Boxcar2 notification failed: %s" % e)
return False
+ def get_sounds(self):
+ sounds = {'': '',
+ 'beep-crisp': 'Beep (Crisp)',
+ 'beep-soft': 'Beep (Soft)',
+ 'bell-modern': 'Bell (Modern)',
+ 'bell-one-tone': 'Bell (One Tone)',
+ 'bell-simple': 'Bell (Simple)',
+ 'bell-triple': 'Bell (Triple)',
+ 'bird-1': 'Bird (1)',
+ 'bird-2': 'Bird (2)',
+ 'boing': 'Boing',
+ 'cash': 'Cash',
+ 'clanging': 'Clanging',
+ 'detonator-charge': 'Detonator Charge',
+ 'digital-alarm': 'Digital Alarm',
+ 'done': 'Done',
+ 'echo': 'Echo',
+ 'flourish': 'Flourish',
+ 'harp': 'Harp',
+ 'light': 'Light',
+ 'magic-chime':'Magic Chime',
+ 'magic-coin': 'Magic Coin',
+ 'no-sound': 'No Sound',
+ 'notifier-1': 'Notifier (1)',
+ 'notifier-2': 'Notifier (2)',
+ 'notifier-3': 'Notifier (3)',
+ 'orchestral-long': 'Orchestral (Long)',
+ 'orchestral-short': 'Orchestral (Short)',
+ 'score': 'Score',
+ 'success': 'Success',
+ 'up': 'Up'}
+
+ return sounds
+
def return_config_options(self):
config_option = [{'label': 'Boxcar Access Token',
'value': plexpy.CONFIG.BOXCAR_TOKEN,
@@ -1401,36 +1440,7 @@ class BOXCAR(object):
'name': 'boxcar_sound',
'description': 'Set the notification sound. Leave blank for the default sound.',
'input_type': 'select',
- 'select_options': {'': '',
- 'beep-crisp': 'Beep (Crisp)',
- 'beep-soft': 'Beep (Soft)',
- 'bell-modern': 'Bell (Modern)',
- 'bell-one-tone': 'Bell (One Tone)',
- 'bell-simple': 'Bell (Simple)',
- 'bell-triple': 'Bell (Triple)',
- 'bird-1': 'Bird (1)',
- 'bird-2': 'Bird (2)',
- 'boing': 'Boing',
- 'cash': 'Cash',
- 'clanging': 'Clanging',
- 'detonator-charge': 'Detonator Charge',
- 'digital-alarm': 'Digital Alarm',
- 'done': 'Done',
- 'echo': 'Echo',
- 'flourish': 'Flourish',
- 'harp': 'Harp',
- 'light': 'Light',
- 'magic-chime': 'Magic Chime',
- 'magic-coin': 'Magic Coin',
- 'no-sound': 'No Sound',
- 'notifier-1': 'Notifier (1)',
- 'notifier-2': 'Notifier (2)',
- 'notifier-3': 'Notifier (3)',
- 'orchestral-long': 'Orchestral (Long)',
- 'orchestral-short': 'Orchestral (Short)',
- 'score': 'Score',
- 'success': 'Success',
- 'up': 'Up'}
+ 'select_options': self.get_sounds()
}
]
@@ -1471,11 +1481,11 @@ class Email(object):
mailserver.sendmail(plexpy.CONFIG.EMAIL_FROM, recipients, message.as_string())
mailserver.quit()
- logger.info(u"Email notifications sent.")
+ logger.info(u"PlexPy Notifier :: Email notification sent.")
return True
- except Exception, e:
- logger.warn('Error sending Email: %s' % e)
+ except Exception as e:
+ logger.warn(u"PlexPy Notifier :: Email notification failed: %s" % e)
return False
def return_config_options(self):
@@ -1558,7 +1568,7 @@ class IFTTT(object):
data = {'value1': subject.encode("utf-8"),
'value2': message.encode("utf-8")}
- # logger.debug("Ifttt SENDING: %s" % json.dumps(data))
+ # logger.debug(u"Ifttt SENDING: %s" % json.dumps(data))
http_handler.request("POST",
"/trigger/%s/with/key/%s" % (self.event, self.apikey),
@@ -1571,14 +1581,14 @@ class IFTTT(object):
# logger.debug(u"Ifttt response body: %r" % response.read())
if request_status == 200:
- logger.info(u"Ifttt notifications sent.")
- return True
+ logger.info(u"PlexPy Notifier :: Ifttt notification sent.")
+ return True
elif request_status >= 400 and request_status < 500:
- logger.info(u"Ifttt request failed: %s" % response.reason)
- return False
+ logger.warn(u"PlexPy Notifier :: Ifttt notification failed: %s" % response.reason)
+ return False
else:
- logger.info(u"Ifttt notification failed serverside.")
- return False
+ logger.warn(u"PlexPy Notifier :: Ifttt notification failed.")
+ return False
def test(self):
return self.notify('PlexPy', 'Test Message')
@@ -1631,14 +1641,14 @@ class TELEGRAM(object):
request_status = response.status
if request_status == 200:
- logger.info(u"Telegram notifications sent.")
- return True
+ logger.info(u"PlexPy Notifier :: Telegram notification sent.")
+ return True
elif request_status >= 400 and request_status < 500:
- logger.info(u"Telegram request failed: %s" % response.reason)
- return False
+ logger.warn(u"PlexPy Notifier :: Telegram notification failed: %s" % response.reason)
+ return False
else:
- logger.info(u"Telegram notification failed serverside.")
- return False
+ logger.warn(u"PlexPy Notifier :: Telegram notification failed.")
+ return False
def updateLibrary(self):
# For uniformity reasons not removed
@@ -1708,14 +1718,14 @@ class SLACK(object):
request_status = response.status
if request_status == 200:
- logger.info(u"Slack notifications sent.")
- return True
+ logger.info(u"PlexPy Notifier :: Slack notification sent.")
+ return True
elif request_status >= 400 and request_status < 500:
- logger.info(u"Slack request failed: %s" % response.reason)
- return False
+ logger.warn(u"PlexPy Notifier :: Slack notification failed: %s" % response.reason)
+ return False
else:
- logger.info(u"Slack notification failed serverside.")
- return False
+ logger.warn(u"PlexPy Notifier :: Slack notification failed.")
+ return False
def updateLibrary(self):
#For uniformity reasons not removed
diff --git a/plexpy/plextv.py b/plexpy/plextv.py
index 2dc92486..5d8c8000 100644
--- a/plexpy/plextv.py
+++ b/plexpy/plextv.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with PlexPy. If not, see
.
-from plexpy import logger, helpers, users, http_handler, database
+from plexpy import logger, helpers, http_handler, database, users
import xmltodict
import json
from xml.dom import minidom
@@ -26,7 +26,7 @@ import plexpy
def refresh_users():
- logger.info("Requesting users list refresh...")
+ logger.info(u"PlexPy PlexTV :: Requesting users list refresh...")
result = PlexTV().get_full_users_list()
monitor_db = database.MonitorDatabase()
@@ -55,13 +55,13 @@ def refresh_users():
monitor_db.upsert('users', new_value_dict, control_value_dict)
- logger.info("Users list refreshed.")
+ logger.info(u"PlexPy PlexTV :: Users list refreshed.")
else:
- logger.warn("Unable to refresh users list.")
+ logger.warn(u"PlexPy PlexTV :: Unable to refresh users list.")
def get_real_pms_url():
- logger.info("Requesting URLs for server...")
+ logger.info(u"PlexPy PlexTV :: Requesting URLs for server...")
# Reset any current PMS_URL value
plexpy.CONFIG.__setattr__('PMS_URL', '')
@@ -85,15 +85,15 @@ def get_real_pms_url():
if plexpy.CONFIG.PMS_IS_REMOTE and item['local'] == '0':
plexpy.CONFIG.__setattr__('PMS_URL', item['uri'])
plexpy.CONFIG.write()
- logger.info("Server URL retrieved.")
+ logger.info(u"PlexPy PlexTV :: Server URL retrieved.")
if not plexpy.CONFIG.PMS_IS_REMOTE and item['local'] == '1':
plexpy.CONFIG.__setattr__('PMS_URL', item['uri'])
plexpy.CONFIG.write()
- logger.info("Server URL retrieved.")
+ logger.info(u"PlexPy PlexTV :: Server URL retrieved.")
else:
plexpy.CONFIG.__setattr__('PMS_URL', fallback_url)
plexpy.CONFIG.write()
- logger.warn("Unable to retrieve server URLs. Using user-defined value.")
+ logger.warn(u"PlexPy PlexTV :: Unable to retrieve server URLs. Using user-defined value.")
else:
plexpy.CONFIG.__setattr__('PMS_URL', fallback_url)
plexpy.CONFIG.write()
@@ -213,7 +213,7 @@ class PlexTV(object):
try:
xml_parse = minidom.parseString(own_account)
- except Exception, e:
+ except Exception as e:
logger.warn("Error parsing XML for Plex account details: %s" % e)
return []
except:
@@ -238,7 +238,7 @@ class PlexTV(object):
try:
xml_parse = minidom.parseString(friends_list)
- except Exception, e:
+ except Exception as e:
logger.warn("Error parsing XML for Plex friends list: %s" % e)
except:
logger.warn("Error parsing XML for Plex friends list.")
@@ -269,7 +269,7 @@ class PlexTV(object):
try:
xml_parse = minidom.parseString(sync_list)
- except Exception, e:
+ except Exception as e:
logger.warn("Error parsing XML for Plex sync lists: %s" % e)
return []
except:
@@ -383,7 +383,7 @@ class PlexTV(object):
try:
xml_parse = minidom.parseString(plextv_resources)
- except Exception, e:
+ except Exception as e:
logger.warn("Error parsing XML for Plex resources: %s" % e)
return []
except:
@@ -430,6 +430,25 @@ class PlexTV(object):
return server_urls
+ def get_server_times(self):
+ servers = self.get_plextv_server_list(output_format='xml')
+ server_times = []
+
+ try:
+ xml_head = servers.getElementsByTagName('Server')
+ except:
+ logger.warn("Error parsing XML for Plex servers.")
+ return []
+
+ for a in xml_head:
+ if helpers.get_xml_attr(a, 'machineIdentifier') == plexpy.CONFIG.PMS_IDENTIFIER:
+ server_times.append({"created_at": helpers.get_xml_attr(a, 'createdAt'),
+ "updated_at": helpers.get_xml_attr(a, 'updatedAt')
+ })
+ break
+
+ return server_times
+
def discover(self):
""" Query plex for all servers online. Returns the ones you own in a selectize format """
result = self.get_plextv_resources(include_https=True, output_format='raw')
@@ -463,23 +482,4 @@ class PlexTV(object):
logger.warn('Failed to get servers from plex %s' % e)
return clean_servers
- return json.dumps(clean_servers, indent=4)
-
- def get_server_times(self):
- servers = self.get_plextv_server_list(output_format='xml')
- server_times = []
-
- try:
- xml_head = servers.getElementsByTagName('Server')
- except:
- logger.warn("Error parsing XML for Plex servers.")
- return []
-
- for a in xml_head:
- if helpers.get_xml_attr(a, 'machineIdentifier') == plexpy.CONFIG.PMS_IDENTIFIER:
- server_times.append({"created_at": helpers.get_xml_attr(a, 'createdAt'),
- "updated_at": helpers.get_xml_attr(a, 'updatedAt')
- })
- break
-
- return server_times
\ No newline at end of file
+ return json.dumps(clean_servers, indent=4)
\ No newline at end of file
diff --git a/plexpy/plexwatch_import.py b/plexpy/plexwatch_import.py
index e586933a..6959a559 100644
--- a/plexpy/plexwatch_import.py
+++ b/plexpy/plexwatch_import.py
@@ -26,12 +26,12 @@ def extract_plexwatch_xml(xml=None):
try:
xml_parse = minidom.parseString(clean_xml)
except:
- logger.warn("Error parsing XML for Plexwatch database.")
+ logger.warn(u"PlexPy Importer :: Error parsing XML for Plexwatch database.")
return None
xml_head = xml_parse.getElementsByTagName('opt')
if not xml_head:
- logger.warn("Error parsing XML for Plexwatch database.")
+ logger.warn(u"PlexPy Importer :: Error parsing XML for Plexwatch database.")
return None
for a in xml_head:
@@ -205,23 +205,23 @@ def validate_database(database=None, table_name=None):
try:
connection = sqlite3.connect(database, timeout=20)
except sqlite3.OperationalError:
- logger.error('PlexPy Importer :: Invalid database specified.')
+ logger.error(u"PlexPy Importer :: Invalid database specified.")
return 'Invalid database specified.'
except ValueError:
- logger.error('PlexPy Importer :: Invalid database specified.')
+ logger.error(u"PlexPy Importer :: Invalid database specified.")
return 'Invalid database specified.'
except:
- logger.error('PlexPy Importer :: Uncaught exception.')
+ logger.error(u"PlexPy Importer :: Uncaught exception.")
return 'Uncaught exception.'
try:
connection.execute('SELECT ratingKey from %s' % table_name)
connection.close()
except sqlite3.OperationalError:
- logger.error('PlexPy Importer :: Invalid database specified.')
+ logger.error(u"PlexPy Importer :: Invalid database specified.")
return 'Invalid database specified.'
except:
- logger.error('PlexPy Importer :: Uncaught exception.')
+ logger.error(u"PlexPy Importer :: Uncaught exception.")
return 'Uncaught exception.'
return 'success'
@@ -232,16 +232,16 @@ def import_from_plexwatch(database=None, table_name=None, import_ignore_interval
connection = sqlite3.connect(database, timeout=20)
connection.row_factory = sqlite3.Row
except sqlite3.OperationalError:
- logger.error('PlexPy Importer :: Invalid filename.')
+ logger.error(u"PlexPy Importer :: Invalid filename.")
return None
except ValueError:
- logger.error('PlexPy Importer :: Invalid filename.')
+ logger.error(u"PlexPy Importer :: Invalid filename.")
return None
try:
connection.execute('SELECT ratingKey from %s' % table_name)
except sqlite3.OperationalError:
- logger.error('PlexPy Importer :: Database specified does not contain the required fields.')
+ logger.error(u"PlexPy Importer :: Database specified does not contain the required fields.")
return None
logger.debug(u"PlexPy Importer :: PlexWatch data import in progress...")
diff --git a/plexpy/pmsconnect.py b/plexpy/pmsconnect.py
index 79dc1837..2df59007 100644
--- a/plexpy/pmsconnect.py
+++ b/plexpy/pmsconnect.py
@@ -20,7 +20,7 @@ import plexpy
import urllib2
def get_server_friendly_name():
- logger.info("Requesting name from server...")
+ logger.info(u"PlexPy Pmsconnect :: Requesting name from server...")
server_name = PmsConnect().get_server_pref(pref='FriendlyName')
# If friendly name is blank
@@ -34,11 +34,12 @@ def get_server_friendly_name():
if server_name and server_name != plexpy.CONFIG.PMS_NAME:
plexpy.CONFIG.__setattr__('PMS_NAME', server_name)
plexpy.CONFIG.write()
+ logger.info(u"PlexPy Pmsconnect :: Server name retrieved.")
return server_name
def refresh_libraries():
- logger.info("Requesting libraries list refresh...")
+ logger.info(u"PlexPy Pmsconnect :: Requesting libraries list refresh...")
library_sections = PmsConnect().get_library_details()
server_id = plexpy.CONFIG.PMS_IDENTIFIER
@@ -48,7 +49,7 @@ def refresh_libraries():
else:
populate_cards = False
- cards = []
+ library_keys = []
if library_sections:
monitor_db = database.MonitorDatabase()
@@ -64,20 +65,21 @@ def refresh_libraries():
'art': section['art'],
'count': section['count'],
'parent_count': section.get('parent_count', None),
- 'child_count': section.get('child_count', None)
+ 'child_count': section.get('child_count', None),
}
monitor_db.upsert('library_sections', key_dict=section_keys, value_dict=section_values)
- cards.append(section['key'])
+ library_keys.append(section['key'])
+
if populate_cards:
- plexpy.CONFIG.__setattr__('HOME_LIBRARY_CARDS', cards)
+ plexpy.CONFIG.__setattr__('HOME_LIBRARY_CARDS', library_keys)
plexpy.CONFIG.write()
- logger.info("Libraries list refreshed.")
+ logger.info(u"PlexPy Pmsconnect :: Libraries list refreshed.")
else:
- logger.warn("Unable to refresh libraries list.")
+ logger.warn(u"PlexPy Pmsconnect :: Unable to refresh libraries list.")
class PmsConnect(object):
@@ -100,14 +102,14 @@ class PmsConnect(object):
port=port,
token=plexpy.CONFIG.PMS_TOKEN)
- """
- Return current sessions.
-
- Optional parameters: output_format { dict, json }
-
- Output: array
- """
def get_sessions(self, output_format=''):
+ """
+ Return current sessions.
+
+ Optional parameters: output_format { dict, json }
+
+ Output: array
+ """
uri = '/status/sessions'
request = self.request_handler.make_request(uri=uri,
proto=self.protocol,
@@ -116,15 +118,15 @@ class PmsConnect(object):
return request
- """
- Return metadata for request item.
-
- Parameters required: rating_key { Plex ratingKey }
- Optional parameters: output_format { dict, json }
-
- Output: array
- """
def get_metadata(self, rating_key='', output_format=''):
+ """
+ Return metadata for request item.
+
+ Parameters required: rating_key { Plex ratingKey }
+ Optional parameters: output_format { dict, json }
+
+ Output: array
+ """
uri = '/library/metadata/' + rating_key
request = self.request_handler.make_request(uri=uri,
proto=self.protocol,
@@ -133,15 +135,15 @@ class PmsConnect(object):
return request
- """
- Return metadata for children of the request item.
-
- Parameters required: rating_key { Plex ratingKey }
- Optional parameters: output_format { dict, json }
-
- Output: array
- """
def get_metadata_children(self, rating_key='', output_format=''):
+ """
+ Return metadata for children of the request item.
+
+ Parameters required: rating_key { Plex ratingKey }
+ Optional parameters: output_format { dict, json }
+
+ Output: array
+ """
uri = '/library/metadata/' + rating_key + '/children'
request = self.request_handler.make_request(uri=uri,
proto=self.protocol,
@@ -150,15 +152,15 @@ class PmsConnect(object):
return request
- """
- Return list of recently added items.
-
- Parameters required: count { number of results to return }
- Optional parameters: output_format { dict, json }
-
- Output: array
- """
def get_recently_added(self, count='0', output_format=''):
+ """
+ Return list of recently added items.
+
+ Parameters required: count { number of results to return }
+ Optional parameters: output_format { dict, json }
+
+ Output: array
+ """
uri = '/library/recentlyAdded?X-Plex-Container-Start=0&X-Plex-Container-Size=' + count
request = self.request_handler.make_request(uri=uri,
proto=self.protocol,
@@ -167,15 +169,15 @@ class PmsConnect(object):
return request
- """
- Return list of children in requested library item.
-
- Parameters required: rating_key { ratingKey of parent }
- Optional parameters: output_format { dict, json }
-
- Output: array
- """
def get_children_list(self, rating_key='', output_format=''):
+ """
+ Return list of children in requested library item.
+
+ Parameters required: rating_key { ratingKey of parent }
+ Optional parameters: output_format { dict, json }
+
+ Output: array
+ """
uri = '/library/metadata/' + rating_key + '/children'
request = self.request_handler.make_request(uri=uri,
proto=self.protocol,
@@ -184,14 +186,14 @@ class PmsConnect(object):
return request
- """
- Return list of local servers.
-
- Optional parameters: output_format { dict, json }
-
- Output: array
- """
def get_server_list(self, output_format=''):
+ """
+ Return list of local servers.
+
+ Optional parameters: output_format { dict, json }
+
+ Output: array
+ """
uri = '/servers'
request = self.request_handler.make_request(uri=uri,
proto=self.protocol,
@@ -200,14 +202,14 @@ class PmsConnect(object):
return request
- """
- Return the local servers preferences.
-
- Optional parameters: output_format { dict, json }
-
- Output: array
- """
def get_server_prefs(self, output_format=''):
+ """
+ Return the local servers preferences.
+
+ Optional parameters: output_format { dict, json }
+
+ Output: array
+ """
uri = '/:/prefs'
request = self.request_handler.make_request(uri=uri,
proto=self.protocol,
@@ -216,14 +218,14 @@ class PmsConnect(object):
return request
- """
- Return the local server identity.
-
- Optional parameters: output_format { dict, json }
-
- Output: array
- """
def get_local_server_identity(self, output_format=''):
+ """
+ Return the local server identity.
+
+ Optional parameters: output_format { dict, json }
+
+ Output: array
+ """
uri = '/identity'
request = self.request_handler.make_request(uri=uri,
proto=self.protocol,
@@ -232,14 +234,14 @@ class PmsConnect(object):
return request
- """
- Return list of libraries on server.
-
- Optional parameters: output_format { dict, json }
-
- Output: array
- """
def get_libraries_list(self, output_format=''):
+ """
+ Return list of libraries on server.
+
+ Optional parameters: output_format { dict, json }
+
+ Output: array
+ """
uri = '/library/sections'
request = self.request_handler.make_request(uri=uri,
proto=self.protocol,
@@ -248,14 +250,14 @@ class PmsConnect(object):
return request
- """
- Return list of items in library on server.
-
- Optional parameters: output_format { dict, json }
-
- Output: array
- """
def get_library_list(self, section_key='', list_type='all', count='0', sort_type='', output_format=''):
+ """
+ Return list of items in library on server.
+
+ Optional parameters: output_format { dict, json }
+
+ Output: array
+ """
uri = '/library/sections/' + section_key + '/' + list_type +'?X-Plex-Container-Start=0&X-Plex-Container-Size=' + count + sort_type
request = self.request_handler.make_request(uri=uri,
proto=self.protocol,
@@ -264,15 +266,15 @@ class PmsConnect(object):
return request
- """
- Return sync item details.
-
- Parameters required: sync_id { unique sync id for item }
- Optional parameters: output_format { dict, json }
-
- Output: array
- """
def get_sync_item(self, sync_id=None, output_format=''):
+ """
+ Return sync item details.
+
+ Parameters required: sync_id { unique sync id for item }
+ Optional parameters: output_format { dict, json }
+
+ Output: array
+ """
uri = '/sync/items/' + sync_id
request = self.request_handler.make_request(uri=uri,
proto=self.protocol,
@@ -281,14 +283,14 @@ class PmsConnect(object):
return request
- """
- Return sync transcode queue.
-
- Optional parameters: output_format { dict, json }
-
- Output: array
- """
def get_sync_transcode_queue(self, output_format=''):
+ """
+ Return sync transcode queue.
+
+ Optional parameters: output_format { dict, json }
+
+ Output: array
+ """
uri = '/sync/transcodeQueue'
request = self.request_handler.make_request(uri=uri,
proto=self.protocol,
@@ -297,14 +299,14 @@ class PmsConnect(object):
return request
- """
- Return search results.
-
- Optional parameters: output_format { dict, json }
-
- Output: array
- """
def get_search(self, query='', track='', output_format=''):
+ """
+ Return search results.
+
+ Optional parameters: output_format { dict, json }
+
+ Output: array
+ """
uri = '/search?query=' + urllib2.quote(query.encode('utf8')) + track
request = self.request_handler.make_request(uri=uri,
proto=self.protocol,
@@ -313,14 +315,14 @@ class PmsConnect(object):
return request
- """
- Return account details.
-
- Optional parameters: output_format { dict, json }
-
- Output: array
- """
def get_account(self, output_format=''):
+ """
+ Return account details.
+
+ Optional parameters: output_format { dict, json }
+
+ Output: array
+ """
uri = '/myplex/account'
request = self.request_handler.make_request(uri=uri,
proto=self.protocol,
@@ -329,34 +331,35 @@ class PmsConnect(object):
return request
- """
- Refresh Plex remote access port mapping.
-
- Optional parameters: None
-
- Output: None
- """
def put_refresh_reachability(self):
+ """
+ Refresh Plex remote access port mapping.
+
+ Optional parameters: None
+
+ Output: None
+ """
uri = '/myplex/refreshReachability'
request = self.request_handler.make_request(uri=uri,
proto=self.protocol,
request_type='PUT')
return request
- """
- Return processed and validated list of recently added items.
- Parameters required: count { number of results to return }
-
- Output: array
- """
def get_recently_added_details(self, count='0'):
+ """
+ Return processed and validated list of recently added items.
+
+ Parameters required: count { number of results to return }
+
+ Output: array
+ """
recent = self.get_recently_added(count, output_format='xml')
try:
xml_head = recent.getElementsByTagName('MediaContainer')
- except:
- logger.warn("Unable to parse XML for get_recently_added.")
+ except Exception as e:
+ logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_recently_added: %s." % e)
return []
recents_list = []
@@ -377,7 +380,7 @@ class PmsConnect(object):
'title': helpers.get_xml_attr(item, 'title'),
'parent_title': helpers.get_xml_attr(item, 'parentTitle'),
'library_id': helpers.get_xml_attr(item, 'librarySectionID'),
- 'library_title': helpers.get_xml_attr(item, 'librarySectionTitle'),
+ 'library_name': helpers.get_xml_attr(item, 'librarySectionTitle'),
'thumb': helpers.get_xml_attr(item, 'thumb'),
'added_at': helpers.get_xml_attr(item, 'addedAt')
}
@@ -394,7 +397,7 @@ class PmsConnect(object):
'title': helpers.get_xml_attr(item, 'title'),
'parent_title': helpers.get_xml_attr(item, 'parentTitle'),
'library_id': helpers.get_xml_attr(item, 'librarySectionID'),
- 'library_title': helpers.get_xml_attr(item, 'librarySectionTitle'),
+ 'library_name': helpers.get_xml_attr(item, 'librarySectionTitle'),
'year': helpers.get_xml_attr(item, 'year'),
'thumb': helpers.get_xml_attr(item, 'thumb'),
'added_at': helpers.get_xml_attr(item, 'addedAt')
@@ -406,20 +409,20 @@ class PmsConnect(object):
output = {'recently_added': sorted(recents_list, key=lambda k: k['added_at'], reverse=True)}
return output
- """
- Return processed and validated metadata list for requested item.
-
- Parameters required: rating_key { Plex ratingKey }
-
- Output: array
- """
def get_metadata_details(self, rating_key=''):
+ """
+ Return processed and validated metadata list for requested item.
+
+ Parameters required: rating_key { Plex ratingKey }
+
+ Output: array
+ """
metadata = self.get_metadata(str(rating_key), output_format='xml')
try:
xml_head = metadata.getElementsByTagName('MediaContainer')
- except:
- logger.warn("Unable to parse XML for get_metadata.")
+ except Exception as e:
+ logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_metadata: %s: %s." % e)
return []
metadata_list = []
@@ -440,11 +443,11 @@ class PmsConnect(object):
metadata_main = a.getElementsByTagName('Track')[0]
metadata_type = helpers.get_xml_attr(metadata_main, 'type')
else:
- logger.debug(u"Metadata failed")
+ logger.debug(u"PlexPy Pmsconnect :: Metadata failed")
return None
library_id = helpers.get_xml_attr(a, 'librarySectionID')
- library_title = helpers.get_xml_attr(a, 'librarySectionTitle')
+ library_name = helpers.get_xml_attr(a, 'librarySectionTitle')
genres = []
actors = []
@@ -470,7 +473,7 @@ class PmsConnect(object):
if metadata_type == 'movie':
metadata = {'media_type': metadata_type,
'library_id': library_id,
- 'library_title': library_title,
+ 'library_name': library_name,
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
@@ -505,7 +508,7 @@ class PmsConnect(object):
elif metadata_type == 'show':
metadata = {'media_type': metadata_type,
'library_id': library_id,
- 'library_title': library_title,
+ 'library_name': library_name,
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
@@ -542,7 +545,7 @@ class PmsConnect(object):
show_details = self.get_metadata_details(parent_rating_key)
metadata = {'media_type': metadata_type,
'library_id': library_id,
- 'library_title': library_title,
+ 'library_name': library_name,
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
@@ -579,7 +582,7 @@ class PmsConnect(object):
show_details = self.get_metadata_details(grandparent_rating_key)
metadata = {'media_type': metadata_type,
'library_id': library_id,
- 'library_title': library_title,
+ 'library_name': library_name,
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
@@ -614,7 +617,7 @@ class PmsConnect(object):
elif metadata_type == 'artist':
metadata = {'media_type': metadata_type,
'library_id': library_id,
- 'library_title': library_title,
+ 'library_name': library_name,
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
@@ -651,7 +654,7 @@ class PmsConnect(object):
artist_details = self.get_metadata_details(parent_rating_key)
metadata = {'media_type': metadata_type,
'library_id': library_id,
- 'library_title': library_title,
+ 'library_name': library_name,
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
@@ -688,7 +691,7 @@ class PmsConnect(object):
album_details = self.get_metadata_details(parent_rating_key)
metadata = {'media_type': metadata_type,
'library_id': library_id,
- 'library_title': library_title,
+ 'library_name': library_name,
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
@@ -725,20 +728,20 @@ class PmsConnect(object):
return metadata_list
- """
- Return processed and validated metadata list for all children of requested item.
-
- Parameters required: rating_key { Plex ratingKey }
-
- Output: array
- """
def get_metadata_children_details(self, rating_key=''):
+ """
+ Return processed and validated metadata list for all children of requested item.
+
+ Parameters required: rating_key { Plex ratingKey }
+
+ Output: array
+ """
metadata = self.get_metadata_children(str(rating_key), output_format='xml')
try:
xml_head = metadata.getElementsByTagName('MediaContainer')
- except:
- logger.warn("Unable to parse XML for get_metadata_children.")
+ except Exception as e:
+ logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_metadata_children: %s." % e)
metadata_list = []
@@ -767,20 +770,20 @@ class PmsConnect(object):
output = {'metadata': metadata_list}
return output
- """
- Return processed and validated metadata list for requested library.
-
- Parameters required: library_id { Plex library key }
-
- Output: array
- """
def get_library_metadata_details(self, library_id=''):
+ """
+ Return processed and validated metadata list for requested library.
+
+ Parameters required: library_id { Plex library key }
+
+ Output: array
+ """
libraries_data = self.get_libraries_list(output_format='xml')
try:
xml_head = libraries_data.getElementsByTagName('MediaContainer')
- except:
- logger.warn("Unable to parse XML for get_library_metadata_details.")
+ except Exception as e:
+ logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_library_metadata_details: %s." % e)
return []
metadata_list = []
@@ -814,18 +817,18 @@ class PmsConnect(object):
return metadata_list
- """
- Return processed and validated session list.
-
- Output: array
- """
def get_current_activity(self):
+ """
+ Return processed and validated session list.
+
+ Output: array
+ """
session_data = self.get_sessions(output_format='xml')
try:
xml_head = session_data.getElementsByTagName('MediaContainer')
- except:
- logger.warn("Unable to parse XML for get_sessions.")
+ except Exception as e:
+ logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_sessions: %s." % e)
return []
session_list = []
@@ -863,15 +866,15 @@ class PmsConnect(object):
return output
- """
- Return selected data from current sessions.
- This function processes and validates session data
-
- Parameters required: stream_type { track or video }
- session { the session dictionary }
- Output: dict
- """
def get_session_each(self, stream_type='', session=None):
+ """
+ Return selected data from current sessions.
+ This function processes and validates session data
+
+ Parameters required: stream_type { track or video }
+ session { the session dictionary }
+ Output: dict
+ """
session_output = None
user_data = users.Users()
@@ -905,7 +908,7 @@ class PmsConnect(object):
transcode_container = ''
transcode_protocol = ''
- user_details = user_data.get_user_details(
+ user_details = user_data.get_details(
user=helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'))
if helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier').endswith('_Track'):
@@ -914,6 +917,7 @@ class PmsConnect(object):
machine_id = helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier')
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
+ 'library_id': helpers.get_xml_attr(session, 'librarySectionID'),
'media_index': helpers.get_xml_attr(session, 'index'),
'parent_media_index': helpers.get_xml_attr(session, 'parentIndex'),
'art': helpers.get_xml_attr(session, 'art'),
@@ -924,7 +928,7 @@ class PmsConnect(object):
'user': user_details['username'],
'user_id': user_details['user_id'],
'friendly_name': user_details['friendly_name'],
- 'user_thumb': user_details['thumb'],
+ 'user_thumb': user_details['user_thumb'],
'ip_address': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'address').split(':')[-1],
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
@@ -1025,7 +1029,7 @@ class PmsConnect(object):
else:
use_indexes = 0
- user_details = user_data.get_user_details(
+ user_details = user_data.get_details(
user=helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'))
if helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier').endswith('_Video'):
@@ -1035,6 +1039,7 @@ class PmsConnect(object):
if helpers.get_xml_attr(session, 'type') == 'episode':
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
+ 'library_id': helpers.get_xml_attr(session, 'librarySectionID'),
'media_index': helpers.get_xml_attr(session, 'index'),
'parent_media_index': helpers.get_xml_attr(session, 'parentIndex'),
'art': helpers.get_xml_attr(session, 'art'),
@@ -1045,7 +1050,7 @@ class PmsConnect(object):
'user': user_details['username'],
'user_id': user_details['user_id'],
'friendly_name': user_details['friendly_name'],
- 'user_thumb': user_details['thumb'],
+ 'user_thumb': user_details['user_thumb'],
'ip_address': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'address').split(':')[-1],
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
@@ -1092,6 +1097,7 @@ class PmsConnect(object):
elif helpers.get_xml_attr(session, 'type') == 'movie':
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
+ 'library_id': helpers.get_xml_attr(session, 'librarySectionID'),
'media_index': helpers.get_xml_attr(session, 'index'),
'parent_media_index': helpers.get_xml_attr(session, 'parentIndex'),
'art': helpers.get_xml_attr(session, 'art'),
@@ -1102,7 +1108,7 @@ class PmsConnect(object):
'user': user_details['username'],
'user_id': user_details['user_id'],
'friendly_name': user_details['friendly_name'],
- 'user_thumb': user_details['thumb'],
+ 'user_thumb': user_details['user_thumb'],
'ip_address': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'address').split(':')[-1],
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
@@ -1149,6 +1155,7 @@ class PmsConnect(object):
elif helpers.get_xml_attr(session, 'type') == 'clip':
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
+ 'library_id': helpers.get_xml_attr(session, 'librarySectionID'),
'media_index': helpers.get_xml_attr(session, 'index'),
'parent_media_index': helpers.get_xml_attr(session, 'parentIndex'),
'art': helpers.get_xml_attr(session, 'art'),
@@ -1159,7 +1166,7 @@ class PmsConnect(object):
'user': user_details['username'],
'user_id': user_details['user_id'],
'friendly_name': user_details['friendly_name'],
- 'user_thumb': user_details['thumb'],
+ 'user_thumb': user_details['user_thumb'],
'ip_address': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'address').split(':')[-1],
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
@@ -1230,7 +1237,7 @@ class PmsConnect(object):
transcode_container = ''
transcode_protocol = ''
- user_details = user_data.get_user_details(
+ user_details = user_data.get_details(
user=helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'))
if helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier').endswith('_Photo'):
@@ -1239,6 +1246,7 @@ class PmsConnect(object):
machine_id = helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier')
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
+ 'library_id': helpers.get_xml_attr(session, 'librarySectionID'),
'media_index': helpers.get_xml_attr(session, 'index'),
'parent_media_index': helpers.get_xml_attr(session, 'parentIndex'),
'art': helpers.get_xml_attr(session, 'art'),
@@ -1249,7 +1257,7 @@ class PmsConnect(object):
'user': user_details['username'],
'user_id': user_details['user_id'],
'friendly_name': user_details['friendly_name'],
- 'user_thumb': user_details['thumb'],
+ 'user_thumb': user_details['user_thumb'],
'ip_address': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'address').split(':')[-1],
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
@@ -1292,7 +1300,7 @@ class PmsConnect(object):
}
else:
- logger.warn(u"No known stream types found in session list.")
+ logger.warn(u"PlexPy Pmsconnect :: No known stream types found in session list.")
# Rename Mystery platform names
session_output['platform'] = common.PLATFORM_NAME_OVERRIDES.get(session_output['platform'],
@@ -1300,18 +1308,18 @@ class PmsConnect(object):
return session_output
- """
- Return processed and validated children list.
-
- Output: array
- """
def get_item_children(self, rating_key=''):
+ """
+ Return processed and validated children list.
+
+ Output: array
+ """
children_data = self.get_children_list(rating_key, output_format='xml')
try:
xml_head = children_data.getElementsByTagName('MediaContainer')
- except:
- logger.warn("Unable to parse XML for get_children_list.")
+ except Exception as e:
+ logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_children_list: %s." % e)
return []
children_list = []
@@ -1319,7 +1327,7 @@ class PmsConnect(object):
for a in xml_head:
if a.getAttribute('size'):
if a.getAttribute('size') == '0':
- logger.debug(u"No children data.")
+ logger.debug(u"PlexPy Pmsconnect :: No children data.")
children_list = {'children_count': '0',
'children_list': []
}
@@ -1353,18 +1361,18 @@ class PmsConnect(object):
return output
- """
- Return the list of local servers.
-
- Output: array
- """
def get_servers_info(self):
+ """
+ Return the list of local servers.
+
+ Output: array
+ """
recent = self.get_server_list(output_format='xml')
try:
xml_head = recent.getElementsByTagName('Server')
- except:
- logger.warn("Unable to parse XML for get_server_list.")
+ except Exception as e:
+ logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_server_list: %s." % e)
return []
server_info = []
@@ -1380,18 +1388,18 @@ class PmsConnect(object):
return server_info
- """
- Return the local machine identity.
-
- Output: dict
- """
def get_server_identity(self):
+ """
+ Return the local machine identity.
+
+ Output: dict
+ """
identity = self.get_local_server_identity(output_format='xml')
try:
xml_head = identity.getElementsByTagName('MediaContainer')
- except:
- logger.warn("Unable to parse XML for get_local_server_identity.")
+ except Exception as e:
+ logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_local_server_identity: %s." % e)
return []
server_identity = {}
@@ -1402,21 +1410,21 @@ class PmsConnect(object):
return server_identity
- """
- Return a specified server preference.
-
- Parameters required: pref { name of preference }
-
- Output: string
- """
def get_server_pref(self, pref=None):
+ """
+ Return a specified server preference.
+
+ Parameters required: pref { name of preference }
+
+ Output: string
+ """
if pref:
prefs = self.get_server_prefs(output_format='xml')
try:
xml_head = prefs.getElementsByTagName('Setting')
- except:
- logger.warn("Unable to parse XML for get_local_server_name.")
+ except Exception as e:
+ logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_local_server_name: %s." % e)
return ''
pref_value = 'None'
@@ -1427,21 +1435,21 @@ class PmsConnect(object):
return pref_value
else:
- logger.debug(u"Server preferences queried but no parameter received.")
+ logger.debug(u"PlexPy Pmsconnect :: Server preferences queried but no parameter received.")
return None
- """
- Return processed and validated server libraries list.
-
- Output: array
- """
def get_server_children(self):
+ """
+ Return processed and validated server libraries list.
+
+ Output: array
+ """
libraries_data = self.get_libraries_list(output_format='xml')
try:
xml_head = libraries_data.getElementsByTagName('MediaContainer')
- except:
- logger.warn("Unable to parse XML for get_libraries_list.")
+ except Exception as e:
+ logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_libraries_list: %s." % e)
return []
libraries_list = []
@@ -1449,7 +1457,7 @@ class PmsConnect(object):
for a in xml_head:
if a.getAttribute('size'):
if a.getAttribute('size') == '0':
- logger.debug(u"No libraries data.")
+ logger.debug(u"PlexPy Pmsconnect :: No libraries data.")
libraries_list = {'libraries_count': '0',
'libraries_list': []
}
@@ -1473,15 +1481,15 @@ class PmsConnect(object):
return output
- """
- Return processed and validated server library items list.
-
- Parameters required: library_type { movie, show, episode, artist }
- section_key { unique library key }
-
- Output: array
- """
def get_library_children(self, library_type='', section_key='', list_type='all', sort_type = ''):
+ """
+ Return processed and validated server library items list.
+
+ Parameters required: library_type { movie, show, episode, artist }
+ section_key { unique library key }
+
+ Output: array
+ """
# Currently only grab the library with 1 items so 'size' is not 0
count = '1'
@@ -1511,8 +1519,8 @@ class PmsConnect(object):
try:
xml_head = library_data.getElementsByTagName('MediaContainer')
- except:
- logger.warn("Unable to parse XML for get_library_children.")
+ except Exception as e:
+ logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_library_children: %s." % e)
return []
library_list = []
@@ -1520,7 +1528,7 @@ class PmsConnect(object):
for a in xml_head:
if a.getAttribute('size'):
if a.getAttribute('size') == '0':
- logger.debug(u"No library data.")
+ logger.debug(u"PlexPy Pmsconnect :: No library data.")
library_list = {'library_count': '0',
'library_list': []
}
@@ -1543,12 +1551,12 @@ class PmsConnect(object):
return output
- """
- Return processed and validated library statistics.
-
- Output: array
- """
def get_library_details(self):
+ """
+ Return processed and validated library statistics.
+
+ Output: array
+ """
server_libraries = self.get_server_children()
server_library_stats = []
@@ -1614,16 +1622,16 @@ class PmsConnect(object):
return server_library_stats
- """
- Return image data as array.
- Array contains the image content type and image binary
-
- Parameters required: img { Plex image location }
- Optional parameters: width { the image width }
- height { the image height }
- Output: array
- """
def get_image(self, img=None, width=None, height=None):
+ """
+ Return image data as array.
+ Array contains the image content type and image binary
+
+ Parameters required: img { Plex image location }
+ Optional parameters: width { the image width }
+ height { the image height }
+ Output: array
+ """
if img:
if width.isdigit() and height.isdigit():
uri = '/photo/:/transcode?url=http://127.0.0.1:32400' + img + '&width=' + width + '&height=' + height
@@ -1637,15 +1645,15 @@ class PmsConnect(object):
return [request, content_type]
else:
- logger.error("Image proxy queries but no input received.")
+ logger.error(u"PlexPy Pmsconnect :: Image proxy queries but no input received.")
return None
- """
- Return processed list of search results.
-
- Output: array
- """
def get_search_results(self, query=''):
+ """
+ Return processed list of search results.
+
+ Output: array
+ """
search_results = self.get_search(query=query, output_format='xml')
search_results_tracks = self.get_search(query=query, track='&type=10', output_format='xml')
@@ -1659,8 +1667,8 @@ class PmsConnect(object):
xml_head += search_results_tracks.getElementsByTagName('MediaContainer')
except:
pass
- except:
- logger.warn("Unable to parse XML for get_search_result_details.")
+ except Exception as e:
+ logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_search_result_details: %s." % e)
return []
search_results_count = 0
@@ -1678,7 +1686,7 @@ class PmsConnect(object):
if a.getAttribute('size'):
totalSize += int(a.getAttribute('size'))
if totalSize == 0:
- logger.debug(u"No search results.")
+ logger.debug(u"PlexPy Pmsconnect :: No search results.")
search_results_list = {'results_count': search_results_count,
'results_list': []
}
@@ -1733,12 +1741,12 @@ class PmsConnect(object):
return output
- """
- Return processed list of grandparent/parent/child rating keys.
-
- Output: array
- """
def get_rating_keys_list(self, rating_key='', media_type=''):
+ """
+ Return processed list of grandparent/parent/child rating keys.
+
+ Output: array
+ """
if media_type == 'movie':
key_list = {0: {'rating_key': int(rating_key)}}
@@ -1750,7 +1758,7 @@ class PmsConnect(object):
match_type = 'index'
library_id = None
- library_title = None
+ library_name = None
# get grandparent rating key
if media_type == 'season' or media_type == 'album':
@@ -1758,9 +1766,9 @@ class PmsConnect(object):
metadata = self.get_metadata_details(rating_key=rating_key)
rating_key = metadata['metadata']['parent_rating_key']
library_id = metadata['metadata']['library_id']
- library_title = metadata['metadata']['library_title']
- except:
- logger.warn("Unable to get parent_rating_key for get_rating_keys_list.")
+ library_name = metadata['metadata']['library_name']
+ except Exception as e:
+ logger.warn(u"PlexPy Pmsconnect :: Unable to get parent_rating_key for get_rating_keys_list: %s." % e)
return {}
elif media_type == 'episode' or media_type == 'track':
@@ -1768,9 +1776,9 @@ class PmsConnect(object):
metadata = self.get_metadata_details(rating_key=rating_key)
rating_key = metadata['metadata']['grandparent_rating_key']
library_id = metadata['metadata']['library_id']
- library_title = metadata['metadata']['library_title']
- except:
- logger.warn("Unable to get grandparent_rating_key for get_rating_keys_list.")
+ library_name = metadata['metadata']['library_name']
+ except Exception as e:
+ logger.warn(u"PlexPy Pmsconnect :: Unable to get grandparent_rating_key for get_rating_keys_list: %s." % e)
return {}
# get parent_rating_keys
@@ -1778,8 +1786,8 @@ class PmsConnect(object):
try:
xml_head = metadata.getElementsByTagName('MediaContainer')
- except:
- logger.warn("Unable to parse XML for get_rating_keys_list.")
+ except Exception as e:
+ logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_rating_keys_list: %s." % e)
return {}
for a in xml_head:
@@ -1806,8 +1814,8 @@ class PmsConnect(object):
try:
xml_head = metadata.getElementsByTagName('MediaContainer')
- except:
- logger.warn("Unable to parse XML for get_rating_keys_list.")
+ except Exception as e:
+ logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_rating_keys_list: %s." % e)
return {}
for a in xml_head:
@@ -1843,7 +1851,7 @@ class PmsConnect(object):
{'rating_key': int(rating_key),
'children': parents },
'library_id': library_id,
- 'library_title': library_title
+ 'library_name': library_name
}
return key_list
@@ -1855,8 +1863,8 @@ class PmsConnect(object):
try:
xml_head = account_data.getElementsByTagName('MyPlex')
- except:
- logger.warn("Unable to parse XML for get_server_response.")
+ except Exception as e:
+ logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_server_response: %s." % e)
return None
server_response = {}
@@ -1868,4 +1876,4 @@ class PmsConnect(object):
'public_port': helpers.get_xml_attr(a, 'publicPort')
}
- return server_response
+ return server_response
\ No newline at end of file
diff --git a/plexpy/users.py b/plexpy/users.py
index 87572b76..5210f3cd 100644
--- a/plexpy/users.py
+++ b/plexpy/users.py
@@ -21,28 +21,28 @@ class Users(object):
def __init__(self):
pass
- def get_user_list(self, kwargs=None):
+ def get_datatables_list(self, kwargs=None):
data_tables = datatables.DataTables()
custom_where = ['users.deleted_user', 0]
- columns = ['users.user_id as user_id',
- 'users.custom_avatar_url as user_thumb',
- '(case when users.friendly_name is null then users.username else \
- users.friendly_name end) as friendly_name',
- 'MAX(session_history.started) as last_seen',
- 'session_history.ip_address as ip_address',
- 'COUNT(session_history.id) as plays',
- 'session_history.platform as platform',
- 'session_history.player as player',
- 'session_history_metadata.full_title as last_watched',
+ columns = ['users.user_id',
+ 'users.username',
+ 'users.friendly_name',
+ 'users.thumb AS user_thumb',
+ 'users.custom_avatar_url AS custom_thumb',
+ 'COUNT(session_history.id) AS plays',
+ 'MAX(session_history.started) AS last_seen',
+ 'session_history_metadata.full_title AS last_watched',
+ 'session_history.ip_address',
+ 'session_history.platform',
+ 'session_history.player',
'session_history_metadata.thumb',
'session_history_metadata.parent_thumb',
'session_history_metadata.grandparent_thumb',
'session_history_metadata.media_type',
- 'session_history.rating_key as rating_key',
+ 'session_history.rating_key',
'session_history_media_info.video_decision',
- 'users.username as user',
'users.do_notify as do_notify',
'users.keep_history as keep_history'
]
@@ -61,8 +61,8 @@ class Users(object):
['session_history.id', 'session_history_metadata.id'],
['session_history.id', 'session_history_media_info.id']],
kwargs=kwargs)
- except:
- logger.warn("Unable to execute database query.")
+ except Exception as e:
+ logger.warn(u"PlexPy Users :: Unable to execute database query for get_list: %s." % e)
return {'recordsFiltered': 0,
'recordsTotal': 0,
'draw': 0,
@@ -80,28 +80,30 @@ class Users(object):
else:
thumb = item['thumb']
- if not item['user_thumb'] or item['user_thumb'] == '':
- user_thumb = common.DEFAULT_USER_THUMB
- else:
+ if item['custom_thumb'] and item['custom_thumb'] != item['user_thumb']:
+ user_thumb = item['custom_thumb']
+ elif item['user_thumb']:
user_thumb = item['user_thumb']
+ else:
+ user_thumb = common.DEFAULT_USER_THUMB
# Rename Mystery platform names
platform = common.PLATFORM_NAME_OVERRIDES.get(item['platform'], item['platform'])
- row = {'plays': item['plays'],
- 'last_seen': item['last_seen'],
+ row = {'user_id': item['user_id'],
+ 'username': item['username'],
'friendly_name': item['friendly_name'],
+ 'user_thumb': user_thumb,
+ 'plays': item['plays'],
+ 'last_seen': item['last_seen'],
+ 'last_watched': item['last_watched'],
'ip_address': item['ip_address'],
'platform': platform,
'player': item['player'],
- 'last_watched': item['last_watched'],
'thumb': thumb,
'media_type': item['media_type'],
'rating_key': item['rating_key'],
'video_decision': item['video_decision'],
- 'user_thumb': user_thumb,
- 'user': item['user'],
- 'user_id': item['user_id'],
'do_notify': helpers.checked(item['do_notify']),
'keep_history': helpers.checked(item['keep_history'])
}
@@ -116,35 +118,34 @@ class Users(object):
return dict
- def get_user_unique_ips(self, kwargs=None, custom_where=None):
+ def get_datatables_unique_ips(self, user_id=None, kwargs=None):
data_tables = datatables.DataTables()
- # Change custom_where column name due to ambiguous column name after JOIN
- custom_where[0][0] = 'custom_user_id' if custom_where[0][0] == 'user_id' else custom_where[0][0]
+ custom_where = ['users.user_id', user_id]
columns = ['session_history.id',
- 'session_history.started as last_seen',
- 'session_history.ip_address as ip_address',
- 'COUNT(session_history.id) as play_count',
- 'session_history.platform as platform',
- 'session_history.player as player',
- 'session_history_metadata.full_title as last_watched',
+ 'session_history.started AS last_seen',
+ 'session_history.ip_address',
+ 'COUNT(session_history.id) AS play_count',
+ 'session_history.platform',
+ 'session_history.player',
+ 'session_history_metadata.full_title AS last_watched',
'session_history_metadata.thumb',
'session_history_metadata.parent_thumb',
'session_history_metadata.grandparent_thumb',
'session_history_metadata.media_type',
- 'session_history.rating_key as rating_key',
+ 'session_history.rating_key',
'session_history_media_info.video_decision',
- 'session_history.user as user',
+ 'session_history.user',
'session_history.user_id as custom_user_id',
- '(case when users.friendly_name is null then users.username else \
- users.friendly_name end) as friendly_name'
+ '(CASE WHEN users.friendly_name IS NULL THEN users.username ELSE \
+ users.friendly_name END) AS friendly_name'
]
try:
query = data_tables.ssp_query(table_name='session_history',
columns=columns,
- custom_where=custom_where,
+ custom_where=[custom_where],
group_by=['ip_address'],
join_types=['JOIN',
'JOIN',
@@ -156,8 +157,8 @@ class Users(object):
['session_history.id', 'session_history_metadata.id'],
['session_history.id', 'session_history_media_info.id']],
kwargs=kwargs)
- except:
- logger.warn("Unable to execute database query.")
+ except Exception as e:
+ logger.warn(u"PlexPy Users :: Unable to execute database query for get_unique_ips: %s." % e)
return {'recordsFiltered': 0,
'recordsTotal': 0,
'draw': 0,
@@ -178,18 +179,18 @@ class Users(object):
# Rename Mystery platform names
platform = common.PLATFORM_NAME_OVERRIDES.get(item["platform"], item["platform"])
- row = {"id": item['id'],
- "last_seen": item['last_seen'],
- "ip_address": item['ip_address'],
- "play_count": item['play_count'],
- "platform": platform,
- "player": item['player'],
- "last_watched": item['last_watched'],
- "thumb": thumb,
- "media_type": item['media_type'],
- "rating_key": item['rating_key'],
- "video_decision": item['video_decision'],
- "friendly_name": item['friendly_name']
+ row = {'id': item['id'],
+ 'last_seen': item['last_seen'],
+ 'ip_address': item['ip_address'],
+ 'play_count': item['play_count'],
+ 'platform': platform,
+ 'player': item['player'],
+ 'last_watched': item['last_watched'],
+ 'thumb': thumb,
+ 'media_type': item['media_type'],
+ 'rating_key': item['rating_key'],
+ 'video_decision': item['video_decision'],
+ 'friendly_name': item['friendly_name']
}
rows.append(row)
@@ -202,286 +203,169 @@ class Users(object):
return dict
- # TODO: The getter and setter for this needs to become a config getter/setter for more than just friendlyname
- def set_user_friendly_name(self, user=None, user_id=None, friendly_name=None, do_notify=0, keep_history=1):
- if user_id:
- if friendly_name.strip() == '':
- friendly_name = None
-
+ def set_config(self, user_id=None, friendly_name='', custom_thumb='', do_notify=1, keep_history=1):
+ if str(user_id).isdigit():
monitor_db = database.MonitorDatabase()
- control_value_dict = {"user_id": user_id}
- new_value_dict = {"friendly_name": friendly_name,
- "do_notify": do_notify,
- "keep_history": keep_history}
+ key_dict = {'user_id': user_id}
+ value_dict = {'friendly_name': friendly_name,
+ 'custom_avatar_url': custom_thumb,
+ 'do_notify': do_notify,
+ 'keep_history': keep_history}
try:
- monitor_db.upsert('users', new_value_dict, control_value_dict)
- except Exception, e:
- logger.debug(u"Uncaught exception %s" % e)
- if user:
- if friendly_name.strip() == '':
- friendly_name = None
+ monitor_db.upsert('users', value_dict, key_dict)
+ except Exception as e:
+ logger.warn(u"PlexPy Users :: Unable to execute database query for set_config: %s." % e)
- monitor_db = database.MonitorDatabase()
-
- control_value_dict = {"username": user}
- new_value_dict = {"friendly_name": friendly_name,
- "do_notify": do_notify,
- "keep_history": keep_history}
- try:
- monitor_db.upsert('users', new_value_dict, control_value_dict)
- except Exception, e:
- logger.debug(u"Uncaught exception %s" % e)
-
- def set_user_profile_url(self, user=None, user_id=None, profile_url=None):
- if user_id:
- if profile_url.strip() == '':
- profile_url = None
-
- monitor_db = database.MonitorDatabase()
-
- control_value_dict = {"user_id": user_id}
- new_value_dict = {"custom_avatar_url": profile_url}
- try:
- monitor_db.upsert('users', new_value_dict, control_value_dict)
- except Exception, e:
- logger.debug(u"Uncaught exception %s" % e)
- if user:
- if profile_url.strip() == '':
- profile_url = None
-
- monitor_db = database.MonitorDatabase()
-
- control_value_dict = {"username": user}
- new_value_dict = {"custom_avatar_url": profile_url}
- try:
- monitor_db.upsert('users', new_value_dict, control_value_dict)
- except Exception, e:
- logger.debug(u"Uncaught exception %s" % e)
-
- def get_user_friendly_name(self, user=None, user_id=None):
- if user_id:
- monitor_db = database.MonitorDatabase()
- query = 'select username, ' \
- '(CASE WHEN friendly_name IS NULL THEN username ELSE friendly_name END) as friendly_name,' \
- 'do_notify, keep_history, custom_avatar_url as thumb ' \
- 'FROM users WHERE user_id = ?'
- result = monitor_db.select(query, args=[user_id])
- if result:
- user_detail = {'user_id': user_id,
- 'user': result[0]['username'],
- 'friendly_name': result[0]['friendly_name'],
- 'thumb': result[0]['thumb'],
- 'do_notify': helpers.checked(result[0]['do_notify']),
- 'keep_history': helpers.checked(result[0]['keep_history'])
- }
- return user_detail
- else:
- user_detail = {'user_id': user_id,
- 'user': '',
- 'friendly_name': '',
- 'do_notify': '',
- 'thumb': '',
- 'keep_history': ''}
- return user_detail
- elif user:
- monitor_db = database.MonitorDatabase()
- query = 'select user_id, ' \
- '(CASE WHEN friendly_name IS NULL THEN username ELSE friendly_name END) as friendly_name,' \
- 'do_notify, keep_history, custom_avatar_url as thumb ' \
- 'FROM users WHERE username = ?'
- result = monitor_db.select(query, args=[user])
- if result:
- user_detail = {'user_id': result[0]['user_id'],
- 'user': user,
- 'friendly_name': result[0]['friendly_name'],
- 'thumb': result[0]['thumb'],
- 'do_notify': helpers.checked(result[0]['do_notify']),
- 'keep_history': helpers.checked(result[0]['keep_history'])}
- return user_detail
- else:
- user_detail = {'user_id': None,
- 'user': user,
- 'friendly_name': '',
- 'do_notify': '',
- 'thumb': '',
- 'keep_history': ''}
- return user_detail
-
- return None
-
- def get_user_id(self, user=None):
- if user:
- try:
- monitor_db = database.MonitorDatabase()
- query = 'select user_id FROM users WHERE username = ?'
- result = monitor_db.select_single(query, args=[user])
- if result:
- return result['user_id']
- else:
- return None
- except:
- return None
-
- return None
-
- def get_user_details(self, user=None, user_id=None):
+ def get_details(self, user_id=None, user=None):
from plexpy import plextv
monitor_db = database.MonitorDatabase()
-
- if user:
- query = 'SELECT user_id, username, friendly_name, email, ' \
- 'custom_avatar_url as thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
- 'FROM users ' \
- 'WHERE username = ? ' \
- 'UNION ALL ' \
- 'SELECT null, user, null, null, null, null, null, null, null ' \
- 'FROM session_history ' \
- 'WHERE user = ? ' \
- 'GROUP BY user ' \
- 'LIMIT 1'
- result = monitor_db.select(query, args=[user, user])
- elif user_id:
- query = 'SELECT user_id, username, friendly_name, email, ' \
- 'custom_avatar_url as thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
- 'FROM users ' \
- 'WHERE user_id = ? ' \
- 'UNION ALL ' \
- 'SELECT user_id, user, null, null, null, null, null, null, null ' \
- 'FROM session_history ' \
- 'WHERE user_id = ? ' \
- 'GROUP BY user ' \
- 'LIMIT 1'
- result = monitor_db.select(query, args=[user_id, user_id])
- else:
- result = None
+
+ try:
+ if str(user_id).isdigit():
+ query = 'SELECT user_id, username, friendly_name, thumb AS user_thumb, custom_avatar_url AS custom_thumb, ' \
+ 'email, is_home_user, is_allow_sync, is_restricted, do_notify, keep_history ' \
+ 'FROM users ' \
+ 'WHERE user_id = ? '
+ result = monitor_db.select(query, args=[user_id])
+ elif user:
+ query = 'SELECT user_id, username, friendly_name, thumb AS user_thumb, custom_avatar_url AS custom_thumb, ' \
+ 'email, is_home_user, is_allow_sync, is_restricted, do_notify, keep_history ' \
+ 'FROM users ' \
+ 'WHERE username = ? '
+ result = monitor_db.select(query, args=[user])
+ else:
+ result = []
+ except Exception as e:
+ logger.warn(u"PlexPy Users :: Unable to execute database query for get_details: %s." % e)
+ result = []
if result:
user_details = {}
for item in result:
- if not item['friendly_name']:
- friendly_name = item['username']
- else:
+ if item['friendly_name']:
friendly_name = item['friendly_name']
- if not item['thumb'] or item['thumb'] == '':
- user_thumb = common.DEFAULT_USER_THUMB
else:
- user_thumb = item['thumb']
+ friendly_name = item['username']
- user_details = {"user_id": item['user_id'],
- "username": item['username'],
- "friendly_name": friendly_name,
- "email": item['email'],
- "thumb": user_thumb,
- "is_home_user": item['is_home_user'],
- "is_allow_sync": item['is_allow_sync'],
- "is_restricted": item['is_restricted'],
- "do_notify": item['do_notify']
+ if item['custom_thumb'] and item['custom_thumb'] != item['user_thumb']:
+ user_thumb = item['custom_thumb']
+ elif item['user_thumb']:
+ user_thumb = item['user_thumb']
+ else:
+ user_thumb = common.DEFAULT_USER_THUMB
+
+ user_details = {'user_id': item['user_id'],
+ 'username': item['username'],
+ 'friendly_name': friendly_name,
+ 'user_thumb': user_thumb,
+ 'email': item['email'],
+ 'is_home_user': item['is_home_user'],
+ 'is_allow_sync': item['is_allow_sync'],
+ 'is_restricted': item['is_restricted'],
+ 'do_notify': item['do_notify'],
+ 'keep_history': item['keep_history']
}
return user_details
else:
- logger.warn(u"PlexPy :: Unable to retrieve user from local database. Requesting user list refresh.")
+ logger.warn(u"PlexPy Users :: Unable to retrieve user from local database. Requesting user list refresh.")
# Let's first refresh the user list to make sure the user isn't newly added and not in the db yet
- if user:
- # Refresh users
- plextv.refresh_users()
- query = 'SELECT user_id, username, friendly_name, email, ' \
- 'custom_avatar_url as thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
- 'FROM users ' \
- 'WHERE username = ? ' \
- 'UNION ALL ' \
- 'SELECT null, user, null, null, null, null, null, null, null ' \
- 'FROM session_history ' \
- 'WHERE user = ? ' \
- 'GROUP BY user ' \
- 'LIMIT 1'
- result = monitor_db.select(query, args=[user, user])
- elif user_id:
- # Refresh users
- plextv.refresh_users()
- query = 'SELECT user_id, username, friendly_name, email, ' \
- 'custom_avatar_url as thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
- 'FROM users ' \
- 'WHERE user_id = ? ' \
- 'UNION ALL ' \
- 'SELECT user_id, user, null, null, null, null, null, null, null ' \
- 'FROM session_history ' \
- 'WHERE user_id = ? ' \
- 'GROUP BY user ' \
- 'LIMIT 1'
- result = monitor_db.select(query, args=[user_id, user_id])
- else:
- result = None
+ try:
+ if str(user_id).isdigit():
+ # Refresh users
+ plextv.refresh_users()
+ query = 'SELECT user_id, username, friendly_name, thumb AS user_thumb, custom_avatar_url AS custom_thumb, ' \
+ 'email, is_home_user, is_allow_sync, is_restricted, do_notify, keep_history ' \
+ 'FROM users ' \
+ 'WHERE user_id = ? '
+ result = monitor_db.select(query, args=[user_id])
+ elif user:
+ query = 'SELECT user_id, username, friendly_name, thumb AS user_thumb, custom_avatar_url AS custom_thumb, ' \
+ 'email, is_home_user, is_allow_sync, is_restricted, do_notify, keep_history ' \
+ 'FROM users ' \
+ 'WHERE username = ? '
+ result = monitor_db.select(query, args=[user])
+ else:
+ result = []
+ except Exception as e:
+ logger.warn(u"PlexPy Users :: Unable to execute database query for get_details: %s." % e)
+ result = []
if result:
user_details = {}
for item in result:
- if not item['friendly_name']:
- friendly_name = item['username']
- else:
+ if item['friendly_name']:
friendly_name = item['friendly_name']
- if not item['thumb'] or item['thumb'] == '':
- user_thumb = common.DEFAULT_USER_THUMB
else:
- user_thumb = item['thumb']
+ friendly_name = item['username']
- user_details = {"user_id": item['user_id'],
- "username": item['username'],
- "friendly_name": friendly_name,
- "email": item['email'],
- "thumb": user_thumb,
- "is_home_user": item['is_home_user'],
- "is_allow_sync": item['is_allow_sync'],
- "is_restricted": item['is_restricted'],
- "do_notify": item['do_notify']
+ if item['custom_thumb'] and item['custom_thumb'] != item['user_thumb']:
+ user_thumb = item['custom_thumb']
+ elif item['user_thumb']:
+ user_thumb = item['user_thumb']
+ else:
+ user_thumb = common.DEFAULT_USER_THUMB
+
+ user_details = {'user_id': item['user_id'],
+ 'username': item['username'],
+ 'friendly_name': friendly_name,
+ 'user_thumb': user_thumb,
+ 'email': item['email'],
+ 'is_home_user': item['is_home_user'],
+ 'is_allow_sync': item['is_allow_sync'],
+ 'is_restricted': item['is_restricted'],
+ 'do_notify': item['do_notify'],
+ 'keep_history': item['keep_history']
}
return user_details
else:
# If there is no user data we must return something
# Use "Local" user to retain compatibility with PlexWatch database value
- return {"user_id": None,
- "username": 'Local',
- "friendly_name": 'Local',
- "email": '',
- "thumb": '',
- "is_home_user": 0,
- "is_allow_sync": 0,
- "is_restricted": 0,
- "do_notify": 0
+ return {'user_id': None,
+ 'username': 'Local',
+ 'friendly_name': 'Local',
+ 'user_thumb': common.DEFAULT_USER_THUMB,
+ 'email': '',
+ 'is_home_user': 0,
+ 'is_allow_sync': 0,
+ 'is_restricted': 0,
+ 'do_notify': 0,
+ 'keep_history': 0
}
- def get_user_watch_time_stats(self, user=None, user_id=None):
+ def get_watch_time_stats(self, user_id=None):
monitor_db = database.MonitorDatabase()
time_queries = [1, 7, 30, 0]
user_watch_time_stats = []
for days in time_queries:
- if days > 0:
- if user_id:
- query = 'SELECT (SUM(stopped - started) - ' \
- 'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
- 'COUNT(id) AS total_plays ' \
- 'FROM session_history ' \
- 'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
- 'AND user_id = ?' % days
- result = monitor_db.select(query, args=[user_id])
- elif user:
- query = 'SELECT (SUM(stopped - started) - ' \
- 'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
- 'COUNT(id) AS total_plays ' \
- 'FROM session_history ' \
- 'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
- 'AND user = ?' % days
- result = monitor_db.select(query, args=[user])
- else:
- query = 'SELECT (SUM(stopped - started) - ' \
- 'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
- 'COUNT(id) AS total_plays ' \
- 'FROM session_history ' \
- 'WHERE user = ?'
- result = monitor_db.select(query, args=[user])
+ try:
+ if days > 0:
+ if str(user_id).isdigit():
+ query = 'SELECT (SUM(stopped - started) - ' \
+ ' SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
+ 'COUNT(id) AS total_plays ' \
+ 'FROM session_history ' \
+ 'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
+ 'AND user_id = ?' % days
+ result = monitor_db.select(query, args=[user_id])
+ else:
+ result = []
+ else:
+ if str(user_id).isdigit():
+ query = 'SELECT (SUM(stopped - started) - ' \
+ ' SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
+ 'COUNT(id) AS total_plays ' \
+ 'FROM session_history ' \
+ 'WHERE user_id = ?'
+ result = monitor_db.select(query, args=[user_id])
+ else:
+ result = []
+ except Exception as e:
+ logger.warn(u"PlexPy Users :: Unable to execute database query for get_watch_time_stats: %s." % e)
+ result = []
for item in result:
if item['total_time']:
@@ -500,14 +384,14 @@ class Users(object):
return user_watch_time_stats
- def get_user_player_stats(self, user=None, user_id=None):
+ def get_player_stats(self, user_id=None):
monitor_db = database.MonitorDatabase()
player_stats = []
result_id = 0
try:
- if user_id:
+ if str(user_id).isdigit():
query = 'SELECT player, COUNT(player) as player_count, platform ' \
'FROM session_history ' \
'WHERE user_id = ? ' \
@@ -515,15 +399,10 @@ class Users(object):
'ORDER BY player_count DESC'
result = monitor_db.select(query, args=[user_id])
else:
- query = 'SELECT player, COUNT(player) as player_count, platform ' \
- 'FROM session_history ' \
- 'WHERE user = ? ' \
- 'GROUP BY player ' \
- 'ORDER BY player_count DESC'
- result = monitor_db.select(query, args=[user])
- except:
- logger.warn("Unable to execute database query.")
- return None
+ result = []
+ except Exception as e:
+ logger.warn(u"PlexPy Users :: Unable to execute database query for get_player_stats: %s." % e)
+ result = []
for item in result:
# Rename Mystery platform names
@@ -538,3 +417,140 @@ class Users(object):
result_id += 1
return player_stats
+
+ def get_recently_watched(self, user_id=None, limit='10'):
+ monitor_db = database.MonitorDatabase()
+ recently_watched = []
+
+ if not limit.isdigit():
+ limit = '10'
+
+ try:
+ if str(user_id).isdigit():
+ query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, session_history.parent_rating_key, ' \
+ 'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_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 = ? ' \
+ 'GROUP BY (CASE WHEN session_history.media_type = "track" THEN session_history.parent_rating_key ' \
+ ' ELSE session_history.rating_key END) ' \
+ 'ORDER BY started DESC LIMIT ?'
+ result = monitor_db.select(query, args=[user_id, limit])
+ else:
+ result = []
+ except Exception as e:
+ logger.warn(u"PlexPy Users :: Unable to execute database query for get_recently_watched: %s." % e)
+ result = []
+
+ for row in result:
+ if row['media_type'] == 'episode' and row['parent_thumb']:
+ thumb = row['parent_thumb']
+ elif row['media_type'] == 'episode':
+ thumb = row['grandparent_thumb']
+ else:
+ thumb = row['thumb']
+
+ recent_output = {'row_id': row['id'],
+ 'type': row['media_type'],
+ 'rating_key': row['rating_key'],
+ 'title': row['title'],
+ 'parent_title': row['parent_title'],
+ 'grandparent_title': row['grandparent_title'],
+ 'thumb': thumb,
+ 'media_index': row['media_index'],
+ 'parent_media_index': row['parent_media_index'],
+ 'year': row['year'],
+ 'time': row['started'],
+ 'user': row['user']
+ }
+ recently_watched.append(recent_output)
+
+ return recently_watched
+
+ def delete_all_history(self, user_id=None):
+ monitor_db = database.MonitorDatabase()
+
+ try:
+ if str(user_id).isdigit():
+ logger.info(u"PlexPy DataFactory :: Deleting all history for user id %s from database." % user_id)
+ session_history_media_info_del = \
+ monitor_db.action('DELETE FROM '
+ 'session_history_media_info '
+ 'WHERE session_history_media_info.id IN (SELECT session_history_media_info.id '
+ 'FROM session_history_media_info '
+ 'JOIN session_history ON session_history_media_info.id = session_history.id '
+ 'WHERE session_history.user_id = ?)', [user_id])
+ session_history_metadata_del = \
+ monitor_db.action('DELETE FROM '
+ 'session_history_metadata '
+ 'WHERE session_history_metadata.id IN (SELECT session_history_metadata.id '
+ 'FROM session_history_metadata '
+ 'JOIN session_history ON session_history_metadata.id = session_history.id '
+ 'WHERE session_history.user_id = ?)', [user_id])
+ session_history_del = \
+ monitor_db.action('DELETE FROM '
+ 'session_history '
+ 'WHERE session_history.user_id = ?', [user_id])
+
+ return 'Deleted all items for user_id %s.' % user_id
+ else:
+ return 'Unable to delete items. Input user_id not valid.'
+ except Exception as e:
+ logger.warn(u"PlexPy Users :: Unable to execute database query for delete_all_history: %s." % e)
+
+ def delete(self, user_id=None):
+ monitor_db = database.MonitorDatabase()
+
+ try:
+ if str(user_id).isdigit():
+ self.delete_all_history(user_id)
+ logger.info(u"PlexPy DataFactory :: Deleting user with id %s from database." % user_id)
+ monitor_db.action('UPDATE users SET deleted_user = 1 WHERE user_id = ?', [user_id])
+ monitor_db.action('UPDATE users SET keep_history = 0 WHERE user_id = ?', [user_id])
+ monitor_db.action('UPDATE users SET do_notify = 0 WHERE user_id = ?', [user_id])
+
+ return 'Deleted user with id %s.' % user_id
+ else:
+ return 'Unable to delete user, user_id not valid.'
+ except Exception as e:
+ logger.warn(u"PlexPy Users :: Unable to execute database query for delete: %s." % e)
+
+ def undelete(self, user_id=None, username=None):
+ monitor_db = database.MonitorDatabase()
+
+ try:
+ if user_id and str(user_id).isdigit():
+ logger.info(u"PlexPy DataFactory :: Re-adding user with id %s to database." % user_id)
+ monitor_db.action('UPDATE users SET deleted_user = 0 WHERE user_id = ?', [user_id])
+ monitor_db.action('UPDATE users SET keep_history = 1 WHERE user_id = ?', [user_id])
+ monitor_db.action('UPDATE users SET do_notify = 1 WHERE user_id = ?', [user_id])
+
+ return 'Re-added user with id %s.' % user_id
+ elif username:
+ logger.info(u"PlexPy DataFactory :: Re-adding user with username %s to database." % username)
+ monitor_db.action('UPDATE users SET deleted_user = 0 WHERE username = ?', [username])
+ monitor_db.action('UPDATE users SET keep_history = 1 WHERE username = ?', [username])
+ monitor_db.action('UPDATE users SET do_notify = 1 WHERE username = ?', [username])
+
+ return 'Re-added user with username %s.' % username
+ else:
+ return 'Unable to re-add user, user_id or username not valid.'
+ except Exception as e:
+ logger.warn(u"PlexPy Users :: Unable to execute database query for undelete: %s." % e)
+
+ # Keep method for PlexWatch import
+ def get_user_id(self, user=None):
+ if user:
+ try:
+ monitor_db = database.MonitorDatabase()
+ query = 'SELECT user_id FROM users WHERE username = ?'
+ result = monitor_db.select_single(query, args=[user])
+ if result:
+ return result['user_id']
+ else:
+ return None
+ except:
+ return None
+
+ return None
\ No newline at end of file
diff --git a/plexpy/webserve.py b/plexpy/webserve.py
index b43d1d44..0069b6e6 100644
--- a/plexpy/webserve.py
+++ b/plexpy/webserve.py
@@ -64,16 +64,8 @@ class WebInterface(object):
else:
raise cherrypy.HTTPRedirect("welcome")
- @cherrypy.expose
- def home(self):
- config = {
- "home_stats_length": plexpy.CONFIG.HOME_STATS_LENGTH,
- "home_stats_cards": plexpy.CONFIG.HOME_STATS_CARDS,
- "home_library_cards": plexpy.CONFIG.HOME_LIBRARY_CARDS,
- "pms_identifier": plexpy.CONFIG.PMS_IDENTIFIER,
- "pms_name": plexpy.CONFIG.PMS_NAME
- }
- return serve_template(templatename="index.html", title="Home", config=config)
+
+ ##### Welcome #####
@cherrypy.expose
def welcome(self, **kwargs):
@@ -108,6 +100,36 @@ class WebInterface(object):
else:
return serve_template(templatename="welcome.html", title="Welcome", config=config)
+ @cherrypy.expose
+ def discover(self, token=''):
+ """
+ Returns the servers that you own as a
+ list of dicts (formatted for selectize)
+ """
+ # Need to set token so result dont return http 401
+ plexpy.CONFIG.__setattr__('PMS_TOKEN', token)
+ plexpy.CONFIG.write()
+
+ result = plextv.PlexTV()
+ servers = result.discover()
+ if servers:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return servers
+
+
+ ##### Home #####
+
+ @cherrypy.expose
+ def home(self):
+ config = {
+ "home_stats_length": plexpy.CONFIG.HOME_STATS_LENGTH,
+ "home_stats_cards": plexpy.CONFIG.HOME_STATS_CARDS,
+ "home_library_cards": plexpy.CONFIG.HOME_LIBRARY_CARDS,
+ "pms_identifier": plexpy.CONFIG.PMS_IDENTIFIER,
+ "pms_name": plexpy.CONFIG.PMS_NAME
+ }
+ return serve_template(templatename="index.html", title="Home", config=config)
+
@cherrypy.expose
def get_date_formats(self):
if plexpy.CONFIG.DATE_FORMAT:
@@ -125,6 +147,43 @@ class WebInterface(object):
cherrypy.response.headers['Content-type'] = 'application/json'
return json.dumps(formats)
+ @cherrypy.expose
+ def get_current_activity(self, **kwargs):
+
+ try:
+ pms_connect = pmsconnect.PmsConnect()
+ result = pms_connect.get_current_activity()
+
+ data_factory = datafactory.DataFactory()
+ for session in result['sessions']:
+ if not session['ip_address']:
+ ip_address = data_factory.get_session_ip(session['session_key'])
+ session['ip_address'] = ip_address
+
+ except:
+ return serve_template(templatename="current_activity.html", data=None)
+
+ if result:
+ return serve_template(templatename="current_activity.html", data=result)
+ else:
+ logger.warn(u"Unable to retrieve data for get_current_activity.")
+ return serve_template(templatename="current_activity.html", data=None)
+
+ @cherrypy.expose
+ def get_current_activity_header(self, **kwargs):
+
+ try:
+ pms_connect = pmsconnect.PmsConnect()
+ result = pms_connect.get_current_activity()
+ except IOError, e:
+ return serve_template(templatename="current_activity_header.html", data=None)
+
+ if result:
+ return serve_template(templatename="current_activity_header.html", data=result['stream_count'])
+ else:
+ logger.warn(u"Unable to retrieve data for get_current_activity_header.")
+ return serve_template(templatename="current_activity_header.html", data=None)
+
@cherrypy.expose
def home_stats(self, **kwargs):
data_factory = datafactory.DataFactory()
@@ -156,127 +215,53 @@ class WebInterface(object):
return serve_template(templatename="library_stats.html", title="Library Stats", data=stats_data)
@cherrypy.expose
- def history(self):
- # Make sure our library sections are up to date.
- data_factory = datafactory.DataFactory()
- data_factory.update_library_sections()
+ def get_recently_added(self, count='0', **kwargs):
- return serve_template(templatename="history.html", title="History")
+ try:
+ pms_connect = pmsconnect.PmsConnect()
+ result = pms_connect.get_recently_added_details(count)
+ except IOError, e:
+ return serve_template(templatename="recently_added.html", data=None)
- @cherrypy.expose
- def users(self):
- return serve_template(templatename="users.html", title="Users")
+ if result:
+ return serve_template(templatename="recently_added.html", data=result['recently_added'])
+ else:
+ logger.warn(u"Unable to retrieve data for get_recently_added.")
+ return serve_template(templatename="recently_added.html", data=None)
+
+
+ ##### Libraries #####
@cherrypy.expose
def libraries(self):
return serve_template(templatename="libraries.html", title="Libraries")
@cherrypy.expose
- def graphs(self):
+ def get_library_list(self, **kwargs):
- config = {
- "graph_type": plexpy.CONFIG.GRAPH_TYPE,
- "graph_days": plexpy.CONFIG.GRAPH_DAYS,
- "graph_tab": plexpy.CONFIG.GRAPH_TAB,
- "music_logging_enable": plexpy.CONFIG.MUSIC_LOGGING_ENABLE
- }
+ library_data = libraries.Libraries()
+ library_list = library_data.get_datatables_list(kwargs=kwargs)
- return serve_template(templatename="graphs.html", title="Graphs", config=config)
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps(library_list)
@cherrypy.expose
- def sync(self):
- return serve_template(templatename="sync.html", title="Synced Items")
-
- @cherrypy.expose
- def user(self, user=None, user_id=None):
- user_data = users.Users()
- if user_id:
- try:
- user_details = user_data.get_user_details(user_id=user_id)
- except:
- logger.warn("Unable to retrieve friendly name for user_id %s " % user_id)
- elif user:
- try:
- user_details = user_data.get_user_details(user=user)
- except:
- logger.warn("Unable to retrieve friendly name for user %s " % user)
- else:
- logger.debug(u"User page requested but no parameters received.")
- raise cherrypy.HTTPRedirect("home")
-
- return serve_template(templatename="user.html", title="User", data=user_details)
-
- @cherrypy.expose
- def edit_user_dialog(self, user=None, user_id=None, **kwargs):
- user_data = users.Users()
- if user_id:
- result = user_data.get_user_friendly_name(user_id=user_id)
- status_message = ''
- elif user:
- result = user_data.get_user_friendly_name(user=user)
- status_message = ''
- else:
- result = None
- status_message = 'An error occured.'
-
- return serve_template(templatename="edit_user.html", title="Edit User", data=result, status_message=status_message)
-
- @cherrypy.expose
- def edit_user(self, user=None, user_id=None, friendly_name=None, **kwargs):
- if 'do_notify' in kwargs:
- do_notify = kwargs.get('do_notify')
- else:
- do_notify = 0
- if 'keep_history' in kwargs:
- keep_history = kwargs.get('keep_history')
- else:
- keep_history = 0
- if 'thumb' in kwargs:
- custom_avatar = kwargs['thumb']
- else:
- custom_avatar = ''
-
- user_data = users.Users()
- if user_id:
- try:
- user_data.set_user_friendly_name(user_id=user_id,
- friendly_name=friendly_name,
- do_notify=do_notify,
- keep_history=keep_history)
- user_data.set_user_profile_url(user_id=user_id,
- profile_url=custom_avatar)
-
- status_message = "Successfully updated user."
- return status_message
- except:
- status_message = "Failed to update user."
- return status_message
- if user:
- try:
- user_data.set_user_friendly_name(user=user,
- friendly_name=friendly_name,
- do_notify=do_notify,
- keep_history=keep_history)
- user_data.set_user_profile_url(user=user,
- profile_url=custom_avatar)
-
- status_message = "Successfully updated user."
- return status_message
- except:
- status_message = "Failed to update user."
- return status_message
+ def refresh_libraries_list(self, **kwargs):
+ threading.Thread(target=pmsconnect.refresh_libraries).start()
+ logger.info(u"Manual libraries list refresh requested.")
@cherrypy.expose
def library(self, section_id=None):
library_data = libraries.Libraries()
if section_id:
try:
- library_details = library_data.get_library_details(section_id=section_id)
+ library_details = library_data.get_details(section_id=section_id)
except:
- logger.warn("Unable to retrieve user details for library_id %s " % section_id)
+ logger.warn(u"Unable to retrieve library details for section_id %s " % section_id)
+ return serve_template(templatename="library.html", title="Library", data=None)
else:
- logger.debug(u"Library page requested but no parameters received.")
- raise cherrypy.HTTPRedirect("home")
+ logger.debug(u"Library page requested but no section_id received.")
+ return serve_template(templatename="library.html", title="Library", data=None)
return serve_template(templatename="library.html", title="Library", data=library_details)
@@ -284,7 +269,7 @@ class WebInterface(object):
def edit_library_dialog(self, section_id=None, **kwargs):
library_data = libraries.Libraries()
if section_id:
- result = library_data.get_library_details(section_id=section_id)
+ result = library_data.get_details(section_id=section_id)
status_message = ''
else:
result = None
@@ -294,17 +279,19 @@ class WebInterface(object):
@cherrypy.expose
def edit_library(self, section_id=None, **kwargs):
- do_notify = kwargs.get('do_notify', 0)
- keep_history = kwargs.get('keep_history', 0)
custom_thumb = kwargs.get('custom_thumb', '')
+ do_notify = kwargs.get('do_notify', 0)
+ do_notify_created = kwargs.get('do_notify_created', 0)
+ keep_history = kwargs.get('keep_history', 0)
library_data = libraries.Libraries()
if section_id:
try:
- library_data.set_library_config(section_id=section_id,
- do_notify=do_notify,
- keep_history=keep_history,
- custom_thumb=custom_thumb)
+ library_data.set_config(section_id=section_id,
+ custom_thumb=custom_thumb,
+ do_notify=do_notify,
+ do_notify_created=do_notify_created,
+ keep_history=keep_history)
status_message = "Successfully updated library."
return status_message
@@ -312,6 +299,302 @@ class WebInterface(object):
status_message = "Failed to update library."
return status_message
+ @cherrypy.expose
+ def get_library_watch_time_stats(self, library_id=None, **kwargs):
+
+ library_data = libraries.Libraries()
+ result = library_data.get_watch_time_stats(library_id=library_id)
+
+ if result:
+ return serve_template(templatename="user_watch_time_stats.html", data=result, title="Watch Stats")
+ else:
+ logger.warn(u"Unable to retrieve data for get_library_watch_time_stats.")
+ return serve_template(templatename="user_watch_time_stats.html", data=None, title="Watch Stats")
+
+ @cherrypy.expose
+ def get_library_user_stats(self, library_id=None, **kwargs):
+
+ library_data = libraries.Libraries()
+ result = library_data.get_user_stats(library_id=library_id)
+
+ if result:
+ return serve_template(templatename="library_user_stats.html", data=result, title="Player Stats")
+ else:
+ logger.warn(u"Unable to retrieve data for get_library_user_stats.")
+ return serve_template(templatename="library_user_stats.html", data=None, title="Player Stats")
+
+ @cherrypy.expose
+ def get_library_recently_watched(self, library_id=None, limit='10', **kwargs):
+
+ library_data = libraries.Libraries()
+ result = library_data.get_recently_watched(library_id=library_id, limit=limit)
+
+ if result:
+ return serve_template(templatename="user_recently_watched.html", data=result, title="Recently Watched")
+ else:
+ logger.warn(u"Unable to retrieve data for get_library_recently_watched.")
+ return serve_template(templatename="user_recently_watched.html", data=None, title="Recently Watched")
+
+ @cherrypy.expose
+ def delete_all_library_history(self, section_id, **kwargs):
+ library_data = libraries.Libraries()
+
+ if section_id:
+ delete_row = library_data.delete_all_history(section_id=section_id)
+
+ if delete_row:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps({'message': delete_row})
+ else:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps({'message': 'no data received'})
+
+ @cherrypy.expose
+ def delete_library(self, section_id, **kwargs):
+ library_data = libraries.Libraries()
+
+ if section_id:
+ delete_row = library_data.delete(section_id=section_id)
+
+ if delete_row:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps({'message': delete_row})
+ else:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps({'message': 'no data received'})
+
+ @cherrypy.expose
+ def undelete_library(self, section_id=None, section_name=None, **kwargs):
+ library_data = libraries.Libraries()
+
+ if section_id:
+ delete_row = library_data.undelete(section_id=section_id)
+
+ if delete_row:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps({'message': delete_row})
+ elif section_name:
+ delete_row = library_data.undelete(section_name=section_name)
+
+ if delete_row:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps({'message': delete_row})
+ else:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps({'message': 'no data received'})
+
+
+ ##### Users #####
+
+ @cherrypy.expose
+ def users(self):
+ return serve_template(templatename="users.html", title="Users")
+
+ @cherrypy.expose
+ def get_user_list(self, **kwargs):
+
+ user_data = users.Users()
+ user_list = user_data.get_datatables_list(kwargs=kwargs)
+
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps(user_list)
+
+ @cherrypy.expose
+ def refresh_users_list(self, **kwargs):
+ threading.Thread(target=plextv.refresh_users).start()
+ logger.info(u"Manual users list refresh requested.")
+
+ @cherrypy.expose
+ def user(self, user_id=None):
+ user_data = users.Users()
+ if user_id:
+ try:
+ user_details = user_data.get_details(user_id=user_id)
+ except:
+ logger.warn(u"Unable to retrieve user details for user_id %s " % user_id)
+ return serve_template(templatename="user.html", title="User", data=None)
+ else:
+ logger.debug(u"User page requested but no user_id received.")
+ return serve_template(templatename="user.html", title="User", data=None)
+
+ return serve_template(templatename="user.html", title="User", data=user_details)
+
+ @cherrypy.expose
+ def edit_user_dialog(self, user=None, user_id=None, **kwargs):
+ user_data = users.Users()
+ if user_id:
+ result = user_data.get_details(user_id=user_id)
+ status_message = ''
+ else:
+ result = None
+ status_message = 'An error occured.'
+
+ return serve_template(templatename="edit_user.html", title="Edit User", data=result, status_message=status_message)
+
+ @cherrypy.expose
+ def edit_user(self, user_id=None, **kwargs):
+ friendly_name = kwargs.get('friendly_name', '')
+ custom_thumb = kwargs.get('custom_thumb', '')
+ do_notify = kwargs.get('do_notify', 0)
+ keep_history = kwargs.get('keep_history', 0)
+
+ user_data = users.Users()
+ if user_id:
+ try:
+ user_data.set_config(user_id=user_id,
+ friendly_name=friendly_name,
+ custom_thumb=custom_thumb,
+ do_notify=do_notify,
+ keep_history=keep_history)
+ status_message = "Successfully updated user."
+ return status_message
+ except:
+ status_message = "Failed to update user."
+ return status_message
+
+ @cherrypy.expose
+ def get_user_watch_time_stats(self, user=None, user_id=None, **kwargs):
+
+ user_data = users.Users()
+ result = user_data.get_watch_time_stats(user_id=user_id)
+
+ if result:
+ return serve_template(templatename="user_watch_time_stats.html", data=result, title="Watch Stats")
+ else:
+ logger.warn(u"Unable to retrieve data for get_user_watch_time_stats.")
+ return serve_template(templatename="user_watch_time_stats.html", data=None, title="Watch Stats")
+
+ @cherrypy.expose
+ def get_user_player_stats(self, user=None, user_id=None, **kwargs):
+
+ user_data = users.Users()
+ result = user_data.get_player_stats(user_id=user_id)
+
+ if result:
+ return serve_template(templatename="user_player_stats.html", data=result, title="Player Stats")
+ else:
+ logger.warn(u"Unable to retrieve data for get_user_player_stats.")
+ return serve_template(templatename="user_player_stats.html", data=None, title="Player Stats")
+
+ @cherrypy.expose
+ def get_user_recently_watched(self, user=None, user_id=None, limit='10', **kwargs):
+
+ user_data = users.Users()
+ result = user_data.get_recently_watched(user_id=user_id, limit=limit)
+
+ if result:
+ return serve_template(templatename="user_recently_watched.html", data=result, title="Recently Watched")
+ else:
+ logger.warn(u"Unable to retrieve data for get_user_recently_watched.")
+ return serve_template(templatename="user_recently_watched.html", data=None, title="Recently Watched")
+
+ @cherrypy.expose
+ def get_user_ips(self, user_id=None, **kwargs):
+
+ user_data = users.Users()
+ history = user_data.get_datatables_unique_ips(user_id=user_id, kwargs=kwargs)
+
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps(history)
+
+ @cherrypy.expose
+ def delete_all_user_history(self, user_id, **kwargs):
+ user_data = users.Users()
+
+ if user_id:
+ delete_row = user_data.delete_all_history(user_id=user_id)
+ if delete_row:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps({'message': delete_row})
+ else:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps({'message': 'no data received'})
+
+ @cherrypy.expose
+ def delete_user(self, user_id, **kwargs):
+ user_data = users.Users()
+
+ if user_id:
+ delete_row = user_data.delete(user_id=user_id)
+
+ if delete_row:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps({'message': delete_row})
+ else:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps({'message': 'no data received'})
+
+ @cherrypy.expose
+ def undelete_user(self, user_id=None, username=None, **kwargs):
+ user_data = users.Users()
+
+ if user_id:
+ delete_row = user_data.undelete(user_id=user_id)
+
+ if delete_row:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps({'message': delete_row})
+ elif username:
+ delete_row = delete_user.undelete(username=username)
+
+ if delete_row:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps({'message': delete_row})
+ else:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps({'message': 'no data received'})
+
+
+ ##### History #####
+
+ @cherrypy.expose
+ def history(self):
+ return serve_template(templatename="history.html", title="History")
+
+ @cherrypy.expose
+ def get_history(self, user=None, user_id=None, grouping=0, **kwargs):
+
+ if grouping == 'false':
+ grouping = 0
+ else:
+ grouping = plexpy.CONFIG.GROUP_HISTORY_TABLES
+
+ watched_percent = plexpy.CONFIG.NOTIFY_WATCHED_PERCENT
+
+ custom_where = []
+ if user_id:
+ custom_where.append(['session_history.user_id', user_id])
+ elif user:
+ custom_where.append(['session_history.user', user])
+ if 'rating_key' in kwargs:
+ rating_key = kwargs.get('rating_key', "")
+ custom_where.append(['session_history.rating_key', rating_key])
+ if 'parent_rating_key' in kwargs:
+ rating_key = kwargs.get('parent_rating_key', "")
+ custom_where.append(['session_history.parent_rating_key', rating_key])
+ if 'grandparent_rating_key' in kwargs:
+ rating_key = kwargs.get('grandparent_rating_key', "")
+ custom_where.append(['session_history.grandparent_rating_key', rating_key])
+ if 'start_date' in kwargs:
+ start_date = kwargs.get('start_date', "")
+ custom_where.append(['strftime("%Y-%m-%d", datetime(started, "unixepoch", "localtime"))', start_date])
+ if 'reference_id' in kwargs:
+ reference_id = kwargs.get('reference_id', "")
+ custom_where.append(['session_history.reference_id', reference_id])
+ if 'section_id' in kwargs:
+ section_id = kwargs.get('section_id', "")
+ custom_where.append(['session_history_metadata.library_id', section_id])
+ if 'media_type' in kwargs:
+ media_type = kwargs.get('media_type', "")
+ if media_type != 'all':
+ custom_where.append(['session_history.media_type', media_type])
+
+ data_factory = datafactory.DataFactory()
+ history = data_factory.get_datatables_history(kwargs=kwargs, custom_where=custom_where, grouping=grouping, watched_percent=watched_percent)
+
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps(history)
+
@cherrypy.expose
def get_stream_data(self, row_id=None, user=None, **kwargs):
@@ -332,49 +615,220 @@ class WebInterface(object):
return serve_template(templatename="ip_address_modal.html", title="IP Address Details", data=ip_address)
@cherrypy.expose
- def get_user_list(self, **kwargs):
+ def delete_history_rows(self, row_id, **kwargs):
+ data_factory = datafactory.DataFactory()
- user_data = users.Users()
- user_list = user_data.get_user_list(kwargs=kwargs)
+ if row_id:
+ delete_row = data_factory.delete_session_history_rows(row_id=row_id)
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps(user_list)
+ if delete_row:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps({'message': delete_row})
+ else:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps({'message': 'no data received'})
+
+
+ ##### Graphs #####
@cherrypy.expose
- def get_library_list(self, **kwargs):
+ def graphs(self):
- library_data = libraries.Libraries()
- library_list = library_data.get_library_list(kwargs=kwargs)
+ config = {
+ "graph_type": plexpy.CONFIG.GRAPH_TYPE,
+ "graph_days": plexpy.CONFIG.GRAPH_DAYS,
+ "graph_tab": plexpy.CONFIG.GRAPH_TAB,
+ "music_logging_enable": plexpy.CONFIG.MUSIC_LOGGING_ENABLE
+ }
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps(library_list)
+ return serve_template(templatename="graphs.html", title="Graphs", config=config)
@cherrypy.expose
- def checkGithub(self):
- from plexpy import versioncheck
+ def set_graph_config(self, graph_type=None, graph_days=None, graph_tab=None):
+ if graph_type:
+ plexpy.CONFIG.__setattr__('GRAPH_TYPE', graph_type)
+ plexpy.CONFIG.write()
+ if graph_days:
+ plexpy.CONFIG.__setattr__('GRAPH_DAYS', graph_days)
+ plexpy.CONFIG.write()
+ if graph_tab:
+ plexpy.CONFIG.__setattr__('GRAPH_TAB', graph_tab)
+ plexpy.CONFIG.write()
- versioncheck.checkGithub()
- raise cherrypy.HTTPRedirect("home")
+ return "Updated graphs config values."
+
+ @cherrypy.expose
+ def get_plays_by_date(self, time_range='30', y_axis='plays', **kwargs):
+
+ graph = graphs.Graphs()
+ result = graph.get_total_plays_per_day(time_range=time_range, y_axis=y_axis)
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps(result)
+ else:
+ logger.warn(u"Unable to retrieve data for get_plays_by_date.")
+
+ @cherrypy.expose
+ def get_plays_by_dayofweek(self, time_range='30', y_axis='plays', **kwargs):
+
+ graph = graphs.Graphs()
+ result = graph.get_total_plays_per_dayofweek(time_range=time_range, y_axis=y_axis)
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps(result)
+ else:
+ logger.warn(u"Unable to retrieve data for get_plays_by_dayofweek.")
+
+ @cherrypy.expose
+ def get_plays_by_hourofday(self, time_range='30', y_axis='plays', **kwargs):
+
+ graph = graphs.Graphs()
+ result = graph.get_total_plays_per_hourofday(time_range=time_range, y_axis=y_axis)
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps(result)
+ else:
+ logger.warn(u"Unable to retrieve data for get_plays_by_hourofday.")
+
+ @cherrypy.expose
+ def get_plays_per_month(self, y_axis='plays', **kwargs):
+
+ graph = graphs.Graphs()
+ result = graph.get_total_plays_per_month(y_axis=y_axis)
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps(result)
+ else:
+ logger.warn(u"Unable to retrieve data for get_plays_per_month.")
+
+ @cherrypy.expose
+ def get_plays_by_top_10_platforms(self, time_range='30', y_axis='plays', **kwargs):
+
+ graph = graphs.Graphs()
+ result = graph.get_total_plays_by_top_10_platforms(time_range=time_range, y_axis=y_axis)
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps(result)
+ else:
+ logger.warn(u"Unable to retrieve data for get_plays_by_top_10_platforms.")
+
+ @cherrypy.expose
+ def get_plays_by_top_10_users(self, time_range='30', y_axis='plays', **kwargs):
+
+ graph = graphs.Graphs()
+ result = graph.get_total_plays_by_top_10_users(time_range=time_range, y_axis=y_axis)
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps(result)
+ else:
+ logger.warn(u"Unable to retrieve data for get_plays_by_top_10_users.")
+
+ @cherrypy.expose
+ def get_plays_by_stream_type(self, time_range='30', y_axis='plays', **kwargs):
+
+ graph = graphs.Graphs()
+ result = graph.get_total_plays_per_stream_type(time_range=time_range, y_axis=y_axis)
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps(result)
+ else:
+ logger.warn(u"Unable to retrieve data for get_plays_by_stream_type.")
+
+ @cherrypy.expose
+ def get_plays_by_source_resolution(self, time_range='30', y_axis='plays', **kwargs):
+
+ graph = graphs.Graphs()
+ result = graph.get_total_plays_by_source_resolution(time_range=time_range, y_axis=y_axis)
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps(result)
+ else:
+ logger.warn(u"Unable to retrieve data for get_plays_by_source_resolution.")
+
+ @cherrypy.expose
+ def get_plays_by_stream_resolution(self, time_range='30', y_axis='plays', **kwargs):
+
+ graph = graphs.Graphs()
+ result = graph.get_total_plays_by_stream_resolution(time_range=time_range, y_axis=y_axis)
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps(result)
+ else:
+ logger.warn(u"Unable to retrieve data for get_plays_by_stream_resolution.")
+
+ @cherrypy.expose
+ def get_stream_type_by_top_10_users(self, time_range='30', y_axis='plays', **kwargs):
+
+ graph = graphs.Graphs()
+ result = graph.get_stream_type_by_top_10_users(time_range=time_range, y_axis=y_axis)
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps(result)
+ else:
+ logger.warn(u"Unable to retrieve data for get_stream_type_by_top_10_users.")
+
+ @cherrypy.expose
+ def get_stream_type_by_top_10_platforms(self, time_range='30', y_axis='plays', **kwargs):
+
+ graph = graphs.Graphs()
+ result = graph.get_stream_type_by_top_10_platforms(time_range=time_range, y_axis=y_axis)
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps(result)
+ else:
+ logger.warn(u"Unable to retrieve data for get_stream_type_by_top_10_platforms.")
+
+ @cherrypy.expose
+ def history_table_modal(self, start_date=None, **kwargs):
+
+ return serve_template(templatename="history_table_modal.html", title="History Data", data=start_date)
+
+
+ ##### Sync #####
+
+ @cherrypy.expose
+ def sync(self):
+ return serve_template(templatename="sync.html", title="Synced Items")
+
+ @cherrypy.expose
+ def get_sync(self, machine_id=None, user_id=None, **kwargs):
+
+ pms_connect = pmsconnect.PmsConnect()
+ server_id = pms_connect.get_server_identity()
+
+ plex_tv = plextv.PlexTV()
+ if not machine_id:
+ result = plex_tv.get_synced_items(machine_id=server_id['machine_identifier'], user_id=user_id)
+ else:
+ result = plex_tv.get_synced_items(machine_id=machine_id, user_id=user_id)
+
+ if result:
+ output = {"data": result}
+ else:
+ logger.warn(u"Unable to retrieve data for get_sync.")
+ output = {"data": []}
+
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps(output)
+
+
+ ##### Logs #####
@cherrypy.expose
def logs(self):
return serve_template(templatename="logs.html", title="Log", lineList=plexpy.LOG_LIST)
- @cherrypy.expose
- def clearLogs(self):
- plexpy.LOG_LIST = []
- logger.info("Web logs cleared")
- raise cherrypy.HTTPRedirect("logs")
-
- @cherrypy.expose
- def toggleVerbose(self):
- plexpy.VERBOSE = not plexpy.VERBOSE
- logger.initLogger(console=not plexpy.QUIET,
- log_dir=plexpy.CONFIG.LOG_DIR, verbose=plexpy.VERBOSE)
- logger.info("Verbose toggled, set to %s", plexpy.VERBOSE)
- logger.debug("If you read this message, debug logging is available")
- raise cherrypy.HTTPRedirect("logs")
-
@cherrypy.expose
def getLog(self, start=0, length=100, **kwargs):
start = int(start)
@@ -424,16 +878,29 @@ class WebInterface(object):
try:
log_lines = {'data': log_reader.get_log_tail(window=window)}
except:
- logger.warn("Unable to retrieve Plex Logs.")
+ logger.warn(u"Unable to retrieve Plex Logs.")
cherrypy.response.headers['Content-type'] = 'application/json'
return json.dumps(log_lines)
@cherrypy.expose
- def generateAPI(self):
- apikey = hashlib.sha224(str(random.getrandbits(256))).hexdigest()[0:32]
- logger.info("New API generated")
- return apikey
+ def clearLogs(self):
+ plexpy.LOG_LIST = []
+ logger.info(u"Web logs cleared")
+ raise cherrypy.HTTPRedirect("logs")
+
+ @cherrypy.expose
+ def toggleVerbose(self):
+ plexpy.VERBOSE = not plexpy.VERBOSE
+ logger.initLogger(console=not plexpy.QUIET,
+ log_dir=plexpy.CONFIG.LOG_DIR, verbose=plexpy.VERBOSE)
+ logger.info(u"Verbose toggled, set to %s", plexpy.VERBOSE)
+ logger.debug(u"If you read this message, debug logging is available")
+ raise cherrypy.HTTPRedirect("logs")
+
+
+
+ ##### Settings #####
@cherrypy.expose
def settings(self):
@@ -624,10 +1091,10 @@ class WebInterface(object):
# Get new server URLs for SSL communications.
plextv.get_real_pms_url()
-
- # Get new server friendly name
+
+ # Get new server friendly name.
pmsconnect.get_server_friendly_name()
-
+
# Reconfigure scheduler if intervals changed
if reschedule:
plexpy.initialize_scheduler()
@@ -642,919 +1109,6 @@ class WebInterface(object):
raise cherrypy.HTTPRedirect("settings")
- @cherrypy.expose
- def set_notification_config(self, **kwargs):
-
- for plain_config, use_config in [(x[4:], x) for x in kwargs if x.startswith('use_')]:
- # the use prefix is fairly nice in the html, but does not match the actual config
- kwargs[plain_config] = kwargs[use_config]
- del kwargs[use_config]
-
- plexpy.CONFIG.process_kwargs(kwargs)
-
- # Write the config
- plexpy.CONFIG.write()
-
- cherrypy.response.status = 200
-
- @cherrypy.expose
- def do_state_change(self, signal, title, timer):
- message = title
- quote = self.random_arnold_quotes()
- plexpy.SIGNAL = signal
-
- return serve_template(templatename="shutdown.html", title=title,
- message=message, timer=timer, quote=quote)
-
- @cherrypy.expose
- def get_history(self, user=None, user_id=None, grouping=0, **kwargs):
-
- if grouping == 'false':
- grouping = 0
- else:
- grouping = plexpy.CONFIG.GROUP_HISTORY_TABLES
-
- watched_percent = plexpy.CONFIG.NOTIFY_WATCHED_PERCENT
-
- custom_where = []
- if user_id:
- custom_where.append(['session_history.user_id', user_id])
- elif user:
- custom_where.append(['session_history.user', user])
- if 'rating_key' in kwargs:
- rating_key = kwargs.get('rating_key', "")
- custom_where.append(['session_history.rating_key', rating_key])
- if 'parent_rating_key' in kwargs:
- rating_key = kwargs.get('parent_rating_key', "")
- custom_where.append(['session_history.parent_rating_key', rating_key])
- if 'grandparent_rating_key' in kwargs:
- rating_key = kwargs.get('grandparent_rating_key', "")
- custom_where.append(['session_history.grandparent_rating_key', rating_key])
- if 'start_date' in kwargs:
- start_date = kwargs.get('start_date', "")
- custom_where.append(['strftime("%Y-%m-%d", datetime(started, "unixepoch", "localtime"))', start_date])
- if 'reference_id' in kwargs:
- reference_id = kwargs.get('reference_id', "")
- custom_where.append(['session_history.reference_id', reference_id])
- if 'section_id' in kwargs:
- section_id = kwargs.get('section_id', "")
- custom_where.append(['session_history_metadata.library_id', section_id])
- if 'media_type' in kwargs:
- media_type = kwargs.get('media_type', "")
- if media_type != 'all':
- custom_where.append(['session_history.media_type', media_type])
-
- data_factory = datafactory.DataFactory()
- history = data_factory.get_history(kwargs=kwargs, custom_where=custom_where, grouping=grouping, watched_percent=watched_percent)
-
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps(history)
-
- @cherrypy.expose
- def history_table_modal(self, start_date=None, **kwargs):
-
- return serve_template(templatename="history_table_modal.html", title="History Data", data=start_date)
-
- @cherrypy.expose
- def shutdown(self):
- return self.do_state_change('shutdown', 'Shutting Down', 15)
-
- @cherrypy.expose
- def restart(self):
- return self.do_state_change('restart', 'Restarting', 30)
-
- @cherrypy.expose
- def update(self):
- return self.do_state_change('update', 'Updating', 120)
-
- @cherrypy.expose
- def api(self, *args, **kwargs):
- from plexpy.api import Api
-
- a = Api()
- a.checkParams(*args, **kwargs)
-
- return a.fetchData()
-
- @cherrypy.expose
- def test_notifier(self, config_id=None, subject='PlexPy', body='Test notification', **kwargs):
- cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
-
- if config_id.isdigit():
- agents = notifiers.available_notification_agents()
- for agent in agents:
- if int(config_id) == agent['id']:
- this_agent = agent
- break
- else:
- this_agent = None
-
- if this_agent:
- logger.debug("Sending test %s notification." % this_agent['name'])
- notifiers.send_notification(this_agent['id'], subject, body, **kwargs)
- return "Notification sent."
- else:
- logger.debug("Unable to send test notification, invalid notification agent ID %s." % config_id)
- return "Invalid notification agent ID %s." % config_id
- else:
- logger.debug("Unable to send test notification, no notification agent ID received.")
- return "No notification agent ID received."
-
- @cherrypy.expose
- def twitterStep1(self):
- cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
- tweet = notifiers.TwitterNotifier()
- return tweet._get_authorization()
-
- @cherrypy.expose
- def twitterStep2(self, key):
- cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
- tweet = notifiers.TwitterNotifier()
- result = tweet._get_credentials(key)
- # logger.info(u"result: " + str(result))
- if result:
- return "Key verification successful"
- else:
- return "Unable to verify key"
-
- @cherrypy.expose
- def facebookStep1(self):
- cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
- facebook = notifiers.FacebookNotifier()
- return facebook._get_authorization()
-
- @cherrypy.expose
- def facebookStep2(self, code):
- cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
- facebook = notifiers.FacebookNotifier()
- result = facebook._get_credentials(code)
- # logger.info(u"result: " + str(result))
- if result:
- return "Key verification successful, you may close this page now."
- else:
- return "Unable to verify key"
-
- @cherrypy.expose
- def osxnotifyregister(self, app):
- cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
- from osxnotify import registerapp as osxnotify
-
- result, msg = osxnotify.registerapp(app)
- if result:
- osx_notify = notifiers.OSX_NOTIFY()
- osx_notify.notify('Registered', result, 'Success :-)')
- logger.info('Registered %s, to re-register a different app, delete this app first' % result)
- else:
- logger.warn(msg)
- return msg
-
- @cherrypy.expose
- def get_pms_token(self):
-
- token = plextv.PlexTV()
- result = token.get_token()
-
- if result:
- return result
- else:
- logger.warn('Unable to retrieve Plex.tv token.')
- return False
-
- @cherrypy.expose
- def get_pms_sessions_json(self, **kwargs):
-
- pms_connect = pmsconnect.PmsConnect()
- result = pms_connect.get_sessions('json')
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return result
- else:
- logger.warn('Unable to retrieve data.')
- return False
-
- @cherrypy.expose
- def get_current_activity(self, **kwargs):
-
- try:
- pms_connect = pmsconnect.PmsConnect()
- result = pms_connect.get_current_activity()
-
- data_factory = datafactory.DataFactory()
- for session in result['sessions']:
- if not session['ip_address']:
- ip_address = data_factory.get_session_ip(session['session_key'])
- session['ip_address'] = ip_address
-
- except:
- return serve_template(templatename="current_activity.html", data=None)
-
- if result:
- return serve_template(templatename="current_activity.html", data=result)
- else:
- logger.warn('Unable to retrieve data.')
- return serve_template(templatename="current_activity.html", data=None)
-
- @cherrypy.expose
- def get_current_activity_header(self, **kwargs):
-
- try:
- pms_connect = pmsconnect.PmsConnect()
- result = pms_connect.get_current_activity()
- except IOError, e:
- return serve_template(templatename="current_activity_header.html", data=None)
-
- if result:
- return serve_template(templatename="current_activity_header.html", data=result['stream_count'])
- else:
- logger.warn('Unable to retrieve data.')
- return serve_template(templatename="current_activity_header.html", data=None)
-
- @cherrypy.expose
- def get_recently_added(self, count='0', **kwargs):
-
- try:
- pms_connect = pmsconnect.PmsConnect()
- result = pms_connect.get_recently_added_details(count)
- except IOError, e:
- return serve_template(templatename="recently_added.html", data=None)
-
- if result:
- return serve_template(templatename="recently_added.html", data=result['recently_added'])
- else:
- logger.warn('Unable to retrieve data.')
- return serve_template(templatename="recently_added.html", data=None)
-
- @cherrypy.expose
- def pms_image_proxy(self, img='', width='0', height='0', fallback=None, **kwargs):
- try:
- pms_connect = pmsconnect.PmsConnect()
- result = pms_connect.get_image(img, width, height)
- cherrypy.response.headers['Content-type'] = result[1]
- return result[0]
- except:
- logger.warn('Image proxy queried but errors occured.')
- if fallback == 'poster':
- logger.info('Trying fallback image...')
- try:
- fallback_image = open(self.interface_dir + common.DEFAULT_POSTER_THUMB, 'rb')
- cherrypy.response.headers['Content-type'] = 'image/png'
- return fallback_image
- except IOError, e:
- logger.error('Unable to read fallback image. %s' % e)
- elif fallback == 'cover':
- logger.info('Trying fallback image...')
- try:
- fallback_image = open(self.interface_dir + common.DEFAULT_COVER_THUMB, 'rb')
- cherrypy.response.headers['Content-type'] = 'image/png'
- return fallback_image
- except IOError, e:
- logger.error('Unable to read fallback image. %s' % e)
-
- return None
-
- @cherrypy.expose
- def info(self, rating_key=None, source=None, **kwargs):
- # Make sure our library sections are up to date.
- data_factory = datafactory.DataFactory()
- data_factory.update_library_sections()
- # temporary until I find a beter place to put this
- #data_factory.update_library_ids()
-
- metadata = None
-
- config = {
- "pms_identifier": plexpy.CONFIG.PMS_IDENTIFIER,
- "update_library_ids": plexpy.CONFIG.UPDATE_LIBRARY_IDS
- }
-
- if source == 'history':
- data_factory = datafactory.DataFactory()
- metadata = data_factory.get_metadata_details(rating_key=rating_key)
- else:
- pms_connect = pmsconnect.PmsConnect()
- result = pms_connect.get_metadata_details(rating_key=rating_key)
- if result:
- metadata = result['metadata']
-
- if metadata:
- return serve_template(templatename="info.html", data=metadata, title="Info", config=config)
- else:
- return self.update_metadata(rating_key)
- #raise cherrypy.InternalRedirect("/update_metadata?rating_key=" + rating_key)
-
- @cherrypy.expose
- def update_metadata(self, rating_key=None, query=None, **kwargs):
-
- query_string = query
-
- data_factory = datafactory.DataFactory()
- query = data_factory.get_search_query(rating_key=rating_key)
- if query_string:
- query['query_string'] = query_string
-
- if query:
- return serve_template(templatename="update_metadata.html", query=query, title="Info")
- else:
- logger.warn('Unable to retrieve data.')
- return serve_template(templatename="update_metadata.html", query=query, title="Info")
-
- @cherrypy.expose
- def update_metadata_details(self, old_rating_key, new_rating_key, media_type, **kwargs):
- data_factory = datafactory.DataFactory()
- pms_connect = pmsconnect.PmsConnect()
-
- if new_rating_key:
- old_key_list = data_factory.get_rating_keys_list(rating_key=old_rating_key, media_type=media_type)
- new_key_list = pms_connect.get_rating_keys_list(rating_key=new_rating_key, media_type=media_type)
-
- result = data_factory.update_metadata(old_key_list=old_key_list,
- new_key_list=new_key_list,
- media_type=media_type)
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps({'message': result})
- else:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps({'message': 'no data received'})
-
- @cherrypy.expose
- def get_user_recently_watched(self, user=None, user_id=None, limit='10', **kwargs):
-
- data_factory = datafactory.DataFactory()
- result = data_factory.get_recently_watched(user_id=user_id, user=user, limit=limit)
-
- if result:
- return serve_template(templatename="user_recently_watched.html", data=result,
- title="Recently Watched")
- else:
- logger.warn('Unable to retrieve data.')
- return serve_template(templatename="user_recently_watched.html", data=None,
- title="Recently Watched")
-
- @cherrypy.expose
- def get_library_recently_watched(self, library_id=None, limit='10', **kwargs):
-
- data_factory = datafactory.DataFactory()
- result = data_factory.get_recently_watched(library_id=library_id, limit=limit)
-
- if result:
- return serve_template(templatename="user_recently_watched.html", data=result,
- title="Recently Watched")
- else:
- logger.warn('Unable to retrieve data.')
- return serve_template(templatename="user_recently_watched.html", data=None,
- title="Recently Watched")
-
- @cherrypy.expose
- def get_user_watch_time_stats(self, user=None, user_id=None, **kwargs):
-
- user_data = users.Users()
- result = user_data.get_user_watch_time_stats(user_id=user_id, user=user)
-
- if result:
- return serve_template(templatename="user_watch_time_stats.html", data=result, title="Watch Stats")
- else:
- logger.warn('Unable to retrieve data.')
- return serve_template(templatename="user_watch_time_stats.html", data=None, title="Watch Stats")
-
- @cherrypy.expose
- def get_library_watch_time_stats(self, library_id=None, **kwargs):
-
- library_data = libraries.Libraries()
- result = library_data.get_library_watch_time_stats(library_id=library_id)
-
- if result:
- return serve_template(templatename="user_watch_time_stats.html", data=result, title="Watch Stats")
- else:
- logger.warn('Unable to retrieve data.')
- return serve_template(templatename="user_watch_time_stats.html", data=None, title="Watch Stats")
-
- @cherrypy.expose
- def get_user_player_stats(self, user=None, user_id=None, **kwargs):
-
- user_data = users.Users()
- result = user_data.get_user_player_stats(user_id=user_id, user=user)
-
- if result:
- return serve_template(templatename="user_player_stats.html", data=result,
- title="Player Stats")
- else:
- logger.warn('Unable to retrieve data.')
- return serve_template(templatename="user_player_stats.html", data=None, title="Player Stats")
-
- @cherrypy.expose
- def get_library_user_stats(self, library_id=None, **kwargs):
-
- library_data = libraries.Libraries()
- result = library_data.get_library_user_stats(library_id=library_id)
-
- if result:
- return serve_template(templatename="library_user_stats.html", data=result, title="Player Stats")
- else:
- logger.warn('Unable to retrieve data.')
- return serve_template(templatename="library_user_stats.html", data=None, title="Player Stats")
-
- @cherrypy.expose
- def get_item_children(self, rating_key='', **kwargs):
-
- pms_connect = pmsconnect.PmsConnect()
- result = pms_connect.get_item_children(rating_key)
-
- if result:
- return serve_template(templatename="info_children_list.html", data=result, title="Children List")
- else:
- logger.warn('Unable to retrieve data.')
- return serve_template(templatename="info_children_list.html", data=None, title="Children List")
-
- @cherrypy.expose
- def get_metadata_json(self, rating_key='', **kwargs):
-
- pms_connect = pmsconnect.PmsConnect()
- result = pms_connect.get_metadata(rating_key, 'json')
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return result
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_metadata_xml(self, rating_key='', **kwargs):
-
- pms_connect = pmsconnect.PmsConnect()
- result = pms_connect.get_metadata(rating_key)
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/xml'
- return result
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_recently_added_json(self, count='0', **kwargs):
-
- pms_connect = pmsconnect.PmsConnect()
- result = pms_connect.get_recently_added(count, 'json')
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return result
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_episode_list_json(self, rating_key='', **kwargs):
-
- pms_connect = pmsconnect.PmsConnect()
- result = pms_connect.get_episode_list(rating_key, 'json')
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return result
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_user_ips(self, user_id=None, user=None, **kwargs):
-
- custom_where = []
- if user_id:
- custom_where = [['user_id', user_id]]
- elif user:
- custom_where = [['user', user]]
-
- user_data = users.Users()
- history = user_data.get_user_unique_ips(kwargs=kwargs,
- custom_where=custom_where)
-
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps(history)
-
- @cherrypy.expose
- def set_graph_config(self, graph_type=None, graph_days=None, graph_tab=None):
- if graph_type:
- plexpy.CONFIG.__setattr__('GRAPH_TYPE', graph_type)
- plexpy.CONFIG.write()
- if graph_days:
- plexpy.CONFIG.__setattr__('GRAPH_DAYS', graph_days)
- plexpy.CONFIG.write()
- if graph_tab:
- plexpy.CONFIG.__setattr__('GRAPH_TAB', graph_tab)
- plexpy.CONFIG.write()
-
- return "Updated graphs config values."
-
- @cherrypy.expose
- def get_plays_by_date(self, time_range='30', y_axis='plays', **kwargs):
-
- graph = graphs.Graphs()
- result = graph.get_total_plays_per_day(time_range=time_range, y_axis=y_axis)
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps(result)
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_plays_by_dayofweek(self, time_range='30', y_axis='plays', **kwargs):
-
- graph = graphs.Graphs()
- result = graph.get_total_plays_per_dayofweek(time_range=time_range, y_axis=y_axis)
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps(result)
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_plays_by_hourofday(self, time_range='30', y_axis='plays', **kwargs):
-
- graph = graphs.Graphs()
- result = graph.get_total_plays_per_hourofday(time_range=time_range, y_axis=y_axis)
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps(result)
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_plays_per_month(self, y_axis='plays', **kwargs):
-
- graph = graphs.Graphs()
- result = graph.get_total_plays_per_month(y_axis=y_axis)
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps(result)
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_plays_by_top_10_platforms(self, time_range='30', y_axis='plays', **kwargs):
-
- graph = graphs.Graphs()
- result = graph.get_total_plays_by_top_10_platforms(time_range=time_range, y_axis=y_axis)
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps(result)
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_plays_by_top_10_users(self, time_range='30', y_axis='plays', **kwargs):
-
- graph = graphs.Graphs()
- result = graph.get_total_plays_by_top_10_users(time_range=time_range, y_axis=y_axis)
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps(result)
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_plays_by_stream_type(self, time_range='30', y_axis='plays', **kwargs):
-
- graph = graphs.Graphs()
- result = graph.get_total_plays_per_stream_type(time_range=time_range, y_axis=y_axis)
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps(result)
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_plays_by_source_resolution(self, time_range='30', y_axis='plays', **kwargs):
-
- graph = graphs.Graphs()
- result = graph.get_total_plays_by_source_resolution(time_range=time_range, y_axis=y_axis)
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps(result)
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_plays_by_stream_resolution(self, time_range='30', y_axis='plays', **kwargs):
-
- graph = graphs.Graphs()
- result = graph.get_total_plays_by_stream_resolution(time_range=time_range, y_axis=y_axis)
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps(result)
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_stream_type_by_top_10_users(self, time_range='30', y_axis='plays', **kwargs):
-
- graph = graphs.Graphs()
- result = graph.get_stream_type_by_top_10_users(time_range=time_range, y_axis=y_axis)
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps(result)
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_stream_type_by_top_10_platforms(self, time_range='30', y_axis='plays', **kwargs):
-
- graph = graphs.Graphs()
- result = graph.get_stream_type_by_top_10_platforms(time_range=time_range, y_axis=y_axis)
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps(result)
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_friends_list(self, **kwargs):
-
- plex_tv = plextv.PlexTV()
- result = plex_tv.get_plextv_friends('json')
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return result
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_user_details(self, **kwargs):
-
- plex_tv = plextv.PlexTV()
- result = plex_tv.get_plextv_user_details('json')
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return result
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_server_list(self, **kwargs):
-
- plex_tv = plextv.PlexTV()
- result = plex_tv.get_plextv_server_list('json')
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return result
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_sync_lists(self, machine_id='', **kwargs):
-
- plex_tv = plextv.PlexTV()
- result = plex_tv.get_plextv_sync_lists(machine_id=machine_id, output_format='json')
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return result
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_servers(self, **kwargs):
-
- pms_connect = pmsconnect.PmsConnect()
- result = pms_connect.get_server_list(output_format='json')
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return result
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_servers_info(self, **kwargs):
-
- pms_connect = pmsconnect.PmsConnect()
- result = pms_connect.get_servers_info()
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps(result)
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_server_friendly_name(self, **kwargs):
-
- result = pmsconnect.get_server_friendly_name()
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return result
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_server_prefs(self, pref=None, **kwargs):
-
- if pref:
- pms_connect = pmsconnect.PmsConnect()
- result = pms_connect.get_server_pref(pref=pref)
- else:
- result = None
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return result
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_library_sections(self, **kwargs):
-
- data_factory = datafactory.DataFactory()
- result = data_factory.get_library_sections()
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps(result)
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_activity(self, **kwargs):
-
- pms_connect = pmsconnect.PmsConnect()
- result = pms_connect.get_current_activity()
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps(result)
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_full_users_list(self, **kwargs):
-
- plex_tv = plextv.PlexTV()
- result = plex_tv.get_full_users_list()
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps(result)
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def refresh_libraries_list(self, **kwargs):
- threading.Thread(target=pmsconnect.refresh_libraries).start()
- logger.info('Manual libraries list refresh requested.')
-
- @cherrypy.expose
- def refresh_users_list(self, **kwargs):
- threading.Thread(target=plextv.refresh_users).start()
- logger.info('Manual users list refresh requested.')
-
- @cherrypy.expose
- def get_sync(self, machine_id=None, user_id=None, **kwargs):
-
- pms_connect = pmsconnect.PmsConnect()
- server_id = pms_connect.get_server_identity()
-
- plex_tv = plextv.PlexTV()
- if not machine_id:
- result = plex_tv.get_synced_items(machine_id=server_id['machine_identifier'], user_id=user_id)
- else:
- result = plex_tv.get_synced_items(machine_id=machine_id, user_id=user_id)
-
- if result:
- output = {"data": result}
- else:
- logger.warn('Unable to retrieve sync data for user.')
- output = {"data": []}
-
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps(output)
-
- @cherrypy.expose
- def get_sync_item(self, sync_id, **kwargs):
-
- pms_connect = pmsconnect.PmsConnect()
- result = pms_connect.get_sync_item(sync_id, output_format='json')
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return result
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_sync_transcode_queue(self, **kwargs):
-
- pms_connect = pmsconnect.PmsConnect()
- result = pms_connect.get_sync_transcode_queue(output_format='json')
-
- if result:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return result
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_server_pref(self, pref=None, **kwargs):
-
- pms_connect = pmsconnect.PmsConnect()
- result = pms_connect.get_server_pref(pref=pref)
-
- if result:
- return result
- else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def get_plexwatch_export_data(self, database_path=None, table_name=None, import_ignore_interval=0, **kwargs):
- from plexpy import plexwatch_import
-
- db_check_msg = plexwatch_import.validate_database(database=database_path,
- table_name=table_name)
- if db_check_msg == 'success':
- threading.Thread(target=plexwatch_import.import_from_plexwatch,
- kwargs={'database': database_path,
- 'table_name': table_name,
- 'import_ignore_interval': import_ignore_interval}).start()
- return 'Import has started. Check the PlexPy logs to monitor any problems.'
- else:
- return db_check_msg
-
- @cherrypy.expose
- def plexwatch_import(self, **kwargs):
- return serve_template(templatename="plexwatch_import.html", title="Import PlexWatch Database")
-
- @cherrypy.expose
- def get_server_id(self, hostname=None, port=None, identifier=None, ssl=0, remote=0, **kwargs):
- from plexpy import http_handler
-
- if hostname and port:
- # Set PMS attributes to get the real PMS url
- plexpy.CONFIG.__setattr__('PMS_IP', hostname)
- plexpy.CONFIG.__setattr__('PMS_PORT', port)
- plexpy.CONFIG.__setattr__('PMS_IDENTIFIER', identifier)
- plexpy.CONFIG.__setattr__('PMS_SSL', ssl)
- plexpy.CONFIG.__setattr__('PMS_IS_REMOTE', remote)
- plexpy.CONFIG.write()
-
- plextv.get_real_pms_url()
-
- pms_connect = pmsconnect.PmsConnect()
- request = pms_connect.get_local_server_identity()
-
- if request:
- cherrypy.response.headers['Content-type'] = 'application/xml'
- return request
- else:
- logger.warn('Unable to retrieve data.')
- return None
- else:
- return None
-
- @cherrypy.expose
- def random_arnold_quotes(self, **kwargs):
- from random import randint
- quote_list = ['To crush your enemies, see them driven before you, and to hear the lamentation of their women!',
- 'Your clothes, give them to me, now!',
- 'Do it!',
- 'If it bleeds, we can kill it',
- 'See you at the party Richter!',
- 'Let off some steam, Bennett',
- 'I\'ll be back',
- 'Get to the chopper!',
- 'Hasta La Vista, Baby!',
- 'It\'s not a tumor!',
- 'Dillon, you son of a bitch!',
- 'Benny!! Screw you!!',
- 'Stop whining! You kids are soft. You lack discipline.',
- 'Nice night for a walk.',
- 'Stick around!',
- 'I need your clothes, your boots and your motorcycle.',
- 'No, it\'s not a tumor. It\'s not a tumor!',
- 'I LIED!',
- 'See you at the party, Richter!',
- 'Are you Sarah Conner?',
- '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)
- return quote_list[int(random_number)]
-
@cherrypy.expose
def get_notification_agent_config(self, config_id, **kwargs):
if config_id.isdigit():
@@ -1591,80 +1145,266 @@ class WebInterface(object):
data=this_agent)
@cherrypy.expose
- def delete_history_rows(self, row_id, **kwargs):
- data_factory = datafactory.DataFactory()
+ def test_notifier(self, config_id=None, subject='PlexPy', body='Test notification', **kwargs):
+ cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
- if row_id:
- delete_row = data_factory.delete_session_history_rows(row_id=row_id)
-
- if delete_row:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps({'message': delete_row})
+ if config_id.isdigit():
+ agents = notifiers.available_notification_agents()
+ for agent in agents:
+ if int(config_id) == agent['id']:
+ this_agent = agent
+ break
+ else:
+ this_agent = None
+
+ if this_agent:
+ logger.debug(u"Sending test %s notification." % this_agent['name'])
+ notifiers.send_notification(this_agent['id'], subject, body)
+ return "Notification sent."
+ else:
+ logger.debug(u"Unable to send test notification, invalid notification agent ID %s." % config_id)
+ return "Invalid notification agent ID %s." % config_id
else:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps({'message': 'no data received'})
+ logger.debug(u"Unable to send test notification, no notification agent ID received.")
+ return "No notification agent ID received."
+
+ @cherrypy.expose
+ def twitterStep1(self):
+ cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
+ tweet = notifiers.TwitterNotifier()
+ return tweet._get_authorization()
@cherrypy.expose
- def delete_all_user_history(self, user_id, **kwargs):
- data_factory = datafactory.DataFactory()
-
- if user_id:
- delete_row = data_factory.delete_all_user_history(user_id=user_id)
-
- if delete_row:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps({'message': delete_row})
+ def twitterStep2(self, key):
+ cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
+ tweet = notifiers.TwitterNotifier()
+ result = tweet._get_credentials(key)
+ # logger.info(u"result: " + str(result))
+ if result:
+ return "Key verification successful"
else:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps({'message': 'no data received'})
+ return "Unable to verify key"
+
+ def facebookStep1(self):
+ cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
+ facebook = notifiers.FacebookNotifier()
+ return facebook._get_authorization()
@cherrypy.expose
- def delete_user(self, user_id, **kwargs):
- data_factory = datafactory.DataFactory()
-
- if user_id:
- delete_row = data_factory.delete_user(user_id=user_id)
-
- if delete_row:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps({'message': delete_row})
+ def facebookStep2(self, code):
+ cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
+ facebook = notifiers.FacebookNotifier()
+ result = facebook._get_credentials(code)
+ # logger.info(u"result: " + str(result))
+ if result:
+ return "Key verification successful, you may close this page now."
else:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps({'message': 'no data received'})
+ return "Unable to verify key"
@cherrypy.expose
- def undelete_user(self, user_id=None, username=None, **kwargs):
- data_factory = datafactory.DataFactory()
+ def osxnotifyregister(self, app):
+ cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store"
+ from osxnotify import registerapp as osxnotify
- if user_id:
- delete_row = data_factory.undelete_user(user_id=user_id)
-
- if delete_row:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps({'message': delete_row})
- elif username:
- delete_row = data_factory.undelete_user(username=username)
-
- if delete_row:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps({'message': delete_row})
+ result, msg = osxnotify.registerapp(app)
+ if result:
+ osx_notify = notifiers.OSX_NOTIFY()
+ osx_notify.notify('Registered', result, 'Success :-)')
+ # logger.info(u"Registered %s, to re-register a different app, delete this app first" % result)
else:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps({'message': 'no data received'})
+ logger.warn(msg)
+ return msg
@cherrypy.expose
- def delete_all_library_history(self, section_id, **kwargs):
- library_data = libraries.Libraries()
+ def set_notification_config(self, **kwargs):
- if section_id:
- delete_row = library_data.delete_all_library_history(section_id=section_id)
+ for plain_config, use_config in [(x[4:], x) for x in kwargs if x.startswith('use_')]:
+ # the use prefix is fairly nice in the html, but does not match the actual config
+ kwargs[plain_config] = kwargs[use_config]
+ del kwargs[use_config]
- if delete_row:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps({'message': delete_row})
+ plexpy.CONFIG.process_kwargs(kwargs)
+
+ # Write the config
+ plexpy.CONFIG.write()
+
+ cherrypy.response.status = 200
+
+ @cherrypy.expose
+ def get_plexwatch_export_data(self, database_path=None, table_name=None, import_ignore_interval=0, **kwargs):
+ from plexpy import plexwatch_import
+
+ db_check_msg = plexwatch_import.validate_database(database=database_path,
+ table_name=table_name)
+ if db_check_msg == 'success':
+ threading.Thread(target=plexwatch_import.import_from_plexwatch,
+ kwargs={'database': database_path,
+ 'table_name': table_name,
+ 'import_ignore_interval': import_ignore_interval}).start()
+ return 'Import has started. Check the PlexPy logs to monitor any problems.'
else:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return json.dumps({'message': 'no data received'})
+ return db_check_msg
+
+ @cherrypy.expose
+ def plexwatch_import(self, **kwargs):
+ return serve_template(templatename="plexwatch_import.html", title="Import PlexWatch Database")
+
+ @cherrypy.expose
+ def get_pms_token(self):
+
+ token = plextv.PlexTV()
+ result = token.get_token()
+
+ if result:
+ return result
+ else:
+ logger.warn(u"Unable to retrieve Plex.tv token.")
+ return False
+
+ @cherrypy.expose
+ def get_server_id(self, hostname=None, port=None, identifier=None, ssl=0, remote=0, **kwargs):
+ from plexpy import http_handler
+
+ if hostname and port:
+ # Set PMS attributes to get the real PMS url
+ plexpy.CONFIG.__setattr__('PMS_IP', hostname)
+ plexpy.CONFIG.__setattr__('PMS_PORT', port)
+ plexpy.CONFIG.__setattr__('PMS_IDENTIFIER', identifier)
+ plexpy.CONFIG.__setattr__('PMS_SSL', ssl)
+ plexpy.CONFIG.__setattr__('PMS_IS_REMOTE', remote)
+ plexpy.CONFIG.write()
+
+ plextv.get_real_pms_url()
+
+ pms_connect = pmsconnect.PmsConnect()
+ request = pms_connect.get_local_server_identity()
+
+ if request:
+ cherrypy.response.headers['Content-type'] = 'application/xml'
+ return request
+ else:
+ logger.warn(u"Unable to retrieve data for get_server_id.")
+ return None
+ else:
+ return None
+
+ @cherrypy.expose
+ def get_server_pref(self, pref=None, **kwargs):
+
+ pms_connect = pmsconnect.PmsConnect()
+ result = pms_connect.get_server_pref(pref=pref)
+
+ if result:
+ return result
+ else:
+ logger.warn(u"Unable to retrieve data for get_server_pref.")
+
+ @cherrypy.expose
+ def generateAPI(self):
+ apikey = hashlib.sha224(str(random.getrandbits(256))).hexdigest()[0:32]
+ logger.info(u"New API generated")
+ return apikey
+
+ @cherrypy.expose
+ def checkGithub(self):
+ from plexpy import versioncheck
+
+ versioncheck.checkGithub()
+ raise cherrypy.HTTPRedirect("home")
+
+ @cherrypy.expose
+ def do_state_change(self, signal, title, timer):
+ message = title
+ quote = self.random_arnold_quotes()
+ plexpy.SIGNAL = signal
+
+ return serve_template(templatename="shutdown.html", title=title,
+ message=message, timer=timer, quote=quote)
+
+ @cherrypy.expose
+ def shutdown(self):
+ return self.do_state_change('shutdown', 'Shutting Down', 15)
+
+ @cherrypy.expose
+ def restart(self):
+ return self.do_state_change('restart', 'Restarting', 30)
+
+ @cherrypy.expose
+ def update(self):
+ return self.do_state_change('update', 'Updating', 120)
+
+
+ ##### Info #####
+
+ @cherrypy.expose
+ def info(self, rating_key=None, source=None, **kwargs):
+ # temporary until I find a beter place to put this
+ #data_factory.update_library_ids()
+
+ metadata = None
+
+ config = {
+ "pms_identifier": plexpy.CONFIG.PMS_IDENTIFIER,
+ "update_library_ids": plexpy.CONFIG.UPDATE_LIBRARY_IDS
+ }
+
+ if source == 'history':
+ data_factory = datafactory.DataFactory()
+ metadata = data_factory.get_metadata_details(rating_key=rating_key)
+ else:
+ pms_connect = pmsconnect.PmsConnect()
+ result = pms_connect.get_metadata_details(rating_key=rating_key)
+ if result:
+ metadata = result['metadata']
+
+ if metadata:
+ return serve_template(templatename="info.html", data=metadata, title="Info", config=config)
+ else:
+ return self.update_metadata(rating_key)
+ #raise cherrypy.InternalRedirect("/update_metadata?rating_key=" + rating_key)
+
+ @cherrypy.expose
+ def get_item_children(self, rating_key='', **kwargs):
+
+ pms_connect = pmsconnect.PmsConnect()
+ result = pms_connect.get_item_children(rating_key)
+
+ if result:
+ return serve_template(templatename="info_children_list.html", data=result, title="Children List")
+ else:
+ logger.warn(u"Unable to retrieve data for get_item_children.")
+ return serve_template(templatename="info_children_list.html", data=None, title="Children List")
+
+ @cherrypy.expose
+ def pms_image_proxy(self, img='', width='0', height='0', fallback=None, **kwargs):
+ try:
+ pms_connect = pmsconnect.PmsConnect()
+ result = pms_connect.get_image(img, width, height)
+ cherrypy.response.headers['Content-type'] = result[1]
+ return result[0]
+ except:
+ logger.warn(u"Image proxy queried but errors occured.")
+ if fallback == 'poster':
+ logger.info(u"Trying fallback image...")
+ try:
+ fallback_image = open(self.interface_dir + common.DEFAULT_POSTER_THUMB, 'rb')
+ cherrypy.response.headers['Content-type'] = 'image/png'
+ return fallback_image
+ except IOError, e:
+ logger.error(u"Unable to read fallback %s image: %s" % (fallback, e))
+ elif fallback == 'cover':
+ logger.info(u"Trying fallback image...")
+ try:
+ fallback_image = open(self.interface_dir + common.DEFAULT_COVER_THUMB, 'rb')
+ cherrypy.response.headers['Content-type'] = 'image/png'
+ return fallback_image
+ except IOError, e:
+ logger.error(u"Unable to read fallback %s image: %s" % (fallback, e))
+
+ return None
+
+
+ ##### Search #####
@cherrypy.expose
def search(self, query=''):
@@ -1681,7 +1421,7 @@ class WebInterface(object):
cherrypy.response.headers['Content-type'] = 'application/json'
return json.dumps(result)
else:
- logger.warn('Unable to retrieve data.')
+ logger.warn(u"Unable to retrieve data for search_results.")
@cherrypy.expose
def get_search_results_children(self, query, media_type=None, season_index=None, **kwargs):
@@ -1700,9 +1440,49 @@ class WebInterface(object):
if result:
return serve_template(templatename="info_search_results_list.html", data=result, title="Search Result List")
else:
- logger.warn('Unable to retrieve data.')
+ logger.warn(u"Unable to retrieve data for get_search_results_children.")
return serve_template(templatename="info_search_results_list.html", data=None, title="Search Result List")
+
+
+ ##### Update Metadata #####
+
+ @cherrypy.expose
+ def update_metadata(self, rating_key=None, query=None, **kwargs):
+
+ query_string = query
+
+ data_factory = datafactory.DataFactory()
+ query = data_factory.get_search_query(rating_key=rating_key)
+ if query_string:
+ query['query_string'] = query_string
+
+ if query:
+ return serve_template(templatename="update_metadata.html", query=query, title="Info")
+ else:
+ logger.warn(u"Unable to retrieve data for update_metadata.")
+ return serve_template(templatename="update_metadata.html", query=query, title="Info")
+
+ @cherrypy.expose
+ def update_metadata_details(self, old_rating_key, new_rating_key, media_type, **kwargs):
+ data_factory = datafactory.DataFactory()
+ pms_connect = pmsconnect.PmsConnect()
+
+ if new_rating_key:
+ old_key_list = data_factory.get_rating_keys_list(rating_key=old_rating_key, media_type=media_type)
+ new_key_list = pms_connect.get_rating_keys_list(rating_key=new_rating_key, media_type=media_type)
+
+ result = data_factory.update_metadata(old_key_list=old_key_list,
+ new_key_list=new_key_list,
+ media_type=media_type)
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps({'message': result})
+ else:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps({'message': 'no data received'})
+
@cherrypy.expose
def update_history_rating_key(self, old_rating_key, new_rating_key, media_type, **kwargs):
data_factory = datafactory.DataFactory()
@@ -1733,7 +1513,7 @@ class WebInterface(object):
cherrypy.response.headers['Content-type'] = 'application/json'
return json.dumps(result)
else:
- logger.warn('Unable to retrieve data.')
+ logger.warn(u"Unable to retrieve data for get_new_rating_keys.")
@cherrypy.expose
def get_old_rating_keys(self, rating_key='', media_type='', **kwargs):
@@ -1745,23 +1525,7 @@ class WebInterface(object):
cherrypy.response.headers['Content-type'] = 'application/json'
return json.dumps(result)
else:
- logger.warn('Unable to retrieve data.')
-
- @cherrypy.expose
- def discover(self, token=''):
- """
- Returns the servers that you own as a
- list of dicts (formatted for selectize)
- """
- # Need to set token so result dont return http 401
- plexpy.CONFIG.__setattr__('PMS_TOKEN', token)
- plexpy.CONFIG.write()
-
- result = plextv.PlexTV()
- servers = result.discover()
- if servers:
- cherrypy.response.headers['Content-type'] = 'application/json'
- return servers
+ logger.warn(u"Unable to retrieve data for get_old_rating_keys.")
@cherrypy.expose
def update_library_ids(self, **kwargs):
@@ -1779,16 +1543,267 @@ class WebInterface(object):
logger.debug(u"Unable to update library_id's in database.")
return "Unable to update library ids in database."
- @cherrypy.expose
- def update_library_sections(self, **kwargs):
- logger.debug(u"Updating library sections in database.")
- data_factory = datafactory.DataFactory()
- result = data_factory.update_library_sections()
+ ##### API #####
+
+ @cherrypy.expose
+ def api(self, *args, **kwargs):
+ from plexpy.api import Api
+
+ a = Api()
+ a.checkParams(*args, **kwargs)
+
+ return a.fetchData()
+
+ @cherrypy.expose
+ def get_pms_sessions_json(self, **kwargs):
+
+ pms_connect = pmsconnect.PmsConnect()
+ result = pms_connect.get_sessions('json')
if result:
- logger.debug(u"Updated all library sections in database.")
- return "Library sections updated."
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return result
else:
- logger.debug(u"Unable to update library sections in database.")
- return "Unable to update library sections in database."
+ logger.warn(u"Unable to retrieve data for get_pms_sessions_json.")
+ return False
+
+ @cherrypy.expose
+ def get_metadata_json(self, rating_key='', **kwargs):
+
+ pms_connect = pmsconnect.PmsConnect()
+ result = pms_connect.get_metadata(rating_key, 'json')
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return result
+ else:
+ logger.warn(u"Unable to retrieve data for get_metadata_json.")
+
+ @cherrypy.expose
+ def get_metadata_xml(self, rating_key='', **kwargs):
+
+ pms_connect = pmsconnect.PmsConnect()
+ result = pms_connect.get_metadata(rating_key)
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/xml'
+ return result
+ else:
+ logger.warn(u"Unable to retrieve data for get_metadata_xml.")
+
+ @cherrypy.expose
+ def get_recently_added_json(self, count='0', **kwargs):
+
+ pms_connect = pmsconnect.PmsConnect()
+ result = pms_connect.get_recently_added(count, 'json')
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return result
+ else:
+ logger.warn(u"Unable to retrieve data for get_recently_added_json.")
+
+ @cherrypy.expose
+ def get_episode_list_json(self, rating_key='', **kwargs):
+
+ pms_connect = pmsconnect.PmsConnect()
+ result = pms_connect.get_episode_list(rating_key, 'json')
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return result
+ else:
+ logger.warn(u"Unable to retrieve data for get_episode_list_json.")
+
+ @cherrypy.expose
+ def get_friends_list(self, **kwargs):
+
+ plex_tv = plextv.PlexTV()
+ result = plex_tv.get_plextv_friends('json')
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return result
+ else:
+ logger.warn(u"Unable to retrieve data for get_friends_list.")
+
+ @cherrypy.expose
+ def get_user_details(self, **kwargs):
+
+ plex_tv = plextv.PlexTV()
+ result = plex_tv.get_plextv_user_details('json')
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return result
+ else:
+ logger.warn(u"Unable to retrieve data for get_user_details.")
+
+ @cherrypy.expose
+ def get_server_list(self, **kwargs):
+
+ plex_tv = plextv.PlexTV()
+ result = plex_tv.get_plextv_server_list('json')
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return result
+ else:
+ logger.warn(u"Unable to retrieve data for get_server_list.")
+
+ @cherrypy.expose
+ def get_sync_lists(self, machine_id='', **kwargs):
+
+ plex_tv = plextv.PlexTV()
+ result = plex_tv.get_plextv_sync_lists(machine_id=machine_id, output_format='json')
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return result
+ else:
+ logger.warn(u"Unable to retrieve data for get_sync_lists.")
+
+ @cherrypy.expose
+ def get_servers(self, **kwargs):
+
+ pms_connect = pmsconnect.PmsConnect()
+ result = pms_connect.get_server_list(output_format='json')
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return result
+ else:
+ logger.warn(u"Unable to retrieve data for get_servers.")
+
+ @cherrypy.expose
+ def get_servers_info(self, **kwargs):
+
+ pms_connect = pmsconnect.PmsConnect()
+ result = pms_connect.get_servers_info()
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps(result)
+ else:
+ logger.warn(u"Unable to retrieve data for get_servers_info.")
+
+ @cherrypy.expose
+ def get_server_friendly_name(self, **kwargs):
+
+ result = pmsconnect.get_server_friendly_name()
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return result
+ else:
+ logger.warn(u"Unable to retrieve data for get_server_friendly_name.")
+
+ @cherrypy.expose
+ def get_server_prefs(self, pref=None, **kwargs):
+
+ if pref:
+ pms_connect = pmsconnect.PmsConnect()
+ result = pms_connect.get_server_pref(pref=pref)
+ else:
+ result = None
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return result
+ else:
+ logger.warn(u"Unable to retrieve data for get_server_prefs.")
+
+ @cherrypy.expose
+ def get_library_sections(self, **kwargs):
+
+ library_data = libraries.Libraries()
+ result = library_data.get_sections()
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps(result)
+ else:
+ logger.warn(u"Unable to retrieve data for get_library_sections.")
+
+ @cherrypy.expose
+ def get_activity(self, **kwargs):
+
+ pms_connect = pmsconnect.PmsConnect()
+ result = pms_connect.get_current_activity()
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps(result)
+ else:
+ logger.warn(u"Unable to retrieve data for get_activity.")
+
+ @cherrypy.expose
+ def get_full_users_list(self, **kwargs):
+
+ plex_tv = plextv.PlexTV()
+ result = plex_tv.get_full_users_list()
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return json.dumps(result)
+ else:
+ logger.warn(u"Unable to retrieve data for get_full_users_list.")
+
+ @cherrypy.expose
+ def get_sync_item(self, sync_id, **kwargs):
+
+ pms_connect = pmsconnect.PmsConnect()
+ result = pms_connect.get_sync_item(sync_id, output_format='json')
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return result
+ else:
+ logger.warn(u"Unable to retrieve data for get_sync_item.")
+
+ @cherrypy.expose
+ def get_sync_transcode_queue(self, **kwargs):
+
+ pms_connect = pmsconnect.PmsConnect()
+ result = pms_connect.get_sync_transcode_queue(output_format='json')
+
+ if result:
+ cherrypy.response.headers['Content-type'] = 'application/json'
+ return result
+ else:
+ logger.warn(u"Unable to retrieve data for get_sync_transcode_queue.")
+
+
+
+
+ @cherrypy.expose
+ def random_arnold_quotes(self, **kwargs):
+ from random import randint
+ quote_list = ['To crush your enemies, see them driven before you, and to hear the lamentation of their women!',
+ 'Your clothes, give them to me, now!',
+ 'Do it!',
+ 'If it bleeds, we can kill it',
+ 'See you at the party Richter!',
+ 'Let off some steam, Bennett',
+ 'I\'ll be back',
+ 'Get to the chopper!',
+ 'Hasta La Vista, Baby!',
+ 'It\'s not a tumor!',
+ 'Dillon, you son of a bitch!',
+ 'Benny!! Screw you!!',
+ 'Stop whining! You kids are soft. You lack discipline.',
+ 'Nice night for a walk.',
+ 'Stick around!',
+ 'I need your clothes, your boots and your motorcycle.',
+ 'No, it\'s not a tumor. It\'s not a tumor!',
+ 'I LIED!',
+ 'See you at the party, Richter!',
+ 'Are you Sarah Conner?',
+ '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)
+ return quote_list[int(random_number)]
\ No newline at end of file