
    g2                     J    d dl mZ d dlmZ d dlmZ d dlmZ  G d de      Zy)    )
quote_plus)utils)
PlexObject)
BadRequestc                       e Zd ZdZd ZdZd Zd Zd Zd Z	d Z
d Ze	 	 	 	 	 dd
       Ze	 	 	 	 	 	 dd       Zed        ZddZddZddZd Zd Zy	)	PlayQueuea  Control a PlayQueue.

    Attributes:
        TAG (str): 'PlayQueue'
        TYPE (str): 'playqueue'
        identifier (str): com.plexapp.plugins.library
        items (list): List of :class:`~plexapi.base.Playable` or :class:`~plexapi.playlist.Playlist`
        mediaTagPrefix (str): Fx /system/bundle/media/flags/
        mediaTagVersion (int): Fx 1485957738
        playQueueID (int): ID of the PlayQueue.
        playQueueLastAddedItemID (int):
            Defines where the "Up Next" region starts. Empty unless PlayQueue is modified after creation.
        playQueueSelectedItemID (int): The queue item ID of the currently selected item.
        playQueueSelectedItemOffset (int):
            The offset of the selected item in the PlayQueue, from the beginning of the queue.
        playQueueSelectedMetadataItemID (int): ID of the currently selected item, matches ratingKey.
        playQueueShuffled (bool): True if shuffled.
        playQueueSourceURI (str): Original URI used to create the PlayQueue.
        playQueueTotalCount (int): How many items in the PlayQueue.
        playQueueVersion (int): Version of the PlayQueue. Increments every time a change is made to the PlayQueue.
        selectedItem (:class:`~plexapi.base.Playable`): Media object for the currently selected item.
        _server (:class:`~plexapi.server.PlexServer`): PlexServer associated with the PlayQueue.
        size (int): Alias for playQueueTotalCount.
    	playqueuec                    || _         |j                  j                  d      | _        |j                  j                  d      | _        t        j                  t        |j                  j                  d            | _        t        j                  t        |j                  j                  d            | _	        t        j                  t        |j                  j                  d            | _
        t        j                  t        |j                  j                  d            | _        t        j                  t        |j                  j                  d            | _        t        j                  t        |j                  j                  d            | _        t        j                  t        |j                  j                  d	d
            | _        |j                  j                  d      | _        t        j                  t        |j                  j                  d            | _        t        j                  t        |j                  j                  d            | _        t        j                  t        |j                  j                  dd
            | _        | j)                  |      | _        | | j                     | _        y )N
identifiermediaTagPrefixmediaTagVersionplayQueueIDplayQueueLastAddedItemIDplayQueueSelectedItemIDplayQueueSelectedItemOffsetplayQueueSelectedMetadataItemIDplayQueueShuffledr   playQueueSourceURIplayQueueTotalCountplayQueueVersionsize)_dataattribgetr   r   r   castintr   r   r   r   r   r   boolr   r   r   r   r   	findItemsitemsselectedItem)selfdatas     &/opt/Tautulli/lib/plexapi/playqueue.py	_loadDatazPlayQueue._loadData&   s   
++//,7"kkoo.>?$zz#t{{?P/QR ::c4;;??=+IJ(-

!;<)
% (-zz!:;(
$ ,1::!>?,
( 05zz!BC0
, "'$++//"5q9"
 #'++//2F"G#(::!67$
  !&

3@R0S TJJsDKKOOFA$>?	^^D)
 !A!AB    c                 :    | j                   sy | j                   |   S Nr   )r!   keys     r#   __getitem__zPlayQueue.__getitem__D   s    zzzz#r%   c                     | j                   S r'   )r   r!   s    r#   __len__zPlayQueue.__len__I   s    '''r%   c              #   8   K   | j                   E d {    y 7 wr'   r(   r,   s    r#   __iter__zPlayQueue.__iter__L   s     ::s   c                 @    t        fd| j                  D              S )z?Returns True if the PlayQueue contains the provided media item.c              3   P   K   | ]  }|j                   j                   k(    y wr'   )playQueueItemID).0xmedias     r#   	<genexpr>z)PlayQueue.__contains__.<locals>.<genexpr>Q   s"     R!1$$(=(==Rs   #&)anyr   )r!   r5   s    `r#   __contains__zPlayQueue.__contains__O   s    RtzzRRRr%   c                     | j                   D cg c]
  }||k(  s	| }}t        |      dk(  r|d   S t        |      dkD  rt        | d      t        | d      c c}w )z
        Accepts a media item and returns a similar object from this PlayQueue.
        Useful for looking up playQueueItemIDs using items obtained from the Library.
           r   z< occurs multiple times in this PlayQueue, provide exact itemz not valid for this PlayQueue)r   lenr   )r!   itemr4   matchess       r#   getQueueItemzPlayQueue.getQueueItemS   su    
 #jj6AI166w<11:\A&TU  v%BCDD 7s
   
