Fix bug with xml and unicode conversion.

Fix some minor front-end issues.
Initial work on new users table.
This commit is contained in:
Tim 2015-07-01 19:51:42 +02:00
parent 12331e1c4c
commit 2d822c8468
8 changed files with 256 additions and 18 deletions

View file

@ -23,7 +23,7 @@ from plexpy import helpers
<div class="span9"><h2><i class="fa fa-book"></i> Logs</h2></div> <div class="span9"><h2><i class="fa fa-book"></i> Logs</h2></div>
<div class="span3"> <div class="span3">
<div class="pull-right"> <div class="pull-right">
<h5><a id="menu_link_edit" href="clearLogs"><i class="fa fa-trash-o"></i> Clear log</a> <h5><a id="menu_link_edit" href="clearLogs"><i class="fa fa-trash-o"></i> Clear log</a></h5>
</div> </div>
</div> </div>
</div> </div>

View file

@ -14,7 +14,12 @@ from plexpy import helpers
<div class="span12"> <div class="span12">
<div class="wellheader-bg"> <div class="wellheader-bg">
<div class="dashboard-wellheader-no-chevron"> <div class="dashboard-wellheader-no-chevron">
<h2><i class="fa fa-group"></i> Users</h2> <div class="span9"><h2><i class="fa fa-group"></i> Users</h2></div>
<div class="span3">
<div class="pull-right">
<h5><a href="refresh_users_list"><i class="fa fa-refresh"></i> Refresh users</a></h5>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -307,8 +307,35 @@ def sig_handler(signum=None, frame=None):
def dbcheck(): def dbcheck():
conn = sqlite3.connect(plexpy.CONFIG.PLEXWATCH_DATABASE) conn = sqlite3.connect(plexpy.CONFIG.PLEXWATCH_DATABASE)
c = conn.cursor() c = conn.cursor()
c.execute('CREATE TABLE IF NOT EXISTS plexpy_users (id INTEGER PRIMARY KEY AUTOINCREMENT, ' c.execute(
'username TEXT NOT NULL UNIQUE, friendly_name TEXT)') '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() conn.commit()
c.close() c.close()

View file

@ -81,11 +81,11 @@ def latinToAscii(unicrap):
0xfd: 'y', 0xfe: 'th', 0xff: 'y', 0xfd: 'y', 0xfe: 'th', 0xff: 'y',
0xa1: '!', 0xa2: '{cent}', 0xa3: '{pound}', 0xa4: '{currency}', 0xa1: '!', 0xa2: '{cent}', 0xa3: '{pound}', 0xa4: '{currency}',
0xa5: '{yen}', 0xa6: '|', 0xa7: '{section}', 0xa8: '{umlaut}', 0xa5: '{yen}', 0xa6: '|', 0xa7: '{section}', 0xa8: '{umlaut}',
0xa9: '{C}', 0xaa: '{^a}', 0xab: '<<', 0xac: '{not}', 0xa9: '{C}', 0xaa: '{^a}', 0xab: '&lt;&lt;', 0xac: '{not}',
0xad: '-', 0xae: '{R}', 0xaf: '_', 0xb0: '{degrees}', 0xad: '-', 0xae: '{R}', 0xaf: '_', 0xb0: '{degrees}',
0xb1: '{+/-}', 0xb2: '{^2}', 0xb3: '{^3}', 0xb4: "'", 0xb1: '{+/-}', 0xb2: '{^2}', 0xb3: '{^3}', 0xb4: "'",
0xb5: '{micro}', 0xb6: '{paragraph}', 0xb7: '*', 0xb8: '{cedilla}', 0xb5: '{micro}', 0xb6: '{paragraph}', 0xb7: '*', 0xb8: '{cedilla}',
0xb9: '{^1}', 0xba: '{^o}', 0xbb: '>>', 0xb9: '{^1}', 0xba: '{^o}', 0xbb: '&gt;&gt;',
0xbc: '{1/4}', 0xbd: '{1/2}', 0xbe: '{3/4}', 0xbf: '?', 0xbc: '{1/4}', 0xbd: '{1/2}', 0xbe: '{3/4}', 0xbf: '?',
0xd7: '*', 0xf7: '/' 0xd7: '*', 0xf7: '/'
} }

