Fix crash on user page if user no longer exists as friend.

Provide fallback images if we can't load the real one.
Some sync table improvements.
This commit is contained in:
Tim 2015-07-02 15:55:31 +02:00
parent aa700e2b63
commit 2aa833d127
6 changed files with 59 additions and 46 deletions

View file

@ -46,9 +46,9 @@ DOCUMENTATION :: END
<li> <li>
<span> <span>
<a href="info?rating_key=${a['rows'][0]['rating_key']}"> <a href="info?rating_key=${a['rows'][0]['rating_key']}">
% if a['rows'][0]['grandparent_thumb'] != '': % if a['rows'][0]['grandparent_thumb']:
<img class="home-platforms-instance-poster" <img class="home-platforms-instance-poster"
src="pms_image_proxy?img=${a['rows'][0]['grandparent_thumb']}&width=162&height=240"> src="pms_image_proxy?img=${a['rows'][0]['grandparent_thumb']}&width=162&height=240&fallback=poster">
% else: % else:
<img class="home-platforms-instance-poster" src="interfaces/default/images/poster.png"> <img class="home-platforms-instance-poster" src="interfaces/default/images/poster.png">
% endif % endif
@ -75,7 +75,7 @@ DOCUMENTATION :: END
<a href="info?rating_key=${a['rows'][0]['rating_key']}"> <a href="info?rating_key=${a['rows'][0]['rating_key']}">
% if a['rows'][0]['grandparent_thumb'] != '': % if a['rows'][0]['grandparent_thumb'] != '':
<img class="home-platforms-instance-poster" <img class="home-platforms-instance-poster"
src="pms_image_proxy?img=${a['rows'][0]['grandparent_thumb']}&width=162&height=240"> src="pms_image_proxy?img=${a['rows'][0]['grandparent_thumb']}&width=162&height=240&fallback=poster">
% else: % else:
<img class="home-platforms-instance-poster" src="interfaces/default/images/poster.png"> <img class="home-platforms-instance-poster" src="interfaces/default/images/poster.png">
% endif % endif

View file

