
    g)                         d dl Z d dlmZ d dlZd dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlm	Z	 d d	lm
Z
 d d
lmZ ddZ G d de      Zy)    N)unquote)common)helpers)http_handler)logger)users)
pmsconnect)session)Plexc                 B   | s|st        j                  d       t        j                         t        j
                  j                  t        j
                  j                  t        j
                  j                  t        j
                  j                  t        j
                  j                  t        j
                  j                  t        j
                  j                  t        j
                  j                  t        j
                  j                  t        j
                  j                  d|rS |r)j!                  |       dD ]  }t#        |         |<    d   rd   sd   rd}nd}d	j%                  |d
   d         }t'               }|j)                          |j+                  d   d
   d   d         }|r6|j-                  dg       }	j!                  |       j-                  dd      }
ng }	d}
| r|
S |j/                         }t#        |      d<   d   sud   rp|	rIt1        fd|	D        |	d         }|d   d<   t#        |d   dk(        d<   t        j                  d       d   s?|d<   dd<   t        j2                  d       n|d<   dd<   t        j                  d       |rS t        j                  dd   d   d   d          t        j
                  j5                         t        j
                  j7                          y ) Nz5Tautulli PlexTV :: Requesting resources for server...)pms_namepms_versionpms_platformpms_ippms_portpms_sslpms_is_cloudpms_urlpms_url_manualpms_identifierpms_plexpass)r   r   r   r   r   r   httpshttpz{scheme}://{hostname}:{port}r   r   )schemehostnameportr   )r   r   r   include_httpsconnectionspms_presencer   r   c              3   d   K   | ]'  }|d    d   k(  s|d   t        d         k(  s$| ) yw)addressr   r   r   N)str).0cservers     /opt/Tautulli/plexpy/plextv.py	<genexpr>z'get_server_resources.<locals>.<genexpr>\   s<     uq1Y<6(;K+KPQRXPY]`aghras]tPtus   000urir   local0pms_is_remotez(Tautulli PlexTV :: Server URL retrieved.zXTautulli PlexTV :: Unable to retrieve server URLs. Using user-defined value without SSL.z*Tautulli PlexTV :: Using user-defined URL.z=Tautulli PlexTV :: Selected server: %s (%s) (%s - Version %s)r   r   r   )r   infor   r   plexpyCONFIGPMS_VERSIONPMS_PLATFORMPMS_IPPMS_PORTPMS_SSLPMS_IS_CLOUDPMS_URLPMS_URL_MANUALPMS_IDENTIFIERPMS_PLEXPASSupdateintformatPlexTVpingget_server_connectionspopget_plexpass_statusnextwarnprocess_kwargswrite)return_presencereturn_serverreturn_infokwargskr   fallback_urlplex_tvresultr   presenceplexpass
connectionr%   s                @r&   get_server_resourcesrP       s   ;KL!**,#]]66$mm88,, --00..$mm88.. & < < & < <$mm88F f> 	'AF1IF1I	' F9$59O188BHBR>DZ>P 9 RL hGLLN++6BR;S39(3C5;J5G:@:K , MF
 jj3f::na0**,H ]F> "#y(9uKuAJ !+5 1F9&)*W*=*D&EF?#KKBC i  ,F9&'F?#KKrs )y"#@A
KKOz"F9$5vn7MvVcOdf MM  (
MM    c                      e Zd ZdZd$dZd Zd%dZd&dZd&dZd&dZ	d&d	Z
d&d
Zd%dZd%dZd'dZd(dZd%dZd%dZd%dZd&dZd&dZd%dZd&dZd Z	 	 d)dZd Zd*dZd Zd+dZd Zd Zd Zd Z d  Z!d! Z"d&d"Z#d# Z$y),r<   z 
    Plex.tv authentication
    Nc                    || _         || _        || _        d| _        t        j
                  j                  | _        t        j
                  j                  | _	        | j                   | j                  | j                  svt        j                         rCt        j                         }|j                  t        j                               }|d   | _        nt        j
                  j                  | _        | j                  st!        j"                  d       t%        j&                  | j                  | j                  | j                  | j                  |      | _        y )Nzhttps://plex.tvuser_idserver_tokenz8Tautulli PlexTV :: PlexTV called, but no token provided.)urlstokentimeout
ssl_verifyheaders)usernamepasswordrX   rW   r-   r.   PMS_TIMEOUTrY   VERIFY_SSL_CERTrZ   r
   get_session_user_idr   Users
