mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-11 15:56:07 -07:00
Use Plex downloads to check for PMS updates instead of server API
* Check for PMS updates has been disabled and must be re-enabled in the settings
This commit is contained in:
parent
a42a1af867
commit
984e5588c8
5 changed files with 225 additions and 61 deletions
|
@ -581,15 +581,31 @@
|
|||
<div role="tabpanel" class="tab-pane" id="tabs-5">
|
||||
|
||||
<div class="padded-header">
|
||||
<h3>Plex Media Server <small style="color: #fff;">Version <span id="pms_version">unknown</span></small></h3>
|
||||
<h3>Plex Media Server <small style="color: #fff;">Version <span id="pms_version">${config['pms_version']}</span></small></h3>
|
||||
</div>
|
||||
<p class="help-block">If you're using websocket monitoring, any server changes require a restart of PlexPy.</p>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" id="monitor_pms_updates" name="monitor_pms_updates" value="1" ${config['monitor_pms_updates']}> Monitor Plex Updates
|
||||
</label>
|
||||
<p class="help-block">Enable to have PlexPy check if updates are available for the Plex Media Server.<br />
|
||||
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.</p>
|
||||
<p class="help-block">Enable to have PlexPy check if updates are available for the Plex Media Server.</p>
|
||||
</div>
|
||||
<div id="pms_update_options">
|
||||
<div class="form-group">
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<label for="pms_update_channel">Update Channel</label>
|
||||
<select class="form-control" id="pms_update_channel" name="pms_update_channel">
|
||||
<option value="public">Public</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<label for="pms_update_distro_build">Release</label>
|
||||
<select class="form-control" id="pms_update_distro_build" name="pms_update_distro_build">
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
|
@ -2115,6 +2131,7 @@ $(document).ready(function() {
|
|||
}
|
||||
$("#http_hashed_password").val($("#http_hash_password").is(":checked") ? 1 : 0)
|
||||
getSchedulerTable();
|
||||
loadUpdateDistros();
|
||||
settingsChanged = false;
|
||||
}
|
||||
|
||||
|
@ -2145,6 +2162,7 @@ $(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?");
|
||||
|
@ -2348,6 +2366,7 @@ $(document).ready(function() {
|
|||
} else {
|
||||
$("#pms-token-status").html('<i class="fa fa-exclamation-circle"></i> Invalid username or password.');
|
||||
}
|
||||
loadUpdateDistros();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
@ -2406,12 +2425,7 @@ $(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);
|
||||
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);
|
||||
|
@ -2431,8 +2445,6 @@ $(document).ready(function() {
|
|||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$("#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($('<option></option>')
|
||||
.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($('<option></option>')
|
||||
.text(label)
|
||||
.val(item.build)
|
||||
.prop('selected', selected));
|
||||
})
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
loadUpdateDistros();
|
||||
});
|
||||
</script>
|
||||
</%def>
|
||||
|
|
|
@ -24,6 +24,7 @@ import libraries
|
|||
import logger
|
||||
import notification_handler
|
||||
import notifiers
|
||||
import plextv
|
||||
import pmsconnect
|
||||
|
||||
|
||||
|
@ -372,18 +373,14 @@ 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()):
|
||||
|
|
|
@ -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),
|
||||
|
@ -720,3 +725,7 @@ class Config(object):
|
|||
home_sections.remove('library_stats')
|
||||
self.HOME_SECTIONS = home_sections
|
||||
self.CONFIG_VERSION = '5'
|
||||
|
||||
if self.CONFIG_VERSION == '5':
|
||||
self.MONITOR_PMS_UPDATES = 0
|
||||
self.CONFIG_VERSION = '6'
|
128
plexpy/plextv.py
128
plexpy/plextv.py
|
@ -17,6 +17,7 @@
|
|||
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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')
|
||||
|
@ -589,3 +613,71 @@ class PlexTV(object):
|
|||
clean_servers.append(server)
|
||||
|
||||
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
|
|
@ -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"))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue