diff --git a/data/interfaces/default/settings.html b/data/interfaces/default/settings.html
index 4561070a..01a826d2 100644
--- a/data/interfaces/default/settings.html
+++ b/data/interfaces/default/settings.html
@@ -581,15 +581,31 @@
If you're using websocket monitoring, any server changes require a restart of PlexPy.
Monitor Plex Updates
-
Enable to have PlexPy check if updates are available for the Plex Media Server.
- Note: The Plex updater is broken on certain Plex Pass version of Plex Media Server. PlexPy will automatically disable checking for Plex updates if one of these versions is found.
+
Enable to have PlexPy check if updates are available for the Plex Media Server.
+
+
@@ -2115,6 +2131,7 @@ $(document).ready(function() {
}
$("#http_hashed_password").val($("#http_hash_password").is(":checked") ? 1 : 0)
getSchedulerTable();
+ loadUpdateDistros();
settingsChanged = false;
}
@@ -2145,7 +2162,8 @@ $(document).ready(function() {
initConfigCheckbox('#https_create_cert');
initConfigCheckbox('#check_github');
initConfigCheckbox('#notify_upload_posters');
-
+ initConfigCheckbox('#monitor_pms_updates');
+
$("#menu_link_shutdown").click(function() {
$("#confirm-message").text("Are you sure you want to shutdown PlexPy?");
$('#confirm-modal').modal();
@@ -2348,6 +2366,7 @@ $(document).ready(function() {
} else {
$("#pms-token-status").html(' Invalid username or password.');
}
+ loadUpdateDistros();
}
});
} else {
@@ -2406,33 +2425,26 @@ $(document).ready(function() {
pms_logs = false;
// Checks to see if PMS server version is >= 0.9.14 with automaatically logged IP addresses
- $.ajax({
- url: 'get_server_identity',
- async: true,
- success: function(data) {
- if (data.version){ $("#pms_version").text(data.version); }
- var version = (data.version ? data.version.split('.') : null);
- if (version && parseInt(version[0]) >= 0 && parseInt(version[1]) >= 9 && parseInt(version[2]) >= 14) {
- $("#debugLogCheck").html("IP address is automatically logged for PMS version 0.9.14 and above.");
- $("#ip_logging_enable").attr("disabled", true);
- $("#ip_logging_enable").attr("checked", true);
- pms_version = true;
+ var version = "${config['pms_version']}".split('.');
+ if (version && parseInt(version[0]) >= 0 && parseInt(version[1]) >= 9 && parseInt(version[2]) >= 14) {
+ $("#debugLogCheck").html("IP address is automatically logged for PMS version 0.9.14 and above.");
+ $("#ip_logging_enable").attr("disabled", true);
+ $("#ip_logging_enable").attr("checked", true);
+ pms_version = true;
+ checkLogsPath();
+ } else {
+ // Check to see if debug logs are enabled on the PMS.
+ $.ajax({
+ url: 'get_server_pref',
+ data: { pref: 'logDebug' },
+ async: true,
+ success: function(data) {
+ pms_logs_debug = (data == 'true' ? true : false);
+ // Check to see if our logs folder is set before allowing IP logging to be enabled.
checkLogsPath();
- } else {
- // Check to see if debug logs are enabled on the PMS.
- $.ajax({
- url: 'get_server_pref',
- data: { pref: 'logDebug' },
- async: true,
- success: function(data) {
- pms_logs_debug = (data == 'true' ? true : false);
- // Check to see if our logs folder is set before allowing IP logging to be enabled.
- checkLogsPath();
- }
- });
}
- }
- });
+ });
+ }
$("#pms_logs_folder").change(function() {
checkLogsPath();
@@ -2642,6 +2654,47 @@ $(document).ready(function() {
$("#http_hashed_password").val($("#http_hash_password").is(":checked") ? 1 : 0);
$("#http_hash_password_error").html("");
});
+
+ // Load PMS downloads
+ function loadUpdateDistros(distro_build) {
+ var update_params_ajax = $.getJSON('get_server_update_params', function (data) { return data; });
+
+ $.when(update_params_ajax).done(function() {
+ var update_params = update_params_ajax.responseJSON;
+
+ var plexpass = update_params.plexpass;
+ var platform = update_params.pms_platform;
+ var update_channel = update_params.pms_update_channel;
+ var update_distro_build = update_params.pms_update_distro_build;
+
+ $("#pms_update_channel option[value='plexpass']").remove();
+ if (plexpass) {
+ var selected = (update_channel == 'plexpass') ? true : false;
+ $('#pms_update_channel')
+ .append($(' ')
+ .text('Plex Pass')
+ .val('plexpass')
+ .prop('selected', selected));
+ }
+
+ $.getJSON('https://plex.tv/api/downloads/1.json?channel=' + update_channel, function (downloads) {
+ platform_downloads = downloads.computer[platform] || downloads.nas[platform];
+ if (platform_downloads) {
+ $("#pms_update_distro_build option").remove();
+ $.each(platform_downloads.releases, function (index, item) {
+ var label = (platform_downloads.releases.length == 1) ? platform_downloads.name : platform_downloads.name + ' - ' + item.label;
+ var selected = (item.build == update_distro_build) ? true : false;
+ $('#pms_update_distro_build')
+ .append($(' ')
+ .text(label)
+ .val(item.build)
+ .prop('selected', selected));
+ })
+ }
+ });
+ });
+ }
+ loadUpdateDistros();
});
%def>
diff --git a/plexpy/activity_pinger.py b/plexpy/activity_pinger.py
index ea6449c0..8ab3bf31 100644
--- a/plexpy/activity_pinger.py
+++ b/plexpy/activity_pinger.py
@@ -24,6 +24,7 @@ import libraries
import logger
import notification_handler
import notifiers
+import plextv
import pmsconnect
@@ -372,23 +373,19 @@ def check_server_updates():
with monitor_lock:
logger.info(u"PlexPy Monitor :: Checking for PMS updates...")
- pms_connect = pmsconnect.PmsConnect()
+ plex_tv = plextv.PlexTV()
+ download_info = plex_tv.get_plex_downloads()
- server_identity = pms_connect.get_server_identity()
- update_status = pms_connect.get_update_staus()
+ if download_info:
+ logger.info(u"PlexPy Monitor :: Current PMS version: %s", plexpy.CONFIG.PMS_VERSION)
- if server_identity and update_status:
- version = server_identity['version']
- logger.info(u"PlexPy Monitor :: Current PMS version: %s", version)
-
- if update_status['state'] == 'available':
- update_version = update_status['version']
- logger.info(u"PlexPy Monitor :: PMS update available version: %s", update_version)
+ if download_info['update_available']:
+ logger.info(u"PlexPy Monitor :: PMS update available version: %s", download_info['version'])
# Check if any notification agents have notifications enabled
if any(d['on_pmsupdate'] for d in notifiers.available_notification_agents()):
# Fire off notifications
threading.Thread(target=notification_handler.notify_timeline,
- kwargs=dict(notify_action='pmsupdate')).start()
+ kwargs=dict(notify_action='pmsupdate')).start()
else:
logger.info(u"PlexPy Monitor :: No PMS update available.")
\ No newline at end of file
diff --git a/plexpy/config.py b/plexpy/config.py
index 92bc4ee0..094ca9cf 100644
--- a/plexpy/config.py
+++ b/plexpy/config.py
@@ -55,6 +55,11 @@ _CONFIG_DEFINITIONS = {
'PMS_USE_BIF': (int, 'PMS', 0),
'PMS_UUID': (str, 'PMS', ''),
'PMS_TIMEOUT': (int, 'Advanced', 15),
+ 'PMS_PLEXPASS': (int, 'PMS', 0),
+ 'PMS_PLATFORM': (str, 'PMS', ''),
+ 'PMS_VERSION': (str, 'PMS', ''),
+ 'PMS_UPDATE_CHANNEL': (str, 'PMS', 'public'),
+ 'PMS_UPDATE_DISTRO_BUILD': (str, 'PMS', ''),
'TIME_FORMAT': (str, 'General', 'HH:mm'),
'ANON_REDIRECT': (str, 'General', 'http://dereferer.org/?'),
'API_ENABLED': (int, 'General', 0),
@@ -719,4 +724,8 @@ class Config(object):
home_sections = self.HOME_SECTIONS
home_sections.remove('library_stats')
self.HOME_SECTIONS = home_sections
- self.CONFIG_VERSION = '5'
\ No newline at end of file
+ self.CONFIG_VERSION = '5'
+
+ if self.CONFIG_VERSION == '5':
+ self.MONITOR_PMS_UPDATES = 0
+ self.CONFIG_VERSION = '6'
\ No newline at end of file
diff --git a/plexpy/plextv.py b/plexpy/plextv.py
index ee46aa95..ce816946 100644
--- a/plexpy/plextv.py
+++ b/plexpy/plextv.py
@@ -17,6 +17,7 @@
# along with PlexPy. If not, see .
import base64
+import json
from xml.dom import minidom
import plexpy
@@ -95,14 +96,20 @@ def get_real_pms_url():
fallback_url = 'http://' + plexpy.CONFIG.PMS_IP + ':' + str(plexpy.CONFIG.PMS_PORT)
- if plexpy.CONFIG.PMS_SSL:
- result = PlexTV().get_server_urls(include_https=True)
- else:
- result = PlexTV().get_server_urls(include_https=False)
+ plex_tv = PlexTV()
+ result = plex_tv.get_server_urls(include_https=plexpy.CONFIG.PMS_SSL)
+ plexpass = plex_tv.get_plexpass_status()
+
+ connections = []
+ if result:
+ plexpy.CONFIG.__setattr__('PMS_VERSION', result['version'])
+ plexpy.CONFIG.__setattr__('PMS_PLATFORM', result['platform'])
+ plexpy.CONFIG.__setattr__('PMS_PLEXPASS', plexpass)
+ connections = result['connections']
# Only need to retrieve PMS_URL if using SSL
if plexpy.CONFIG.PMS_SSL:
- if result:
+ if connections:
if plexpy.CONFIG.PMS_IS_REMOTE:
# Get all remote connections
connections = [c for c in result if c['local'] == '0' and 'plex.direct' in c['uri']]
@@ -273,6 +280,18 @@ class PlexTV(object):
return request
+ def get_plextv_downloads(self, plexpass=False, output_format=''):
+ if plexpass:
+ uri = '/api/downloads/1.json?channel=plexpass'
+ else:
+ uri = '/api/downloads/1.json'
+ request = self.request_handler.make_request(uri=uri,
+ proto=self.protocol,
+ request_type='GET',
+ output_format=output_format)
+
+ return request
+
def get_full_users_list(self):
friends_list = self.get_plextv_friends()
own_account = self.get_plextv_user_details()
@@ -454,7 +473,7 @@ class PlexTV(object):
server_id = plexpy.CONFIG.PMS_IDENTIFIER
else:
logger.error(u"PlexPy PlexTV :: Unable to retrieve server identity.")
- return []
+ return {}
plextv_resources = self.get_plextv_resources(include_https=include_https)
@@ -462,22 +481,26 @@ class PlexTV(object):
xml_parse = minidom.parseString(plextv_resources)
except Exception as e:
logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_server_urls: %s" % e)
- return []
+ return {}
except:
logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_server_urls.")
- return []
+ return {}
try:
xml_head = xml_parse.getElementsByTagName('Device')
except Exception as e:
logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_server_urls: %s." % e)
- return []
+ return {}
# Function to get all connections for a device
def get_connections(device):
conn = []
connections = device.getElementsByTagName('Connection')
+ server = {"platform": helpers.get_xml_attr(device, 'platform'),
+ "version": helpers.get_xml_attr(device, 'productVersion')
+ }
+
for c in connections:
server_details = {"protocol": helpers.get_xml_attr(c, 'protocol'),
"address": helpers.get_xml_attr(c, 'address'),
@@ -487,18 +510,19 @@ class PlexTV(object):
}
conn.append(server_details)
- return conn
+ server['connections'] = conn
+ return server
- server_urls = []
+ server = {}
# Try to match the device
for a in xml_head:
if helpers.get_xml_attr(a, 'clientIdentifier') == server_id:
- server_urls = get_connections(a)
+ server = get_connections(a)
break
# Else no device match found
- if not server_urls:
+ if not server:
# Try to match the PMS_IP and PMS_PORT
for a in xml_head:
if helpers.get_xml_attr(a, 'provides') == 'server':
@@ -511,16 +535,16 @@ class PlexTV(object):
plexpy.CONFIG.PMS_IDENTIFIER = helpers.get_xml_attr(a, 'clientIdentifier')
plexpy.CONFIG.write()
- logger.info(u"PlexPy PlexTV :: PMS identifier changed from %s to %s." % \
- (server_id, plexpy.CONFIG.PMS_IDENTIFIER))
+ logger.info(u"PlexPy PlexTV :: PMS identifier changed from %s to %s."
+ % (server_id, plexpy.CONFIG.PMS_IDENTIFIER))
- server_urls = get_connections(a)
+ server = get_connections(a)
break
- if server_urls:
+ if server.get('connections'):
break
- return server_urls
+ return server
def get_server_times(self):
servers = self.get_plextv_server_list(output_format='xml')
@@ -588,4 +612,72 @@ class PlexTV(object):
}
clean_servers.append(server)
- return clean_servers
\ No newline at end of file
+ return clean_servers
+
+ def get_plex_downloads(self):
+ logger.debug(u"PlexPy PlexTV :: Plex update channel is %s." % plexpy.CONFIG.PMS_UPDATE_CHANNEL)
+ plex_downloads = self.get_plextv_downloads(plexpass=(plexpy.CONFIG.PMS_UPDATE_CHANNEL == 'plexpass'))
+
+ try:
+ available_downloads = json.loads(plex_downloads)
+ except Exception as e:
+ logger.warn(u"PlexPy PlexTV :: Unable to load JSON for get_plex_updates.")
+ return {}
+
+ # Get the updates for the platform
+ platform_downloads = available_downloads.get('computer').get(plexpy.CONFIG.PMS_PLATFORM) or \
+ available_downloads.get('nas').get(plexpy.CONFIG.PMS_PLATFORM)
+
+ if not platform_downloads:
+ logger.error(u"PlexPy PlexTV :: Unable to retrieve Plex updates: Could not match server platform: %s."
+ % plexpy.CONFIG.PMS_PLATFORM)
+ return {}
+
+ v_old = plexpy.CONFIG.PMS_VERSION.split('-')[0].split('.')
+ v_new = platform_downloads.get('version', '').split('-')[0].split('.')
+
+ # Compare versions
+ if v_new[0] > v_old[0] or \
+ v_new[0] == v_old[0] and v_new[1] > v_old[1] or \
+ v_new[0] == v_old[0] and v_new[1] == v_old[1] and v_new[2] > v_old[2] or \
+ v_new[0] == v_old[0] and v_new[1] == v_old[1] and v_new[2] == v_old[2] and v_new[3] > v_old[3]:
+ update_available = True
+ else:
+ update_available = False
+
+ # Get proper download
+ releases = platform_downloads.get('releases', [])
+ release = next((r for r in releases if r['build'] == plexpy.CONFIG.PMS_UPDATE_DISTRO_BUILD), releases[0])
+
+ download_info = {'update_available': update_available,
+ 'platform': platform_downloads.get('name'),
+ 'release_date': platform_downloads.get('release_date'),
+ 'version': platform_downloads.get('version'),
+ 'requirements': platform_downloads.get('requirements'),
+ 'extra_info': platform_downloads.get('extra_info'),
+ 'changelog_added': platform_downloads.get('items_added'),
+ 'changelog_fixed': platform_downloads.get('items_fixed'),
+ 'label': release.get('label'),
+ 'distro': release.get('distro'),
+ 'distro_build': release.get('build'),
+ 'download_url': release.get('url'),
+ }
+
+ return download_info
+
+ def get_plexpass_status(self):
+ account_data = self.get_plextv_user_details(output_format='xml')
+
+ try:
+ subscription = account_data.getElementsByTagName('subscription')
+ except Exception as e:
+ logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_plexpass_status: %s." % e)
+ return False
+
+ if subscription and helpers.get_xml_attr(subscription[0], 'active') == '1':
+ return True
+ else:
+ logger.debug(u"PlexPy PlexTV :: Plex Pass subscription not found.")
+ plexpy.CONFIG.__setattr__('PMS_PLEXPASS', 0)
+ plexpy.CONFIG.write()
+ return False
\ No newline at end of file
diff --git a/plexpy/webserve.py b/plexpy/webserve.py
index c7d054c0..434c61d5 100644
--- a/plexpy/webserve.py
+++ b/plexpy/webserve.py
@@ -2606,7 +2606,8 @@ class WebInterface(object):
"group_history_tables": checked(plexpy.CONFIG.GROUP_HISTORY_TABLES),
"git_token": plexpy.CONFIG.GIT_TOKEN,
"imgur_client_id": plexpy.CONFIG.IMGUR_CLIENT_ID,
- "cache_images": checked(plexpy.CONFIG.CACHE_IMAGES)
+ "cache_images": checked(plexpy.CONFIG.CACHE_IMAGES),
+ "pms_version": plexpy.CONFIG.PMS_VERSION,
}
return serve_template(templatename="settings.html", title="Settings", config=config)
@@ -2769,6 +2770,18 @@ class WebInterface(object):
def get_scheduler_table(self, **kwargs):
return serve_template(templatename="scheduler_table.html")
+
+ @cherrypy.expose
+ @cherrypy.tools.json_out()
+ @requireAuth(member_of("admin"))
+ def get_server_update_params(self):
+ plex_tv = plextv.PlexTV()
+ plexpass = plex_tv.get_plexpass_status()
+ return {'plexpass': plexpass,
+ 'pms_platform': plexpy.CONFIG.PMS_PLATFORM,
+ 'pms_update_channel': plexpy.CONFIG.PMS_UPDATE_CHANNEL,
+ 'pms_update_distro_build': plexpy.CONFIG.PMS_UPDATE_DISTRO_BUILD}
+
@cherrypy.expose
@cherrypy.tools.json_out()
@requireAuth(member_of("admin"))