
    gv                     `   d dl Z d dl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mZmZ d dlmZmZ d dlmZ d d	lmZmZ d d
lmZmZmZ d dlZd dlZd dlZd dlmZ d dlZd dl Z d dl!Z!d dl"Z"d dl#Z#d dl$Z$d dl%Z%d dl&Z&d dl'Z'd dl(Z(d dl)Z)d dl*m+Z+ d dl,m-Z- d dl.Z.d dl/Z/d dl/m0Z0 d dl/m1Z1 d dl/m2Z2 d dl3m4Z4 d Z5d Z6d Z7ddZ8d Z9d Z:d Z;d Z<d Z=d Z>d Z?d Z@d ZAddZBd  ZCdd!ZDd" ZEd# ZFd$ ZGdd%ZHdd&ZId' ZJd( ZKd) ZLd* ZMd+ ZNdd,ZOdd-ZPd. ZQd/ ZRdd0ZSdd1ZTd2 ZUd3 ZVdd4ZWd5 ZXd6 ZYd7 ZZd8 Z[d9 Z\dd:Z]d; Z^d< Z_d= Z`d> Zadd?Zbdd@ZcdA ZdddBZedC ZfdD ZgdE ZhdF ZidG ZjdH ZkdI ZldJ ZmddKZnddLZoddMZpddNZqddOZr	 	 ddPZsddQZtddRZuddSZvdT ZwdU ZxddVZyddWZzddXZ{dY Z|dZ Z}d[ Z~dd\Zd] Zdd^Zd_ Zd` Zda Zdb ZddcZdddZde Zdf Zdg ZddhZdi Zdj ZddkZdl Zdm Zdn Zdo Zdp Z	 	 	 ddqZddrZddsZddtZdduZdv Zdw Zdx ZddyZdz Zd{ed|efd}Zd{ed|efd~Zy)    N)delete_resources_by_tag)upload)cloudinary_url)OrderedDict)datedatetimetimezone)reducewraps)groupby)islicezip_longest)
ip_address
ip_networkIPv4Address)IP)	urlencode)minidom)common)logger)request)API2c                        fd}|S )a#   Helper decorator that adds function to the API class.
        is used to reuse as much code as possible

        args:
            dargs: (string, optional) Used to rename a function

        Example:
            @addtoapi("i_was_renamed", "im_a_second_alias")
            @addtoapi()

    c                     t                fd       }rZD ]S  } j                  r4t         j                        r j                  j                          _        t	        t
        |        U |S  j                  r4t         j                        r j                  j                          _        t	        t
         j                          |S )Nc                       | i |S N argskwargsfunctions     /opt/Tautulli/plexpy/helpers.pywrapperz%addtoapi.<locals>.rd.<locals>.wrapperE   s    T,V,,    )r   __doc__lenstripsetattrr   __name__)r!   r#   ndargss   `  r"   rdzaddtoapi.<locals>.rdD   s    	x	- 
	-   +##H,<,<(='/'7'7'='='?H$a*+ NH$4$4 5'//557Hh''2r$   r   r+   dkwargsr,   s   `  r"   addtoapir/   8   s    & Ir$   c                 
    | ryyNChecked r   )variables    r"   checkedr5   Z   s    r$   c                     | |k(  ryyr1   r   )r4   poss     r"   radior8   a   s    3r$   c                    i dddddddddddddd	d
dddddddddddddddddddi ddddddddddd dd!dd"dd#d$d%d$d&d$d'd$d(d)d*d+d,d-d.d/d0d/i d1d/d2d/d3d/d4d/d5d6d7d8d9dd:dd;dd<dd=dd>d?d@d?dAd?dBd?dCd+dDdEi dFdGdHdGdIdGdJdGdKdGdLdGdMdNdOdNdPdNdQdNdRdSdTd+dUdSdVdWdXdYdZd[d\d]i d^d_d`dadbdcdddedfdgdhdidjdkdldmdndodpdqdrdsdtdudvdwdxdydzd{d|d}d~dddddddddddddd}d}| rK| D ]F  }t        |      |v r||t        |         z  }"t        |      dk\  r	|s3|dz  }9|t        |      z  }H |S )z
    From couch potato
       A                  Ae   C   E            e   I            Th   N   O                  U            Y   th   ss   a                  ae   c            iY     i               r*      o                  u            y         !   z{cent}   z{pound}   z
{currency}   z{yen}   |   z	{section}   z{umlaut}   z{C}   z{^a}   z&lt;&lt;   z{not}   -   z{R}   _   z	{degrees}   z{+/-}   z{^2}   z{^3}   '   z{micro}z{paragraph}*z	{cedilla}z{^1}z{^o}z&gt;&gt;z{1/4}z{1/2}z{3/4}?/)                                    r3      )ordstr)unicrapreplacexlaterrw   s        r"   latinToAsciir   i   s   c"C)-s48#?CSd# 	c  #C *.s 59# 	c	 	 #C	 *.s	
 	d
 # 	c  #C *.s 59# @DS 	c  #C *.s 	c   $T 	c  #C *.s 59# @DS 	d # 	c  #C *.s 5;C 	c  #C *.s 	d # 	c  #C *.s 59# @DS 	c  #C *.s  	c!  !   $S!" 	c#" #" $(#" 59,#$ 	g%$ S%$ #'%$ 6::%& 	e'& 6'& $('& 6:7'( 	c)( )( !%c)( ,0)* 	g+* V+* &*6+* 48+, 	i-,  -C{F*WG33E8 	A 	A1vU3q6]"Q4HASV	 Hr$   c                     | dz  }t        j                  |      }|dkD  rt        j                  d|      }|S t        j                  d|      }|S )N    %H:%M:%S%M:%Stimegmtimestrftime)mssecondsr   minutess       r"   convert_millisecondsr      sN    DjG[[!F~--
F3 N --0Nr$   c                 |    t        |       j                         r#t        |       dz  }t        j                  |      S y)Nr   r   )r   isdigitfloatmathtrunc)r   r   s     r"   convert_milliseconds_to_secondsr      s0    
2w)d"zz'""r$   c                     t        |       j                         r2t        |       dz  }t        |dz  d      }t	        j
                  |      S y)Nr   <   r   )r   r   r   roundr   r   )r   r   r   s      r"   convert_milliseconds_to_minutesr      s@    
