mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-06 05:01:14 -07:00
Update PlexAPI to 3.3.0
This commit is contained in:
parent
2fa62f71e1
commit
c55c00a19e
17 changed files with 1559 additions and 135 deletions
|
@ -3,7 +3,7 @@ import copy
|
|||
import requests
|
||||
import time
|
||||
from requests.status_codes import _codes as codes
|
||||
from plexapi import BASE_HEADERS, CONFIG, TIMEOUT
|
||||
from plexapi import BASE_HEADERS, CONFIG, TIMEOUT, X_PLEX_IDENTIFIER, X_PLEX_ENABLE_FAST_CONNECT
|
||||
from plexapi import log, logfilter, utils
|
||||
from plexapi.base import PlexObject
|
||||
from plexapi.exceptions import BadRequest, NotFound
|
||||
|
@ -11,6 +11,7 @@ from plexapi.client import PlexClient
|
|||
from plexapi.compat import ElementTree
|
||||
from plexapi.library import LibrarySection
|
||||
from plexapi.server import PlexServer
|
||||
from plexapi.sync import SyncList, SyncItem
|
||||
from plexapi.utils import joinArgs
|
||||
|
||||
|
||||
|
@ -61,9 +62,12 @@ class MyPlexAccount(PlexObject):
|
|||
_session (obj): Requests session object used to access this client.
|
||||
"""
|
||||
FRIENDINVITE = 'https://plex.tv/api/servers/{machineId}/shared_servers' # post with data
|
||||
HOMEUSERCREATE = 'https://plex.tv/api/home/users?title={title}' # post with data
|
||||
EXISTINGUSER = 'https://plex.tv/api/home/users?invitedEmail={username}' # post with data
|
||||
FRIENDSERVERS = 'https://plex.tv/api/servers/{machineId}/shared_servers/{serverId}' # put with data
|
||||
PLEXSERVERS = 'https://plex.tv/api/servers/{machineId}' # get
|
||||
FRIENDUPDATE = 'https://plex.tv/api/friends/{userId}' # put with args, delete
|
||||
REMOVEHOMEUSER = 'https://plex.tv/api/home/users/{userId}' # delete
|
||||
REMOVEINVITE = 'https://plex.tv/api/invites/requested/{userId}?friend=0&server=1&home=0' # delete
|
||||
REQUESTED = 'https://plex.tv/api/invites/requested' # get
|
||||
REQUESTS = 'https://plex.tv/api/invites/requests' # get
|
||||
|
@ -112,13 +116,31 @@ class MyPlexAccount(PlexObject):
|
|||
self.title = data.attrib.get('title')
|
||||
self.username = data.attrib.get('username')
|
||||
self.uuid = data.attrib.get('uuid')
|
||||
subscription = data.find('subscription')
|
||||
|
||||
self.subscriptionActive = utils.cast(bool, subscription.attrib.get('active'))
|
||||
self.subscriptionStatus = subscription.attrib.get('status')
|
||||
self.subscriptionPlan = subscription.attrib.get('plan')
|
||||
|
||||
self.subscriptionFeatures = []
|
||||
for feature in subscription.iter('feature'):
|
||||
self.subscriptionFeatures.append(feature.attrib.get('id'))
|
||||
|
||||
roles = data.find('roles')
|
||||
self.roles = []
|
||||
if roles:
|
||||
for role in roles.iter('role'):
|
||||
self.roles.append(role.attrib.get('id'))
|
||||
|
||||
entitlements = data.find('entitlements')
|
||||
self.entitlements = []
|
||||
for entitlement in entitlements.iter('entitlement'):
|
||||
self.entitlements.append(entitlement.attrib.get('id'))
|
||||
|
||||
# TODO: Fetch missing MyPlexAccount attributes
|
||||
self.subscriptionActive = None # renamed on server
|
||||
self.subscriptionStatus = None # renamed on server
|
||||
self.subscriptionPlan = None # renmaed on server
|
||||
self.subscriptionFeatures = None # renamed on server
|
||||
self.roles = None
|
||||
self.entitlements = None
|
||||
self.profile_settings = None
|
||||
self.services = None
|
||||
self.joined_at = None
|
||||
|
||||
def device(self, name):
|
||||
""" Returns the :class:`~plexapi.myplex.MyPlexDevice` that matches the name specified.
|
||||
|
@ -153,7 +175,6 @@ class MyPlexAccount(PlexObject):
|
|||
if response.status_code not in (200, 201, 204): # pragma: no cover
|
||||
codename = codes.get(response.status_code)[0]
|
||||
errtext = response.text.replace('\n', ' ')
|
||||
log.warning('BadRequest (%s) %s %s; %s' % (response.status_code, codename, response.url, errtext))
|
||||
raise BadRequest('(%s) %s %s; %s' % (response.status_code, codename, response.url, errtext))
|
||||
data = response.text.encode('utf8')
|
||||
return ElementTree.fromstring(data) if data.strip() else None
|
||||
|
@ -175,13 +196,14 @@ class MyPlexAccount(PlexObject):
|
|||
return [MyPlexResource(self, elem) for elem in data]
|
||||
|
||||
def inviteFriend(self, user, server, sections=None, allowSync=False, allowCameraUpload=False,
|
||||
allowChannels=False, filterMovies=None, filterTelevision=None, filterMusic=None):
|
||||
allowChannels=False, filterMovies=None, filterTelevision=None, filterMusic=None):
|
||||
""" Share library content with the specified user.
|
||||
|
||||
Parameters:
|
||||
user (str): MyPlexUser, username, email of the user to be added.
|
||||
server (PlexServer): PlexServer object or machineIdentifier containing the library sections to share.
|
||||
sections ([Section]): Library sections, names or ids to be shared (default None shares all sections).
|
||||
sections ([Section]): Library sections, names or ids to be shared (default None).
|
||||
[Section] must be defined in order to update shared sections.
|
||||
allowSync (Bool): Set True to allow user to sync content.
|
||||
allowCameraUpload (Bool): Set True to allow user to upload photos.
|
||||
allowChannels (Bool): Set True to allow user to utilize installed channels.
|
||||
|
@ -211,6 +233,102 @@ class MyPlexAccount(PlexObject):
|
|||
url = self.FRIENDINVITE.format(machineId=machineId)
|
||||
return self.query(url, self._session.post, json=params, headers=headers)
|
||||
|
||||
def createHomeUser(self, user, server, sections=None, allowSync=False, allowCameraUpload=False,
|
||||
allowChannels=False, filterMovies=None, filterTelevision=None, filterMusic=None):
|
||||
""" Share library content with the specified user.
|
||||
|
||||
Parameters:
|
||||
user (str): MyPlexUser, username, email of the user to be added.
|
||||
server (PlexServer): PlexServer object or machineIdentifier containing the library sections to share.
|
||||
sections ([Section]): Library sections, names or ids to be shared (default None shares all sections).
|
||||
allowSync (Bool): Set True to allow user to sync content.
|
||||
allowCameraUpload (Bool): Set True to allow user to upload photos.
|
||||
allowChannels (Bool): Set True to allow user to utilize installed channels.
|
||||
filterMovies (Dict): Dict containing key 'contentRating' and/or 'label' each set to a list of
|
||||
values to be filtered. ex: {'contentRating':['G'], 'label':['foo']}
|
||||
filterTelevision (Dict): Dict containing key 'contentRating' and/or 'label' each set to a list of
|
||||
values to be filtered. ex: {'contentRating':['G'], 'label':['foo']}
|
||||
filterMusic (Dict): Dict containing key 'label' set to a list of values to be filtered.
|
||||
ex: {'label':['foo']}
|
||||
"""
|
||||
machineId = server.machineIdentifier if isinstance(server, PlexServer) else server
|
||||
sectionIds = self._getSectionIds(server, sections)
|
||||
|
||||
headers = {'Content-Type': 'application/json'}
|
||||
url = self.HOMEUSERCREATE.format(title=user)
|
||||
# UserID needs to be created and referenced when adding sections
|
||||
user_creation = self.query(url, self._session.post, headers=headers)
|
||||
userIds = {}
|
||||
for elem in user_creation.findall("."):
|
||||
# Find userID
|
||||
userIds['id'] = elem.attrib.get('id')
|
||||
log.debug(userIds)
|
||||
params = {
|
||||
'server_id': machineId,
|
||||
'shared_server': {'library_section_ids': sectionIds, 'invited_id': userIds['id']},
|
||||
'sharing_settings': {
|
||||
'allowSync': ('1' if allowSync else '0'),
|
||||
'allowCameraUpload': ('1' if allowCameraUpload else '0'),
|
||||
'allowChannels': ('1' if allowChannels else '0'),
|
||||
'filterMovies': self._filterDictToStr(filterMovies or {}),
|
||||
'filterTelevision': self._filterDictToStr(filterTelevision or {}),
|
||||
'filterMusic': self._filterDictToStr(filterMusic or {}),
|
||||
},
|
||||
}
|
||||
url = self.FRIENDINVITE.format(machineId=machineId)
|
||||
library_assignment = self.query(url, self._session.post, json=params, headers=headers)
|
||||
return user_creation, library_assignment
|
||||
|
||||
def createExistingUser(self, user, server, sections=None, allowSync=False, allowCameraUpload=False,
|
||||
allowChannels=False, filterMovies=None, filterTelevision=None, filterMusic=None):
|
||||
""" Share library content with the specified user.
|
||||
|
||||
Parameters:
|
||||
user (str): MyPlexUser, username, email of the user to be added.
|
||||
server (PlexServer): PlexServer object or machineIdentifier containing the library sections to share.
|
||||
sections ([Section]): Library sections, names or ids to be shared (default None shares all sections).
|
||||
allowSync (Bool): Set True to allow user to sync content.
|
||||
allowCameraUpload (Bool): Set True to allow user to upload photos.
|
||||
allowChannels (Bool): Set True to allow user to utilize installed channels.
|
||||
filterMovies (Dict): Dict containing key 'contentRating' and/or 'label' each set to a list of
|
||||
values to be filtered. ex: {'contentRating':['G'], 'label':['foo']}
|
||||
filterTelevision (Dict): Dict containing key 'contentRating' and/or 'label' each set to a list of
|
||||
values to be filtered. ex: {'contentRating':['G'], 'label':['foo']}
|
||||
filterMusic (Dict): Dict containing key 'label' set to a list of values to be filtered.
|
||||
ex: {'label':['foo']}
|
||||
"""
|
||||
headers = {'Content-Type': 'application/json'}
|
||||
# If user already exists, carry over sections and settings.
|
||||
if isinstance(user, MyPlexUser):
|
||||
username = user.username
|
||||
elif user in [_user.username for _user in self.users()]:
|
||||
username = self.user(user).username
|
||||
else:
|
||||
# If user does not already exists, treat request as new request and include sections and settings.
|
||||
newUser = user
|
||||
url = self.EXISTINGUSER.format(username=newUser)
|
||||
user_creation = self.query(url, self._session.post, headers=headers)
|
||||
machineId = server.machineIdentifier if isinstance(server, PlexServer) else server
|
||||
sectionIds = self._getSectionIds(server, sections)
|
||||
params = {
|
||||
'server_id': machineId,
|
||||
'shared_server': {'library_section_ids': sectionIds, 'invited_email': newUser},
|
||||
'sharing_settings': {
|
||||
'allowSync': ('1' if allowSync else '0'),
|
||||
'allowCameraUpload': ('1' if allowCameraUpload else '0'),
|
||||
'allowChannels': ('1' if allowChannels else '0'),
|
||||
'filterMovies': self._filterDictToStr(filterMovies or {}),
|
||||
'filterTelevision': self._filterDictToStr(filterTelevision or {}),
|
||||
'filterMusic': self._filterDictToStr(filterMusic or {}),
|
||||
},
|
||||
}
|
||||
url = self.FRIENDINVITE.format(machineId=machineId)
|
||||
library_assignment = self.query(url, self._session.post, json=params, headers=headers)
|
||||
return user_creation, library_assignment
|
||||
|
||||
url = self.EXISTINGUSER.format(username=username)
|
||||
return self.query(url, self._session.post, headers=headers)
|
||||
|
||||
def removeFriend(self, user):
|
||||
""" Remove the specified user from all sharing.
|
||||
|
||||
|
@ -222,6 +340,16 @@ class MyPlexAccount(PlexObject):
|
|||
url = url.format(userId=user.id)
|
||||
return self.query(url, self._session.delete)
|
||||
|
||||
def removeHomeUser(self, user):
|
||||
""" Remove the specified managed user from home.
|
||||
|
||||
Parameters:
|
||||
user (str): MyPlexUser, username, email of the user to be removed from home.
|
||||
"""
|
||||
user = self.user(user)
|
||||
url = self.REMOVEHOMEUSER.format(userId=user.id)
|
||||
return self.query(url, self._session.delete)
|
||||
|
||||
def updateFriend(self, user, server, sections=None, removeSections=False, allowSync=None, allowCameraUpload=None,
|
||||
allowChannels=None, filterMovies=None, filterTelevision=None, filterMusic=None):
|
||||
""" Update the specified user's share settings.
|
||||
|
@ -229,7 +357,8 @@ class MyPlexAccount(PlexObject):
|
|||
Parameters:
|
||||
user (str): MyPlexUser, username, email of the user to be added.
|
||||
server (PlexServer): PlexServer object or machineIdentifier containing the library sections to share.
|
||||
sections: ([Section]): Library sections, names or ids to be shared (default None shares all sections).
|
||||
sections: ([Section]): Library sections, names or ids to be shared (default None).
|
||||
[Section] must be defined in order to update shared sections.
|
||||
removeSections (Bool): Set True to remove all shares. Supersedes sections.
|
||||
allowSync (Bool): Set True to allow user to sync content.
|
||||
allowCameraUpload (Bool): Set True to allow user to upload photos.
|
||||
|
@ -244,7 +373,7 @@ class MyPlexAccount(PlexObject):
|
|||
# Update friend servers
|
||||
response_filters = ''
|
||||
response_servers = ''
|
||||
user = self.user(user.username if isinstance(user, MyPlexUser) else user)
|
||||
user = user if isinstance(user, MyPlexUser) else self.user(user)
|
||||
machineId = server.machineIdentifier if isinstance(server, PlexServer) else server
|
||||
sectionIds = self._getSectionIds(machineId, sections)
|
||||
headers = {'Content-Type': 'application/json'}
|
||||
|
@ -256,10 +385,10 @@ class MyPlexAccount(PlexObject):
|
|||
url = self.FRIENDSERVERS.format(machineId=machineId, serverId=serverId)
|
||||
else:
|
||||
params = {'server_id': machineId, 'shared_server': {'library_section_ids': sectionIds,
|
||||
"invited_id": user.id}}
|
||||
'invited_id': user.id}}
|
||||
url = self.FRIENDINVITE.format(machineId=machineId)
|
||||
# Remove share sections, add shares to user without shares, or update shares
|
||||
if sectionIds:
|
||||
if not user_servers or sectionIds:
|
||||
if removeSections is True:
|
||||
response_servers = self.query(url, self._session.delete, json=params, headers=headers)
|
||||
elif 'invited_id' in params.get('shared_server', ''):
|
||||
|
@ -289,7 +418,7 @@ class MyPlexAccount(PlexObject):
|
|||
return response_servers, response_filters
|
||||
|
||||
def user(self, username):
|
||||
""" Returns the :class:`~myplex.MyPlexUser` that matches the email or username specified.
|
||||
""" Returns the :class:`~plexapi.myplex.MyPlexUser` that matches the email or username specified.
|
||||
|
||||
Parameters:
|
||||
username (str): Username, email or id of the user to return.
|
||||
|
@ -357,7 +486,8 @@ class MyPlexAccount(PlexObject):
|
|||
|
||||
def setWebhooks(self, urls):
|
||||
log.info('Setting webhooks: %s' % urls)
|
||||
data = self.query(self.WEBHOOKS, self._session.post, data={'urls[]': urls})
|
||||
data = {'urls[]': urls} if len(urls) else {'urls': ''}
|
||||
data = self.query(self.WEBHOOKS, self._session.post, data=data)
|
||||
self._webhooks = self.listAttrs(data, 'url', etag='webhook')
|
||||
return self._webhooks
|
||||
|
||||
|
@ -376,7 +506,99 @@ class MyPlexAccount(PlexObject):
|
|||
if library is not None:
|
||||
params['optOutLibraryStats'] = int(library)
|
||||
url = 'https://plex.tv/api/v2/user/privacy'
|
||||
return self.query(url, method=self._session.put, params=params)
|
||||
return self.query(url, method=self._session.put, data=params)
|
||||
|
||||
def syncItems(self, client=None, clientId=None):
|
||||
""" Returns an instance of :class:`plexapi.sync.SyncList` for specified client.
|
||||
|
||||
Parameters:
|
||||
client (:class:`~plexapi.myplex.MyPlexDevice`): a client to query SyncItems for.
|
||||
clientId (str): an identifier of a client to query SyncItems for.
|
||||
|
||||
If both `client` and `clientId` provided the client would be preferred.
|
||||
If neither `client` nor `clientId` provided the clientId would be set to current clients`s identifier.
|
||||
"""
|
||||
if client:
|
||||
clientId = client.clientIdentifier
|
||||
elif clientId is None:
|
||||
clientId = X_PLEX_IDENTIFIER
|
||||
|
||||
data = self.query(SyncList.key.format(clientId=clientId))
|
||||
|
||||
return SyncList(self, data)
|
||||
|
||||
def sync(self, sync_item, client=None, clientId=None):
|
||||
""" Adds specified sync item for the client. It's always easier to use methods defined directly in the media
|
||||
objects, e.g. :func:`plexapi.video.Video.sync`, :func:`plexapi.audio.Audio.sync`.
|
||||
|
||||
Parameters:
|
||||
client (:class:`~plexapi.myplex.MyPlexDevice`): a client for which you need to add SyncItem to.
|
||||
clientId (str): an identifier of a client for which you need to add SyncItem to.
|
||||
sync_item (:class:`plexapi.sync.SyncItem`): prepared SyncItem object with all fields set.
|
||||
|
||||
If both `client` and `clientId` provided the client would be preferred.
|
||||
If neither `client` nor `clientId` provided the clientId would be set to current clients`s identifier.
|
||||
|
||||
Returns:
|
||||
:class:`plexapi.sync.SyncItem`: an instance of created syncItem.
|
||||
|
||||
Raises:
|
||||
:class:`plexapi.exceptions.BadRequest`: when client with provided clientId wasn`t found.
|
||||
:class:`plexapi.exceptions.BadRequest`: provided client doesn`t provides `sync-target`.
|
||||
"""
|
||||
if not client and not clientId:
|
||||
clientId = X_PLEX_IDENTIFIER
|
||||
|
||||
if not client:
|
||||
for device in self.devices():
|
||||
if device.clientIdentifier == clientId:
|
||||
client = device
|
||||
break
|
||||
|
||||
if not client:
|
||||
raise BadRequest('Unable to find client by clientId=%s', clientId)
|
||||
|
||||
if 'sync-target' not in client.provides:
|
||||
raise BadRequest('Received client doesn`t provides sync-target')
|
||||
|
||||
params = {
|
||||
'SyncItem[title]': sync_item.title,
|
||||
'SyncItem[rootTitle]': sync_item.rootTitle,
|
||||
'SyncItem[metadataType]': sync_item.metadataType,
|
||||
'SyncItem[machineIdentifier]': sync_item.machineIdentifier,
|
||||
'SyncItem[contentType]': sync_item.contentType,
|
||||
'SyncItem[Policy][scope]': sync_item.policy.scope,
|
||||
'SyncItem[Policy][unwatched]': str(int(sync_item.policy.unwatched)),
|
||||
'SyncItem[Policy][value]': str(sync_item.policy.value if hasattr(sync_item.policy, 'value') else 0),
|
||||
'SyncItem[Location][uri]': sync_item.location,
|
||||
'SyncItem[MediaSettings][audioBoost]': str(sync_item.mediaSettings.audioBoost),
|
||||
'SyncItem[MediaSettings][maxVideoBitrate]': str(sync_item.mediaSettings.maxVideoBitrate),
|
||||
'SyncItem[MediaSettings][musicBitrate]': str(sync_item.mediaSettings.musicBitrate),
|
||||
'SyncItem[MediaSettings][photoQuality]': str(sync_item.mediaSettings.photoQuality),
|
||||
'SyncItem[MediaSettings][photoResolution]': sync_item.mediaSettings.photoResolution,
|
||||
'SyncItem[MediaSettings][subtitleSize]': str(sync_item.mediaSettings.subtitleSize),
|
||||
'SyncItem[MediaSettings][videoQuality]': str(sync_item.mediaSettings.videoQuality),
|
||||
'SyncItem[MediaSettings][videoResolution]': sync_item.mediaSettings.videoResolution,
|
||||
}
|
||||
|
||||
url = SyncList.key.format(clientId=client.clientIdentifier)
|
||||
data = self.query(url, method=self._session.post, headers={
|
||||
'Content-type': 'x-www-form-urlencoded',
|
||||
}, params=params)
|
||||
|
||||
return SyncItem(self, data, None, clientIdentifier=client.clientIdentifier)
|
||||
|
||||
def claimToken(self):
|
||||
""" Returns a str, a new "claim-token", which you can use to register your new Plex Server instance to your
|
||||
account.
|
||||
See: https://hub.docker.com/r/plexinc/pms-docker/, https://www.plex.tv/claim/
|
||||
"""
|
||||
response = self._session.get('https://plex.tv/api/claim/token.json', headers=self._headers(), timeout=TIMEOUT)
|
||||
if response.status_code not in (200, 201, 204): # pragma: no cover
|
||||
codename = codes.get(response.status_code)[0]
|
||||
errtext = response.text.replace('\n', ' ')
|
||||
raise BadRequest('(%s) %s %s; %s' % (response.status_code, codename, response.url, errtext))
|
||||
return response.json()['token']
|
||||
|
||||
|
||||
class MyPlexUser(PlexObject):
|
||||
|
@ -405,6 +627,7 @@ class MyPlexUser(PlexObject):
|
|||
thumb (str): Link to the users avatar.
|
||||
title (str): Seems to be an aliad for username.
|
||||
username (str): User's username.
|
||||
servers: Servers shared between user and friend
|
||||
"""
|
||||
TAG = 'User'
|
||||
key = 'https://plex.tv/api/users/'
|
||||
|
@ -577,7 +800,7 @@ class MyPlexResource(PlexObject):
|
|||
HTTP or HTTPS connection.
|
||||
|
||||
Raises:
|
||||
:class:`~plexapi.exceptions.NotFound`: When unable to connect to any addresses for this resource.
|
||||
:class:`plexapi.exceptions.NotFound`: When unable to connect to any addresses for this resource.
|
||||
"""
|
||||
# Sort connections from (https, local) to (http, remote)
|
||||
# Only check non-local connections unless we own the resource
|
||||
|
@ -684,7 +907,7 @@ class MyPlexDevice(PlexObject):
|
|||
at least one connection was successful, the PlexClient object is built and returned.
|
||||
|
||||
Raises:
|
||||
:class:`~plexapi.exceptions.NotFound`: When unable to connect to any addresses for this device.
|
||||
:class:`plexapi.exceptions.NotFound`: When unable to connect to any addresses for this device.
|
||||
"""
|
||||
cls = PlexServer if 'server' in self.provides else PlexClient
|
||||
listargs = [[cls, url, self.token, timeout] for url in self.connections]
|
||||
|
@ -697,16 +920,40 @@ class MyPlexDevice(PlexObject):
|
|||
key = 'https://plex.tv/devices/%s.xml' % self.id
|
||||
self._server.query(key, self._server._session.delete)
|
||||
|
||||
def syncItems(self):
|
||||
""" Returns an instance of :class:`plexapi.sync.SyncList` for current device.
|
||||
|
||||
def _connect(cls, url, token, timeout, results, i):
|
||||
Raises:
|
||||
:class:`plexapi.exceptions.BadRequest`: when the device doesn`t provides `sync-target`.
|
||||
"""
|
||||
if 'sync-target' not in self.provides:
|
||||
raise BadRequest('Requested syncList for device which do not provides sync-target')
|
||||
|
||||
return self._server.syncItems(client=self)
|
||||
|
||||
|
||||
def _connect(cls, url, token, timeout, results, i, job_is_done_event=None):
|
||||
""" Connects to the specified cls with url and token. Stores the connection
|
||||
information to results[i] in a threadsafe way.
|
||||
|
||||
Arguments:
|
||||
cls: the class which is responsible for establishing connection, basically it's
|
||||
:class:`~plexapi.client.PlexClient` or :class:`~plexapi.server.PlexServer`
|
||||
url (str): url which should be passed as `baseurl` argument to cls.__init__()
|
||||
token (str): authentication token which should be passed as `baseurl` argument to cls.__init__()
|
||||
timeout (int): timeout which should be passed as `baseurl` argument to cls.__init__()
|
||||
results (list): pre-filled list for results
|
||||
i (int): index of current job, should be less than len(results)
|
||||
job_is_done_event (:class:`~threading.Event`): is X_PLEX_ENABLE_FAST_CONNECT is True then the
|
||||
event would be set as soon the connection is established
|
||||
"""
|
||||
starttime = time.time()
|
||||
try:
|
||||
device = cls(baseurl=url, token=token, timeout=timeout)
|
||||
runtime = int(time.time() - starttime)
|
||||
results[i] = (url, token, device, runtime)
|
||||
if X_PLEX_ENABLE_FAST_CONNECT and job_is_done_event:
|
||||
job_is_done_event.set()
|
||||
except Exception as err:
|
||||
runtime = int(time.time() - starttime)
|
||||
log.error('%s: %s', url, err)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue