mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-07 21:51:14 -07:00
Merge branch 'dev'
This commit is contained in:
commit
a07f54ca33
9 changed files with 67 additions and 69 deletions
|
@ -1,5 +1,12 @@
|
|||
# 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)
|
||||
|
||||
* Fix: Missing python ipaddress module preventing PlexPy from starting.
|
||||
|
|
|
@ -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)
|
||||
* [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
|
||||
|
||||
|
|
|
@ -2679,7 +2679,7 @@ $(document).ready(function() {
|
|||
});
|
||||
|
||||
// Load PMS downloads
|
||||
function loadUpdateDistros(distro_build) {
|
||||
function loadUpdateDistros() {
|
||||
var update_params_ajax = $.getJSON('get_server_update_params', function (data) { return data; });
|
||||
|
||||
$.when(update_params_ajax).done(function() {
|
||||
|
|
|
@ -65,23 +65,20 @@ class DataTables(object):
|
|||
extracted_columns['column_named'],
|
||||
parameters['columns'])
|
||||
|
||||
args = cw_args + w_args
|
||||
|
||||
# Build union parameters
|
||||
if table_name_union:
|
||||
extracted_columns_union = self.extract_columns(columns=columns_union)
|
||||
group_u = self.build_grouping(group_by_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'],
|
||||
table_name_union,
|
||||
c_where_u,
|
||||
group_u)
|
||||
else:
|
||||
union = ''
|
||||
cwu_args = []
|
||||
|
||||
args = cw_args + cwu_args + w_args
|
||||
|
||||
# Build the query
|
||||
query = 'SELECT * FROM (SELECT %s FROM %s %s %s %s %s) %s %s' \
|
||||
|
|
|
@ -616,6 +616,7 @@ def send_notification(agent_id, subject, body, notify_action, **kwargs):
|
|||
else:
|
||||
logger.debug(u"PlexPy Notifiers :: Notification requested but no agent id received.")
|
||||
|
||||
|
||||
class PrettyMetadata(object):
|
||||
def __init__(self, metadata):
|
||||
self.metadata = metadata
|
||||
|
@ -683,6 +684,7 @@ class PrettyMetadata(object):
|
|||
self.plex_url = self.metadata['plex_url']
|
||||
return self.plex_url
|
||||
|
||||
|
||||
class GROWL(object):
|
||||
"""
|
||||
Growl notifications, for OS X.
|
||||
|
@ -2114,6 +2116,21 @@ class Scripts(object):
|
|||
def __init__(self, **kwargs):
|
||||
self.script_exts = ('.bat', '.cmd', '.exe', '.php', '.pl', '.ps1', '.py', '.pyw', '.rb', '.sh')
|
||||
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):
|
||||
return cherrypy.config['config'].get('Scripts', options)
|
||||
|
@ -2160,52 +2177,7 @@ class Scripts(object):
|
|||
if not self.script_folder:
|
||||
return
|
||||
|
||||
# Make sure we use the correct 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', '')
|
||||
script = self.scripts.get(notify_action, kwargs.get('script', ''))
|
||||
|
||||
# Don't try to run the script if the action does not have one
|
||||
if notify_action and not script:
|
||||
|
@ -2297,98 +2269,98 @@ class Scripts(object):
|
|||
'input_type': 'text',
|
||||
},
|
||||
{'label': 'Playback Start',
|
||||
'value': plexpy.CONFIG.SCRIPTS_ON_PLAY_SCRIPT,
|
||||
'value': self.scripts['play'],
|
||||
'name': 'scripts_on_play_script',
|
||||
'description': 'Choose the script for on play.',
|
||||
'input_type': 'select',
|
||||
'select_options': self.list_scripts()
|
||||
},
|
||||
{'label': 'Playback Stop',
|
||||
'value': plexpy.CONFIG.SCRIPTS_ON_STOP_SCRIPT,
|
||||
'value': self.scripts['stop'],
|
||||
'name': 'scripts_on_stop_script',
|
||||
'description': 'Choose the script for on stop.',
|
||||
'input_type': 'select',
|
||||
'select_options': self.list_scripts()
|
||||
},
|
||||
{'label': 'Playback Pause',
|
||||
'value': plexpy.CONFIG.SCRIPTS_ON_PAUSE_SCRIPT,
|
||||
'value': self.scripts['pause'],
|
||||
'name': 'scripts_on_pause_script',
|
||||
'description': 'Choose the script for on pause.',
|
||||
'input_type': 'select',
|
||||
'select_options': self.list_scripts()
|
||||
},
|
||||
{'label': 'Playback Resume',
|
||||
'value': plexpy.CONFIG.SCRIPTS_ON_RESUME_SCRIPT,
|
||||
'value': self.scripts['resume'],
|
||||
'name': 'scripts_on_resume_script',
|
||||
'description': 'Choose the script for on resume.',
|
||||
'input_type': 'select',
|
||||
'select_options': self.list_scripts()
|
||||
},
|
||||
{'label': 'Watched',
|
||||
'value': plexpy.CONFIG.SCRIPTS_ON_WATCHED_SCRIPT,
|
||||
'value': self.scripts['watched'],
|
||||
'name': 'scripts_on_watched_script',
|
||||
'description': 'Choose the script for on watched.',
|
||||
'input_type': 'select',
|
||||
'select_options': self.list_scripts()
|
||||
},
|
||||
{'label': 'Buffer Warnings',
|
||||
'value': plexpy.CONFIG.SCRIPTS_ON_BUFFER_SCRIPT,
|
||||
'value': self.scripts['buffer'],
|
||||
'name': 'scripts_on_buffer_script',
|
||||
'description': 'Choose the script for buffer warnings.',
|
||||
'input_type': 'select',
|
||||
'select_options': self.list_scripts()
|
||||
},
|
||||
{'label': 'Recently Added',
|
||||
'value': plexpy.CONFIG.SCRIPTS_ON_CREATED_SCRIPT,
|
||||
'value': self.scripts['created'],
|
||||
'name': 'scripts_on_created_script',
|
||||
'description': 'Choose the script for recently added.',
|
||||
'input_type': 'select',
|
||||
'select_options': self.list_scripts()
|
||||
},
|
||||
{'label': 'Plex Server Down',
|
||||
'value': plexpy.CONFIG.SCRIPTS_ON_INTDOWN_SCRIPT,
|
||||
'value': self.scripts['intdown'],
|
||||
'name': 'scripts_on_intdown_script',
|
||||
'description': 'Choose the script for Plex server down.',
|
||||
'input_type': 'select',
|
||||
'select_options': self.list_scripts()
|
||||
},
|
||||
{'label': 'Plex Server Back Up',
|
||||
'value': plexpy.CONFIG.SCRIPTS_ON_INTUP_SCRIPT,
|
||||
'value': self.scripts['intup'],
|
||||
'name': 'scripts_on_intup_script',
|
||||
'description': 'Choose the script for Plex server back up.',
|
||||
'input_type': 'select',
|
||||
'select_options': self.list_scripts()
|
||||
},
|
||||
{'label': 'Plex Remote Access Down',
|
||||
'value': plexpy.CONFIG.SCRIPTS_ON_EXTDOWN_SCRIPT,
|
||||
'value': self.scripts['extdown'],
|
||||
'name': 'scripts_on_extdown_script',
|
||||
'description': 'Choose the script for Plex remote access down.',
|
||||
'input_type': 'select',
|
||||
'select_options': self.list_scripts()
|
||||
},
|
||||
{'label': 'Plex Remote Access Back Up',
|
||||
'value': plexpy.CONFIG.SCRIPTS_ON_EXTUP_SCRIPT,
|
||||
'value': self.scripts['extup'],
|
||||
'name': 'scripts_on_extup_script',
|
||||
'description': 'Choose the script for Plex remote access back up.',
|
||||
'input_type': 'select',
|
||||
'select_options': self.list_scripts()
|
||||
},
|
||||
{'label': 'Plex Update Available',
|
||||
'value': plexpy.CONFIG.SCRIPTS_ON_PMSUPDATE_SCRIPT,
|
||||
'value': self.scripts['pmsupdate'],
|
||||
'name': 'scripts_on_pmsupdate_script',
|
||||
'description': 'Choose the script for Plex update available.',
|
||||
'input_type': 'select',
|
||||
'select_options': self.list_scripts()
|
||||
},
|
||||
{'label': 'User Concurrent Streams',
|
||||
'value': plexpy.CONFIG.SCRIPTS_ON_CONCURRENT_SCRIPT,
|
||||
'value': self.scripts['concurrent'],
|
||||
'name': 'scripts_on_concurrent_script',
|
||||
'description': 'Choose the script for user concurrent streams.',
|
||||
'input_type': 'select',
|
||||
'select_options': self.list_scripts()
|
||||
},
|
||||
{'label': 'User New Device',
|
||||
'value': plexpy.CONFIG.SCRIPTS_ON_NEWDEVICE_SCRIPT,
|
||||
'value': self.scripts['newdevice'],
|
||||
'name': 'scripts_on_newdevice_script',
|
||||
'description': 'Choose the script for user new device.',
|
||||
'input_type': 'select',
|
||||
|
|
|
@ -136,6 +136,14 @@ def extract_plexivity_xml(xml=None):
|
|||
video_decision = helpers.get_xml_attr(e, 'videoDecision')
|
||||
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
|
||||
|
||||
if a.getElementsByTagName('User'):
|
||||
|
@ -215,6 +223,7 @@ def extract_plexivity_xml(xml=None):
|
|||
'transcode_video_codec': transcode_video_codec,
|
||||
'video_decision': video_decision,
|
||||
'transcode_width': transcode_width,
|
||||
'transcode_decision': transcode_decision,
|
||||
'user_id': user_id,
|
||||
'writers': writers,
|
||||
'actors': actors,
|
||||
|
@ -339,6 +348,7 @@ def import_from_plexivity(database=None, table_name=None, import_ignore_interval
|
|||
'title': row['title'],
|
||||
'parent_title': extracted_xml['parent_title'],
|
||||
'grandparent_title': row['grandparent_title'],
|
||||
'full_title': row['full_title'],
|
||||
'user_id': user_id,
|
||||
'user': row['user'],
|
||||
'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'],
|
||||
'video_decision': extracted_xml['video_decision'],
|
||||
'audio_decision': extracted_xml['audio_decision'],
|
||||
'transcode_decision': extracted_xml['transcode_decision'],
|
||||
'duration': extracted_xml['duration'],
|
||||
'width': extracted_xml['width'],
|
||||
'height': extracted_xml['height'],
|
||||
|
|
|
@ -130,6 +130,14 @@ def extract_plexwatch_xml(xml=None):
|
|||
video_decision = helpers.get_xml_attr(e, 'videoDecision')
|
||||
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
|
||||
|
||||
if a.getElementsByTagName('User'):
|
||||
|
@ -206,6 +214,7 @@ def extract_plexwatch_xml(xml=None):
|
|||
'transcode_video_codec': transcode_video_codec,
|
||||
'video_decision': video_decision,
|
||||
'transcode_width': transcode_width,
|
||||
'transcode_decision': transcode_decision,
|
||||
'user_id': user_id,
|
||||
'writers': writers,
|
||||
'actors': actors,
|
||||
|
@ -332,6 +341,7 @@ def import_from_plexwatch(database=None, table_name=None, import_ignore_interval
|
|||
'title': row['title'],
|
||||
'parent_title': extracted_xml['parent_title'],
|
||||
'grandparent_title': row['grandparent_title'],
|
||||
'full_title': row['full_title'],
|
||||
'user_id': user_id,
|
||||
'user': row['user'],
|
||||
'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'],
|
||||
'video_decision': extracted_xml['video_decision'],
|
||||
'audio_decision': extracted_xml['audio_decision'],
|
||||
'transcode_decision': extracted_xml['transcode_decision'],
|
||||
'duration': extracted_xml['duration'],
|
||||
'width': extracted_xml['width'],
|
||||
'height': extracted_xml['height'],
|
||||
|
|
|
@ -279,7 +279,7 @@ class Users(object):
|
|||
'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
|
||||
|
||||
def get_user_details(user_id=user_id, user=user, email=email):
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
PLEXPY_VERSION = "master"
|
||||
PLEXPY_RELEASE_VERSION = "1.4.10"
|
||||
PLEXPY_RELEASE_VERSION = "1.4.11"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue