Merge branch 'dev'

This commit is contained in:
JonnyWong16 2016-09-02 11:51:51 -07:00
commit a07f54ca33
9 changed files with 67 additions and 69 deletions

View file

@ -1,5 +1,12 @@
# Changelog # Changelog
## v1.4.11 (2016-09-02)
* Fix: PlexWatch and Plexivity import errors.
* Fix: Searching in history datatables.
* Fix: Notifications not sending for Local user.
## v1.4.10 (2016-08-15) ## v1.4.10 (2016-08-15)
* Fix: Missing python ipaddress module preventing PlexPy from starting. * Fix: Missing python ipaddress module preventing PlexPy from starting.

View file

@ -8,7 +8,7 @@ This project is based on code from [Headphones](https://github.com/rembo10/headp
* [Plex forum thread](https://forums.plex.tv/discussion/169591/plexpy-another-plex-monitoring-program) * [Plex forum thread](https://forums.plex.tv/discussion/169591/plexpy-another-plex-monitoring-program)
* [Gitter chat](https://gitter.im/drzoidberg33/plexpy) * [Gitter chat](https://gitter.im/drzoidberg33/plexpy)
* [Discord server](https://discord.gg/011TFFWSuNFI02EKr) | [PlexPy Discord server](https://discord.gg/36ggawe) * [/r/Plex Discord server](https://discord.gg/011TFFWSuNFI02EKr) | [PlexPy Discord server](https://discord.gg/36ggawe)
## Features ## Features

View file

@ -2679,7 +2679,7 @@ $(document).ready(function() {
}); });
// Load PMS downloads // Load PMS downloads
function loadUpdateDistros(distro_build) { function loadUpdateDistros() {
var update_params_ajax = $.getJSON('get_server_update_params', function (data) { return data; }); var update_params_ajax = $.getJSON('get_server_update_params', function (data) { return data; });
$.when(update_params_ajax).done(function() { $.when(update_params_ajax).done(function() {

View file

@ -65,23 +65,20 @@ class DataTables(object):
extracted_columns['column_named'], extracted_columns['column_named'],
parameters['columns']) parameters['columns'])
args = cw_args + w_args
# Build union parameters # Build union parameters
if table_name_union: if table_name_union:
extracted_columns_union = self.extract_columns(columns=columns_union) extracted_columns_union = self.extract_columns(columns=columns_union)
group_u = self.build_grouping(group_by_union) group_u = self.build_grouping(group_by_union)
c_where_u, cwu_args = self.build_custom_where(custom_where_union) c_where_u, cwu_args = self.build_custom_where(custom_where_union)
args += cwu_args
union = 'UNION SELECT %s FROM %s %s %s' % (extracted_columns_union['column_string'], union = 'UNION SELECT %s FROM %s %s %s' % (extracted_columns_union['column_string'],
table_name_union, table_name_union,
c_where_u, c_where_u,
group_u) group_u)
else: else:
union = '' union = ''
cwu_args = []
args = cw_args + cwu_args + w_args
# Build the query # Build the query
query = 'SELECT * FROM (SELECT %s FROM %s %s %s %s %s) %s %s' \ query = 'SELECT * FROM (SELECT %s FROM %s %s %s %s %s) %s %s' \

View file

@ -616,6 +616,7 @@ def send_notification(agent_id, subject, body, notify_action, **kwargs):
else: else:
logger.debug(u"PlexPy Notifiers :: Notification requested but no agent id received.") logger.debug(u"PlexPy Notifiers :: Notification requested but no agent id received.")
class PrettyMetadata(object): class PrettyMetadata(object):
def __init__(self, metadata): def __init__(self, metadata):
self.metadata = metadata self.metadata = metadata
@ -683,6 +684,7 @@ class PrettyMetadata(object):
self.plex_url = self.metadata['plex_url'] self.plex_url = self.metadata['plex_url']
return self.plex_url return self.plex_url
class GROWL(object): class GROWL(object):
""" """
Growl notifications, for OS X. Growl notifications, for OS X.
@ -2114,6 +2116,21 @@ class Scripts(object):
def __init__(self, **kwargs): def __init__(self, **kwargs):
self.script_exts = ('.bat', '.cmd', '.exe', '.php', '.pl', '.ps1', '.py', '.pyw', '.rb', '.sh') self.script_exts = ('.bat', '.cmd', '.exe', '.php', '.pl', '.ps1', '.py', '.pyw', '.rb', '.sh')
self.script_folder = plexpy.CONFIG.SCRIPTS_FOLDER self.script_folder = plexpy.CONFIG.SCRIPTS_FOLDER
self.scripts = {'play': plexpy.CONFIG.SCRIPTS_ON_PLAY_SCRIPT,
'stop': plexpy.CONFIG.SCRIPTS_ON_STOP_SCRIPT,
'pause': plexpy.CONFIG.SCRIPTS_ON_PAUSE_SCRIPT,
'resume': plexpy.CONFIG.SCRIPTS_ON_RESUME_SCRIPT,
'watched': plexpy.CONFIG.SCRIPTS_ON_WATCHED_SCRIPT,
'buffer': plexpy.CONFIG.SCRIPTS_ON_BUFFER_SCRIPT,
'created': plexpy.CONFIG.SCRIPTS_ON_CREATED_SCRIPT,
'intdown': plexpy.CONFIG.SCRIPTS_ON_INTDOWN_SCRIPT,
'intup': plexpy.CONFIG.SCRIPTS_ON_INTUP_SCRIPT,
'extdown': plexpy.CONFIG.SCRIPTS_ON_EXTDOWN_SCRIPT,
'extup': plexpy.CONFIG.SCRIPTS_ON_EXTUP_SCRIPT,
'pmsupdate': plexpy.CONFIG.SCRIPTS_ON_PMSUPDATE_SCRIPT,
'concurrent': plexpy.CONFIG.SCRIPTS_ON_CONCURRENT_SCRIPT,
'newdevice': plexpy.CONFIG.SCRIPTS_ON_NEWDEVICE_SCRIPT
}
def conf(self, options): def conf(self, options):
return cherrypy.config['config'].get('Scripts', options) return cherrypy.config['config'].get('Scripts', options)
@ -2160,52 +2177,7 @@ class Scripts(object):
if not self.script_folder: if not self.script_folder:
return return
# Make sure we use the correct script.. script = self.scripts.get(notify_action, kwargs.get('script', ''))
if notify_action == 'play':
script = plexpy.CONFIG.SCRIPTS_ON_PLAY_SCRIPT
elif notify_action == 'stop':
script = plexpy.CONFIG.SCRIPTS_ON_STOP_SCRIPT
elif notify_action == 'pause':
script = plexpy.CONFIG.SCRIPTS_ON_PAUSE_SCRIPT
elif notify_action == 'resume':
script = plexpy.CONFIG.SCRIPTS_ON_RESUME_SCRIPT
elif notify_action == 'watched':
script = plexpy.CONFIG.SCRIPTS_ON_WATCHED_SCRIPT
elif notify_action == 'buffer':
script = plexpy.CONFIG.SCRIPTS_ON_BUFFER_SCRIPT
elif notify_action == 'created':
script = plexpy.CONFIG.SCRIPTS_ON_CREATED_SCRIPT
elif notify_action == 'intdown':
script = plexpy.CONFIG.SCRIPTS_ON_INTDOWN_SCRIPT
elif notify_action == 'intup':
script = plexpy.CONFIG.SCRIPTS_ON_INTUP_SCRIPT
elif notify_action == 'extdown':
script = plexpy.CONFIG.SCRIPTS_ON_EXTDOWN_SCRIPT
elif notify_action == 'extup':
script = plexpy.CONFIG.SCRIPTS_ON_EXTUP_SCRIPT
elif notify_action == 'pmsupdate':
script = plexpy.CONFIG.SCRIPTS_ON_PMSUPDATE_SCRIPT
elif notify_action == 'concurrent':
script = plexpy.CONFIG.SCRIPTS_ON_CONCURRENT_SCRIPT
elif notify_action == 'newdevice':
script = plexpy.CONFIG.SCRIPTS_ON_NEWDEVICE_SCRIPT
else:
# For manual scripts
script = kwargs.get('script', '')
# Don't try to run the script if the action does not have one # Don't try to run the script if the action does not have one
if notify_action and not script: if notify_action and not script:
@ -2297,98 +2269,98 @@ class Scripts(object):
'input_type': 'text', 'input_type': 'text',
}, },
{'label': 'Playback Start', {'label': 'Playback Start',
'value': plexpy.CONFIG.SCRIPTS_ON_PLAY_SCRIPT, 'value': self.scripts['play'],
'name': 'scripts_on_play_script', 'name': 'scripts_on_play_script',
'description': 'Choose the script for on play.', 'description': 'Choose the script for on play.',
'input_type': 'select', 'input_type': 'select',
'select_options': self.list_scripts() 'select_options': self.list_scripts()
}, },
{'label': 'Playback Stop', {'label': 'Playback Stop',
'value': plexpy.CONFIG.SCRIPTS_ON_STOP_SCRIPT, 'value': self.scripts['stop'],
'name': 'scripts_on_stop_script', 'name': 'scripts_on_stop_script',
'description': 'Choose the script for on stop.', 'description': 'Choose the script for on stop.',
'input_type': 'select', 'input_type': 'select',
'select_options': self.list_scripts() 'select_options': self.list_scripts()
}, },
{'label': 'Playback Pause', {'label': 'Playback Pause',
'value': plexpy.CONFIG.SCRIPTS_ON_PAUSE_SCRIPT, 'value': self.scripts['pause'],
'name': 'scripts_on_pause_script', 'name': 'scripts_on_pause_script',
'description': 'Choose the script for on pause.', 'description': 'Choose the script for on pause.',
'input_type': 'select', 'input_type': 'select',
'select_options': self.list_scripts() 'select_options': self.list_scripts()
}, },
{'label': 'Playback Resume', {'label': 'Playback Resume',
'value': plexpy.CONFIG.SCRIPTS_ON_RESUME_SCRIPT, 'value': self.scripts['resume'],
'name': 'scripts_on_resume_script', 'name': 'scripts_on_resume_script',
'description': 'Choose the script for on resume.', 'description': 'Choose the script for on resume.',
'input_type': 'select', 'input_type': 'select',
'select_options': self.list_scripts() 'select_options': self.list_scripts()
}, },
{'label': 'Watched', {'label': 'Watched',
'value': plexpy.CONFIG.SCRIPTS_ON_WATCHED_SCRIPT, 'value': self.scripts['watched'],
'name': 'scripts_on_watched_script', 'name': 'scripts_on_watched_script',
'description': 'Choose the script for on watched.', 'description': 'Choose the script for on watched.',
'input_type': 'select', 'input_type': 'select',
'select_options': self.list_scripts() 'select_options': self.list_scripts()
}, },
{'label': 'Buffer Warnings', {'label': 'Buffer Warnings',
'value': plexpy.CONFIG.SCRIPTS_ON_BUFFER_SCRIPT, 'value': self.scripts['buffer'],
'name': 'scripts_on_buffer_script', 'name': 'scripts_on_buffer_script',
'description': 'Choose the script for buffer warnings.', 'description': 'Choose the script for buffer warnings.',
'input_type': 'select', 'input_type': 'select',
'select_options': self.list_scripts() 'select_options': self.list_scripts()
}, },
{'label': 'Recently Added', {'label': 'Recently Added',
'value': plexpy.CONFIG.SCRIPTS_ON_CREATED_SCRIPT, 'value': self.scripts['created'],
'name': 'scripts_on_created_script', 'name': 'scripts_on_created_script',
'description': 'Choose the script for recently added.', 'description': 'Choose the script for recently added.',
'input_type': 'select', 'input_type': 'select',
'select_options': self.list_scripts() 'select_options': self.list_scripts()
}, },
{'label': 'Plex Server Down', {'label': 'Plex Server Down',
'value': plexpy.CONFIG.SCRIPTS_ON_INTDOWN_SCRIPT, 'value': self.scripts['intdown'],
'name': 'scripts_on_intdown_script', 'name': 'scripts_on_intdown_script',
'description': 'Choose the script for Plex server down.', 'description': 'Choose the script for Plex server down.',
'input_type': 'select', 'input_type': 'select',
'select_options': self.list_scripts() 'select_options': self.list_scripts()
}, },
{'label': 'Plex Server Back Up', {'label': 'Plex Server Back Up',
'value': plexpy.CONFIG.SCRIPTS_ON_INTUP_SCRIPT, 'value': self.scripts['intup'],
'name': 'scripts_on_intup_script', 'name': 'scripts_on_intup_script',
'description': 'Choose the script for Plex server back up.', 'description': 'Choose the script for Plex server back up.',
'input_type': 'select', 'input_type': 'select',
'select_options': self.list_scripts() 'select_options': self.list_scripts()
}, },
{'label': 'Plex Remote Access Down', {'label': 'Plex Remote Access Down',
'value': plexpy.CONFIG.SCRIPTS_ON_EXTDOWN_SCRIPT, 'value': self.scripts['extdown'],
'name': 'scripts_on_extdown_script', 'name': 'scripts_on_extdown_script',
'description': 'Choose the script for Plex remote access down.', 'description': 'Choose the script for Plex remote access down.',
'input_type': 'select', 'input_type': 'select',
'select_options': self.list_scripts() 'select_options': self.list_scripts()
}, },
{'label': 'Plex Remote Access Back Up', {'label': 'Plex Remote Access Back Up',
'value': plexpy.CONFIG.SCRIPTS_ON_EXTUP_SCRIPT, 'value': self.scripts['extup'],
'name': 'scripts_on_extup_script', 'name': 'scripts_on_extup_script',
'description': 'Choose the script for Plex remote access back up.', 'description': 'Choose the script for Plex remote access back up.',
'input_type': 'select', 'input_type': 'select',
'select_options': self.list_scripts() 'select_options': self.list_scripts()
}, },
{'label': 'Plex Update Available', {'label': 'Plex Update Available',
'value': plexpy.CONFIG.SCRIPTS_ON_PMSUPDATE_SCRIPT, 'value': self.scripts['pmsupdate'],
'name': 'scripts_on_pmsupdate_script', 'name': 'scripts_on_pmsupdate_script',
'description': 'Choose the script for Plex update available.', 'description': 'Choose the script for Plex update available.',
'input_type': 'select', 'input_type': 'select',
'select_options': self.list_scripts() 'select_options': self.list_scripts()
}, },
{'label': 'User Concurrent Streams', {'label': 'User Concurrent Streams',
'value': plexpy.CONFIG.SCRIPTS_ON_CONCURRENT_SCRIPT, 'value': self.scripts['concurrent'],
'name': 'scripts_on_concurrent_script', 'name': 'scripts_on_concurrent_script',
'description': 'Choose the script for user concurrent streams.', 'description': 'Choose the script for user concurrent streams.',
'input_type': 'select', 'input_type': 'select',
'select_options': self.list_scripts() 'select_options': self.list_scripts()
}, },
{'label': 'User New Device', {'label': 'User New Device',
'value': plexpy.CONFIG.SCRIPTS_ON_NEWDEVICE_SCRIPT, 'value': self.scripts['newdevice'],
'name': 'scripts_on_newdevice_script', 'name': 'scripts_on_newdevice_script',
'description': 'Choose the script for user new device.', 'description': 'Choose the script for user new device.',
'input_type': 'select', 'input_type': 'select',

View file

@ -136,6 +136,14 @@ def extract_plexivity_xml(xml=None):
video_decision = helpers.get_xml_attr(e, 'videoDecision') video_decision = helpers.get_xml_attr(e, 'videoDecision')
transcode_width = helpers.get_xml_attr(e, 'width') transcode_width = helpers.get_xml_attr(e, 'width')
# Generate a combined transcode decision value
if video_decision == 'transcode' or audio_decision == 'transcode':
transcode_decision = 'transcode'
elif video_decision == 'copy' or audio_decision == 'copy':
transcode_decision = 'copy'
else:
transcode_decision = 'direct play'
user_id = None user_id = None
if a.getElementsByTagName('User'): if a.getElementsByTagName('User'):
@ -215,6 +223,7 @@ def extract_plexivity_xml(xml=None):
'transcode_video_codec': transcode_video_codec, 'transcode_video_codec': transcode_video_codec,
'video_decision': video_decision, 'video_decision': video_decision,
'transcode_width': transcode_width, 'transcode_width': transcode_width,
'transcode_decision': transcode_decision,
'user_id': user_id, 'user_id': user_id,
'writers': writers, 'writers': writers,
'actors': actors, 'actors': actors,
@ -339,6 +348,7 @@ def import_from_plexivity(database=None, table_name=None, import_ignore_interval
'title': row['title'], 'title': row['title'],
'parent_title': extracted_xml['parent_title'], 'parent_title': extracted_xml['parent_title'],
'grandparent_title': row['grandparent_title'], 'grandparent_title': row['grandparent_title'],
'full_title': row['full_title'],
'user_id': user_id, 'user_id': user_id,
'user': row['user'], 'user': row['user'],
'ip_address': row['ip_address'] if row['ip_address'] else extracted_xml['ip_address'], 'ip_address': row['ip_address'] if row['ip_address'] else extracted_xml['ip_address'],
@ -352,6 +362,7 @@ def import_from_plexivity(database=None, table_name=None, import_ignore_interval
'view_offset': extracted_xml['view_offset'], 'view_offset': extracted_xml['view_offset'],
'video_decision': extracted_xml['video_decision'], 'video_decision': extracted_xml['video_decision'],
'audio_decision': extracted_xml['audio_decision'], 'audio_decision': extracted_xml['audio_decision'],
'transcode_decision': extracted_xml['transcode_decision'],
'duration': extracted_xml['duration'], 'duration': extracted_xml['duration'],
'width': extracted_xml['width'], 'width': extracted_xml['width'],
'height': extracted_xml['height'], 'height': extracted_xml['height'],

View file

@ -130,6 +130,14 @@ def extract_plexwatch_xml(xml=None):
video_decision = helpers.get_xml_attr(e, 'videoDecision') video_decision = helpers.get_xml_attr(e, 'videoDecision')
transcode_width = helpers.get_xml_attr(e, 'width') transcode_width = helpers.get_xml_attr(e, 'width')
# Generate a combined transcode decision value
if video_decision == 'transcode' or audio_decision == 'transcode':
transcode_decision = 'transcode'
elif video_decision == 'copy' or audio_decision == 'copy':
transcode_decision = 'copy'
else:
transcode_decision = 'direct play'
user_id = None user_id = None
if a.getElementsByTagName('User'): if a.getElementsByTagName('User'):
@ -206,6 +214,7 @@ def extract_plexwatch_xml(xml=None):
'transcode_video_codec': transcode_video_codec, 'transcode_video_codec': transcode_video_codec,
'video_decision': video_decision, 'video_decision': video_decision,
'transcode_width': transcode_width, 'transcode_width': transcode_width,
'transcode_decision': transcode_decision,
'user_id': user_id, 'user_id': user_id,
'writers': writers, 'writers': writers,
'actors': actors, 'actors': actors,
@ -332,6 +341,7 @@ def import_from_plexwatch(database=None, table_name=None, import_ignore_interval
'title': row['title'], 'title': row['title'],
'parent_title': extracted_xml['parent_title'], 'parent_title': extracted_xml['parent_title'],
'grandparent_title': row['grandparent_title'], 'grandparent_title': row['grandparent_title'],
'full_title': row['full_title'],
'user_id': user_id, 'user_id': user_id,
'user': row['user'], 'user': row['user'],
'ip_address': row['ip_address'] if row['ip_address'] else extracted_xml['ip_address'], 'ip_address': row['ip_address'] if row['ip_address'] else extracted_xml['ip_address'],
@ -345,6 +355,7 @@ def import_from_plexwatch(database=None, table_name=None, import_ignore_interval
'view_offset': extracted_xml['view_offset'], 'view_offset': extracted_xml['view_offset'],
'video_decision': extracted_xml['video_decision'], 'video_decision': extracted_xml['video_decision'],
'audio_decision': extracted_xml['audio_decision'], 'audio_decision': extracted_xml['audio_decision'],
'transcode_decision': extracted_xml['transcode_decision'],
'duration': extracted_xml['duration'], 'duration': extracted_xml['duration'],
'width': extracted_xml['width'], 'width': extracted_xml['width'],
'height': extracted_xml['height'], 'height': extracted_xml['height'],

View file

@ -279,7 +279,7 @@ class Users(object):
'shared_libraries': () 'shared_libraries': ()
} }
if not user_id and not user and not email: if user_id is None and not user and not email:
return default_return return default_return
def get_user_details(user_id=user_id, user=user, email=email): def get_user_details(user_id=user_id, user=user, email=email):

View file

@ -1,2 +1,2 @@
PLEXPY_VERSION = "master" PLEXPY_VERSION = "master"
PLEXPY_RELEASE_VERSION = "1.4.10" PLEXPY_RELEASE_VERSION = "1.4.11"