2w)d""a(zz'""r$   c                 ~    t        |       j                         r$t        | dz  d      }t        j                  |      S yNr   r   )r   r   r   r   r   sr   s     r"   seconds_to_minutesr      s2    
1v~~B"zz'""r$   c                     t        j                  |       }| dkD  rt        j                  d|      }|S t        j                  d|      }|S )Nr   r   r   r   )r   r   r   s      r"   convert_secondsr      sD    [[^F4x--
F3 N --0Nr$   c                     t        |       j                         r-t        t        |       dz  d      }t	        j
                  |      S yr   )r   r   r   r   r   r   r   s     r"   convert_seconds_to_minutesr      s6    
1v~~a2q)zz'""r$   c                  <    t        t        j                               S r   )intr   r   r$   r"   	timestampr      s    tyy{r$   c                  X    t        j                         } t        j                  |       }|S r   )r   today	isoformat)r   yyyymmdds     r"   r   r      s     JJLE~~e$HOr$   c                      t        j                  t        j                        j	                  d       } | j                         S )N)tz)tzinfo)r   nowr	   utcr   r   )utcnows    r"   utc_now_isor      s1    \\X\\*22$2?Fr$   c                 ,    t        t               |       S )Nsep)timestamp_to_YMDHMSr   r   s    r"   r   r      s    y{44r$   c                 J    t        j                  | d      j                         S N%Y-%m-%d)r   strptimer   )ymds    r"   YMD_to_timestampr      s    S*-7799r$   c                     t        |       }|r$|r|j                  d      S |j                  d      S |r|j                  d      S |j                  d      S )Nr   z%Y-%m-%d %H:%M:%Sz%Y%m%dz%Y%m%d%H%M%S)timestamp_to_datetimer   )tsr   r   dts       r"   r   r      sR    	r	"B
;;z**{{.//
{{8$$;;~&&r$   c                 ,    t        j                  |       S r   )r   fromtimestamp)r   s    r"   r   r      s    !!"%%r$   c                 6    t        |       j                  d      S r   )iso_to_datetimer   isos    r"   
iso_to_YMDr      s    3((44r$   c                 @    t        j                  |       j                  S r   )arrowgetr   r   s    r"   r   r      s    99S>"""r$   c                 j    t        | t              r"|r| j                         } | j                         S | S r   )
isinstancer   r   r   )r   to_dates     r"   datetime_to_isor     s+    "hB||~Ir$   c                 R   dddddd}t        |       j                         r| dkD  r||r| |k  rd}||d	      }t        | ||   z  |z        |z  } t        | |d
         \  }}t        ||d         \  }}t        ||d         \  }}	t        |	|d         \  }	} g }
|d
k\  r=|dkD  r8|d
k(  r
|dk\  r|dz   n|}|
j	                  t        |      dz   |dkD  rdndz          |dk\  r=|dkD  r8|dk(  r
|dk\  r|dz   n|}|
j	                  t        |      dz   |dkD  rdndz          |dk\  r=|dkD  r8|dk(  r
|	dk\  r|dz   n|}|
j	                  t        |      dz   |dkD  rdndz          |dk\  r,|	dkD  r'|
j	                  t        |	      dz   |	dkD  rdndz          dj                  |
      }|S d}|S )Ni \&i6 i`  r      )dhmr   r   r   dhmsr
  r  r  r      z dayr3   dh   z hrdhmz minz sec 0)r   r   r   divmodappendjoin)r   sigunitsreturn_secondsfactorsr   r
  r  r  r   hd_listhds               r"   human_durationr    s   	G 2wR!Vb>1CCG2&*+a/b'#,'1a&1a&1q'#,'2#:!a%RAQANN3q6F?QUcCD$;1q5bAaANN3q6E>AESrBC%<AE!r'AqANN3q6F?QUcCD&=QUNN3q6F?QUcCDXXg I Ir$   c                     | j                         }|dz  }|dz  dz  }|dz  }dj                  t        |      t        |      t        |            S )Nr   r   z{:02d}:{:02d}:{:02d})total_secondsformatr   )tdr   hoursr   r   s        r"   format_timedelta_Hmsr$  0  sQ    
AIE4xBG"fG!((US\3w<PPr$   c                     	  | j                   d      }	 t        |d         dz  t        |d         dz  z   t        |d         z   }|S #  Y yxY w# t        $ r d}Y |S w xY w)Nr   Fr   im  r	  r     )splitr   
IndexError)r   
split_datedays_olds      r"   get_ager+  8  s{    TZZ_
z!}%+c*Q-.@2.EEJWXMHZZ O  Os   A	 2A 	AAAc                 ,    t        |       dz  }d|z  }|S )N   z%.1f MB)r   )bytesmbsizes      r"   bytes_to_mbr1  G  s    	u	Br>DKr$   c                     t        j                  d| t         j                        }|r&t        t	        |j                  d            dz        S y )Nz^(\d+(?:\.\d+)?)\s?(?:mb)?)flagsr	  r-  )researchrM   r   r   group)mb_strresults     r"   mb_to_bytesr9  N  s>    YY4fBDDIF5a)G344 r$   c                    | j                  d      }t        |d         }|d   j                         }|dk(  r|dz  } | S |dk(  r|dz  } | S |dk(  r|d	z  } | S |d
k(  r|dz  } | S |dk(  r|dz  } | S |dk(  r|dz  } | S |dk(  r|} | S d} | S )Nr  r   r	  MiBr-  MBi@B GiBi   @GBi ʚ;KiB   KBr   B)r'  r   upper)r0  r'  factorunits       r"   
piratesizerF  T  s    JJsOE58_F8>>Du}  K 
 K 

" K 

" K 
} K 
} K 
 K Kr$   c           	      l   | sy|j                         D ]Z  \  }}|rA	 t        j                  dk(  rt        j                  d|      }nt        j                  d|      }| j                  ||      } \ | S # t
        $ r7 t        j                  d|j                  t        j                  d            }Y Uw xY w)Nr3   darwinNFDNFCr   )
itemssysplatformunicodedata	normalize	TypeErrordecodeplexpySYS_ENCODINGr   )textdicrO  rw   js        r"   replace_allrW  m  s    		 	"1[<<8+#--eQ7A#--eQ7A ||Aq!	" K  [))%&:M:My1YZ[s   A A33=B32B3c                 v    |dk(  rt        j                  dd|       } |dk(  rt        j                  dd|       } | S )Nfilez[\?"*:|<>/]r   folderz	[:\?<>"|])r4  sub)stringtypes     r"   replace_illegal_charsr^    s:    v~V4xc62Mr$   c                     t        |       j                         }t        j                  dd|      j	                  d      }|S )Nz:[\.\-\/\!\@\#\$\%\^\&\*\(\)\+\-\"\'\,\;\:\[\]\{\}\<\>\=\_]r3   utf-8)r   lowerr4  r[  encode)r\  pass1
out_strings      r"   	cleanNamere    s<     &&(EUWY[`ahhipqJr$   c                     t        j                  dd|       j                         } dj                  | j	                               } | j                         } | S )Nz
[\.\-\/\_]r  )r4  r[  ra  r  r'  titlerg  s    r"   
cleanTitleri    sC    FF=#u-335E HHU[[]#EKKMELr$   c                    dj                  t        j                  t        j                        t	        j
                  d|       j                  dd      j                         }dj                  fd|D              }|S )Nz-_.()[] {}{}NFKDASCIIignorer3   c              3   .   K   | ]  }|v r|n  y wr   r   ).0rq   r   	whitelists     r"   	<genexpr>z!clean_filename.<locals>.<genexpr>  s     ZAANq?Zs   )	r!  r\  ascii_lettersdigitsrN  rO  rb  rQ  r  )filenamer   cleaned_filenamerp  s    ` @r"   clean_filenamerv    sd    %%f&:&:FMMJI",,VX>EEgxX__awwZIYZZr$   c                     t        |       j                  |      D cg c]#  }|j                         s|j                         % c}S c c}w r   )r   r'  r'   )r   	delimiterxs      r"   split_striprz    s1    "1v||I6D!!'')AGGIDDDs
   AAc                 ,   g }t         j                  j                  |       \  }}	 t         j                  j                  |      \  }}|r|j	                  |       n|r|j	                  |       nK|r|j	                  |       |j                          |S )z
    Split a path into components, starting with the drive letter (if any). Given
    a path, os.path.join(*split_path(f)) should be path equal to f.
    )ospath