get_tokens	PMS_TOKENr   errorr   HTTPHandlerrequest_handler)selfr\   r]   rX   r[   	user_datauser_tokenss          r&   __init__zPlexTV.__init__~   s      
%	}}00 --77== T]]%:::..0 %I"+"6"6w?Z?Z?\"6"]K!,^!<DJ!'!8!8DJ::WX+77TYY>Bjj@DCG??@G	 IrQ   c                    | j                  d      }d}	 |j                  d      }|D ]e  }t        j                  |d      t        j                  j                  k(  s5dt        j                  |d      v sNt        j                  |d	      } |S  |S # t        $ r"}t        j                  d|z         Y d }~y d }~ww xY w)
Nxmloutput_format Devicez@Tautulli PlexTV :: Unable to parse XML for get_server_token: %s.clientIdentifierr%   providesaccessToken)
get_plextv_resourcesgetElementsByTagName	Exceptionr   rB   r   get_xml_attrr-   r.   r7   )rg   serversrV   xml_headeas         r&   get_server_tokenzPlexTV.get_server_token   s    ++%+@	33H=H
  	A##A'9:fmm>Z>ZZ G$8$8J$GG&33A}E	   	KKZ]^^_	s   B 	B>B99B>c                     |r&d|z   }| j                   j                  |d|d      }|S d}| j                   j                  |d|d      }|S )Nz/api/v2/pins/GETT)r(   request_typern   no_tokenz/api/v2/pins?strong=truePOSTrf   make_request)rg   pinrn   r(   requests        r&   get_plextv_pinzPlexTV.get_plextv_pin   sr    !C'C**77CEJFSAE 8 GG  -C**77CEKFSAE 8 GG rQ   c                 Z   | j                  |d      }|rh	 |j                  d      }|r>|d   j                  d      |d   j                  d      |d   j                  d      d}|S t        j                  d	       y y # t
        $ r"}t        j                  d
|z         Y d }~y d }~ww xY w)Nrl   )r   rn   r   r   idcode	authToken)r   r   rX   z9Tautulli PlexTV :: Could not get Plex authentication pin.z7Tautulli PlexTV :: Unable to parse XML for get_pin: %s.)r   ru   getAttributer   rB   rv   )rg   r   plextv_responsery   rz   s        r&   get_pinzPlexTV.get_pin   s    --#<A . C *??F!)!!9!9$!?#+A;#;#;F#C$,QK$<$<[$IC JKK [\   UXYYZs   AA? (A? ?	B*B%%B*c                 F    d}| j                   j                  |d|      }|S )Nz
/api/usersr~   r(   r   rn   r   rg   rn   r(   r   s       r&   get_plextv_friendszPlexTV.get_plextv_friends   s2    &&33AFBO 4 Q rQ   c                 F    d}| j                   j                  |d|      }|S )Nz/users/accountr~   r   r   r   s       r&   get_plextv_user_detailszPlexTV.get_plextv_user_details   s2    &&33AFBO 4 Q rQ   c                 F    d}| j                   j                  |d|      }|S )Nz/devices.xmlr~   r   r   r   s       r&   get_plextv_devices_listzPlexTV.get_plextv_devices_list   s2    &&33AFBO 4 Q rQ   c                 F    d}| j                   j                  |d|      }|S )Nz/pms/servers.xmlr~   r   r   r   s       r&   get_plextv_server_listzPlexTV.get_plextv_server_list   s2     &&33AFBO 4 Q rQ   c                 L    d|z  }| j                   j                  |d|      }|S )Nz/api/servers/%s/shared_serversr~   r   r   rg   
machine_idrn   r(   r   s        r&   get_plextv_shared_serversz PlexTV.get_plextv_shared_servers   s7    .;&&33AFBO 4 Q rQ   c                 L    d|z  }| j                   j                  |d|      }|S )Nz/servers/%s/sync_listsr~   r   r   r   s        r&   get_plextv_sync_listszPlexTV.get_plextv_sync_lists   s7    &3&&33AFBO 4 Q rQ   c                 R    |rd}nd}| j                   j                  |d||      }|S )Nz/api/resources?includeHttps=1z/api/resourcesr~   )r(   r   return_responsern   r   )rg   r   r   rn   r(   r   s         r&   rt   zPlexTV.get_plextv_resources  s=    1C"C&&33AFDSBO 4 Q
 rQ   c                 P    |rd}nd}| j                   j                  |d|      }|S )Nz&/api/downloads/5.json?channel=plexpassz/api/downloads/1.jsonr~   r   r   )rg   rN   rn   r(   r   s        r&   get_plextv_downloadszPlexTV.get_plextv_downloads  s:    :C)C&&33AFBO 4 Q rQ   c                 L    d|z  }| j                   j                  |d|      }|S )Nz/devices/%s.xmlDELETEr   r   )rg   	device_idrn   r(   r   s        r&   delete_plextv_devicezPlexTV.delete_plextv_device  s7    )+&&33AIBO 4 Q rQ   c                 L    d|z  }| j                   j                  |d|      }|S )Nz/devices/%s/sync_itemsr~   r   r   )rg   	client_idrn   r(   r   s        r&   delete_plextv_device_sync_listsz&PlexTV.delete_plextv_device_sync_lists"  s7    &2&&33AFBO 4 Q rQ   c                 R    d|d|}| j                   j                  |dd      }|S )Nz	/devices/z/sync_items/r   T)r(   r   r   r   )rg   r   sync_idr(   r   s        r&   delete_plextv_synczPlexTV.delete_plextv_sync*  s7    -6@&&33AIDH 4 J rQ   c                 F    d}| j                   j                  |d|      }|S )Nz/api/v2/cloud_serverr~   r   r   r   s       r&   cloud_server_statuszPlexTV.cloud_server_status2  s2    $&&33AFBO 4 Q rQ   c                 F    d}| j                   j                  |d|      }|S )Nz/:/ipr~   r   r   r   s       r&   get_public_ipzPlexTV.get_public_ip:  s2    &&33AFBO 4 Q rQ   c                 L    d|z  }| j                   j                  |d|      }|S )Nz/api/v2/geoip?ip_address=%sr~   r   r   )rg   
ip_addressrn   r(   r   s        r&   get_plextv_geoipzPlexTV.get_plextv_geoipB  s7    +j8&&33AFBO 4 Q rQ   c                 F    d}| j                   j                  |d|      }|S )Nz/api/v2/pingr~   r   r   r   s       r&   ping_plextvzPlexTV.ping_plextvJ  s2    &&33AFBO 4 Q rQ   c                    | j                  d      }| j                  d      }| j                  t        j                  j
                  d      }g }	 |j                  d      }|D ]e  }i dt        j                  |d      dt        j                  |d      d	t        j                  |d	      d