AANc                 X   t        j                  t        |      |t        j                  t        |      t        j                  t        |      d}|r||d<   d| t        j                  |       }	|j	                  |	|j
                  j                        }
 | ||
|	      }||_        |S )a7  Retrieve an existing :class:`~plexapi.playqueue.PlayQueue` by identifier.

        Parameters:
            server (:class:`~plexapi.server.PlexServer`): Server you are connected to.
            playQueueID (int): Identifier of an existing PlayQueue.
            own (bool, optional): If server should transfer ownership.
            center (int, optional): The playQueueItemID of the center of the window. Does not change selectedItem.
            window (int, optional): Number of items to return from each side of the center item.
            includeBefore (bool, optional):
                Include items before the center, defaults True. Does not include center if False.
            includeAfter (bool, optional):
                Include items after the center, defaults True. Does not include center if False.
        )ownwindowincludeBeforeincludeAftercenter/playQueues/methodinitpath)r   r   r   joinArgsquery_sessionr   _server)clsserverr   r@   rD   rA   rB   rC   argspathr"   cs               r#   r   zPlayQueue.getb   s    2 ::c3'"ZZ];!JJsL9	
 #DNk]5>>$+?*@A||D)<)<|=t,	r%   c	                 `   |||||d}	t        |t              rAdj                  d |D              }
t        d|
       }d| |	d<   |d   j                  |	d<   nr|j
                  d	k(  r|j                  |	d<   |j                  |	d
<   n|j                  |	d<   d|j                   d|j                  j                   |j                   |	d<   |r|j                  |	d<   dt        j                  |	       }|j                  ||j                  j                         } | |||      }||_        |S )ag  Create and return a new :class:`~plexapi.playqueue.PlayQueue`.

        Parameters:
            server (:class:`~plexapi.server.PlexServer`): Server you are connected to.
            items (:class:`~plexapi.base.PlexPartialObject`):
                A media item or a list of media items.
            startItem (:class:`~plexapi.base.Playable`, optional):
                Media item in the PlayQueue where playback should begin.
            shuffle (int, optional): Start the playqueue shuffled.
            repeat (int, optional): Start the playqueue shuffled.
            includeChapters (int, optional): include Chapters.
            includeRelated (int, optional): include Related.
            continuous (int, optional): include additional items after the initial item.
                For a show this would be the next episodes, for a movie it does nothing.
        )includeChaptersincludeRelatedrepeatshuffle
continuous,c              3   F   K   | ]  }t        |j                          y wr'   )str	ratingKey)r3   r4   s     r#   r6   z#PlayQueue.create.<locals>.<genexpr>   s      AaQ[[!1 As   !z/library/metadata/zlibrary:///directory/urir   typeplaylist
playlistID	server:///r)   /playQueuesrF   rH   )
isinstancelistjoinr   listTyper^   playlistTyper\   machineIdentifierlibraryr   r)   r   rJ   rK   rL   postrM   )rN   rO   r   	startItemrW   rV   rT   rU   rX   rP   	item_keysuri_argsrQ   r"   rR   s                  r#   createzPlayQueue.create   s5   8  /,$
 eT" A5 AAI!$6yk"BCH1(<DK 8,,DLzzZ'$11V%*__\"$~~V%f&>&>%?qAZAZ@[\a\e\e[fgDK#--DKU^^D123||D)=)=|>t,	r%   c                     dd|j                    d|j                  j                   | d}dt        j                  |       }|j                  ||j                  j                        } | |||      }||_        |S )a  Create and return a new :class:`~plexapi.playqueue.PlayQueue`.

        This is a convenience method to create a `PlayQueue` for
        radio stations when only the `key` string is available.

        Parameters:
            server (:class:`~plexapi.server.PlexServer`): Server you are connected to.
            key (str): A station key as provided by :func:`~plexapi.library.LibrarySection.hubs()`
                or :func:`~plexapi.audio.Artist.station()`

        Example:

            .. code-block:: python

                from plexapi.playqueue import PlayQueue
                music = server.library.section("Music")
                artist = music.get("Artist Name")
                station = artist.station()
                key = station.key  # "/library/metadata/12855/station/8bd39616-dbdb-459e-b8da-f46d0b170af4?type=10"
                pq = PlayQueue.fromStationKey(server, key)
                client = server.clients()[0]
                client.playMedia(pq)
        audiora   rb   )r^   r]   rc   rF   rH   )	ri   rj   r   r   rJ   rK   rL   rk   rM   )rN   rO   r)   rP   rQ   r"   rR   s          r#   fromStationKeyzPlayQueue.fromStationKey   s    4 v778&..:S:S9TUXTYZ
 U^^D123||D)=)=|>t,	r%   c                    |r| j                          i }|j                  dk(  r|j                  |d<   n/|j                         j                  }d| d|j
                   |d<   |rd|d<   d| j                   t        j                  |       }| j                  j                  || j                  j                  j                  	      }| j                  |       | S )