splitdriver'  r  reverse)f
componentsdriver}  rZ  s        r"   
split_pathr    s     J''$$Q'KE4 ww}}T*ff%!!$'  %   r$   c                    t        j                  dt         j                        }|j                  |       }|rJ|j	                  d      }|j	                  d      }|j	                  d      }|j	                  d      }||||fS y )NzS(?P<timestamp>.*?)\s\-\s(?P<level>.*?)\s*\:\:\s(?P<thread>.*?)\s\:\s(?P<message>.*)r   levelthreadmessage)r4  compileVERBOSEmatchr6  )r   patternr  r   r  r  r  s          r"   extract_logliner    su    jjoqsq{q{|GMM!EKK,	G$X&++i(5&'22r$   c                 t    g }| j                  |      D ]!  }|j                  |j                                # |S r   )r'  r  r'   )mystringsplitvarmylist	each_words       r"   split_stringr    s7    F^^H- )	ioo'()Mr$   c                 H   	 ddl m} ddlm}m}m} t        j                  }t               }d}d}	t        j                  j                  j                  d      D 
cg c]  }
|
sd|
j!                         z    }}
t        j                  j"                  j                  d      D 
cg c]  }
|
sd	|
j!                         z    }}
dj%                  ||z         j'                  d
      }t        j(                  d        ||d      } ||||||	|      }	 t+        | d      5 }|j-                  |j/                  |j0                  |      j3                  d
             ddd       t+        |d      5 }|j-                  |j5                  |j0                  |      j3                  d
             ddd       y# t        $ r t        j                  d       Y yw xY wc c}
w c c}
w # 1 sw Y   xY w# 1 sw Y   yxY w# t6        $ r }t        j                  d|       Y d}~yd}~ww xY w)z
    Create a self-signed HTTPS certificate and store in it in
    'ssl_cert' and 'ssl_key'. Method assumes pyOpenSSL is installed.

    This code is stolen from SickBeard (http://github.com/midgetspy/Sick-Beard).
    r   )cryptozFUnable to generate self-signed certificates: Missing pyOpenSSL module.F)createKeyPaircreateSelfSignedCertificateTYPE_RSAi ,zDNS:zIP:r`  z'Generating self-signed SSL certificate.i   wNz*Error creating SSL key and certificate: %sT)OpenSSLr  ImportErrorr   errorcertgenr  r  r  r   PRODUCTr   rR  CONFIGHTTPS_DOMAINr'  r'   HTTPS_IPr  rb  debugopenwritedump_certificateFILETYPE_PEMrQ  dump_privatekeyIOError)ssl_certssl_keyr  r  r  r  issuerserial
not_before	not_afterr
  domainsips	alt_namespkeycertfprK   s                     r"   create_https_certificatesr    s   " ML^^F[FJ'I+1==+E+E+K+KC+PVaTUv	!VGV&,mm&<&<&B&B3&G
M151779
MC
M3'..w7I LL:;4(D&vtVZT]^D(C  	YBHHV,,V-@-@$GNNwWX	Y'3 	X2HHV++F,?,?FMMgVW	X 9  ]^ W
M	Y 	Y	X 	  A1Esw   F2 G#G%G-GG8 ;G G8 .;G,)G8 2GG G)%G8 ,G51G8 5G8 8	H!HH!c                 D    	 t        |       S # t        t        f$ r Y yw xY wNr   r   
ValueErrorrP  r   s    r"   cast_to_intr    '    1v	"    
 c                 D    	 t        |       S # t        t        f$ r Y yw xY wr  )r   r  rP  r  s    r"   cast_to_floatr    s'    Qx	" r  c                 F    	 t        | |      S # t        t        f$ r Y yw xY wr  )r  r  rP  )rh   bs     r"   helper_divmodr    s*    a|	"       c                 D    	 t        |       S # t        t        f$ r Y yw xY wr  )r&   r  rP  r  s    r"   
helper_lenr    r  r  c                 F    	 t        | |      S # t        t        f$ r Y yw xY wr  )r   r  rP  )r*   ndigitss     r"   helper_roundr     s+    Q  	" r  c                 V    t        j                  |       }t        j                  |      S r   )	xmltodictparsejsondumpsxmlr~   s     r"   convert_xml_to_jsonr  '  s    A::a=r$   c                 0    t        j                  |       }|S r   )r  r  r  s     r"   convert_xml_to_dictr  ,  s    AHr$   c                     t        |       } t        |      }| dk7  r|dk7  r	| |z  dz  }nd}t        j                  t        |d            S )Nr   d   )r  r   r   r   )value1value2percents      r"   get_percentr  1  sL    6"F6"F{v{F?c)::eGQ'((r$   c                 F    	 t        | d      S # t        t        f$ r Y yw xY w)N   r   r  )hexs    r"   
hex_to_intr  >  s*    3|	" r  c                     | r	 t        j                  |       }|S t        j                  d       g S # t        $ r$}t        j                  d|z         g cY d }~S d }~w t        j                  d       g cY S xY w)NzError parsing XML. %szError parsing XML.z,XML parse request made but no data received.)r   parseString	Exceptionr   warn)unparsed	xml_parserK   s      r"   	parse_xmlr  E  so    	++H5I 	BC	  	KK/!34I	KK,-Is   2 	A8AA8A8c                 V    | j                  |      r|ry| j                  |      S |ry|S )zv
    Validate xml keys to make sure they exist and return their attribute value, return blank value is none found
    TF)getAttribute)xml_key	attributereturn_booldefault_returns       r"   get_xml_attrr  U  s5     I&''	22!!r$   c                 8    i }| rt        j                  |       }|S r   )r  loads)json_kwargsparamss     r"   process_json_kwargsr  e  s    FK(Mr$   c                    |g }i g }t        |       }|d   d   j                         }|r|d   D cg c]  }|d   s	|d    c}|z   }	| D ]k  }
|
j                         D ]V  \  }}|v r|   j                  ||      }n|}t	        |      j                         }||	v s@||v sE|j                  |
        k m n| }t        |      }t        |fd      }|d   }t        |      D ]7  }|d   t        |d	            d   |d
   dk(  rdnd}t        |fd|      }9 ||d   |d   |d   z    }|||d}|S c c}w )Nr5  valuecolumns
searchabledatac                 *    |    j                         S r   )ra  )kdefault_sorts    r"   <lambda>z(process_datatable_rows.<locals>.<lambda>  s    AlO,A,A,C r$   keyordercolumndirdescTFc                     t        |       S r   )sort_helper)r  sort_key	sort_keyss    r"   r  z(process_datatable_rows.<locals>.<lambda>  s    Ax0S r$   )r  r  startlength)resultstotal_countfiltered_count)	r&   ra  rK  r  r   r  sortedreversedr   )rows	json_datar  search_colsr  r  r  search_valuer
  searchable_columnsrowr  vr  r  
sort_orderr  r  r  r  s     ` `              @r"   process_datatable_rowsr  m  s   	Gd)K X&w/557L1:91EYA<aiY\gg 		C		 1	>%aL,,Q2EEE
((***|u/DNN3'		 \N W"CDG7#J*% fY'E(O(<=fE,&0$e&S]def i()G*<y?R*RTG "(D KC Zs   
EEc                     | |   }||v r||   j                  | |   |      }t        |t              r|j                         }|S r   )r  r  r   ra  )r  r  r  r  s       r"   r   r     sH    	(A9h##AhK3!SGGIHr$   c                      d }|S )z0 Helper decorator that sanitized the output
    c                 .     t                fd       }|S )Nc                  &    t         | i |      S r   )sanitizer   s     r"   r#   z)sanitize_out.<locals>.rd.<locals>.wrapper  s    Hd5f566r$   )r   )r!   r#   s   ` r"   r,   zsanitize_out.<locals>.rd  s    	x	7 
	7r$   r   r-   s      r"   sanitize_outr    s    
 Ir$   c                    t        | t              r+t        |       j                  dd      j                  dd      S t        | t              r| D cg c]  }t	        |       c}S t        | t
              r-| j                         D ci c]  \  }}|t	        |       c}}S t        | t              rt        t	        t        |                   S | S c c}w c c}}w )N<&lt;>&gt;)r  r   r   listr  dictrK  tuple)objr~   r  r  s       r"   r  r    s    #s3xV,44S&AA	C	%()))	C	+.99;741a8A;77	C	Xd3i())
 *7s   CCc                     t        t        |             }|j                         }|j                         }|r|dk7  r|dk(  r|dk(  s	|dk(  rd|vryy)NLOOPBACK   PUBLIC   LOCALTF)is_valid_ipget_ipversioniptype)hostip