t        j                  |d
      dt        j                  |d      dddddt        j                  |d      dddt        j                  |d      dt        j                  |d      dt        j                  |d      dt        j                  |d      dt        j                  |d      dt        j                  |d      dt        j                  |d      d t        j                  |d      d!d i}|j                  |       h 	 |j                  d"      }|D ]*  }t        j                  |d      t        j                  |d      t        j                  |d	      t        j                  |d
      t        j                  |d      dd$t        j                  |d      t        j                  |d%      t        j                  |d      t        j                  |d      t        j                  |d      t        j                  |d      t        j                  |d      t        j                  |d      d&}	|j                  |	       - 	 |j                  d'      }i }
|D ]  }t        j                  |d)      }t        j                  |d*      }|j                  d+      }|D cg c]1  }t        j                  |d,      d-k(  rt        j                  |d.      3 }}||d/|
|<    |D ](  }|
j                  |d   i       }|j                  |       * |S # t        $ r$}t        j                  d|z         g cY d }~S d }~ww xY w# t        $ r$}t        j                  d#|z         g cY d }~S d }~ww xY w# t        $ r$}t        j                  d(|z         g cY d }~S d }~ww xY wc c}w )0Nrl   rm   )r   rn   userzOTautulli PlexTV :: Unable to parse own account XML for get_full_users_list: %s.rU   r   r\   titlethumbemail	is_active   is_adminis_home_userhomeis_allow_syncis_restricted
restricted
filter_all	filterAllfilter_moviesfilterMovies	filter_tvfilterTelevisionfilter_musicfilterMusicfilter_photosfilterPhotos
user_tokenr   rV   shared_librariesUserzPTautulli PlexTV :: Unable to parse friends list XML for get_full_users_list: %s.r   	allowSync)rU   r\   r   r   r   r   r   r   r   r   r   r   r   r   r   SharedServerzVTautulli PlexTV :: Unable to parse shared server list XML for get_full_users_list: %s.userIDrs   Sectionshared1key)rV   r   )r   r   r   r-   r.   r7   ru   rv   r   rB   r   rw   appendgetr9   )rg   own_accountfriends_listshared_servers
users_listry   rz   r{   own_detailsfrienduser_maprU   rV   sectionssr   uds                     r&   get_full_users_listzPlexTV.get_full_users_listQ  s   222G..U.C776==C_C_FK 8 M 
	"77?H
  	+A9g&:&:1d&C %w';';Az'J"G$8$8G$D #G$8$8G$D #G$8$8G$D	
 ' &q *7+?+?6+J +A +G,@,@L,Q ()=)=a)M +G,@,@N,S '(<(<Q@R(S *7+?+?=+Q +G,@,@N,S ()=)=a)M  *7+?+?;+O!" .t#K( k*+	+.	#88@H
  	&A!(!5!5a!>")"6"6q*"E&33Aw?&33Aw?&33Aw?#$"#&-&:&:1f&E'.';';A{'K'.';';A|'L$+$8$8K$H'.';';A~'N#*#7#7;M#N&-&:&:1m&L'.';';A~'NF" f%%	&(	%::>JH
  		GA**1h7G"//=AL--i8H)1 _$%W5I5I!X5VZ]5] !( 4 4Q >  _  _ 2>5E!GHW		G  	AQy\2.AHHQK	 W  	KKilmmnI	:  	KKjmnnoI	4  	KKpsttuI	 _s`   O P P< +6Q,	P	%P>P	P		P9P4.P94P9<	Q)Q$Q)$Q)c                    |st         j                  j                  }t        |t              r|D cg c]  }t        |       }}n|rt        |      g}t        |t              r|D cg c]  }t        |       }}n|rt        |      g}| j                  |d      }t        j                         }g }		 |j                  d      }
|
D ]7  }t        j                  |d      }|rt        |      |k7  r+t        j                  |d      }|j                  d      }|D ]  }t        j                  |d      }	 |j                  |	      d
   }|j                  |	      d   }t        j                  |d      }t        j                  |d      }t        j                  |d      }t        j                  |d      }t        j                  |d      }t        j                  |d      }t        j                  |d      }t        j                  |d      } |r|vrR|j                  d      D ]  }|j                  d      }|D ]  }d }d } |j                  d      D ]  }!t!        t        j                  |!d            }"|"j#                  d      r;d|"v rd}|"j%                  d      }#t'        d t)        |#d d |#dd        D        d       } o|"j#                  d      sd }t        j                         j+                  	      }$|$d!   st-        |$d!   "      }%|%j.                  j1                         D ]3  }&|"j3                  |&j4                        st        |&j6                        } 5  |r| |vr0t        j                  |d      }'|rt        |      |'k7  rXt        j                  |d#      }(t        j                  |d$      })t        j                  |d%      }*t        j                  |d&      }+t        j                  |d'      },|j                  d(      D ]  }-t        j                  |-d)      }.t        j                  |-d*      }/t        j                  |-d+      }0t        j                  |-d,      }1t        j                  |-d-      }2t        j                  |-d.      }3t        j                  |-d/      }4t        j                  |-d0      }5t        j                  |-d1      }6t        j8                  |3|1      }7 |j                  d2      D ]  }8t        j                  |8d3      }9t        j                  |8d4      }:t        j                  |8d5      };t        j                  |8d6      }<t        j                  |8d7      }=t        j                  |8d8      }>t        j                  |8d9      }? i d:dd;d<d