a  
        Append the provided item to the "Up Next" section of the PlayQueue.
        Items can only be added to the section immediately following the current playing item.

        Parameters:
            item (:class:`~plexapi.base.Playable` or :class:`~plexapi.playlist.Playlist`): Single media item or Playlist.
            playNext (bool, optional): If True, add this item to the front of the "Up Next" section.
                If False, the item will be appended to the end of the "Up Next" section.
                Only has an effect if an item has already been added to the "Up Next" section.
                See https://support.plex.tv/articles/202188298-play-queues/ for more details.
            refresh (bool, optional): Refresh the PlayQueue from the server before updating.
        r_   r`   z
library://z/itemr]   r:   nextrE   rF   )refreshr^   r\   sectionuuidr)   r   r   rJ   rM   rK   rL   putr$   )r!   r<   playNextru   rP   rw   rQ   r"   s           r#   addItemzPlayQueue.addItem   s     LLN99
"!%D<<>&&D&tfE$((<DKDLd../t0D/EF||!!$t||/D/D/H/H!Itr%   c                    i }|r| j                          || vr| j                  |      }|r$|| vr| j                  |      }|j                  |d<   d| j                   d|j                   dt	        j
                  |       }| j                  j                  || j                  j                  j                        }| j                  |       | S )a/  
        Moves an item to the beginning of the PlayQueue.  If `after` is provided,
        the item will be placed immediately after the specified item.

        Parameters:
            item (:class:`~plexapi.base.Playable`): An existing item in the PlayQueue to move.
            afterItemID (:class:`~plexapi.base.Playable`, optional): A different item in the PlayQueue.
                If provided, `item` will be placed in the PlayQueue after this item.
            refresh (bool, optional): Refresh the PlayQueue from the server before updating.
        afterrE   /items/z/moverF   )ru   r>   r2   r   r   rJ   rM   rK   rL   rx   r$   )r!   r<   r|   ru   rP   rQ   r"   s          r#   moveItemzPlayQueue.moveItem  s     LLNt$$T*DD ))%0!11DMd../wt7K7K6LERWR`R`aeRfQgh||!!$t||/D/D/H/H!Itr%   c                 $   |r| j                          || vr| j                  |      }d| j                   d|j                   }| j                  j                  || j                  j                  j                        }| j                  |       | S )zRemove an item from the PlayQueue.

        Parameters:
            item (:class:`~plexapi.base.Playable`): An existing item in the PlayQueue to move.
            refresh (bool, optional): Refresh the PlayQueue from the server before updating.
        rE   r}   rF   )	ru   r>   r   r2   rM   rK   rL   deleter$   )r!   r<   ru   rQ   r"   s        r#   
removeItemzPlayQueue.removeItem!  s     LLNt$$T*Dd../wt7K7K6LM||!!$t||/D/D/K/K!Ltr%   c                     d| j                    d}| j                  j                  || j                  j                  j                        }| j                  |       | S )z$Remove all items from the PlayQueue.rE   z/itemsrF   )r   rM   rK   rL   r   r$   r!   rQ   r"   s      r#   clearzPlayQueue.clear3  sQ    d../v6||!!$t||/D/D/K/K!Ltr%   c                     d| j                    }| j                  j                  || j                  j                  j                        }| j                  |       | S )z+Refresh the PlayQueue from the Plex server.rE   rF   )r   rM   rK   rL   r   r$   r   s      r#   ru   zPlayQueue.refresh:  sO    d../0||!!$t||/D/D/H/H!Itr%   )FN2   TT)Nr   r   r:   r:   r   )FT)NT)T)__name__
__module____qualname____doc__TAGTYPEr$   r*   r-   r/   r8   r>   classmethodr   ro   rr   rz   r~   r   r   ru    r%   r#   r   r   	   s    2 CDC<
(SE 
 $ $L 
 6 6p    D>:$r%   r   N)	urllib.parser   plexapir   plexapi.baser   plexapi.exceptionsr   r   r   r%   r#   <module>r      s    #  # )v
 vr%   