ip_versionip_types       r"   is_public_ipr0    sR    	VD\	"BJiikG	g#!O8 3!Ow 6r$   c                    d}t        |       r| S t        j                  d|       s>	 t        j                  | d       d   d   d   }t        j                  d| d|d       |S |S #  t        j                  d| z         Y |S xY w)	Nr3   z*^[0-9]+(?:\.[0-9]+){3}(?!\d*-[a-z0-9]{6})$r   r$  zIP Checker :: Resolved z to .z.IP Checker :: Bad IP or hostname provided: %s.)r(  r4  r  socketgetaddrinfor   r  r  )r,  r   s     r"   r)  r)    s    J4XXCTJ	R++D$7:1=a@JLLtZPQ :	RLLIDPQs   ;A& &Bc                 L    	 t        |       S # t        $ r Y yt        $ r Y yw xY wNF)r   rP  r  )addresss    r"   r(  r(    s.    '{  s   
 	###c                    g }d }	 t        j                  |       j                  dg d      }t         j                  j	                         }|d   }|D ]7  }|j                  |d         |d<   |d   s |d   j                  dd      |d<   9 	 d}	 t        j                  |       j                  d      d   }||d}|r||d<   |S # t        $ r}d	| z  }Y d }~Ld }~wt         j                  j                  $ r}d
|z  }Y d }~vd }~wt         j                  j                  $ r}d
|z  }Y d }~d }~wt        $ r}d|z  }Y d }~d }~ww xY w# t        $ r}d}Y d }~d }~ww xY w)Nr   )dnswhoishttp)retry_countasn_methodsnetscountrypostal_coder   r  z Invalid IP address provided: %s.z%sz	Error: %sr3   )r<  zNot available)r,  r>  r  )ipwhoisIPWhoislookup_whoisutilsget_countriesr  r   r  
exceptionsIPDefinedErrorASNRegistryErrorr  Netget_host)	r   r>  errr:  	countriesnetrK   r,  
whois_infos	            r"   whois_lookuprO    sl   D
C
+88QE] 9 _MM//1	V} 	KC&]]3y>:C	N=!&)-&8&@&@c&J]#	K D{{:&//A/>qA J !
7-  >0:=,, Qh.. Qh Ao  sZ   A,C 3C (E 	E	C E	:D E	$D..E	:EE		E!EE!c                  >    d | v rdS dj                  d | D              S )Nr3   c              3   2   K   | ]  }t        |        y wr   )r   )ro  r   s     r"   rq  zanon_url.<locals>.<genexpr>  s     )>Q#a&)>   )r  )urls    r"   anon_urlrT    s"    2>"'')>#)>">>r$   c                     t         j                  j                  dk(  ryt         j                  j                  dk(  r| ryt         j                  j                  dk(  ryy )Nr	  imgurr&  zself-hosted   
cloudinary)rR  r  NOTIFY_UPLOAD_POSTERS)include_selfs    r"   get_img_servicer[    sF    }}**a/		,	,	1l		,	,	1r$   c                 B   dx}}t         j                  j                  st        j                  d       ||fS ddt         j                  j                  z  i}t        j                  |       |j                  d      t        |      dz   dd}t        j                  d	d
||      \  }}	}
|r~|	s|t        j                  dj                  ||             |j                         j                  d      }|j                  dd      j                  dd      }|j                  dd      }||fS |	r't        j                  dj                  |||	             n%t        j                  dj                  ||             |
r$t        j                  dj                  |
             ||fS )z Uploads an image to Imgur r3   z_Tautulli Helpers :: Cannot upload image to Imgur. No Imgur client id specified in the settings.AuthorizationClient-ID %sr`  z.pngpng)imagerg  namer]  zhttps://api.imgur.com/3/imagePOST)headersr  z6Tautulli Helpers :: Image '{}' ({}) uploaded to Imgur.r  linkzhttp://zhttps://
deletehashzATautulli Helpers :: Unable to upload image '{}' ({}) to Imgur: {}z>Tautulli Helpers :: Unable to upload image '{}' ({}) to Imgur.z(Tautulli Helpers :: Request response: {})rR  r  IMGUR_CLIENT_IDr   r  base64	b64encoderb  r   r   request_response2r  r!  r  r  r   )img_data	img_title
rating_keyfallbackimg_urldelete_hashrc  r  responseerr_msgreq_msgimgur_response_datas               r"   upload_to_imgurrt    s   Gk==((vw##1N1N NOG%%h/%%g.
Of,D
 ")!:!:;Z\bCJQU"WHgw MTTU^`hij&mmo11&9%))&"5==iT)--lB? K LL\ccdmow  zA  B  CLLY``ajltuvLLCJJ7STKr$   c                    t         j                  j                  st        j                  d       yddt         j                  j                  z  i}t        j                  d| z  d|      \  }}}|r(|s&t        j                  dj                  ||             y	|r't        j                  d