d=|)d>|*d?|+d@|,dA| d+0dB1dC2dD3dE7dF9dG=>:6/||'|dH}@|	j;                  |@         : t=        j>                  |	d;I      S c c}w c c}w # t        $ r$}t        j                  d|z         i cY d }~S d }~ww xY w#  d}d}Y xY w)JNrl   rm   SyncListz@Tautulli PlexTV :: Unable to parse XML for get_synced_items: %s.rq   r   rp   r   rT   r\   friendly_namero   nameproductproductVersionplatformplatformVersiondevicemodel
lastSeenAt	SyncItemsSyncItemLocationr(   z
library://
collection/c              3   .   K   | ]  \  }}|d v r|  yw))metadatacollectionsN )r#   ijs      r&   r'   z*PlexTV.get_synced_items.<locals>.<genexpr>  s&      /STQ126Q1Q 01 /Ss   r   zplaylist://playlistrV   )rX   version	rootTitler   metadataTypecontentTypeStatusfailureCodefailurestate
itemsCountitemsCompleteCountitemsDownloadedCountitemsReadyCountitemsSuccessfulCount	totalSizeMediaSettingsmaxVideoBitratevideoQualityvideoResolution
audioBoostmusicBitratephotoQualityphotoResolutiondevice_namerU   r   
root_title
sync_titlemetadata_typecontent_type
rating_key
item_countitem_complete_countitem_downloaded_count item_downloaded_percent_completevideo_bitrateaudio_bitrate)photo_qualityvideo_quality
total_sizer  r   r   sync_media_type)
filter_key) r-   r.   r7   
isinstancelistr"   r   r   ra   ru   rv   r   rB   r   rw   get_detailsr   
startswithsplitrA   ziprb   r   
PlexServer	playlistsendswithguid	ratingKeyget_percentr   r
   filter_session_info)Arg   r   client_id_filteruser_id_filterrating_key_filtersync_id_filterrI   	sync_listrh   synced_itemsry   rz   r{   r   sync_list_idsync_devicer   device_user_iddevice_usernamedevice_friendly_namer  device_productdevice_product_versiondevice_platformdevice_platform_versiondevice_typedevice_modeldevice_last_seensynced	sync_itemitemr!  r  locationlocation_uri	clean_uritokensplexr   r   sync_versionsync_root_titler  sync_metadata_typesync_content_typestatusstatus_failure_codestatus_failurestatus_statestatus_item_countstatus_item_complete_countstatus_item_downloaded_countstatus_item_ready_countstatus_item_successful_countstatus_total_size%status_item_download_percent_completesettingssettings_video_bitratesettings_video_qualitysettings_video_resolutionsettings_audio_boostsettings_audio_bitratesettings_photo_qualitysettings_photo_resolutionsync_detailssA                                                                    r&   get_synced_itemszPlexTV.get_synced_items  s    55J'.1B CAQ C C!$%6!7 8nd+.<=c!f=N=!.12N..z.O	KKM		 55jAH
  x	6A,,Q0BCI  C(8$9Y$F"//48L00:K% N!(!5!5fh!G.&/&;&;N&;&ST^&_O+4+@+@+@+XYh+i( &2266B!(!5!5fi!H)0)=)=fFV)W&")"6"6vz"J*1*>*>vGX*Y'%2268D&33FGD#*#7#7#M N$ ."F00= Y6"77
C	% W6D&*O!%J$($=$=j$I M'.w/C/CHe/T'U'22<@+|;2>(4(:(:3(?I)- /SS3BQZ[\[]Q^=_ /STX*ZJ *44]C.8O%*[[]%=%=n%=%UF%n5'+&2H'I040I0I0K !MH'3'<'<X]]'K589K9K5L
!MM( )Z?P-P %224>G &#n*=*H #*#7#7i#HL&-&:&:4&MO!(!5!5dG!DJ)0)=)=dN)S&(/(<(<T=(Q%"&";";H"E M.5.B.B6=.Y+)0)=)=fi)P'.';';FG'L,3,@,@,V)5<5I5I&Rf5g27>7K7KFTj7k4292F2FvO`2a/7>7K7KFTj7k4,3,@,@,U)@G@S@S8:KAM=M %)$=$=o$N f181E1EhPa1b.181E1EhP^1_.4;4H4HSd4e1/6/C/CHl/[,181E1EhP^1_.181E1EhP^1_.4;4H4HSd4e1f$&M; $&$.$&$-~$& %+,@$& %/	$&
 %1/$& %1*$& %45G$& %34E$& %1*$& %,\$& %12C$& %:;U$& %<=Y$& %GHm$& %45K$&  %45K!$&" 6L5K2C/=1:/67F/$&L4 !''5oW6Y6?x	6t **<INN] !D
 >  	KKZ]^^_I	&.&(O+-(s5   X(X5X$ 6*Y$	Y-YYYYc                 p    t        j                  d|z         | j                  ||      }|j                  S )Nz+Tautulli PlexTV :: Deleting sync item '%s'.)r   r   )r   r,   r   ok)rg   r   r   responses       r&   delete_synczPlexTV.delete_sync?  s3    AGKL**Y*P{{rQ   c                 j   |st        j                  d       i S | j                  |d      }	 |j                  d      }d }i }	|D ]%  }
