diff --git a/data/interfaces/default/logs.html b/data/interfaces/default/logs.html
index 4c4d88ae..fca7b4d0 100644
--- a/data/interfaces/default/logs.html
+++ b/data/interfaces/default/logs.html
@@ -23,7 +23,7 @@ from plexpy import helpers
Logs
diff --git a/data/interfaces/default/users.html b/data/interfaces/default/users.html
index 5b55da1f..ac4c3391 100644
--- a/data/interfaces/default/users.html
+++ b/data/interfaces/default/users.html
@@ -14,7 +14,12 @@ from plexpy import helpers
diff --git a/plexpy/__init__.py b/plexpy/__init__.py
index 07141e9b..58b3b2c2 100644
--- a/plexpy/__init__.py
+++ b/plexpy/__init__.py
@@ -307,8 +307,35 @@ def sig_handler(signum=None, frame=None):
def dbcheck():
conn = sqlite3.connect(plexpy.CONFIG.PLEXWATCH_DATABASE)
c = conn.cursor()
- c.execute('CREATE TABLE IF NOT EXISTS plexpy_users (id INTEGER PRIMARY KEY AUTOINCREMENT, '
- 'username TEXT NOT NULL UNIQUE, friendly_name TEXT)')
+ c.execute(
+ 'CREATE TABLE IF NOT EXISTS plexpy_users (id INTEGER PRIMARY KEY AUTOINCREMENT, '
+ 'user_id INTEGER DEFAULT NULL UNIQUE, username TEXT NOT NULL UNIQUE, '
+ 'friendly_name TEXT, thumb TEXT, email TEXT, is_home_user INTEGER DEFAULT NULL, '
+ 'is_allow_sync INTEGER DEFAULT NULL, is_restricted INTEGER DEFAULT NULL)'
+ )
+
+ # Upgrade plexpy_users table from earlier versions
+ try:
+ c.execute('SELECT user_id from plexpy_users')
+ except sqlite3.OperationalError:
+ logger.debug(u"Altering database. Updating database table plexpy_users.")
+ c.execute(
+ 'CREATE TABLE tmp_table (id INTEGER PRIMARY KEY AUTOINCREMENT, '
+ 'user_id INTEGER DEFAULT NULL UNIQUE, username TEXT NOT NULL UNIQUE, '
+ 'friendly_name TEXT, thumb TEXT, email TEXT, is_home_user INTEGER DEFAULT NULL, '
+ 'is_allow_sync INTEGER DEFAULT NULL, is_restricted INTEGER DEFAULT NULL)'
+ )
+ c.execute(
+ 'INSERT INTO tmp_table SELECT id, NULL, username, friendly_name, NULL, NULL, NULL, NULL, NULL '
+ 'FROM plexpy_users'
+ )
+ c.execute(
+ 'DROP TABLE plexpy_users'
+ )
+ c.execute(
+ 'ALTER TABLE tmp_table RENAME TO plexpy_users'
+ )
+
conn.commit()
c.close()
diff --git a/plexpy/helpers.py b/plexpy/helpers.py
index a8bcac49..8d402e49 100644
--- a/plexpy/helpers.py
+++ b/plexpy/helpers.py
@@ -81,11 +81,11 @@ def latinToAscii(unicrap):
0xfd: 'y', 0xfe: 'th', 0xff: 'y',
0xa1: '!', 0xa2: '{cent}', 0xa3: '{pound}', 0xa4: '{currency}',
0xa5: '{yen}', 0xa6: '|', 0xa7: '{section}', 0xa8: '{umlaut}',
- 0xa9: '{C}', 0xaa: '{^a}', 0xab: '<<', 0xac: '{not}',
+ 0xa9: '{C}', 0xaa: '{^a}', 0xab: '<<', 0xac: '{not}',
0xad: '-', 0xae: '{R}', 0xaf: '_', 0xb0: '{degrees}',
0xb1: '{+/-}', 0xb2: '{^2}', 0xb3: '{^3}', 0xb4: "'",
0xb5: '{micro}', 0xb6: '{paragraph}', 0xb7: '*', 0xb8: '{cedilla}',
- 0xb9: '{^1}', 0xba: '{^o}', 0xbb: '>>',
+ 0xb9: '{^1}', 0xba: '{^o}', 0xbb: '>>',
0xbc: '{1/4}', 0xbd: '{1/2}', 0xbe: '{3/4}', 0xbf: '?',
0xd7: '*', 0xf7: '/'
}
diff --git a/plexpy/plextv.py b/plexpy/plextv.py
index c8a44f7a..1eb848a6 100644
--- a/plexpy/plextv.py
+++ b/plexpy/plextv.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, helpers, common, request
+from plexpy import logger, helpers
from xml.dom import minidom
from httplib import HTTPSConnection
@@ -213,4 +213,73 @@ class PlexTV(object):
logger.warn(u"Failed to access server list. Status code %r" % request_status)
return None
- return output
\ No newline at end of file
+ return output
+
+ """
+ Validate xml keys to make sure they exist and return their attribute value, return blank value is none found
+ """
+ @staticmethod
+ def get_xml_attr(xml_key, attribute, return_bool=False, default_return=''):
+ if xml_key.getAttribute(attribute):
+ if return_bool:
+ return True
+ else:
+ return xml_key.getAttribute(attribute)
+ else:
+ if return_bool:
+ return False
+ else:
+ return default_return
+
+ def get_full_users_list(self):
+ friends_list = self.get_plextv_friends()
+ own_account = self.get_plextv_user_details()
+ users_list = []
+
+ try:
+ xml_parse = minidom.parseString(own_account)
+ except Exception, e:
+ logger.warn("Error parsing XML for Plex account details: %s" % e)
+ except:
+ logger.warn("Error parsing XML for Plex account details.")
+
+ xml_head = xml_parse.getElementsByTagName('user')
+ if not xml_head:
+ logger.warn("Error parsing XML for Plex account details.")
+ else:
+ for a in xml_head:
+ own_details = {"user_id": self.get_xml_attr(a, 'id'),
+ "username": self.get_xml_attr(a, 'username'),
+ "thumb": self.get_xml_attr(a, 'thumb'),
+ "email": self.get_xml_attr(a, 'email'),
+ "is_home_user": self.get_xml_attr(a, 'home'),
+ "is_allow_sync": None,
+ "is_restricted": self.get_xml_attr(a, 'restricted')
+ }
+
+ users_list.append(own_details)
+
+ try:
+ xml_parse = minidom.parseString(friends_list)
+ except Exception, e:
+ logger.warn("Error parsing XML for Plex friends list: %s" % e)
+ except:
+ logger.warn("Error parsing XML for Plex friends list.")
+
+ xml_head = xml_parse.getElementsByTagName('User')
+ if not xml_head:
+ logger.warn("Error parsing XML for Plex friends list.")
+ else:
+ for a in xml_head:
+ friend = {"user_id": self.get_xml_attr(a, 'id'),
+ "username": self.get_xml_attr(a, 'title'),
+ "thumb": self.get_xml_attr(a, 'thumb'),
+ "email": self.get_xml_attr(a, 'email'),
+ "is_home_user": self.get_xml_attr(a, 'home'),
+ "is_allow_sync": self.get_xml_attr(a, 'allowSync'),
+ "is_restricted": self.get_xml_attr(a, 'restricted')
+ }
+
+ users_list.append(friend)
+
+ return users_list
\ No newline at end of file
diff --git a/plexpy/plexwatch.py b/plexpy/plexwatch.py
index 28819846..4c959070 100644
--- a/plexpy/plexwatch.py
+++ b/plexpy/plexwatch.py
@@ -72,7 +72,9 @@ class PlexWatch(object):
t + '.time',
t + '.ip_address',
'COUNT(' + t + '.title) as plays',
- t + '.user']
+ t + '.user',
+ 'plexpy_users.user_id as user_id',
+ 'plexpy_users.thumb as thumb']
try:
query = data_tables.ssp_query(table_name=t,
columns=columns,
@@ -98,14 +100,18 @@ class PlexWatch(object):
rows = []
for item in users:
- thumb = self.get_user_gravatar_image(item['user'])
+ if not item['thumb']:
+ user_thumb = 'interfaces/default/images/gravatar-default-80x80.png'
+ else:
+ user_thumb = item['thumb']
row = {"plays": item['plays'],
"time": item['time'],
"friendly_name": item["friendly_name"],
"ip_address": item["ip_address"],
- "thumb": thumb['user_thumb'],
- "user": item["user"]
+ "thumb": user_thumb,
+ "user": item["user"],
+ "user_id": item['user_id']
}
rows.append(row)
@@ -295,12 +301,12 @@ class PlexWatch(object):
try:
xml_parse = minidom.parseString(helpers.latinToAscii(item['xml']))
- except IOError, e:
- logger.warn("Error parsing XML in PlexWatch db: %s" % e)
+ except:
+ logger.warn("Error parsing XML in PlexWatch db")
xml_head = xml_parse.getElementsByTagName('opt')
if not xml_head:
- logger.warn("Error parsing XML in PlexWatch db: %s" % e)
+ logger.warn("Error parsing XML in PlexWatch db.")
for s in xml_head:
if s.getAttribute('duration') and s.getAttribute('viewOffset'):
@@ -925,7 +931,10 @@ class PlexWatch(object):
myDB = db.DBConnection()
query = 'select friendly_name FROM plexpy_users WHERE username = ?'
result = myDB.select_single(query, args=[user])
- return result
+ if result:
+ return result
+ else:
+ return user
except:
return user
@@ -956,7 +965,9 @@ def check_db_tables():
try:
myDB = db.DBConnection()
query = 'CREATE TABLE IF NOT EXISTS plexpy_users (id INTEGER PRIMARY KEY AUTOINCREMENT, ' \
- 'username TEXT NOT NULL UNIQUE, friendly_name TEXT)'
+ 'user_id INTEGER DEFAULT NULL UNIQUE, username TEXT NOT NULL UNIQUE, ' \
+ 'friendly_name TEXT, thumb TEXT, email TEXT, is_home_user INTEGER DEFAULT NULL, ' \
+ 'is_allow_sync INTEGER DEFAULT NULL, is_restricted INTEGER DEFAULT NULL)'
result = myDB.action(query)
except:
logger.debug(u"Unable to create users table.")
diff --git a/plexpy/pmsconnect.py b/plexpy/pmsconnect.py
index f5a5b703..64d599fe 100644
--- a/plexpy/pmsconnect.py
+++ b/plexpy/pmsconnect.py
@@ -212,6 +212,39 @@ class PmsConnect(object):
return output
+ """
+ Return the local servers preferences.
+
+ Optional parameters: output_format { dict, json }
+
+ Output: array
+ """
+ def get_server_prefs(self, output_format=''):
+ url_command = '/:/prefs'
+ http_handler = HTTPConnection(self.host, self.port, timeout=10)
+
+ try:
+ http_handler.request("GET", url_command + '?X-Plex-Token=' + self.token)
+ response = http_handler.getresponse()
+ request_status = response.status
+ request_content = response.read()
+ except IOError, e:
+ logger.warn(u"Failed to access metadata. %s" % e)
+ return None
+
+ if request_status == 200:
+ if output_format == 'dict':
+ output = helpers.convert_xml_to_dict(request_content)
+ elif output_format == 'json':
+ output = helpers.convert_xml_to_json(request_content)
+ else:
+ output = request_content
+ else:
+ logger.warn(u"Failed to access metadata. Status code %r" % request_status)
+ return None
+
+ return output
+
"""
Return processed and validated list of recently added items.
@@ -681,6 +714,41 @@ class PmsConnect(object):
return output
+ """
+ Return the local machine identifier.
+
+ Output: string
+ """
+ def get_servers_info(self):
+ recent = self.get_server_list()
+
+ try:
+ xml_parse = minidom.parseString(recent)
+ except Exception, e:
+ logger.warn("Error parsing XML for Plex server prefs: %s" % e)
+ return None
+ except:
+ logger.warn("Error parsing XML for Plex server prefs.")
+ return None
+
+ xml_head = xml_parse.getElementsByTagName('Server')
+ if not xml_head:
+ logger.warn("Error parsing XML for Plex server prefs.")
+ return None
+
+ server_info = []
+ for a in xml_head:
+ output = {"name": self.get_xml_attr(a, 'name'),
+ "machineIdentifier": self.get_xml_attr(a, 'machineIdentifier'),
+ "host": self.get_xml_attr(a, 'host'),
+ "port": self.get_xml_attr(a, 'port'),
+ "version": self.get_xml_attr(a, 'version')
+ }
+
+ server_info.append(output)
+
+ return server_info
+
"""
Return image data as array.
Array contains the image content type and image binary
diff --git a/plexpy/webserve.py b/plexpy/webserve.py
index 1d11b6be..ba24b421 100644
--- a/plexpy/webserve.py
+++ b/plexpy/webserve.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, notifiers, plextv, pmsconnect, plexwatch
+from plexpy import logger, notifiers, plextv, pmsconnect, plexwatch, db
from plexpy.helpers import checked, radio
from mako.lookup import TemplateLookup
@@ -833,3 +833,61 @@ class WebInterface(object):
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_prefs(self, **kwargs):
+
+ pms_connect = pmsconnect.PmsConnect()
+ result = pms_connect.get_server_prefs(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_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_users_list(self, **kwargs):
+ plex_tv = plextv.PlexTV()
+ result = plex_tv.get_full_users_list()
+ myDB = db.DBConnection()
+
+ for item in result:
+ control_value_dict = {"username": item['username']}
+ new_value_dict = {"user_id": item['user_id'],
+ "username": item['username'],
+ "thumb": item['thumb'],
+ "email": item['email'],
+ "is_home_user": item['is_home_user'],
+ "is_allow_sync": item['is_allow_sync'],
+ "is_restricted": item['is_restricted']
+ }
+
+ myDB.upsert('plexpy_users', new_value_dict, control_value_dict)
+
+ logger.info("Users list refreshed.")
+ raise cherrypy.HTTPRedirect("users")