View file

@ -13,7 +13,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>. # along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
from plexpy import logger, helpers, common, request from plexpy import logger, helpers
from xml.dom import minidom from xml.dom import minidom
from httplib import HTTPSConnection from httplib import HTTPSConnection
@ -213,4 +213,73 @@ class PlexTV(object):
logger.warn(u"Failed to access server list. Status code %r" % request_status) logger.warn(u"Failed to access server list. Status code %r" % request_status)
return None return None
return output 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

View file

@ -72,7 +72,9 @@ class PlexWatch(object):
t + '.time', t + '.time',
t + '.ip_address', t + '.ip_address',
'COUNT(' + t + '.title) as plays', 'COUNT(' + t + '.title) as plays',
t + '.user'] t + '.user',
'plexpy_users.user_id as user_id',
'plexpy_users.thumb as thumb']
try: try:
query = data_tables.ssp_query(table_name=t, query = data_tables.ssp_query(table_name=t,
columns=columns, columns=columns,
@ -98,14 +100,18 @@ class PlexWatch(object):
rows = [] rows = []
for item in users: 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'], row = {"plays": item['plays'],
"time": item['time'], "time": item['time'],
"friendly_name": item["friendly_name"], "friendly_name": item["friendly_name"],
"ip_address": item["ip_address"], "ip_address": item["ip_address"],
"thumb": thumb['user_thumb'], "thumb": user_thumb,
"user": item["user"] "user": item["user"],
"user_id": item['user_id']
} }
rows.append(row) rows.append(row)
@ -295,12 +301,12 @@ class PlexWatch(object):
try: try:
xml_parse = minidom.parseString(helpers.latinToAscii(item['xml'])) xml_parse = minidom.parseString(helpers.latinToAscii(item['xml']))
except IOError, e: except:
logger.warn("Error parsing XML in PlexWatch db: %s" % e) logger.warn("Error parsing XML in PlexWatch db")
xml_head = xml_parse.getElementsByTagName('opt') xml_head = xml_parse.getElementsByTagName('opt')
if not xml_head: 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: for s in xml_head:
if s.getAttribute('duration') and s.getAttribute('viewOffset'): if s.getAttribute('duration') and s.getAttribute('viewOffset'):
@ -925,7 +931,10 @@ class PlexWatch(object):
myDB = db.DBConnection() myDB = db.DBConnection()
query = 'select friendly_name FROM plexpy_users WHERE username = ?' query = 'select friendly_name FROM plexpy_users WHERE username = ?'
result = myDB.select_single(query, args=[user]) result = myDB.select_single(query, args=[user])
return result if result:
return result
else:
return user
except: except:
return user return user
@ -956,7 +965,9 @@ def check_db_tables():
try: try:
myDB = db.DBConnection() myDB = db.DBConnection()
query = 'CREATE TABLE IF NOT EXISTS plexpy_users (id INTEGER PRIMARY KEY AUTOINCREMENT, ' \ 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) result = myDB.action(query)
except: except:
logger.debug(u"Unable to create users table.") logger.debug(u"Unable to create users table.")

View file

@ -212,6 +212,39 @@ class PmsConnect(object):
return output 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. Return processed and validated list of recently added items.
@ -681,6 +714,41 @@ class PmsConnect(object):
return output 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. Return image data as array.
Array contains the image content type and image binary Array contains the image content type and image binary

View file

@ -13,7 +13,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>. # along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
from plexpy import logger, notifiers, plextv, pmsconnect, plexwatch from plexpy import logger, notifiers, plextv, pmsconnect, plexwatch, db
from plexpy.helpers import checked, radio from plexpy.helpers import checked, radio
from mako.lookup import TemplateLookup from mako.lookup import TemplateLookup
@ -833,3 +833,61 @@ class WebInterface(object):
return result return result
else: else:
logger.warn('Unable to retrieve data.') 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")