t        j                  |
d      |k(  s ||
      }	 n |	s|D ]  }
t        j                  |
d      d	k(  s|
j                  d
      }|D ]H  }t        j                  |d      |k(  st        j                  |d      t        |      k(  s@ ||
      }	 n |	j                  d      s |	S  |	S # t        $ r$}t        j
                  d|z         i cY d }~S d }~ww xY w)NzUTautulli PlexTV :: Unable to retrieve server connections: no pms_identifier provided.rl   r   rn   rp   z?Tautulli PlexTV :: Unable to parse XML for get_server_urls: %s.c           	      N   g }| j                  d      }t        j                  | d      t        j                  | d      t        j                  | d      t        j                  | d      t        j                  | d      t        j                  | d      dk(  rdnd	d
}|D ]  }t        j                  |d      t        j                  |d      t        j                  |d      t        j                  |d      t        j                  |d      d}|j                  |        ||d<   |S )N
Connectionrq   r   r   r   rM   Cloudr   r   )r   r   r   r   r   r   protocolr!   r   r(   r)   )rl  r!   r   r(   r)   r   )ru   r   rw   r   )r   connr   r%   r$   server_detailss         r&   get_connectionsz6PlexTV.get_server_connections.<locals>.get_connectionsS  s   D 55lCK(/(<(<VEW(X")"6"6vv"F%,%9%9&BR%S&-&:&:6:&N&-&:&:6:&N+2+?+?
+SW^+^adeF ! ,.5.B.B1j.Q-4-A-A!Y-O*1*>*>q&*I)0)=)=a)G+2+?+?7+K	"$ N+, %)F=!MrQ   rq   rr   r%   rj  r!   r   r   )
r   rd   rt   ru   rv   rB   r   rw   r"   r   )rg   r   r   r   r   plextv_resourcesry   rz   ro  r%   r{   r   rO   s                r&   r>   zPlexTV.get_server_connectionsD  sT   LLpqI44=CH 5 J	'<<XFH	0   	A##A'9:nL(+	  '':6(B"#"8"8"FK&1 "
"//
IF&P ' 4 4Z HCPXM Y%4Q%7F!	" zz-0 k  	KKY\]]^I	s   D 	D2D-'D2-D2c                    | j                  d      }i }	 |j                  d      }|D ]x  }t        j                  |d      t        j                  j                  k(  s5t        j                  |d      t        j                  |d      t        j                  |d      d	} |S  |S # t        $ r$}t        j                  d|z         i cY d }~S d }~ww xY w)
Nrl   rm   Serverz@Tautulli PlexTV :: Unable to parse XML for get_server_times: %s.machineIdentifier	createdAt	updatedAtr   )
created_at
updated_atr   )
r   ru   rv   r   rB   r   rw   r-   r.   r7   )rg   rx   server_timesry   rz   r{   s         r&   get_server_timeszPlexTV.get_server_times  s    --E-B	33H=H
  	A##A':;v}}?[?[[.5.B.B1k.R.5.B.B1k.R+2+?+?9+M " 	   	KKZ]^^_I	s   B& &	C/CCCc                    d}t        j                  dddd      }|j                  ddd	
      }|r%|j                  d      d   }|j	                  d      }d|dddddddd	}| j                  dd	      }g }		 |j                  d      }|D ]  }|j	                  d      r|j	                  d      dk(  rg c S |j                  d      rO|j                  d      }|D ]8  }t        j                  |d      dk(  st        j                  |d      dk(  s8t        j                  |d      dk(  sRt        j                  |d      j                         dk(  }|s|r~|j                  d      }|D ]  }|sft        j                  |d       dk(  rt        j                  |d!      dk(  r9t        j                  |d       dk(  rt        j                  |d!      dk(  rlt        j                  |d"      |k(  rEt        j                  |d#      |d#<   t        j                  |d$      |d%<   |	j                  |       d}|rdnt        j                  |d#      t        j                  |d"      t        j                  |d$      t        j                  |d&      t        j                  |d'      t        j                  |d(      t        j                  |d!      t        j                  |d&      d)z   t        j                  |d'      z   |d	}|	j                  |        ; |s|	j                  |        |	j                  d* +       |	S # t        $ r$}
t        j                  d|
z         g cY d}
~
S d}
~
ww xY w),zS Query plex for all servers online. Returns the ones you own in a selectize format Nzhttp://127.0.0.1:32400r   FT)rW   rY   rZ   silentz	/identityr~   rl   r   MediaContainerr   rs  r*   Localz	127.0.0.132400r   z127.0.0.1:32400)	httpsRequiredrq   labelipr   r(   r)   valueis_cloudrh  z7Tautulli PlexTV :: Failed to get servers from plex: %s.sizerp   rM   ownedrr   r%   r   cloudrj  publicAddressMatchesr)   rq   r  r   r  r!   r   r(   :c                 2    | d   t        | d          | d   fS )Nr  r)   r  )r:   )r   s    r&   <lambda>z!PlexTV.discover.<locals>.<lambda>  s     !G*s1W:6F$)P rQ   )r   )r   re   r   ru   r   rt   rv   r   rB   r   rw   lowerr   sort)rg   include_cloudall_serverslocal_machine_identifierrf   r   ry   local_serverrx   clean_serversrz   r{   devicesr   r  r   r$   r%   s                     r&   discoverzPlexTV.discover  sz    $( &228PZ[>CDR!..;Ubg.h334DEaHH'/'<'<=P'Q$),,D!() '7!$!2$)	 ++$e+T	334DEH
  2	3A~~f%>>&)S0I%%h/00:  '9A++Az:cA#00G<C#00J?8K$+$8$8J$G$M$M$OSZ$Z,$&'&<&<\&J!, 9A#.#*#7#7;Q#RVY#Y(/(<(<Q(HC(O$, $+#7#7;Q#RVY#Y(/(<(<Q(HC(O$,&33A7IJNff@G@T@TUVXg@h_ =8?8L8LQPV8WW 5 - 4 4\ B;? 8>FsGL`L`abdsLt:A:N:NqRd:e/6/C/CAv/N,3,@,@I,N.5.B.B1f.M-4-A-A!U-K/6/C/CAw/O/6/C/CAy/QTW/WZaZnZnoprxZy/y2:	&(F *00899'9R ($$\2e2	3h 	PQu  	KKQTUUVI	s   9M 	M4M/)M4/M4c                     | j                  |dk(        }	 t        j                  |      S # t        $ r"}t	        j
                  d|       i cY d }~S d }~ww xY w)Nbeta)rN   z?Tautulli PlexTV :: Unable to load JSON for get_plex_updates: %s)r   jsonloadsrv   r   rB   )rg   update_channelplex_downloadsrz   s       r&   get_plex_downloadszPlexTV.get_plex_downloads  sS    22^v=U2W	::n-- 	KKY[\]I	s   , 	AAAAc                 Z   t        j                  d       t        j                         }|j	                          |j                         }t        j                  d|z         | j                  |      }|si S t        j                  j                  t        j                  j                  t        j                  j                        }|j                  d      j                  |      xs  |j                  d      j                  |      }|st        j                  d|z         i S t        j                  dj!                  d t        j                  j"                  j%                  d	      d
   j%                  d      d d D                    }t        j                  dj!                  d |j                  dd      j%                  d	      d
   j%                  d      d d D                    }|s2t        j                  dt        j                  j"                  z         i S |s)t        j                  d|j                  d      z         i S |j                  di g      }t'        d |D        |d
         }	||kD  |j                  d      |j                  d      |j                  d      |j                  d      |j                  d      |j                  d      |j                  d      |	j                  d      |	j                  d      |	j                  d      |	j                  d      d}
