@@ -70,9 +70,6 @@ class MyPlexAccount(PlexObject):
7070 PLEXSERVERS = 'https://plex.tv/api/servers/{machineId}' # get
7171 FRIENDUPDATE = 'https://plex.tv/api/friends/{userId}' # put with args, delete
7272 REMOVEHOMEUSER = 'https://plex.tv/api/home/users/{userId}' # delete
73- REMOVEINVITE = 'https://plex.tv/api/invites/requested/{userId}?friend=1&server=1&home=1' # delete
74- REQUESTED = 'https://plex.tv/api/invites/requested' # get
75- REQUESTS = 'https://plex.tv/api/invites/requests' # get
7673 SIGNIN = 'https://plex.tv/users/sign_in.xml' # get with auth
7774 WEBHOOKS = 'https://plex.tv/api/v2/user/webhooks' # get, post with data
7875 OPTOUTS = 'https://plex.tv/api/v2/user/%(userUUID)s/settings/opt_outs' # get
@@ -365,26 +362,55 @@ def createExistingUser(self, user, server, sections=None, allowSync=False, allow
365362 return self .query (url , self ._session .post , headers = headers )
366363
367364 def removeFriend (self , user ):
368- """ Remove the specified user from all sharing .
365+ """ Remove the specified user from your friends .
369366
370367 Parameters:
371- user (str): MyPlexUser, username, email of the user to be added .
368+ user (str): :class:`~plexapi.myplex. MyPlexUser` , username, or email of the user to be removed .
372369 """
373- user = self .user (user )
374- url = self .FRIENDUPDATE if user .friend else self .REMOVEINVITE
375- url = url .format (userId = user .id )
370+ user = user if isinstance (user , MyPlexUser ) else self .user (user )
371+ url = self .FRIENDUPDATE .format (userId = user .id )
376372 return self .query (url , self ._session .delete )
377373
378374 def removeHomeUser (self , user ):
379- """ Remove the specified managed user from home.
375+ """ Remove the specified user from your home users .
380376
381377 Parameters:
382- user (str): MyPlexUser, username, email of the user to be removed from home .
378+ user (str): :class:`~plexapi.myplex. MyPlexUser` , username, or email of the user to be removed.
383379 """
384- user = self .user (user )
380+ user = user if isinstance ( user , MyPlexUser ) else self .user (user )
385381 url = self .REMOVEHOMEUSER .format (userId = user .id )
386382 return self .query (url , self ._session .delete )
387383
384+ def acceptInvite (self , user ):
385+ """ Accept a pending firend invite from the specified user.
386+
387+ Parameters:
388+ user (str): :class:`~plexapi.myplex.MyPlexInvite`, username, or email of the friend invite to accept.
389+ """
390+ invite = user if isinstance (user , MyPlexInvite ) else self .pendingInvite (user , includeSent = False )
391+ params = {
392+ 'friend' : int (invite .friend ),
393+ 'home' : int (invite .home ),
394+ 'server' : int (invite .server )
395+ }
396+ url = MyPlexInvite .REQUESTS + '/%s' % invite .id + utils .joinArgs (params )
397+ return self .query (url , self ._session .put )
398+
399+ def cancelInvite (self , user ):
400+ """ Cancel a pending firend invite for the specified user.
401+
402+ Parameters:
403+ user (str): :class:`~plexapi.myplex.MyPlexInvite`, username, or email of the friend invite to cancel.
404+ """
405+ invite = user if isinstance (user , MyPlexInvite ) else self .pendingInvite (user , includeReceived = False )
406+ params = {
407+ 'friend' : int (invite .friend ),
408+ 'home' : int (invite .home ),
409+ 'server' : int (invite .server )
410+ }
411+ url = MyPlexInvite .REQUESTED + '/%s' % invite .id + utils .joinArgs (params )
412+ return self .query (url , self ._session .delete )
413+
388414 def updateFriend (self , user , server , sections = None , removeSections = False , allowSync = None , allowCameraUpload = None ,
389415 allowChannels = None , filterMovies = None , filterTelevision = None , filterMusic = None ):
390416 """ Update the specified user's share settings.
@@ -455,7 +481,7 @@ def updateFriend(self, user, server, sections=None, removeSections=False, allowS
455481 return response_servers , response_filters
456482
457483 def user (self , username ):
458- """ Returns the :class:`~plexapi.myplex.MyPlexUser` that matches the email or username specified .
484+ """ Returns the :class:`~plexapi.myplex.MyPlexUser` that matches the specified username or email .
459485
460486 Parameters:
461487 username (str): Username, email or id of the user to return.
@@ -467,19 +493,50 @@ def user(self, username):
467493 return user
468494
469495 elif (user .username and user .email and user .id and username .lower () in
470- (user .username .lower (), user .email .lower (), str (user .id ))):
496+ (user .username .lower (), user .email .lower (), str (user .id ))):
471497 return user
472498
473499 raise NotFound ('Unable to find user %s' % username )
474500
475501 def users (self ):
476502 """ Returns a list of all :class:`~plexapi.myplex.MyPlexUser` objects connected to your account.
477- This includes both friends and pending invites. You can reference the user.friend to
478- distinguish between the two.
479503 """
480- friends = [MyPlexUser (self , elem ) for elem in self .query (MyPlexUser .key )]
481- requested = [MyPlexUser (self , elem , self .REQUESTED ) for elem in self .query (self .REQUESTED )]
482- return friends + requested
504+ elem = self .query (MyPlexUser .key )
505+ return self .findItems (elem , cls = MyPlexUser )
506+
507+ def pendingInvite (self , username , includeSent = True , includeReceived = True ):
508+ """ Returns the :class:`~plexapi.myplex.MyPlexInvite` that matches the specified username or email.
509+ Note: This can be a pending invite sent from your account or received to your account.
510+
511+ Parameters:
512+ username (str): Username, email or id of the user to return.
513+ includeSent (bool): True to include sent invites.
514+ includeReceived (bool): True to include received invites.
515+ """
516+ username = str (username )
517+ for invite in self .pendingInvites (includeSent , includeReceived ):
518+ if (invite .username and invite .email and invite .id and username .lower () in
519+ (invite .username .lower (), invite .email .lower (), str (invite .id ))):
520+ return invite
521+
522+ raise NotFound ('Unable to find invite %s' % username )
523+
524+ def pendingInvites (self , includeSent = True , includeReceived = True ):
525+ """ Returns a list of all :class:`~plexapi.myplex.MyPlexInvite` objects connected to your account.
526+ Note: This includes all pending invites sent from your account and received to your account.
527+
528+ Parameters:
529+ includeSent (bool): True to include sent invites.
530+ includeReceived (bool): True to include received invites.
531+ """
532+ invites = []
533+ if includeSent :
534+ elem = self .query (MyPlexInvite .REQUESTED )
535+ invites += self .findItems (elem , cls = MyPlexInvite )
536+ if includeReceived :
537+ elem = self .query (MyPlexInvite .REQUESTS )
538+ invites += self .findItems (elem , cls = MyPlexInvite )
539+ return invites
483540
484541 def _getSectionIds (self , server , sections ):
485542 """ Converts a list of section objects or names to sectionIds needed for library sharing. """
@@ -731,10 +788,10 @@ class MyPlexUser(PlexObject):
731788 protected (False): Unknown (possibly SSL enabled?).
732789 recommendationsPlaylistId (str): Unknown.
733790 restricted (str): Unknown.
791+ servers (List<:class:`~plexapi.myplex.<MyPlexServerShare`>)): Servers shared with the user.
734792 thumb (str): Link to the users avatar.
735793 title (str): Seems to be an aliad for username.
736794 username (str): User's username.
737- servers: Servers shared between user and friend
738795 """
739796 TAG = 'User'
740797 key = 'https://plex.tv/api/users/'
@@ -796,6 +853,43 @@ def history(self, maxresults=9999999, mindate=None):
796853 return hist
797854
798855
856+ class MyPlexInvite (PlexObject ):
857+ """ This object represents pending friend invites.
858+
859+ Attributes:
860+ TAG (str): 'Invite'
861+ createdAt (datetime): Datetime the user was invited.
862+ email (str): User's email address (user@gmail.com).
863+ friend (bool): True or False if the user is invited as a friend.
864+ friendlyName (str): The user's friendly name.
865+ home (bool): True or False if the user is invited to a Plex Home.
866+ id (int): User's Plex account ID.
867+ server (bool): True or False if the user is invited to any servers.
868+ servers (List<:class:`~plexapi.myplex.<MyPlexServerShare`>)): Servers shared with the user.
869+ thumb (str): Link to the users avatar.
870+ username (str): User's username.
871+ """
872+ TAG = 'Invite'
873+ REQUESTS = 'https://plex.tv/api/invites/requests'
874+ REQUESTED = 'https://plex.tv/api/invites/requested'
875+
876+ def _loadData (self , data ):
877+ """ Load attribute values from Plex XML response. """
878+ self ._data = data
879+ self .createdAt = utils .toDatetime (data .attrib .get ('createdAt' ))
880+ self .email = data .attrib .get ('email' )
881+ self .friend = utils .cast (bool , data .attrib .get ('friend' ))
882+ self .friendlyName = data .attrib .get ('friendlyName' )
883+ self .home = utils .cast (bool , data .attrib .get ('home' ))
884+ self .id = utils .cast (int , data .attrib .get ('id' ))
885+ self .server = utils .cast (bool , data .attrib .get ('server' ))
886+ self .servers = self .findItems (data , MyPlexServerShare )
887+ self .thumb = data .attrib .get ('thumb' )
888+ self .username = data .attrib .get ('username' , '' )
889+ for server in self .servers :
890+ server .accountID = self .id
891+
892+
799893class Section (PlexObject ):
800894 """ This refers to a shared section. The raw xml for the data presented here
801895 can be found at: https://plex.tv/api/servers/{machineId}/shared_servers
0 commit comments