Cleanup plex_api.py
This commit is contained in:
parent
1ac19109ba
commit
c1bb083933
1 changed files with 61 additions and 85 deletions
|
@ -33,8 +33,6 @@ http://stackoverflow.com/questions/111945/is-there-any-way-to-do-http-put-in-pyt
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from re import sub
|
from re import sub
|
||||||
from urllib import urlencode, unquote, quote
|
|
||||||
from urlparse import parse_qsl
|
|
||||||
|
|
||||||
from xbmcgui import ListItem
|
from xbmcgui import ListItem
|
||||||
|
|
||||||
|
@ -101,10 +99,8 @@ class API(object):
|
||||||
"""
|
"""
|
||||||
Returns the unique int <ratingKey><updatedAt>
|
Returns the unique int <ratingKey><updatedAt>
|
||||||
"""
|
"""
|
||||||
return int('%s%s' % (self.item.get('ratingKey'),
|
return int('%s%s' % (self.plex_id(),
|
||||||
self.item.get('updatedAt',
|
self.updated_at() or self.item.get('addedAt', 1541572987)))
|
||||||
self.item.get('addedAt',
|
|
||||||
1541572987))))
|
|
||||||
|
|
||||||
def plex_id(self):
|
def plex_id(self):
|
||||||
"""
|
"""
|
||||||
|
@ -152,9 +148,9 @@ class API(object):
|
||||||
|
|
||||||
def directory_path(self, section_id=None, plex_type=None, old_key=None,
|
def directory_path(self, section_id=None, plex_type=None, old_key=None,
|
||||||
synched=True):
|
synched=True):
|
||||||
key = cast(unicode, self.item.get('fastKey'))
|
key = self.item.get('fastKey')
|
||||||
if not key:
|
if not key:
|
||||||
key = cast(unicode, self.item.get('key'))
|
key = self.item.get('key')
|
||||||
if old_key:
|
if old_key:
|
||||||
key = '%s/%s' % (old_key, key)
|
key = '%s/%s' % (old_key, key)
|
||||||
elif not key.startswith('/'):
|
elif not key.startswith('/'):
|
||||||
|
@ -169,7 +165,7 @@ class API(object):
|
||||||
params['synched'] = 'false'
|
params['synched'] = 'false'
|
||||||
if self.item.get('prompt'):
|
if self.item.get('prompt'):
|
||||||
# User input needed, e.g. search for a movie or episode
|
# User input needed, e.g. search for a movie or episode
|
||||||
params['prompt'] = cast(unicode, self.item.get('prompt'))
|
params['prompt'] = self.item.get('prompt')
|
||||||
if section_id:
|
if section_id:
|
||||||
params['id'] = section_id
|
params['id'] = section_id
|
||||||
return utils.extend_url('plugin://%s/' % v.ADDON_ID, params)
|
return utils.extend_url('plugin://%s/' % v.ADDON_ID, params)
|
||||||
|
@ -210,7 +206,7 @@ class API(object):
|
||||||
def file_path(self, force_first_media=False):
|
def file_path(self, force_first_media=False):
|
||||||
"""
|
"""
|
||||||
Returns the direct path to this item, e.g. '\\NAS\movies\movie.mkv'
|
Returns the direct path to this item, e.g. '\\NAS\movies\movie.mkv'
|
||||||
or None
|
as unicode or None
|
||||||
|
|
||||||
force_first_media=True:
|
force_first_media=True:
|
||||||
will always use 1st media stream, e.g. when several different
|
will always use 1st media stream, e.g. when several different
|
||||||
|
@ -221,51 +217,43 @@ class API(object):
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
if force_first_media is False:
|
if force_first_media is False:
|
||||||
ans = self.item[self.mediastream][self.part].attrib['file']
|
ans = cast(str, self.item[self.mediastream][self.part].attrib['file'])
|
||||||
else:
|
else:
|
||||||
ans = self.item[0][self.part].attrib['file']
|
ans = cast(str, self.item[0][self.part].attrib['file'])
|
||||||
except (TypeError, AttributeError, IndexError, KeyError):
|
except (TypeError, AttributeError, IndexError, KeyError):
|
||||||
ans = None
|
return
|
||||||
if ans is not None:
|
return utils.unquote(ans)
|
||||||
try:
|
|
||||||
ans = utils.try_decode(unquote(ans))
|
|
||||||
except UnicodeDecodeError:
|
|
||||||
# Sometimes, Plex seems to have encoded in latin1
|
|
||||||
ans = unquote(ans).decode('latin1')
|
|
||||||
return ans
|
|
||||||
|
|
||||||
def get_picture_path(self):
|
def get_picture_path(self):
|
||||||
"""
|
"""
|
||||||
Returns the item's picture path (transcode, if necessary) as string.
|
Returns the item's picture path (transcode, if necessary) as string.
|
||||||
Will always use addon paths, never direct paths
|
Will always use addon paths, never direct paths
|
||||||
"""
|
"""
|
||||||
extension = self.item[0][0].attrib['key'][self.item[0][0].attrib['key'].rfind('.'):].lower()
|
path = self.item[0][0].get('key')
|
||||||
|
extension = path[path.rfind('.'):].lower()
|
||||||
if app.SYNC.force_transcode_pix or extension not in v.KODI_SUPPORTED_IMAGES:
|
if app.SYNC.force_transcode_pix or extension not in v.KODI_SUPPORTED_IMAGES:
|
||||||
# Let Plex transcode
|
# Let Plex transcode
|
||||||
# max width/height supported by plex image transcoder is 1920x1080
|
# max width/height supported by plex image transcoder is 1920x1080
|
||||||
path = app.CONN.server + PF.transcode_image_path(
|
path = app.CONN.server + PF.transcode_image_path(
|
||||||
self.item[0][0].get('key'),
|
path,
|
||||||
app.ACCOUNT.pms_token,
|
app.ACCOUNT.pms_token,
|
||||||
"%s%s" % (app.CONN.server, self.item[0][0].get('key')),
|
"%s%s" % (app.CONN.server, path),
|
||||||
1920,
|
1920,
|
||||||
1080)
|
1080)
|
||||||
else:
|
else:
|
||||||
path = self.attach_plex_token_to_url(
|
path = self.attach_plex_token_to_url('%s%s' % (app.CONN.server, path))
|
||||||
'%s%s' % (app.CONN.server, self.item[0][0].attrib['key']))
|
|
||||||
# Attach Plex id to url to let it be picked up by our playqueue agent
|
# Attach Plex id to url to let it be picked up by our playqueue agent
|
||||||
# later
|
# later
|
||||||
return utils.try_encode('%s&plex_id=%s' % (path, self.plex_id()))
|
return '%s&plex_id=%s' % (path, self.plex_id())
|
||||||
|
|
||||||
def tv_show_path(self):
|
def tv_show_path(self):
|
||||||
"""
|
"""
|
||||||
Returns the direct path to the TV show, e.g. '\\NAS\tv\series'
|
Returns the direct path to the TV show, e.g. '\\NAS\tv\series'
|
||||||
or None
|
or None
|
||||||
"""
|
"""
|
||||||
res = None
|
|
||||||
for child in self.item:
|
for child in self.item:
|
||||||
if child.tag == 'Location':
|
if child.tag == 'Location':
|
||||||
res = child.get('path')
|
return child.get('path')
|
||||||
return res
|
|
||||||
|
|
||||||
def season_number(self):
|
def season_number(self):
|
||||||
"""
|
"""
|
||||||
|
@ -295,10 +283,7 @@ class API(object):
|
||||||
"""
|
"""
|
||||||
Returns the play count for the item as an int or the int 0 if not found
|
Returns the play count for the item as an int or the int 0 if not found
|
||||||
"""
|
"""
|
||||||
try:
|
return cast(int, self.item.get('viewCount')) or 0
|
||||||
return int(self.item.attrib['viewCount'])
|
|
||||||
except (KeyError, ValueError):
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def userdata(self):
|
def userdata(self):
|
||||||
"""
|
"""
|
||||||
|
@ -781,8 +766,7 @@ class API(object):
|
||||||
'container': self._data_from_part_or_media('container'),
|
'container': self._data_from_part_or_media('container'),
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
answ['bitDepth'] = self.item[0][self.part][self.mediastream].get(
|
answ['bitDepth'] = self.item[0][self.part][self.mediastream].get('bitDepth')
|
||||||
'bitDepth')
|
|
||||||
except (TypeError, AttributeError, KeyError, IndexError):
|
except (TypeError, AttributeError, KeyError, IndexError):
|
||||||
answ['bitDepth'] = None
|
answ['bitDepth'] = None
|
||||||
return answ
|
return answ
|
||||||
|
@ -848,7 +832,7 @@ class API(object):
|
||||||
subtitlelanguages = []
|
subtitlelanguages = []
|
||||||
try:
|
try:
|
||||||
# Sometimes, aspectratio is on the "toplevel"
|
# Sometimes, aspectratio is on the "toplevel"
|
||||||
aspect = self.item[0].get('aspectRatio')
|
aspect = cast(float, self.item[0].get('aspectRatio'))
|
||||||
except IndexError:
|
except IndexError:
|
||||||
# There is no stream info at all, returning empty
|
# There is no stream info at all, returning empty
|
||||||
return {
|
return {
|
||||||
|
@ -860,39 +844,37 @@ class API(object):
|
||||||
for child in self.item[0]:
|
for child in self.item[0]:
|
||||||
container = child.get('container')
|
container = child.get('container')
|
||||||
# Loop over Streams
|
# Loop over Streams
|
||||||
for grandchild in child:
|
for stream in child:
|
||||||
stream = grandchild.attrib
|
|
||||||
media_type = int(stream.get('streamType', 999))
|
media_type = int(stream.get('streamType', 999))
|
||||||
track = {}
|
track = {}
|
||||||
if media_type == 1: # Video streams
|
if media_type == 1: # Video streams
|
||||||
if 'codec' in stream:
|
if 'codec' in stream.attrib:
|
||||||
track['codec'] = stream['codec'].lower()
|
track['codec'] = stream.get('codec').lower()
|
||||||
if "msmpeg4" in track['codec']:
|
if "msmpeg4" in track['codec']:
|
||||||
track['codec'] = "divx"
|
track['codec'] = "divx"
|
||||||
elif "mpeg4" in track['codec']:
|
elif "mpeg4" in track['codec']:
|
||||||
# if "simple profile" in profile or profile == "":
|
|
||||||
# track['codec'] = "xvid"
|
|
||||||
pass
|
pass
|
||||||
elif "h264" in track['codec']:
|
elif "h264" in track['codec']:
|
||||||
if container in ("mp4", "mov", "m4v"):
|
if container in ("mp4", "mov", "m4v"):
|
||||||
track['codec'] = "avc1"
|
track['codec'] = "avc1"
|
||||||
track['height'] = stream.get('height')
|
track['height'] = cast(int, stream.get('height'))
|
||||||
track['width'] = stream.get('width')
|
track['width'] = cast(int, stream.get('width'))
|
||||||
# track['Video3DFormat'] = item.get('Video3DFormat')
|
# track['Video3DFormat'] = item.get('Video3DFormat')
|
||||||
track['aspect'] = stream.get('aspectRatio', aspect)
|
track['aspect'] = cast(float,
|
||||||
track['duration'] = self.resume_runtime()[1]
|
stream.get('aspectRatio') or aspect)
|
||||||
|
track['duration'] = self.runtime()
|
||||||
track['video3DFormat'] = None
|
track['video3DFormat'] = None
|
||||||
videotracks.append(track)
|
videotracks.append(track)
|
||||||
elif media_type == 2: # Audio streams
|
elif media_type == 2: # Audio streams
|
||||||
if 'codec' in stream:
|
if 'codec' in stream.attrib:
|
||||||
track['codec'] = stream['codec'].lower()
|
track['codec'] = stream.get('codec').lower()
|
||||||
if ("dca" in track['codec'] and
|
if ("dca" in track['codec'] and
|
||||||
"ma" in stream.get('profile', '').lower()):
|
"ma" in stream.get('profile', '').lower()):
|
||||||
track['codec'] = "dtshd_ma"
|
track['codec'] = "dtshd_ma"
|
||||||
track['channels'] = stream.get('channels')
|
track['channels'] = cast(int, stream.get('channels'))
|
||||||
# 'unknown' if we cannot get language
|
# 'unknown' if we cannot get language
|
||||||
track['language'] = stream.get(
|
track['language'] = stream.get('languageCode',
|
||||||
'languageCode', utils.lang(39310)).lower()
|
utils.lang(39310).lower())
|
||||||
audiotracks.append(track)
|
audiotracks.append(track)
|
||||||
elif media_type == 3: # Subtitle streams
|
elif media_type == 3: # Subtitle streams
|
||||||
# 'unknown' if we cannot get language
|
# 'unknown' if we cannot get language
|
||||||
|
@ -925,7 +907,7 @@ class API(object):
|
||||||
# e.g. Plex collections where artwork already contains
|
# e.g. Plex collections where artwork already contains
|
||||||
# width and height. Need to upscale for better resolution
|
# width and height. Need to upscale for better resolution
|
||||||
artwork, args = artwork.split('?')
|
artwork, args = artwork.split('?')
|
||||||
args = dict(parse_qsl(args))
|
args = dict(utils.parse_qsl(args))
|
||||||
width = int(args.get('width', 400))
|
width = int(args.get('width', 400))
|
||||||
height = int(args.get('height', 400))
|
height = int(args.get('height', 400))
|
||||||
# Adjust to 4k resolution 1920x1080
|
# Adjust to 4k resolution 1920x1080
|
||||||
|
@ -938,7 +920,7 @@ class API(object):
|
||||||
artwork = '%s?width=%s&height=%s' % (artwork, width, height)
|
artwork = '%s?width=%s&height=%s' % (artwork, width, height)
|
||||||
artwork = ('%s/photo/:/transcode?width=1920&height=1920&'
|
artwork = ('%s/photo/:/transcode?width=1920&height=1920&'
|
||||||
'minSize=1&upscale=0&url=%s'
|
'minSize=1&upscale=0&url=%s'
|
||||||
% (app.CONN.server, quote(artwork)))
|
% (app.CONN.server, utils.quote(artwork)))
|
||||||
artwork = self.attach_plex_token_to_url(artwork)
|
artwork = self.attach_plex_token_to_url(artwork)
|
||||||
return artwork
|
return artwork
|
||||||
|
|
||||||
|
@ -1297,9 +1279,9 @@ class API(object):
|
||||||
def library_section_id(self):
|
def library_section_id(self):
|
||||||
"""
|
"""
|
||||||
Returns the id of the Plex library section (for e.g. a movies section)
|
Returns the id of the Plex library section (for e.g. a movies section)
|
||||||
or None
|
as an int or None
|
||||||
"""
|
"""
|
||||||
return self.item.get('librarySectionID')
|
return cast(int, self.item.get('librarySectionID'))
|
||||||
|
|
||||||
def collections_match(self, section_id):
|
def collections_match(self, section_id):
|
||||||
"""
|
"""
|
||||||
|
@ -1345,7 +1327,7 @@ class API(object):
|
||||||
Returns True if the item's 'optimizedForStreaming' is set, False other-
|
Returns True if the item's 'optimizedForStreaming' is set, False other-
|
||||||
wise
|
wise
|
||||||
"""
|
"""
|
||||||
return self.item[0].get('optimizedForStreaming') == '1'
|
return cast(bool, self.item[0].get('optimizedForStreaming')) or False
|
||||||
|
|
||||||
def mediastream_number(self):
|
def mediastream_number(self):
|
||||||
"""
|
"""
|
||||||
|
@ -1371,16 +1353,16 @@ class API(object):
|
||||||
for entry in self.item.iterfind('./Media'):
|
for entry in self.item.iterfind('./Media'):
|
||||||
# Get additional info (filename / languages)
|
# Get additional info (filename / languages)
|
||||||
if 'file' in entry[0].attrib:
|
if 'file' in entry[0].attrib:
|
||||||
option = utils.try_decode(entry[0].attrib['file'])
|
option = entry[0].get('file')
|
||||||
option = path_ops.path.basename(option)
|
option = path_ops.basename(option)
|
||||||
else:
|
else:
|
||||||
option = self.title() or ''
|
option = self.title() or ''
|
||||||
# Languages of audio streams
|
# Languages of audio streams
|
||||||
languages = []
|
languages = []
|
||||||
for stream in entry[0]:
|
for stream in entry[0]:
|
||||||
if (stream.attrib['streamType'] == '1' and
|
if (cast(int, stream.get('streamType')) == 1 and
|
||||||
'language' in stream.attrib):
|
'language' in stream.attrib):
|
||||||
language = utils.try_decode(stream.attrib['language'])
|
language = stream.get('language')
|
||||||
languages.append(language)
|
languages.append(language)
|
||||||
languages = ', '.join(languages)
|
languages = ', '.join(languages)
|
||||||
if languages:
|
if languages:
|
||||||
|
@ -1391,19 +1373,19 @@ class API(object):
|
||||||
else:
|
else:
|
||||||
option = '%s ' % option
|
option = '%s ' % option
|
||||||
if 'videoResolution' in entry.attrib:
|
if 'videoResolution' in entry.attrib:
|
||||||
res = utils.try_decode(entry.attrib['videoResolution'])
|
res = entry.get('videoResolution')
|
||||||
option = '%s%sp ' % (option, res)
|
option = '%s%sp ' % (option, res)
|
||||||
if 'videoCodec' in entry.attrib:
|
if 'videoCodec' in entry.attrib:
|
||||||
codec = utils.try_decode(entry.attrib['videoCodec'])
|
codec = entry.get('videoCodec')
|
||||||
option = '%s%s' % (option, codec)
|
option = '%s%s' % (option, codec)
|
||||||
option = option.strip() + ' - '
|
option = option.strip() + ' - '
|
||||||
if 'audioProfile' in entry.attrib:
|
if 'audioProfile' in entry.attrib:
|
||||||
profile = utils.try_decode(entry.attrib['audioProfile'])
|
profile = entry.get('audioProfile')
|
||||||
option = '%s%s ' % (option, profile)
|
option = '%s%s ' % (option, profile)
|
||||||
if 'audioCodec' in entry.attrib:
|
if 'audioCodec' in entry.attrib:
|
||||||
codec = utils.try_decode(entry.attrib['audioCodec'])
|
codec = entry.get('audioCodec')
|
||||||
option = '%s%s ' % (option, codec)
|
option = '%s%s ' % (option, codec)
|
||||||
option = utils.try_encode(option.strip())
|
option = cast(str, option.strip())
|
||||||
dialoglist.append(option)
|
dialoglist.append(option)
|
||||||
media = utils.dialog('select', 'Select stream', dialoglist)
|
media = utils.dialog('select', 'Select stream', dialoglist)
|
||||||
if media == -1:
|
if media == -1:
|
||||||
|
@ -1437,20 +1419,15 @@ class API(object):
|
||||||
"""
|
"""
|
||||||
if self.mediastream is None and self.mediastream_number() is None:
|
if self.mediastream is None and self.mediastream_number() is None:
|
||||||
return
|
return
|
||||||
if quality is None:
|
quality = {} if quality is None else quality
|
||||||
quality = {}
|
|
||||||
xargs = clientinfo.getXArgsDeviceInfo()
|
xargs = clientinfo.getXArgsDeviceInfo()
|
||||||
# For DirectPlay, path/key of PART is needed
|
# For DirectPlay, path/key of PART is needed
|
||||||
# trailers are 'clip' with PMS xmls
|
# trailers are 'clip' with PMS xmls
|
||||||
if action == "DirectStream":
|
if action == "DirectStream":
|
||||||
path = self.item[self.mediastream][self.part].attrib['key']
|
path = self.item[self.mediastream][self.part].get('key')
|
||||||
url = app.CONN.server + path
|
url = app.CONN.server + path
|
||||||
# e.g. Trailers already feature an '?'!
|
# e.g. Trailers already feature an '?'!
|
||||||
if '?' in url:
|
return utils.extend_url(url, xargs)
|
||||||
url += '&' + urlencode(xargs)
|
|
||||||
else:
|
|
||||||
url += '?' + urlencode(xargs)
|
|
||||||
return url
|
|
||||||
|
|
||||||
# For Transcoding
|
# For Transcoding
|
||||||
headers = {
|
headers = {
|
||||||
|
@ -1460,7 +1437,7 @@ class API(object):
|
||||||
'X-Plex-Version': '5.8.0.475'
|
'X-Plex-Version': '5.8.0.475'
|
||||||
}
|
}
|
||||||
# Path/key to VIDEO item of xml PMS response is needed, not part
|
# Path/key to VIDEO item of xml PMS response is needed, not part
|
||||||
path = self.item.attrib['key']
|
path = self.item.get('key')
|
||||||
transcode_path = app.CONN.server + \
|
transcode_path = app.CONN.server + \
|
||||||
'/video/:/transcode/universal/start.m3u8?'
|
'/video/:/transcode/universal/start.m3u8?'
|
||||||
args = {
|
args = {
|
||||||
|
@ -1469,7 +1446,7 @@ class API(object):
|
||||||
'directPlay': 0,
|
'directPlay': 0,
|
||||||
'directStream': 1,
|
'directStream': 1,
|
||||||
'protocol': 'hls', # seen in the wild: 'dash', 'http', 'hls'
|
'protocol': 'hls', # seen in the wild: 'dash', 'http', 'hls'
|
||||||
'session': utils.window('plex_client_Id'),
|
'session': v.PKC_MACHINE_IDENTIFIER, # TODO: create new unique id
|
||||||
'fastSeek': 1,
|
'fastSeek': 1,
|
||||||
'path': path,
|
'path': path,
|
||||||
'mediaIndex': self.mediastream,
|
'mediaIndex': self.mediastream,
|
||||||
|
@ -1478,12 +1455,11 @@ class API(object):
|
||||||
'location': 'lan',
|
'location': 'lan',
|
||||||
'subtitleSize': utils.settings('subtitleSize')
|
'subtitleSize': utils.settings('subtitleSize')
|
||||||
}
|
}
|
||||||
# Look like Android to let the PMS use the transcoding profile
|
|
||||||
xargs.update(headers)
|
|
||||||
LOG.debug("Setting transcode quality to: %s", quality)
|
LOG.debug("Setting transcode quality to: %s", quality)
|
||||||
args.update(quality)
|
xargs.update(headers)
|
||||||
url = transcode_path + urlencode(xargs) + '&' + urlencode(args)
|
xargs.update(args)
|
||||||
return url
|
xargs.update(quality)
|
||||||
|
return utils.extend_url(transcode_path, xargs)
|
||||||
|
|
||||||
def cache_external_subs(self):
|
def cache_external_subs(self):
|
||||||
"""
|
"""
|
||||||
|
@ -1500,7 +1476,7 @@ class API(object):
|
||||||
for stream in mediastreams:
|
for stream in mediastreams:
|
||||||
# Since plex returns all possible tracks together, have to pull
|
# Since plex returns all possible tracks together, have to pull
|
||||||
# only external subtitles - only for these a 'key' exists
|
# only external subtitles - only for these a 'key' exists
|
||||||
if stream.get('streamType') != "3":
|
if cast(int, stream.get('streamType')) != 3:
|
||||||
# Not a subtitle
|
# Not a subtitle
|
||||||
continue
|
continue
|
||||||
# Only set for additional external subtitles NOT lying beside video
|
# Only set for additional external subtitles NOT lying beside video
|
||||||
|
@ -1510,11 +1486,11 @@ class API(object):
|
||||||
if key:
|
if key:
|
||||||
# We do know the language - temporarily download
|
# We do know the language - temporarily download
|
||||||
if stream.get('languageCode') is not None:
|
if stream.get('languageCode') is not None:
|
||||||
|
language = stream.get('languageCode')
|
||||||
|
codec = stream.get('codec')
|
||||||
path = self.download_external_subtitles(
|
path = self.download_external_subtitles(
|
||||||
"{server}%s" % key,
|
"{server}%s" % key,
|
||||||
"subtitle%02d.%s.%s" % (fileindex,
|
"subtitle%02d.%s.%s" % (fileindex, language, codec))
|
||||||
stream.attrib['languageCode'],
|
|
||||||
stream.attrib['codec']))
|
|
||||||
fileindex += 1
|
fileindex += 1
|
||||||
# We don't know the language - no need to download
|
# We don't know the language - no need to download
|
||||||
else:
|
else:
|
||||||
|
@ -1878,7 +1854,7 @@ class API(object):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
args = quote(args)
|
args = utils.quote(args)
|
||||||
path = '%s:%s:%s' % (protocol, hostname, args)
|
path = '%s:%s:%s' % (protocol, hostname, args)
|
||||||
if (app.SYNC.path_verified and not force_check) or omit_check:
|
if (app.SYNC.path_verified and not force_check) or omit_check:
|
||||||
return path
|
return path
|
||||||
|
|
Loading…
Reference in a new issue