|
S )Nz5Tautulli PlexTV :: Retrieving current server version.z-Tautulli PlexTV :: Plex update channel is %s.)r  computernaszXTautulli PlexTV :: Unable to retrieve Plex updates: Could not match server platform: %s.ro   c              3   >   K   | ]  }|j                  d         yw   Nzfillr#   vs     r&   r'   z)PlexTV.get_plex_update.<locals>.<genexpr>  s     +w1AGGAJ+w   -r   .r  c              3   >   K   | ]  }|j                  d         ywr  r  r  s     r&   r'   z)PlexTV.get_plex_update.<locals>.<genexpr>  s       ,D1AGGAJ  ,Dr  r   zWTautulli PlexTV :: Unable to retrieve Plex updates: Invalid current server version: %s.zSTautulli PlexTV :: Unable to retrieve Plex updates: Invalid new server version: %s.releasesc              3      K   | ]G  }|d    t         j                  j                  k(  s$|d   t         j                  j                  k(  r| I yw)distrobuildN)r-   r.   PMS_UPDATE_DISTROPMS_UPDATE_DISTRO_BUILD)r#   rs     r&   r'   z)PlexTV.get_plex_update.<locals>.<genexpr>   sD      Maq{fmm>]>]/]'
fmm&K&KK  Ms
   %A'Ar   release_daterequirements
