diff --git a/data/interfaces/default/config.html b/data/interfaces/default/config.html
index b2c18b47..e592a6e8 100644
--- a/data/interfaces/default/config.html
+++ b/data/interfaces/default/config.html
@@ -146,6 +146,17 @@
Set your preferred time format. Click here to see the parameter list.
+
@@ -154,21 +165,25 @@
Plex Media Server
+
+
Remote Server
+
Check this is your Plex Server is not on the same local network as PlexPy.
+
+
+
Force SSL
+
Force PlexPy to connect to your Plex Server via SSL. Your server needs to have remote access enabled.
-
- Fetch Token
+
+ Verify
@@ -181,12 +196,6 @@
If you have media indexing enabled on your server, use these on the activity pane.
-
@@ -825,15 +834,56 @@
$(document).ready(function () {
var configForm = $("#configUpdate");
$('.save-button').click(function() {
- if (configForm.parsley().validate()) {
- doAjaxCall('configUpdate',$(this),'tabs',true);
- return false;
+ if ($("#pms_identifier").val() == "") {
+ showMsg(' Please verify your server.',false,true,2000)
} else {
- showMsg(' Please verify your settings.',false,true,2000)
+ if (configForm.parsley().validate()) {
+ doAjaxCall('configUpdate',$(this),'tabs',true);
+ return false;
+ } else {
+ showMsg(' Please verify your settings.',false,true,2000)
+ }
}
});
});
+ $( ".pms-settings" ).change(function() {
+ $("#pms_identifier").val("");
+ $("#pms-verify-status").html("");
+ });
+
+ $("#verify-plex-server").click(function() {
+ var pms_ip = $("#pms_ip").val()
+ var pms_port = $("#pms_port").val()
+ if (($("#pms_ip").val() !== '') || ($("#pms_port").val() !== '')) {
+ $("#pms-verify-status").html(' Verifying server...');
+ $('#pms-verify-status').fadeIn('fast');
+ $.ajax({
+ url: 'http://' + pms_ip + ':' + pms_port + '/identity',
+ cache: true,
+ async: true,
+ timeout: 5000,
+ error: function(jqXHR, textStatus, errorThrown) {
+ $("#pms-verify-status").html(' This is not a Plex Server!');
+ $('#pms-verify-status').fadeIn('fast');
+ },
+ success: function (xml) {
+ if ( $(xml).find('MediaContainer').attr('machineIdentifier') ) {
+ $("#pms_identifier").val($(xml).find('MediaContainer').attr('machineIdentifier'));
+ $("#pms-verify-status").html(' Server verified!');
+ $('#pms-verify-status').fadeIn('fast');
+ } else {
+ $("#pms-verify-status").html(' This is not a Plex Server!');
+ $('#pms-verify-status').fadeIn('fast');
+ }
+ }
+ });
+ } else {
+ $("#pms-verify-status").html(' Please enter IP and port number.');
+ $('#pms-verify-status').fadeIn('fast');
+ }
+ });
+
// Plex.tv auth token fetch
$("#get-pms-auth-token").click(function() {
$("#pms-token-status").html(' Fetching token...');
diff --git a/data/interfaces/default/welcome.html b/data/interfaces/default/welcome.html
index 3fa324bc..571c4c6d 100644
--- a/data/interfaces/default/welcome.html
+++ b/data/interfaces/default/welcome.html
@@ -57,9 +57,16 @@ from plexpy import version
+
+ Server uses SSL
+
+
+ Remote Server
+
+
Verify
@@ -160,6 +167,14 @@ from plexpy import version
+
+
Setup Complete!
+
+
Setup is now complete. For more configuration options please visit the Settings menu on the home page.
+
+
Just configuring a few things, please wait...
+
+
@@ -185,6 +200,8 @@ from plexpy import version
wizard.show();
wizard.on("submit", function(wizard) {
+ // Probably should not success before we know, but hopefully validation is good enough.
+ wizard.submitSuccess();
$.ajax({
url: "configUpdate",
type: "POST",
@@ -194,7 +211,7 @@ from plexpy import version
complete: function (data) {
setTimeout(function(){
location.reload();
- }, 3000);
+ }, 5000);
}
})
});
@@ -293,6 +310,7 @@ from plexpy import version
},
success: function (xml) {
if ( $(xml).find('MediaContainer').attr('machineIdentifier') ) {
+ $("#pms_identifier").val($(xml).find('MediaContainer').attr('machineIdentifier'));
$("#pms-verify-status").html(' Server found!');
$('#pms-verify-status').fadeIn('fast');
pms_verified = true;
diff --git a/plexpy/__init__.py b/plexpy/__init__.py
index ce658cff..36bd552f 100644
--- a/plexpy/__init__.py
+++ b/plexpy/__init__.py
@@ -159,9 +159,13 @@ def initialize(config_file):
else:
LATEST_VERSION = CURRENT_VERSION
+ # Get the real PMS urls for SSL and remote access
+ if CONFIG.PMS_TOKEN and CONFIG.PMS_IP and CONFIG.PMS_PORT:
+ plextv.get_real_pms_url()
+
# Refresh the users list on startup
if CONFIG.PMS_TOKEN and CONFIG.REFRESH_USERS_ON_STARTUP:
- plextv.refresh_users()
+ threading.Thread(target=plextv.refresh_users).start()
# Store the original umask
UMASK = os.umask(0)
@@ -268,6 +272,7 @@ def initialize_scheduler():
seconds = 0
if CONFIG.PMS_IP:
+ schedule_job(plextv.get_real_pms_url, 'Refresh Plex Server URLs', hours=12, minutes=0, seconds=0)
schedule_job(monitor.check_active_sessions, 'Check for active sessions', hours=0, minutes=0, seconds=seconds)
# Refresh the users list
diff --git a/plexpy/config.py b/plexpy/config.py
index 55033cf9..b7f51e73 100644
--- a/plexpy/config.py
+++ b/plexpy/config.py
@@ -22,12 +22,15 @@ _CONFIG_DEFINITIONS = {
'GROUPING_USER_HISTORY': (int, 'PlexWatch', 0),
'GROUPING_CHARTS': (int, 'PlexWatch', 0),
'PLEXWATCH_DATABASE': (str, 'PlexWatch', ''),
+ 'PMS_IDENTIFIER': (str, 'PMS', ''),
'PMS_IP': (str, 'PMS', '127.0.0.1'),
+ 'PMS_IS_REMOTE': (int, 'PMS', 0),
'PMS_LOGS_FOLDER': (str, 'PMS', ''),
'PMS_PORT': (int, 'PMS', 32400),
'PMS_PASSWORD': (str, 'PMS', ''),
'PMS_TOKEN': (str, 'PMS', ''),
'PMS_SSL': (int, 'General', 0),
+ 'PMS_URL': (str, 'PMS', ''),
'PMS_USERNAME': (str, 'PMS', ''),
'PMS_USE_BIF': (int, 'PMS', 0),
'PMS_UUID': (str, 'PMS', ''),
diff --git a/plexpy/datafactory.py b/plexpy/datafactory.py
index 9186e832..1f4ea71a 100644
--- a/plexpy/datafactory.py
+++ b/plexpy/datafactory.py
@@ -173,7 +173,7 @@ class DataFactory(object):
search_regex=search_regex,
custom_where=custom_where,
group_by='',
- join_type=['JOIN', 'JOIN', 'JOIN'],
+ join_type=['LEFT OUTER JOIN', 'JOIN', 'JOIN'],
join_table=[t3, t2, t4],
join_evals=[[t1 + '.user_id', t3 + '.user_id'],
[t1 + '.id', t2 + '.id'],
diff --git a/plexpy/http_handler.py b/plexpy/http_handler.py
index e073e723..a03db388 100644
--- a/plexpy/http_handler.py
+++ b/plexpy/http_handler.py
@@ -70,6 +70,11 @@ class HTTPHandler(object):
except IOError, e:
logger.warn(u"Failed to access uri endpoint %s with error %s" % (uri, e))
return None
+ except Exception, e:
+ logger.warn(u"Failed to access uri endpoint %s. Is your server maybe accepting SSL connections only?" % uri)
+ return None
+ except:
+ logger.warn(u"Failed to access uri endpoint %s with Uncaught exception." % uri)
if request_status == 200:
if output_format == 'dict':
diff --git a/plexpy/plextv.py b/plexpy/plextv.py
index 6469e934..4f60131c 100644
--- a/plexpy/plextv.py
+++ b/plexpy/plextv.py
@@ -43,6 +43,42 @@ def refresh_users():
else:
logger.warn("Unable to refresh users list.")
+def get_real_pms_url():
+ logger.info("Requesting URLs for server...")
+
+ # Reset any current PMS_URL value
+ plexpy.CONFIG.__setattr__('PMS_URL', '')
+ plexpy.CONFIG.write()
+
+ if plexpy.CONFIG.PMS_SSL:
+ result = PlexTV().get_server_urls(include_https=True)
+ process_urls = True
+ elif plexpy.CONFIG.PMS_IS_REMOTE:
+ result = PlexTV().get_server_urls(include_https=False)
+ process_urls = True
+ else:
+ real_url = 'http://' + plexpy.CONFIG.PMS_IP + ':' + str(plexpy.CONFIG.PMS_PORT)
+ process_urls = False
+
+ if process_urls:
+ if len(result) > 0:
+ for item in result:
+ if plexpy.CONFIG.PMS_IS_REMOTE and item['local'] == '0':
+ real_url = item['uri']
+ else:
+ real_url = item['uri']
+
+ plexpy.CONFIG.__setattr__('PMS_URL', real_url)
+ plexpy.CONFIG.write()
+ logger.info("Server URL retrieved.")
+ else:
+ fallback_url = 'http://' + plexpy.CONFIG.PMS_IP + ':' + str(plexpy.CONFIG.PMS_PORT)
+ plexpy.CONFIG.__setattr__('PMS_URL', fallback_url)
+ plexpy.CONFIG.write()
+ logger.warn("Unable to retrieve server URLs. Using user-defined value.")
+ else:
+ plexpy.CONFIG.__setattr__('PMS_URL', real_url)
+ plexpy.CONFIG.write()
class PlexTV(object):
"""
@@ -137,6 +173,18 @@ class PlexTV(object):
return request
+ def get_plextv_resources(self, include_https=False, output_format=''):
+ if include_https:
+ uri = '/api/resources?includeHttps=1'
+ else:
+ uri = '/api/resources'
+ 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()
@@ -299,4 +347,45 @@ class PlexTV(object):
synced_items.append(sync_details)
- return synced_items
\ No newline at end of file
+ return synced_items
+
+ def get_server_urls(self, include_https=True):
+
+ if plexpy.CONFIG.PMS_IDENTIFIER:
+ server_id = plexpy.CONFIG.PMS_IDENTIFIER
+ else:
+ logger.error('PlexPy PlexTV connector :: Unable to retrieve server identity.')
+ return []
+
+ plextv_resources = self.get_plextv_resources(include_https=include_https)
+ server_urls = []
+
+ try:
+ xml_parse = minidom.parseString(plextv_resources)
+ except Exception, e:
+ logger.warn("Error parsing XML for Plex resources: %s" % e)
+ return []
+ except:
+ logger.warn("Error parsing XML for Plex resources.")
+ return []
+
+ try:
+ xml_head = xml_parse.getElementsByTagName('Device')
+ except:
+ logger.warn("Error parsing XML for Plex resources.")
+ return []
+
+ for a in xml_head:
+ if helpers.get_xml_attr(a, 'clientIdentifier') == server_id:
+ connections = a.getElementsByTagName('Connection')
+ for connection in connections:
+ server_details = {"protocol": helpers.get_xml_attr(connection, 'protocol'),
+ "address": helpers.get_xml_attr(connection, 'address'),
+ "port": helpers.get_xml_attr(connection, 'port'),
+ "uri": helpers.get_xml_attr(connection, 'uri'),
+ "local": helpers.get_xml_attr(connection, 'local')
+ }
+
+ server_urls.append(server_details)
+
+ return server_urls
\ No newline at end of file
diff --git a/plexpy/pmsconnect.py b/plexpy/pmsconnect.py
index 53317725..29d73516 100644
--- a/plexpy/pmsconnect.py
+++ b/plexpy/pmsconnect.py
@@ -14,6 +14,7 @@
# along with PlexPy. If not, see .
from plexpy import logger, helpers, datafactory, http_handler
+from urlparse import urlparse
import plexpy
@@ -24,12 +25,18 @@ class PmsConnect(object):
"""
def __init__(self):
- if plexpy.CONFIG.PMS_SSL:
- self.protocol = 'HTTPS'
+ if plexpy.CONFIG.PMS_URL:
+ url_parsed = urlparse(plexpy.CONFIG.PMS_URL)
+ hostname = url_parsed.hostname
+ port = url_parsed.port
+ self.protocol = url_parsed.scheme
else:
- self.protocol = 'HTTP'
- self.request_handler = http_handler.HTTPHandler(host=plexpy.CONFIG.PMS_IP,
- port=plexpy.CONFIG.PMS_PORT,
+ hostname = plexpy.CONFIG.PMS_IP
+ port = plexpy.CONFIG.PMS_PORT
+ self.protocol = 'http'
+
+ self.request_handler = http_handler.HTTPHandler(host=hostname,
+ port=port,
token=plexpy.CONFIG.PMS_TOKEN)
"""
diff --git a/plexpy/webserve.py b/plexpy/webserve.py
index b238563c..964493e5 100644
--- a/plexpy/webserve.py
+++ b/plexpy/webserve.py
@@ -71,9 +71,12 @@ class WebInterface(object):
config = {
"launch_browser": checked(plexpy.CONFIG.LAUNCH_BROWSER),
"refresh_users_on_startup": checked(plexpy.CONFIG.REFRESH_USERS_ON_STARTUP),
+ "pms_identifier": plexpy.CONFIG.PMS_IDENTIFIER,
"pms_ip": plexpy.CONFIG.PMS_IP,
+ "pms_is_remote": checked(plexpy.CONFIG.PMS_IS_REMOTE),
"pms_port": plexpy.CONFIG.PMS_PORT,
"pms_token": plexpy.CONFIG.PMS_TOKEN,
+ "pms_ssl": checked(plexpy.CONFIG.PMS_SSL),
"pms_uuid": plexpy.CONFIG.PMS_UUID,
"tv_notify_enable": checked(plexpy.CONFIG.TV_NOTIFY_ENABLE),
"movie_notify_enable": checked(plexpy.CONFIG.MOVIE_NOTIFY_ENABLE),
@@ -364,6 +367,7 @@ class WebInterface(object):
"email_smtp_password": plexpy.CONFIG.EMAIL_SMTP_PASSWORD,
"email_smtp_port": int(plexpy.CONFIG.EMAIL_SMTP_PORT),
"email_tls": checked(plexpy.CONFIG.EMAIL_TLS),
+ "pms_identifier": plexpy.CONFIG.PMS_IDENTIFIER,
"pms_ip": plexpy.CONFIG.PMS_IP,
"pms_logs_folder": plexpy.CONFIG.PMS_LOGS_FOLDER,
"pms_port": plexpy.CONFIG.PMS_PORT,
@@ -395,7 +399,8 @@ class WebInterface(object):
"ip_logging_enable": checked(plexpy.CONFIG.IP_LOGGING_ENABLE),
"video_logging_enable": checked(plexpy.CONFIG.VIDEO_LOGGING_ENABLE),
"music_logging_enable": checked(plexpy.CONFIG.MUSIC_LOGGING_ENABLE),
- "logging_ignore_interval": plexpy.CONFIG.LOGGING_IGNORE_INTERVAL
+ "logging_ignore_interval": plexpy.CONFIG.LOGGING_IGNORE_INTERVAL,
+ "pms_is_remote": checked(plexpy.CONFIG.PMS_IS_REMOTE)
}
return serve_template(templatename="config.html", title="Settings", config=config)
@@ -416,7 +421,7 @@ class WebInterface(object):
"tv_notify_on_start", "movie_notify_on_start", "music_notify_on_start",
"tv_notify_on_stop", "movie_notify_on_stop", "music_notify_on_stop",
"tv_notify_on_pause", "movie_notify_on_pause", "music_notify_on_pause", "refresh_users_on_startup",
- "ip_logging_enable", "video_logging_enable", "music_logging_enable"
+ "ip_logging_enable", "video_logging_enable", "music_logging_enable", "pms_is_remote"
]
for checked_config in checked_configs:
if checked_config not in kwargs:
@@ -441,6 +446,8 @@ class WebInterface(object):
# Reconfigure scheduler
plexpy.initialize_scheduler()
+ plextv.get_real_pms_url()
+
# Refresh users table. Probably shouldn't do this on every config save, will improve this later.
threading.Thread(target=plextv.refresh_users).start()