j                  |||             yt        j                  dj                  ||             y)z Deletes an image from Imgur zaTautulli Helpers :: Cannot delete image from Imgur. No Imgur client id specified in the settings.Fr]  r^  z https://api.imgur.com/3/image/%sDELETE)rc  z7Tautulli Helpers :: Image '{}' ({}) deleted from Imgur.TzCTautulli Helpers :: Unable to delete image '{}' ({}) from Imgur: {}z@Tautulli Helpers :: Unable to delete image '{}' ({}) from Imgur.)	rR  r  rf  r   r  r   ri  r  r!  )ro  rk  rm  rc  rp  rq  rr  s          r"   delete_from_imgurrw  8  s    ==((xy1N1N NOG!(!:!:;]`k;kmuCJ"LHgw NUUV_aijkLL^eefoqy  |C  D  E  LL[bbclnvwxr$   c           	         d}t         j                  j                  r4t         j                  j                  rt         j                  j                  st        j                  d       |S t        j                  t         j                  j                  t         j                  j                  t         j                  j                         	 t        || fdj                  ||      d|t        |      g|t        |      |d      }t        j                  dj                  ||             |j                  d	d      }|S # t        $ r1}t        j                  d
j                  |||             Y d}~|S d}~ww xY w)z  Uploads an image to Cloudinary r3   ziTautulli Helpers :: Cannot upload image to Cloudinary. Cloudinary settings not specified in the settings.
cloud_nameapi_key
api_secret{}_{}tautulli)rg  rl  rm  )	public_idtagscontextz;Tautulli Helpers :: Image '{}' ({}) uploaded to Cloudinary.rS  zFTautulli Helpers :: Unable to upload image '{}' ({}) to Cloudinary: {}N)rR  r  CLOUDINARY_CLOUD_NAMECLOUDINARY_API_KEYCLOUDINARY_API_SECRETr   r  rX  configr   r!  r   r  r  r  )rj  rk  rl  rm  rn  rp  rK   s          r"   upload_to_cloudinaryr  N  s7   G==..fmm6V6V^d^k^k  _B  _B  A  	B==6600==66~9h/$+NN8Z$H *Hc*oF,5S_bj"km 	RYYZcemno,,ub) N  ~]ddenpxz{|}}N~s   	A1D< <	E6&E11E6c                    t         j                  j                  r4t         j                  j                  rt         j                  j                  st        j                  d       yt        j                  t         j                  j                  t         j                  j                  t         j                  j                         |rTd}d}|du r6t        d|      }|j                  dd      }|j                  d	d      }|du r6t        j                  d
       y| r9t        t        |              t        j                  dj                  |              yt        j                  d       y)z" Deletes an image from Cloudinary zkTautulli Helpers :: Cannot delete image from Cloudinary. Cloudinary settings not specified in the settings.Fry  Tr3   r~  )next_cursorpartialr  z7Tautulli Helpers :: Deleted all images from Cloudinary.zFTautulli Helpers :: Deleted images from Cloudinary with rating_key {}.zTTautulli Helpers :: Unable to delete images from Cloudinary: No rating_key provided.)rR  r  r  r  r  r   r  rX  r  r   r  r  r   r!  )rl  
delete_allr  r  r   s        r"   delete_from_cloudinaryr  i  s   ==..fmm6V6V^d^k^k  _B  _B  C  	D==6600==66 o'
LAeeIu-G%%r2K o 	NO  
J0]ddeopq  	klr$   c	                    d}	t         j                  j                  r4t         j                  j                  rt         j                  j                  st        j                  d       |	S t        j                  t         j                  j                  t         j                  j                  t         j                  j                         |ddt               dd}
|dk7  rt        |      |
d<   d	|
d
<   |dk7  rt        |      |
d<   d	|
d
<   |dk7  r||
d<   |dk7  rdj                  |      |
d<   |dk7  rdj                  |dz        |
d<   	 t        dj                  ||       fi |
\  }	}t        j                  dj                  ||             |	S # t        $ r1}t        j                  dj                  |||             Y d }~|	S d }~ww xY w)Nr3   zlTautulli Helpers :: Cannot transform image on Cloudinary. Cloudinary settings not specified in the settings.ry  autoT)r!  fetch_formatqualityr*  securer   widthfillcrop  heightr  opacity000000zrgb:{}
backgroundr   zblur:{}effectr}  z>Tautulli Helpers :: Image '{}' ({}) transformed on Cloudinary.zITautulli Helpers :: Unable to transform image '{}' ({}) on Cloudinary: {})rR  r  r  r  r  r   r  rX  r  r   r   r!  r   r  r  )rl  r  r  r  r  blur
img_formatrk  rm  rS  img_optionsoptionsrK   s                r"   cloudinary_transformr    s   
C==..fmm6V6V^d^k^k  _B  _B  D  	E
==6600==66 (#)$'k!	#K }"5zG$F~ #FH$F#~!(IX$,OOJ$?L!qy ) 0 0 <HA%gnnXz&JZkZWU\\]fhpqr J  A`gghqs{}~  	A  	AJAs   AF 	G&GGc           
      2   |D cg c]  }|d   |d   |d   d }}|s|d   d   }|D cg c]  }|d   	 }}| j                  d|      j                  d      D cg c]  }|j                          }}| j                  dd      j                  d      D cg c]  }|j                          }}g }	t        ||d	
      D ]P  \  }}	 |j	                  |      }
|j                         dv r|j                         }nd}|	j                  |
|d       R d||	t        | j                  dd            t        | j                  dd            d| j                  dd	      id}t        j                  |      S c c}w c c}w c c}w c c}w # t
        $ r Y w xY w)zz Builds datatables json data

        dt_columns:    list of tuples [("column name", "orderable", "searchable"), ...]
    r   r	  r&  )r  	orderabler  order_columnr  	order_dirr  r3   )	fillvalue)ascr  )r  r  r  r     r  r5  )drawr  r  r  r  r5  )popr'  r'   r   indexr  ra  r  r   r  r  )r    
dt_columnsdefault_sort_colrq   r  column_namesorder_columnsr
  
order_dirsr  r  r  r  s                r"   build_datatables_jsonr    s    OYY!1Q4qtDYGY%a=+",-QAaD-L-(.

>CS(T(Z(Z[^(_`1QWWY`M`%+ZZV%D%J%J3%OP!'')PJPEM:D A1	'--a0L 779'	IIY?@A #fjj!45vzz(B78#VZZ"%=>I ::i  ? Z
 .`P  		s(   E6E;F FF

	FFc                    t        |       j                         rt        |       } n| S d}| |k  rt        |       dz   S |rd}nd}d}| |k\  r,|t        |      k  r| |z  } |dz  }| |k\  r|t        |      k  rdj	                  | ||         S )Nr@  z B)kBr<  r>  TBPBEBZBYB)r?  r;  r=  TiBPiBEiBZiBYiBr  r	  z{0:.2f} {1})r   r   r  r&   r!  )r.  sithreshr  r   s        r"   human_file_sizer    s    
5ze$ Fv~5zD  	@H
A
6/a#e*n	Q 6/a#e*n uQx00r$   c                    t        j                  d      }t        j                  d      }t        j                  || j                               D cg c]#  }|j	                         s|j	                         % }}g g}d}d}d}	d}
d}d}t        |      D ]  \  }}|	rA|dk(  r<|d   j                  g        |j                  |d   d          d}d}d}	d}
|sD|dz  }J|
rW|d	k(  rR|j                          |st        d
      d}d}d}	d}
|dkD  s||dkD  s||k(  s|j                          |dz  }|dz  }|rt        j                  ||      rk	 t        |dd       }d|cxk  r|k  st        d       t        d      |d   j                  |       d}d}d}	d}
||kD  s|j                          |dz  }&|r|dk(  r|t        |      dz
  k  rt|d   j                  g        |j                  |d   d          |d   j                  |d   j                  d             |d   j                  |       d}d}d}	d}