extra_infoitems_addeditems_fixedr  r  r  url)update_availabler   r  r   r  r  changelog_addedchangelog_fixedr  r  distro_builddownload_url)r   debugr	   
PmsConnectset_server_versionget_server_update_channelr  r   PMS_PLATFORM_NAME_OVERRIDESr   r-   r.   r0   rd   r   cast_to_intjoinr/   r'  rA   )rg   pms_connectr  available_downloadsr   platform_downloadsv_oldv_newr  releasedownload_infos              r&   get_plex_updatezPlexTV.get_plex_update  s   LM ++-&&($>>@D~UV"55^5T"I 99==fmm>X>XZ`ZgZgZtZtu044Z@DD\R =##E*..|< 	 "LLs'( )I##BGG+w@Y@Y@_@_`c@def@g@m@mnq@rsutu@v+w$wx##BGG  ,D@R@V@VW`bd@e@k@klo@pqr@s@y@yz}@~  @B  AB  AC  ,D  %D  ELLr!==445 6ILLn-11)<= >I &))*rd; M8 MNVWXk[ .3U]%7%;%;F%C);)?)?)O$6$:$:9$E);)?)?)O'9'='=l'K,>,B,B=,Q,>,B,B=,Q")++g"6#*;;x#8)0W)=)0U); rQ   c                    | j                  d      }	 |j                  d      }|r[t        j                  |d   d      dk(  r?t        j                  j                  d	d
       t        j                  j                          yt        j                  d       t        j                  j                  d	d       t        j                  j                          y# t        $ r"}t        j                  d|z         Y d }~yd }~ww xY w)Nrl   rm   subscriptionzCTautulli PlexTV :: Unable to parse XML for get_plexpass_status: %s.Fr   activer   r8   r   Tz4Tautulli PlexTV :: Plex Pass subscription not found.)r   ru   rv   r   rB   r   rw   r-   r.   __setattr__rD   r  )rg   account_datar  rz   s       r&   r@   zPlexTV.get_plexpass_status3  s    33%3H	'<<^LL
 G00a(KsRMM%%na8MM!LLOPMM%%na8MM!  	KK]`aab	s   C 	DC<<Dc                    | j                  d      }	 |j                  d      }g }|D ]  }t        j                  |d      t        j                  |d      t        j                  |d      t        j                  |d      t        j                  |d	      t        j                  |d
      t        j                  |d      t        j                  |d      t        j                  |d      t        j                  |d      t        j                  |d      t        j                  |d      d}|j                  |        |S # t        $ r$}t        j                  d|z         g cY d }~S d }~ww xY w)Nrl   rm   rp   z@Tautulli PlexTV :: Unable to parse XML for get_devices_list: %s.r   r   r   r   r   r   r   vendorrr   rq   r   rX   )r  r   product_versionr   platform_versionr   r   r  rr   device_identifierr   rX   )r   ru   rv   r   rB   r   rw   r   )rg   r  ry   rz   devices_listr{   r   s          r&   get_devices_listzPlexTV.get_devices_listF  sL   ..U.C	33H=H
  	(A%,%9%9!V%D!(!5!5a!C)0)=)=aAQ)R")"6"6q*"E*1*>*>qBS*T ' 4 4Q A&33Aw? ' 4 4Q A")"6"6q*"E+2+?+?CU+V#*#7#74#@&33Aw?F '	(  +  	KKZ]^^_I	s   E 	E/E*$E/*E/c                    | j                  d      }	 |j                  d      }|D ]j  }|j                  d      }|D ]R  }t        j                  |d      t        j                  j                  k(  s5t        j                  |d      d	k(  r  y
  y l y # t        $ r"}t        j                  d|z         Y d }~yd }~ww xY w)Nrl   rm   r,   zGTautulli PlexTV :: Unable to parse XML for get_cloud_server_status: %s.Fr%   r!   runningr   T)
r   ru   rv   r   rB   r   rw   r-   r.   r1   )rg   cloud_statusstatus_inforz   r,   rx   r   s          r&   get_cloud_server_statuszPlexTV.get_cloud_server_statusb  s    //e/D	&;;FCK
   	%D//9G %''959M9MM++D)<C#$%	%	  	KKadeef	s   B 	C B;;C c                    | j                  d      }	 |j                  d      }|D ]  }t        j                  |d      t        j                  |d      t        j                  |d      t        j                  |d      t        j                  |d	      t        j                  |d
      t        j                  |d      t        j                  |d      t        j                  |d      t        j                  |d      t        j                  |d      t        j                  |d      d}|c S  y # t        $ r"}t        j                  d|z         Y d }~y d }~ww xY w)Nrl   rm   r   zHTautulli PlexTV :: Unable to parse XML for get_plex_account_details: %s.r   r\   r   r   r   r   r   r   r   r   r   r   )rU   r\   r   r   r   r   r   r   r   r   r   r   )r   ru   rv   r   rB   r   rw   )rg   r  ry   rz   r{   account_detailss         r&   get_plex_account_detailszPlexTV.get_plex_account_detailst  s3   33%3H	#88@H
  	#A*1*>*>q$*G+2+?+?:+N(/(<(<Q(H(/(<(<Q(H/6/C/CAv/N070D0DQ0U-4-A-A![-Q070D0DQ0W,3,@,@DV,W/6/C/CA}/U070D0DQ0W-4-A-A![-Q!O #"	#	  	KKbeffg	s   D0 0	E9EEc                    |rt        j                  |      sy | j                  |d      }	 |j                  d      }|D ]  }t        j                  |d      j                  d      }d x}}t        |      dk(  r&|D 	cg c]  }	t        j                  |	       c}	\  }}t        j                  |d      xs d t        j                  |d	      xs d t        j                  |d
      xs d t        j                  |d      xs d ||t        j                  |d      xs d t        j                  |d      xs d t        j                  |d      xs d d d
}
|
c S  y # t        $ r"}t        j                  d|z         Y d }~y d }~ww xY wc c}	w )Nrl   )r   rn   rE  z@Tautulli PlexTV :: Unable to parse XML for get_geoip_lookup: %s.coordinates,   cityr   continent_codecountrypostal_codesubdivisions	time_zone)
r  r   	continentr  latitude	longituder  regiontimezoneaccuracy)r   is_valid_ipr   ru   rv   r   rB   rw   r'  lencast_to_float)rg   r   
geoip_datary   rz   r{   r  r  r  r$   geo_infos              r&   get_geoip_lookupzPlexTV.get_geoip_lookup  s   !4!4Z!@**jPU*V
	!66zBH
  	A!..q-@FFsKK#''Hy;1$IT&UAw'<'<Q'?&U#) ' 4 4Q ? G4 ' 4 4Q ? G4%,%9%9!=M%N%VRV#*#7#79#E#M$,%.'.';';A}'M'UQU")"6"6q."I"QT$+$8$8K$H$PD$(
H O%		  	KK[^__`	 'Vs   E ?F
	F%FFc                 .   t        j                  d       | j                  d      }	 |j                  d      }|r,t        j                  |d   j                  j                        S y# t        $ r"}t        j
                  d|z         Y d }~y d }~ww xY w)Nz4Tautulli PlexTV :: Pinging Plex.tv to refresh token.rl   rm   pongz4Tautulli PlexTV :: Unable to parse XML for ping: %s.r   F)
r   r,   r   ru   rv   rB   r   	bool_true
firstChild	nodeValue)rg   r  ry   rz   s       r&   r=   zPlexTV.ping  s    KLe4	008H
 $$Xa[%;%;%E%EFF  	KKORSST	s   A) )	B2BB)NNNN)ro   ro   )ro   )FFro   )Fro   )NNNNN)ro   ro   i~  T)TF)%__name__
__module____qualname____doc__rj   r|   r   r   r   r   r   r   r   r   rt   r   r   r   r   r   r   r   r   r   rb  rf  r>   ry  r  r  r  r@   r  r  r  r  r=   r   rQ   r&   r<   r<   y   s    I8$0
	Un W[@DUOn
?B(Vp7r&8%$#2@rQ   r<   )FFF)r  urllib.parser   r-   r   r   r   r   r   r	   r
   plexpy.plexr   rP   objectr<   r   rQ   r&   <module>r      s=   $            VrAV ArQ   