@ -14,7 +14,9 @@ sync_table_options = {
"emptyTable": "No synced items", "emptyTable": "No synced items",
"info":"Showing _START_ to _END_ of _TOTAL_ lines", "info":"Showing _START_ to _END_ of _TOTAL_ lines",
"infoEmpty":"Showing 0 to 0 of 0 lines", "infoEmpty":"Showing 0 to 0 of 0 lines",
"infoFiltered":"(filtered from _MAX_ total lines)"}, "infoFiltered":"(filtered from _MAX_ total lines)",
"loadingRecords":'<i class="fa fa-refresh fa-spin"></i> Loading items...</div>'
},
"columnDefs": [ "columnDefs": [
{ {
"targets": [0], "targets": [0],
@ -91,11 +93,10 @@ sync_table_options = {
}, },
{ {
"targets": [10], "targets": [10],
"data": null, "data": "item_downloaded_percent_complete",
"createdCell": function (td, cellData, rowData, row, col) { "createdCell": function (td, cellData, rowData, row, col) {
if (rowData['item_count'] > 0 ) { if (rowData['item_count'] > 0 ) {
percent_complete = Math.round((rowData['item_downloaded_count']/rowData['item_count']*100),0); $(td).html('<span class="badge">' + cellData + '%</span>');
$(td).html('<span class="badge">' + percent_complete + '%</span>');
} else { } else {
$(td).html('<span class="badge">0%</span>'); $(td).html('<span class="badge">0%</span>');
} }

View file

@ -25,10 +25,10 @@ import re
from plexpy import version from plexpy import version
#Identify Our Application # Identify Our Application
USER_AGENT = 'PlexPy/-' + version.PLEXPY_VERSION + ' (' + platform.system() + ' ' + platform.release() + ')' USER_AGENT = 'PlexPy/-' + version.PLEXPY_VERSION + ' (' + platform.system() + ' ' + platform.release() + ')'
### Notification Types # Notification Types
NOTIFY_SNATCH = 1 NOTIFY_SNATCH = 1
NOTIFY_DOWNLOAD = 2 NOTIFY_DOWNLOAD = 2
@ -36,13 +36,5 @@ notifyStrings = {}
notifyStrings[NOTIFY_SNATCH] = "Started Download" notifyStrings[NOTIFY_SNATCH] = "Started Download"
notifyStrings[NOTIFY_DOWNLOAD] = "Download Finished" notifyStrings[NOTIFY_DOWNLOAD] = "Download Finished"
### Release statuses DEFAULT_USER_THUMB = "interfaces/default/images/gravatar-default-80x80.png"
UNKNOWN = -1 # should never happen DEFAULT_POSTER_THUMB = "interfaces/default/images/poster.png"
UNAIRED = 1 # releases that haven't dropped yet
SNATCHED = 2 # qualified with quality
WANTED = 3 # releases we don't have but want to get
DOWNLOADED = 4 # qualified with quality
SKIPPED = 5 # releases we don't want
ARCHIVED = 6 # releases that you don't have locally (counts toward download completion stats)
IGNORED = 7 # releases that you don't want included in your download stats
SNATCHED_PROPER = 9 # qualified with quality

View file

@ -17,17 +17,9 @@ from plexpy import logger, helpers, plexwatch
from xml.dom import minidom from xml.dom import minidom
from httplib import HTTPSConnection from httplib import HTTPSConnection
from urlparse import parse_qsl
from urllib import urlencode
import base64 import base64
import cherrypy
import urllib
import urllib2
import plexpy import plexpy
import os.path
import subprocess
import json
class PlexTV(object): class PlexTV(object):
@ -346,6 +338,8 @@ class PlexTV(object):
status_item_ready_count = self.get_xml_attr(status, 'itemsReadyCount') status_item_ready_count = self.get_xml_attr(status, 'itemsReadyCount')
status_item_successful_count = self.get_xml_attr(status, 'itemsSuccessfulCount') status_item_successful_count = self.get_xml_attr(status, 'itemsSuccessfulCount')
status_total_size = self.get_xml_attr(status, 'totalSize') status_total_size = self.get_xml_attr(status, 'totalSize')
status_item_download_percent_complete = helpers.get_percent(
status_item_downloaded_count, status_item_count)
for settings in item.getElementsByTagName('MediaSettings'): for settings in item.getElementsByTagName('MediaSettings'):
settings_audio_boost = self.get_xml_attr(settings, 'audioBoost') settings_audio_boost = self.get_xml_attr(settings, 'audioBoost')
@ -376,6 +370,7 @@ class PlexTV(object):
"item_count": status_item_count, "item_count": status_item_count,
"item_complete_count": status_item_complete_count, "item_complete_count": status_item_complete_count,
"item_downloaded_count": status_item_downloaded_count, "item_downloaded_count": status_item_downloaded_count,
"item_downloaded_percent_complete": status_item_download_percent_complete,
"music_bitrate": settings_music_bitrate, "music_bitrate": settings_music_bitrate,
"photo_quality": settings_photo_quality, "photo_quality": settings_photo_quality,
"video_quality": settings_video_quality, "video_quality": settings_video_quality,

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, datatables, db from plexpy import logger, helpers, datatables, db, common
from xml.dom import minidom from xml.dom import minidom
import sys import sys
if sys.version_info < (2, 7): if sys.version_info < (2, 7):
@ -100,8 +100,8 @@ class PlexWatch(object):
rows = [] rows = []
for item in users: for item in users:
if not item['thumb']: if not item['thumb'] or item['thumb'] == '':
user_thumb = 'interfaces/default/images/gravatar-default-80x80.png' user_thumb = common.DEFAULT_USER_THUMB
else: else:
user_thumb = item['thumb'] user_thumb = item['thumb']
@ -710,8 +710,8 @@ class PlexWatch(object):
return None return None
for item in result: for item in result:
if not item['thumb']: if not item['thumb'] or item['thumb'] == '':
user_thumb = 'interfaces/default/images/gravatar-default-80x80.png' user_thumb = common.DEFAULT_USER_THUMB
else: else:
user_thumb = item[4] user_thumb = item[4]
@ -948,10 +948,20 @@ class PlexWatch(object):
def get_user_details(self, user=None, user_id=None): def get_user_details(self, user=None, user_id=None):
try: try:
myDB = db.DBConnection() myDB = db.DBConnection()
t = self.get_history_table_name()
if user: if user:
query = 'select user_id, username, friendly_name, email, thumb, ' \ query = 'SELECT user_id, username, friendly_name, email, ' \
'is_home_user, is_allow_sync, is_restricted FROM plexpy_users WHERE username = ? LIMIT 1' 'thumb, is_home_user, is_allow_sync, is_restricted ' \
result = myDB.select(query, args=[user]) 'FROM plexpy_users ' \
'WHERE username = ? ' \
'UNION ALL ' \
'SELECT null, user, null, null, null, null, null, null ' \
'FROM %s ' \
'WHERE user = ? ' \
'GROUP BY user ' \
'LIMIT 1' % t
result = myDB.select(query, args=[user, user])
elif user_id: elif user_id:
query = 'select user_id, username, friendly_name, email, thumb, ' \ query = 'select user_id, username, friendly_name, email, thumb, ' \
'is_home_user, is_allow_sync, is_restricted FROM plexpy_users WHERE user_id = ? LIMIT 1' 'is_home_user, is_allow_sync, is_restricted FROM plexpy_users WHERE user_id = ? LIMIT 1'
@ -962,12 +972,16 @@ class PlexWatch(object):
friendly_name = item['username'] friendly_name = item['username']
else: else:
friendly_name = 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']
user_details = {"user_id": item['user_id'], user_details = {"user_id": item['user_id'],
"username": item['username'], "username": item['username'],
"friendly_name": friendly_name, "friendly_name": friendly_name,
"email": item['email'], "email": item['email'],
"thumb": item['thumb'], "thumb": user_thumb,
"is_home_user": item['is_home_user'], "is_home_user": item['is_home_user'],
"is_allow_sync": item['is_allow_sync'], "is_allow_sync": item['is_allow_sync'],
"is_restricted": item['is_restricted'] "is_restricted": item['is_restricted']

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, db from plexpy import logger, notifiers, plextv, pmsconnect, plexwatch, db, common
from plexpy.helpers import checked, radio from plexpy.helpers import checked, radio
from mako.lookup import TemplateLookup from mako.lookup import TemplateLookup
@ -50,6 +50,10 @@ def serve_template(templatename, **kwargs):
class WebInterface(object): class WebInterface(object):
def __init__(self):
self.interface_dir = os.path.join(str(plexpy.PROG_DIR), 'data/')
@cherrypy.expose @cherrypy.expose
def index(self): def index(self):
raise cherrypy.HTTPRedirect("home") raise cherrypy.HTTPRedirect("home")
@ -108,7 +112,6 @@ class WebInterface(object):
user_details = plex_watch.get_user_details(user) user_details = plex_watch.get_user_details(user)
except: except:
logger.warn("Unable to retrieve friendly name for user %s " % user) logger.warn("Unable to retrieve friendly name for user %s " % user)
friendly_name = user
return serve_template(templatename="user.html", title="User", data=user_details) return serve_template(templatename="user.html", title="User", data=user_details)
@ -532,7 +535,7 @@ class WebInterface(object):
logger.warn('Unable to retrieve data.') logger.warn('Unable to retrieve data.')
@cherrypy.expose @cherrypy.expose
def pms_image_proxy(self, img='', width='0', height='0', **kwargs): def pms_image_proxy(self, img='', width='0', height='0', fallback=None, **kwargs):
if img != '': if img != '':
try: try:
pms_connect = pmsconnect.PmsConnect() pms_connect = pmsconnect.PmsConnect()
@ -541,10 +544,18 @@ class WebInterface(object):
return result[1] return result[1]
except: except:
logger.warn('Image proxy queried but errors occured.') logger.warn('Image proxy queried but errors occured.')
return 'No image' 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)
return None
else: else:
logger.warn('Image proxy queried but no parameters received.') logger.warn('Image proxy queried but no parameters received.')
return 'No image' return None
@cherrypy.expose @cherrypy.expose
def info(self, rating_key='', **kwargs): def info(self, rating_key='', **kwargs):