|dz  }|r4|dk(  r/|t        |      dz
  k  r|d   j                  |       d}d}d}	d}
t        d       t        |      dkD  rt        d      |j                         S c c}w #  t        d      xY w)z^ Parse a logic string into a nested list
    Based on http://stackoverflow.com/a/23185606
    z(\(|\)|and|or)z{\d+}TFr   (r  r	  )zopening bracket is missingzinvalid condition logicz+invalid condition number in condition logicandorzclosing bracket is missing)r4  r  r'  ra  r'   	enumerater  r  r  r  r   r&   )r   num_condvalid_tokensconditions_patternry  tokensstack	cond_next	bool_nextopen_bracket_nextclose_bracket_nextnest_andnest_nest_andrw   nums                  r"   parse_condition_logic_stringr    s    ::/0LH-!#,	!BPAaggiaggiPFPDEIIHM&! ;81c"IR LLr2'II $!&"AHIIK !=>>II %!%!| 1h-6O		A"288$6:<!Ab'l s&h& !NOO ' !NOO"IS!II %!%-'		A1:!c&k!m*;"IR LLr2'"IU2Y]]2./"IQII $!&MH19S[]):"IQII $!& 677w;8z 5zA~56699;W QL< !:;;s   J2'J2J77Kc                     t        |       D ]$  \  }}t        |t              st        |      | |<   & ddj	                  |       z   dz   }|S )Nr  r  r  )r  r  r  nested_list_to_stringr  )lrw   ry  r   s       r"   r  r  F  sO    ! ,1a(+AaD, 	chhqkCAHr$   c                    | d   }t        |t              rt        ||      }n||   }t        | dd d   | dd d         D ]?  \  }}t        |t              rt        ||      }n||   }|dk(  r|xr |}4|dk(  s:|xs |}A |S )Nr   r	  r&  r  r  )r  r  eval_logic_groups_to_boolzip)logic_groups
eval_conds
first_condr8  opcond	eval_conds          r"   r  r  N  s    aJ*d#*:zBJ'QTT*LA,>? 	)DdD!1$
CI"4(I;)	F4Z(yF	) Mr$   c                    t         j                  j                  rd}nd}| t         j                  j                  dv rt	        j                  t        j
                  t        j                        }|j                  t        j                  t        j                  d       |j                  d       	 |j                  d       |j                         d   } |j#                          | s]d} nZ| dk(  r7t         j                  j                  dvrt         j                  j                  } n| xs t         j                  j                  } t         j$                  dvrd	t'        t         j$                        z   }nd
}t         j(                  Bt         j(                  j+                  d      r#dt         j(                  j+                  d      z   }nd
}|dz   | z   |z   |z   S # t        j                  $ rF 	 t	        j                  t	        j                               } n# t        j                   $ r Y nw xY wY Zw xY w# |j#                          w xY w)Nhttpsr;  )z0.0.0.0z::r	  r   )z<broadcast>r	  	localhost)P   i  :r3   r   z://)rR  r  ENABLE_HTTPS	HTTP_HOSTr3  AF_INET
SOCK_DGRAM
setsockopt
SOL_SOCKETSO_BROADCAST
settimeoutconnectgetsocknamer  gethostbynamegethostnamegaierrorclose	HTTP_PORTr   	HTTP_ROOTr'   )hostnameschemer   portroots        r"   get_plexpy_urlr  d  s   }}!!FMM337HHMM&..&*;*;<	V&&(;(;Q?	Q		II()}}q)H GGI"H	[	 V]]%<%<DU%U==**6v}}66y(S))**#(8(8(>(>s(CV%%++C00E>H$t+d223 || 	!//0B0B0DE?? 	 GGIsH   1$G H0+'HH0H)&H0(H))H0,H3 /H00H3 3Ic                 R    g d}|r|ddgz  }|D ]  }| j                  |d      }  | S )N)MoDDDodor;   rh   r3   )r   )r!  durationinvalid_formatsr  s       r"   momentjs_to_arrowr    s<    *OC:% '2&'Mr$   c                 6    t        |       g|z  }t        |d|iS )z/Collect data into fixed-length chunks or blocksr  )iterr   )iterabler*   r  r   s       r"   grouperr    s%     NaDT222r$   c                     t        |t        t        f      s|g}t        j                  | }t        | |      }t        ||      D ci c]  \  }}|t        |       c}}S c c}}w )Nr  )r  r  r   operator
itemgetterr  r   )r  keyskey_functionsorted_iterabler  r6  s         r"   group_by_keysr	    s[    dT5M*v&&-LX<8O/6/UVeCeVVVs   A"c                 <     t                t         fdd      S )Nc                  .    t        t                     S r   )r   r   itr0  s   r"   r  zchunk.<locals>.<lambda>  s    fR./ r$   r   )r   r  s   ``r"   chunkr    s    	bB/44r$   c                    t        | t              r&g }| D ]  }|j                  t        ||              |S t        | t              r5i }| j                         D ]  \  }}t        ||      |t        ||      <     |S  ||       }|S r   )r  r  r  traverse_mapr  rK  )r!  funcnew_objrw   r  r  s         r"   r  r    s    #t 	2ANN<401	2 N 
C	IIK 	CDAq-9!T-BGLD)*	C N s)Nr$   c                 x    t        | t              r| S t        | t              rt        j                  |       } | S g S r   )r  r  r   shlexr'  )r   s    r"   
split_argsr    s3    $	D#	{{4 Ir$   c                    t        | t              r9| D ]2  }d|j                  dd      v s|j                  dd      dk7  s.d|d<   4 | S t        | t              r(| j	                         D ]  \  }}d|v s|dk7  sd| |<    | S )Npasswordra  r3   r  z    )r  r  r  r  rK  )r  cfgvals      r"   mask_config_passwordsr    s    &$ 	&CSWWVR00SWWWb5IR5O%G	& M 
FD	! 	%HCS SBY$s		% Mr$   c                 h    | |ry | du s| dk(  ryt        | t              r| j                         dv ryy)NTr	  )1truetyesr   onF)r  r   ra  )r  return_nones     r"   	bool_truer"    s:    }	$%1*	E3	EKKM5Y$Yr$   c                     t        | t        t        f      r| d   j                  d      }n| j                  d      }t	        |      |fS )Nr   r2  )r  r  r   r'  r&   )attrrh   s     r"   
sort_attrsr%    s=    $u&GMM#JJsOq619r$   c                 6   t        | t              r%g }| D ]  }|j                  t        |              |S t        | t              rg }g }| j                         D ]  \  }}t        |t              rg|D ]K  }t        |t              r|j                  |t        |      g       0|j                  |t        |      g       M |ri|j                  ||g       }|j                  |t        |      g        t        t        |      t        |      z         }|S | }|S r   )r  r  r  sort_objr  rK  r   r  )r!  
result_objitemresult_start
result_endr  r  s          r"   r'  r'    s   #t
 	.Dhtn-	.* ' 
C	
IIK 
	6DAq!T" >D!$-"))1hqk*:;$++Q,<=	>
 %%q!f-##Q$45
	6 !!5z8J!JK
  
r$   c           	         i }|j                         D ]3  \  }}d}t        | t              r| j                  |d       }n	 t	        | |      }t        |      r |       }t        |t              r9t        |t              r|D cg c]  }t	        ||d        }}nt	        ||d       }nt        |t              rGt        |t              r*|D cg c]  }t        ||       c}xs t        i |      g}nQt        ||      }nDt        |      r9t        |t              r|D cg c]
  } ||       }}n|r	 ||       }n ||      }|||<   6 |S # t
        $ r d}d }Y w xY wc c}w c c}w c c}w )NFT)
rK  r  r  r  getattrAttributeErrorcallabler   r  get_attrs_to_dict)r!  attrsr
  r$  r[  no_attrr  r~   s           r"   r0  r0    sa   
A[[] "	cc4 GGD$'ET*
 E?GEc3%&8=>1C.>>sD1T"%&<ABq*1c2BbGXY[]`GaFb)%5c]%&)./AQ//HEJE$E"H H9 "  ?
 C
 0s$    EE E%E*EEc                 *    t        t        |             S r   )flatten_treeflatten_keys)r!  s    r"   flatten_dictr6  -  s    S)**r$   c           
         t        | t              r| D cg c]  }t        ||       }}|S t        | t              r?|r||z   nd}| j	                         D ci c]  \  }}||z   t        |||z          }}}|S | }|S c c}w c c}}w )Nr  r3   )r  r  r5  r  rK  )r!  r  r   r~   r  new_keyr  r  s           r"   r5  r5  1  s    #t589<s+99 N 
C	"#)MPYY[YTQ7Q;QGaK @@YY N N : Zs   B Bc                    t        | t              rIg }| D ]@  }t        |t              r|j                  t	        |             .|j                  ||i       B |S t        | t              ri }|gg}| j                         D ]_  \  }}t        |t              r|j                  t	        ||             2t        |t              r |j                  t	        |        [|||<   a t        |di iD 	cg c]/  }|D 	ci c]  }	|	j                         D ]  \  }}||
  c}}}	1 }}}	}}|S g }|S c c}}}	w c c}}}	}w )Nr  )	r  r  r  extendr4  r  rK  updater   )
r!  r  new_rowsr~   common_keysall_rowsr  r  r  r   s
             r"   r4  r4  =  s@   #t 	*A!T"Q0a)		*0 O% 
C	 M?IIK 	#DAq!T"Q 23At$"""LO4!"A	#  +HCCE E $'==a1779=41aQT=Q= E E O O > Es   2D8
="D1D8
1D8
c                 8    t        t        j                  ||       S )z0Access a nested object in root by item sequence.)r
   r  getitem)r  rK  s     r"   get_by_pathrA  ]  s    (""E400r$   c                 .    |t        | |dd       |d   <   y)z8Set a value in a nested object in root by item sequence.Nr  )rA  )r  rK  r  s      r"   set_by_pathrC  b  s    /4KeCRj!%),r$   c                 h    |j                  d      }t        | |      }t        |      D ]  }||i} |S )Nr2  )r'  rA  r	  )r  r$  
split_attrr  _attrs        r"   get_dict_value_by_pathrG  g  s=    CJj)E*% Lr$   c           	          |g }|D ]b  }|| v rTt        | |   t              r4t        ||   t              r!t        | |   ||   |t        |      gz          N| |   ||   k(  rZ[||   | |<   d | S r   )r  r  
dict_merger   )rh   r  r}  r  s       r"   rI  rI  p  s    | 	!8!C&$'Jqvt,D1S61S643s8*+<=31S6!sVAcF	 Hr$   c                  :    i }| D ]  }|j                  |        |S )z
    Given any number of dictionaries, shallow copy and merge into a new dict,
    precedence goes to key value pairs in latter dictionaries.
    )r;  )	dict_argsr8  
dictionarys      r"   dict_updaterM    s)    
 F "
j!"Mr$   c                     | yt        |       j                  dd      j                  dd      j                  dd      j                  dd	      j                  d
d      } | S )Nr3   &z&amp;r  r  r  r  "z&quot;r   z&apos;)r   r   )r  s    r"   
escape_xmlrQ    sY    }J	g		f		f		h		h	 
 Lr$   c           
         |dnd}t        |d u xs t        | t                     }|xs d}|j                  d      rt        | t              r|d d n|}d}g }	t        | t              rt        | j                               D ]  \  }
}t        |t              r!|	j                  t        ||
||dz                7t        |t              r!|	j                  t        ||
||dz                hdj                  ||
t        |            } nut        | t              rK| D ]E  }t        |t              r|dv r|j                  d	|      }|	j                  t        ||||             G n|	j                  t        |              t        |	      d
kD  rdnd}|t        | t              st        | t              r|ndz  }d|z  |xs d
z  }|st        | t              rdj                  ||||      }t        |	      d
kD  rS|	D ]  }dj                  ||      } |st        | t              r(t        | t              r|nd}dj                  ||||      }|S )Nr3   
objectsr   r  r	  z
{} {}="{}")childrenrK  r]  r   r  z/>r  z	{}<{}{}{}z{}{}z{}{}</{}>{})boolr  r  endswithr  r  rK  r  dict_to_xmlr!  rQ  r  r&   )r
  	root_nodeindentr  
line_breakwrapr  root_singularr  rU  r  r  end_tagspaceschilds                  r"   rX  rX    s   ~4JI%<At)<==D!	D!%s!3
1d8KD"IQUM
CH!T + 	GJC%&E3	 JKE4(E3	 JK"))#sJu4EF	G 
At	 	NE%&43H+H %		&- @OOK}feLM		N 	
1&]Q&cDGZ40Jq$4GzROG5[FKa(Fz!T"  sG<
8}q 	,E--U+C	, :a&)!T2VF&&sFD*ECJr$   c                     	 | j                  d| j                  | j                  |                   | S # t        t        f$ r Y | S w xY wr  )insertr  r  r  r(  )r  r  s     r"   move_to_frontrc    sK    	AEE!''%.)* H 
# Hs   04 AAc                 0    t        |       } | dkD  xr |dk(  S )N   bt2020ncr  )	bit_depthcolor_spaces     r"   is_hdrrj    s     I&Iq=6[J66r$   c                     t        d | j                  d      j                  dd      j                  d      D              S )Nc              3   2   K   | ]  }t        |        y wr   rg  )ro  r  s     r"   rq  z#version_to_tuple.<locals>.<genexpr>  s     YAQYrR  r  r   r2  )r   r'   r   r'  )r*  s    r"   version_to_tuplerm    s5    Ys);)C)CC)M)S)STW)XYYYr$   c                 d   t        j                  |       D ]  \  }}}|D ]  }|j                  t         j                  j	                  ||      t         j                  j                  t         j                  j	                  ||      t         j                  j	                  | d                     y )Nr2  )arcname)r|  walkr  r}  r  relpath)r}  ziphr  dirsfilesrY  s         r"   zipdirru    s    WWT] IdE 	IDJJrww||D$/!wwrww||D$/G/1ww||D#/F H  I	IIr$   c                 t    t         t        t        t        d}i }| |v r ||    |i |}| dz   t	        |      z   S )N)pms_image_proxyinfolibraryuserr   )rw  	info_pagelibrary_page	user_pager   )endpointr   r    	endpointsr  s        r"   pager    sN    *	I F9$8$d5f5c>If---r$   c                     i }| | |d<   |||d<   |||d<   |||d<   |||d<   |||d<   |||d<   |||d<   |||d	<   |	d
|d<   |
d
|d<   |S )Nimgrl  r  r  r  r  r  r  rm  r  refreshclipr   )r  rl  r  r  r  r  r  r  rm  r  r  r  s               r"   rw  rw    s     F
u)|w!x#y)|v)|%z"yvMr$   c                 6    i }|r|r||d<   n| |d<   |rd|d<   |S )Nguidrl  historysourcer   )rl  r  r  liver  s        r"   r{  r{    s1    Fv)|$xMr$   c                     i }| | |d<   |S )N
section_idr   )r  r  s     r"   r|  r|    s    F)|Mr$   c                 &    i }| | |d<   |||d<   |S )Nuser_idrz  r   )r  rz  r  s      r"   r}  r}  '  s+    F#yvMr$   c                 8   g }t         j                  dk(  r| j                         dk(  rt        j                  D cg c]*  }t         j
                  j                  d|z        s&d|z  , }}|D ]=  }t        j                  |j                  d            ||ddd}|j                  |       ? t         j
                  j                  |       rt         j
                  j                  |       } t         j
                  j                  |       s|S | t         j
                  j                  |       k7  r[t         j
                  j                  |       }t        j                  |j                  d            |ddd	d}|j                  |       nPt         j                  dk(  r=d
}t        j                  |j                  d            ||dd	d}|j                  |       t        j                  |       D ]"  \  }	}
}t        |
      D ]q  }|s|j!                  d      rt         j
                  j#                  |	|      }t        j                  |j                  d            ||ddd}|j                  |       s |dk(  r |S t        |      D ]  }|s|j!                  d      r|r|j%                  |      s+t         j
                  j#                  |	|      }t        j                  |j                  d            ||ddd}|j                  |         |S  |S c c}w )Nntzmy computerz%s:z%s:\zUTF-8rZ  )r  r}  rg  r]  iconz..zlevel-up-altzMy Computerr2  z.folderonlyrY  )r|  ra  ra  r\  ascii_uppercaser}  existsrg  rh  rb  r  isfiledirnameisdirrp  r  
startswithr  rW  )r}  include_hidden
filter_extoutputr
  drivesr  outparent_pathr  rs  rt  dir_pathr  	file_paths                  r"   browse_pathr  2  s   F	ww$4::<=8'-'='=[!PUXYPYAZ'A+[[ 	E''W(=>  C MM#	 
ww~~dwwt$77==rwwt$$ggood+##K$6$6w$?@"
 	c	D###K$6$6w$?@ "
 	cWWT]  dE 	A!all3&7ww||D!,H''(@A   C MM#	 && M#  	A!all3&7!**Z"8T1-I''	(8(8(AB!C MM#	 	ME D MQ \s   'L#Lc                     t        j                  d|        	 t        j                  |        y# t        $ r t        j
                  d|        Y yw xY w)Nz%Tautulli Helpers :: Deleting file: %sTz-Tautulli Helpers :: Failed to delete file: %sF)r   rx  r|  removeOSErrorr  )r  s    r"   delete_filer    sF    
KK7C
		) DiPs   . AAc                 ^    | j                  d      r| dd  j                         rd| dd  z  S | S )NzSeason    zS%s)r  r   rh  s    r"   short_seasonr    s7    	"uQRy'8'8':uQRy  Lr$   c                 >    d }d }| D ]  }|d   r|}|d   s|} ||fS )Nfirstfinalr   )markersr  r  markers       r"   get_first_final_markerr    s?    EE '?E'?E	
 %<r$   c                 |   t        |t              r|d   }t        |t              r|d   }t        |      }t        |      }t        j                  j
                  t        j                  j                  t        j                  j                  t        j                  j                  d}|j                  | d      dz  |z  }|syt        j                  j                  dk(  r|r||k\  S t        j                  j                  dk(  r|r||k\  S t        j                  j                  dk(  r|r|t        ||      k\  S ||k\  S )	Nstart_time_offset)movieepisodetrackr  r   r  Fr	  r&  rW  )r  r  r  rR  r  MOVIE_WATCHED_PERCENTTV_WATCHED_PERCENTMUSIC_WATCHED_PERCENTr  WATCHED_MARKERmin)
media_typeview_offsetr  marker_credits_firstmarker_credits_finalwatched_percent	thresholds          r"   check_watchedr    s   &-34GH&-34GHk*K8$H 44==334400	O  ##J2S88CI}}##q(-A222		%	%	*/C222		%	%	*/Cc)-ABBBi''r$   c                  n    t         j                  j                  xs t         j                  j                  S r   )rR  r  PMS_NAME_OVERRIDEPMS_NAMEr   r$   r"   pms_namer    s!    ==**Dfmm.D.DDr$   r-  returnc                 ^    	 t        t        |             t        u rdS dS # t        $ r Y yw xY w)NIPv4IPv6Invalid)r]  r   r   r  )r-  s    r"   r/  r/    s4    jn-<vH&H s       	,,c                     d}t        j                  d      }|j                  t        j                  j
                        rt        j                  j
                  }t        t        | |z   d      j                        S )Nz/64z)^/(1([0-1]\d|2[0-8]))$|^/(\d\d)$|^/[1-9]$F)strict)	r4  r  r  rR  r  NOTIFY_CONCURRENT_IPV6_CIDRr   r   network_address)r-  cidrcidr_patterns      r"   get_ipv6_network_addressr    sY    D::JKL&--CCD}}88z"T'%0@@AAr$   )F)FF)r  r   i )rY  )r   )r  r   )Fr3   )NN)r3   r3   r3   )r3   r3   r6  )	Nr   r  r  r  r   r_  r3   N)T)r   )r3   r2  )r3   )NNr   )NNNNNNNNNNN)NNNN)NFr3   )r  rg  rX  cloudinary.apir   cloudinary.uploaderr   cloudinary.utilsr   collectionsr   r   r   r	   	functoolsr
   r   	itertoolsr   future.moves.itertoolsr   r   	ipaddressr   r   r   rA  ipwhois.exceptionsipwhois.utilsIPyr   r  r   r  r|  r4  r  r3  r\  rL  r   rN  urllib.parser   xml.domr   r  rR  r   r   r   plexpy.api2r   r/   r5   r8   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r$  r+  r1  r9  rF  rW  r^  re  ri  rv  rz  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r  r  r0  r)  r(  rO  rT  r[  rt  rw  r  r  r  r  r  r  r  r  r  r  r  r	  r  r  r  r  r"  r%  r'  r0  r6  r5  r4  rA  rC  rG  rI  rM  rQ  rX  rc  rj  rm  ru  r  rw  r{  r|  r}  r  r  r  r  r  r  r   r/  r  r   r$   r"   <module>r     s  $    2 & + # - - #  6 9 9        	 	    
   "       D+\	5:'&5#'TQ52$	E@%P


) " .b

#L?
 D,6: klBF'T%!P12Rj,'3T3W5
" 6'T+	@1
5
"
(V7
Z
I.  CGIM6:>L^(:E  B B Br$   