
    g                       d dl Z d dlmZmZ d dlmZ d dlZd dlmZ d dl	Z	d dl
mZ d dlZd dlZd dlm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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lmZ d dlm Z! d Z"d/dZ#d0dZ$d1dZ%d2dZ&d3dZ d Z'd4dZ(d5dZ)d Z*d Z+d6dZ,d7dZ-d8dZ.d7d Z/d! Z0	 	 d9d"Z1	 	 	 d:d#Z2d7d$Z3d;d%Z4d<d&Z5d1d'Z6	 	 d=d(Z7d) Z8d* Z9 G d+ d,e      Z: G d- d.      Z;y)>    N)Counterdefaultdict)partial)groupby)
itemgetter)	Formatter)Optional)activity_processor)common)database)datafactory)logger)helpers)	notifiers)
pmsconnect)request)notifyc                  P   t         j                  } 	 | j                         }|n?|r,	 d|v rt        di | nd|v rt	        di | nt        di | | j                          Rt        j                  d       y # t        $ r"}t        j                  d|z         Y d }~Md }~ww xY w)N
newsletternotificationzATautulli NotificationHandler :: Notification thread exception: %sz>Tautulli NotificationHandler :: Notification thread exiting... )plexpyNOTIFY_QUEUEgetnotify_newsletterr   add_notifier_each	Exceptionr   	exception	task_doneinfo)queueparamses      ,/opt/Tautulli/plexpy/notification_handler.pyprocess_queuer%   /   s    E
>j6)%//#v-$V$%// 	! $ KKPQ  j  !dgh!hiijs   +A: :	B%B  B%c                     t        j                  dj                  |              t        |       D ]3  }t	        j
                  t              }d|_        |j                          5 y )NzVTautulli NotificationHandler :: Starting background notification handler ({} threads).)targetT)	r   r    formatrange	threadingThreadr%   daemonstart)num_threadsxthreads      r$   start_threadsr1   F   sO    
KKhoop{|}; !!7    c                 P   |st        j                  d       y | rt        j                  |       }nt        j                  |      }|r*|s(t        j                  d|z         t	        d|||d|}nd}|r|s|r|rt        j                  d|z         |s|rt        d||||d|}nt        dd	|i|}|st        j                  d
       y |D ]l  }	|st        |	d   |      r=d|	d   ||||d}
|
j                  |       t        j                  j                  |
       Rt        j                  d|	d   z         n |dk(  rat        j                  j                  |j                         dd       t        j                  j                  |j                         dd       y y )NzETautulli NotificationHandler :: Notify called but no action received.notifier_id)notify_actionzITautulli NotificationHandler :: Notifiers enabled for notify_action '%s'.)r6   stream_datatimeline_dataTzZTautulli NotificationHandler :: Notifiers enabled for notify_action '%s' (manual trigger).)r6   sessiontimelinemanual_triggerr6   zHTautulli NotificationHandler :: Failed to build notification parameters.id)r5   
parameters)r   r5   r6   r7   r8   r=   zfTautulli NotificationHandler :: Custom notification conditions not satisfied, skipping notifier_id %s.on_playon_concurrent)r7   r6   on_newdevicer   )r   debugr   get_notifiersnotify_conditionsbuild_media_notify_paramsbuild_server_notify_paramserrornotify_custom_conditionsupdater   r   putcopy)r5   r6   r7   r8   r;   kwargsnotifiers_enabled
conditionsr=   notifierdatas              r$   r   r   N   s   \]%33L &33-P`cppq ' 1]3>5B1 *01

 
n
LLu  yF  F  G-2 =;F<IBP= 6<	=J 4 >- >6<>J LLcd) 	XH!9htnak!l(,'/~)6'2)6&02 F###''-  F  IQ  RV  IW  W  X	X  	!0@0@0BUd ef0@0@0BUc de "r2   c                 "   t        j                  d       d}|rX| dk(  r4t        j                         }|j	                         }g }|r|d   D cg c]  }|d   |d   k(  s| }}t
        j                  j                  rt               }	|D ]u  }t        j                  |d         dk(  r(|	j                  t        j                  |d                Ft        j                  |d         dk(  sb|	j                  |d          w t        |	      t
        j                  j                  k\  }nt        |      t
        j                  j                  k\  }n| d	k(  rLt        j                          }
|
j#                  |d   t
        j                  j$                   
      }|d   |v}n@|d   dv rt        j&                  |d   |d         }| dk(  rmt
        j                  j(                  xsP |d   dk(  xr |t
        j                  j*                  k  xs' |d   dk(  xr |t
        j                  j,                  k  }n| dk(  r"t
        j                  j(                  xs |dk  }nd}n|d   dk(  rd}nvd}ns|rd}nn| dk(  r1d}t
        j                  j.                  sMt1        | |d   d          }n8| dk(  r1d}t
        j                  j2                  st1        | |d   d          }nd}t        j                  dj5                  |             |S c c}w )NzHTautulli NotificationHandler :: Checking global notification conditions.Fr?   sessionsuser_id
ip_addressIPv6IPv4r@   )rR   history_only
machine_id
media_type)movieepisodeclipview_offsetdurationon_stoprY   rZ   	on_resumec   Ttrackon_pmsupdatepms_download_infoversion)r6   tagon_plexpyupdateplexpy_download_infotag_namezQTautulli NotificationHandler :: Global notification conditions evaluated to '{}'.)r   rA   r   
PmsConnectget_current_activityr   CONFIGNOTIFY_CONCURRENT_BY_IPsetr   ip_typeaddget_ipv6_network_addresslenNOTIFY_CONCURRENT_THRESHOLDr   DataFactoryget_user_devicesNOTIFY_NEW_DEVICE_INITIAL_ONLYget_percentNOTIFY_CONSECUTIVEMOVIE_WATCHED_PERCENTTV_WATCHED_PERCENTNOTIFY_SERVER_UPDATE_REPEATcheck_nofity_tagNOTIFY_PLEXPY_UPDATE_REPEATr(   )r6   r7   r8   rK   	evaluatedpms_connectresultuser_sessionssip_addressesdata_factoryuser_devicesprogress_percents                r$   rC   rC      s   
LL[\I   O+$//1K 557FM,2:,> iq!I,R]^gRhBh i i}}44"u& :Aq76A$(()I)I!L/)Z[ <9VC$((<9	:
  -1Z1ZZ	.&--2[2[[	n,&224L'88YAWJP--JvJvFv 9 xL#L1EI&*FF&22;}3M{[eOfg	)#]]== u .'9t>NQWQ^Q^QtQt>tu .);s@PSYS`S`SsSs@s  +-"MM<<U@PSU@U	 !	&'1I I 
 		.	(	}}88,=178K1LY1WY YI 
+	+	}}88,=178N1OPZ1[] ]I
 	
LLdkkluvwM !js   L!Lc                 
   t        j                  |       }|d   }|d   }|st        d |D              r#t        j                  d| z         d }|r 	 t        j                  |t        |            }d g}t        |      D ]  \  }}	|	d
   }
|	d   }|	d   }|	d   }|j                  |
d      |
r|r|s2d}|j                  |       t        j                  d|dz   d|       et        |t              s|g}	 |dk(  r<|D cg c]0  }|dk(  rdn&t        |      j!                         j#                         2 }}nV|dk(  r#|D cg c]  }t        j$                  |       }}n.|dk(  r#|D cg c]  }t        j&                  |       }}nt        	 |dk(  r(t              j!                         j#                         n<|dk(  rt        j$                        n!|dk(  rt        j&                        nt        |dk(  rt        fd|D              }n)|dk(  rt)        fd |D              }n|d!k(  rt        fd"|D              }n|d#k(  rt)        fd$|D              }n|d%k(  rj+                  t-        |            }n|d&k(  rj+                  t-        |             }n|d'k(  rj/                  t-        |            }ny|d(k(  rj/                  t-        |             }nX|d)k(  rt        fd*|D              }n>|d+k(  rt        fd,|D              }n$d }t        j0                  d|dz   d-|d.|d       |j                  |       t        j                  d|dz   d/|
d0|d0d1j3                  |D cg c]  }d2|z  	 c}      d3d.|        |r3	 t        j4                  ||      }t        j                  d4|d5|       n^t)        |dd        }t        j                  d7d8j3                  t9        t        |            D cg c]
  }d9|dz   z   c}      d5|       t        j                  d:j;                  ||dd               |S y# t        $ r&}t        j                  d|d|d       Y d }~y	d }~ww xY wc c}w c c}w c c}w # t        $ r0}t        j                  d|dz   d|
d|d|d	       Y d }~ y	d }~ww xY w# t        $ r0}t        j                  d|dz   d|
dd|d	       Y d }~ y	d }~ww xY wc c}w # t6        $ r"}t        j                  d6|z         Y d }~y	d }~ww xY wc c}w );Nr4   custom_conditions_logiccustom_conditionsc              3   ,   K   | ]  }|d    s	|  yw)valueNr   ).0cs     r$   	<genexpr>z+notify_custom_conditions.<locals>.<genexpr>   s     %QAaja%Q   
z[Tautulli NotificationHandler :: Checking custom notification conditions for notifier_id %s.zHTautulli NotificationHandler :: Unable to parse custom condition logic 'z': .F	parameteroperatorr   type Tz!Tautulli NotificationHandler :: {   z} Blank condition > str~intfloatz} Unable to cast condition 'z', values 'z', to type 'z'.z} Unable to cast parameter 'z
', value 'containsc              3   &   K   | ]  }|v  
 y wNr   r   r   parameter_values     r$   r   z+notify_custom_conditions.<locals>.<genexpr>B  s     E_ 4E   zdoes not containc              3   &   K   | ]  }|v 
 y wr   r   r   s     r$   r   z+notify_custom_conditions.<locals>.<genexpr>E  s     IQ 8Ir   isc              3   (   K   | ]	  }|k(    y wr   r   r   s     r$   r   z+notify_custom_conditions.<locals>.<genexpr>H       E1 4E   zis notc              3   (   K   | ]	  }|k7    y wr   r   r   s     r$   r   z+notify_custom_conditions.<locals>.<genexpr>K  r   r   zbegins withzdoes not begin withz	ends withzdoes not end withzis greater thanc              3   (   K   | ]	  }|kD    y wr   r   r   s     r$   r   z+notify_custom_conditions.<locals>.<genexpr>Z       D! 3Dr   zis less thanc              3   (   K   | ]	  }|k    y wr   r   r   s     r$   r   z+notify_custom_conditions.<locals>.<genexpr>]  r   r   z} Invalid condition operator 'z' > z} z | z or z'%s'z > 'z1Tautulli NotificationHandler :: Condition logic: z > zNTautulli NotificationHandler :: Unable to evaluate custom condition logic: %s.z9Tautulli NotificationHandler :: Condition logic [blank]: z and z{%s}zTTautulli NotificationHandler :: Custom conditions evaluated to '{}'. Conditions: {}.)r   get_notifier_configanyr   rA   r   parse_condition_logic_stringrq   
ValueErrorrF   	enumerater   append
isinstancelistr   striplowercast_to_intcast_to_floatall
startswithtupleendswithwarnjoineval_logic_groups_to_boolr   r)   r(   )r5   r=   notifier_configr   r   logic_groupsr#   evaluated_conditionsi	conditionr   r   valuesparameter_typer}   vevaluated_logicr   s                    @r$   rG   rG      s1   33LO-.GH'(;<#%Q1B%Q"Qr"# 	$ "&CCD[]`ar]st !%v%&78 ^	~LAy!+.I ,Hw'F&v.N(nnY;O HF 	$++I6\]^_\_ajkl fd+ !U*RXYQAHb#a&,,.2F2F2HHYFY#u,>DEg11!4EFE#w.@FG1g33A6GFG %$!U*&)/&:&@&@&B&H&H&JO#u,&-&9&9/&JO#w.&-&;&;O&LO %$ :%EfEE	//I&II	T!EfEE	X%EfEE	]*+66uV}E	22 / : :5= II	[(+44U6]C	00 / 8 8v GG	..DVDD	^+DVDD	 !	 sHi9 : !''	2LLaCHfkkW]B^RS6A:B^6_apr{} ~{^	~@ ")"C"CLRf"g 7J K ""6qr":;OLL#LL%L]H^B_)`Q&AaC.)`acrt u 	krr1!"57 	8 u   7< =8 Z F H
   !!YH I&   !!YQ RV C_  mpqqr *as   Q :	R5R8RR R,R	RA)S;T 1T U	R
$RR
R	S%%SS	T!%TT	U"T??Uc                    t        j                  d| z         t        j                  |       }|sy |dv rJ|j	                  dd      }|j	                  dd      }t        j                  |j	                  dg             }	nA|d	   |   d   }
|d	   |   d   }t        |
||||d
   |d   j                  dd            \  }}}	t        |xs ||||||	|      }t        j                  d|d   |||	|||xs i d|}|rt        |       |S y )NzJTautulli NotificationHandler :: Preparing notification for notifier_id %s.r4   )testapisubjectTautullibodyzTest Notificationscript_argsnotify_textagent_idconfigas_jsonF)r   r   r6   r=   r   r   )r9   rN   r6   r   r   r   r=   r<   )r5   r   r   r   r6   notification_idr=   r   )r   r    r   r   popr   
split_argsbuild_notify_textr   set_notify_statesend_notificationset_notify_success)r5   r6   r7   r8   r=   rK   r   r   r   r   subject_stringbody_stringr   successs                 r$   r   r   ~  sT   
KK\_jjk33LO'**Y
3zz&"56((M2)FG )7FyQ%m4]CFK &7~<GERBL@OPZ@[?Nx?X?\?\]fhm?n&p"{ '{/Km0?5B/6,03>2<>O )) 4od6K29/36A8E:I5?5E24 -34G ?+ r2   c                     t        j                         }|j                  d| d   | d   | d   g      }g }|D ]"  }|d   |d   |d   d	}|j                  |       $ |S )
NzSELECT timestamp, notify_action, notifier_id FROM notify_log WHERE session_key = ? AND rating_key = ? AND user_id = ? ORDER BY id DESCsession_key
rating_keyrR   args	timestampr6   r5   )r   r6   r5   )r   MonitorDatabaseselectr   )r9   
monitor_dbr   notify_statesitemnotify_states         r$   get_notify_stater     s    ))+J  2 &-]%;W\=RT[\eTf$g  iF M +%)+%6)-o)>'+M':< 	\*	+ r2   c                     |rd}nd}t        j                         }|j                  d|d|| d   | d   | d   |g      }|S )	NzAND timestamp IS NOT NULLzAND timestamp IS NULLzSELECT id AS notifier_id, timestamp FROM notifiers LEFT OUTER JOIN (SELECT timestamp, notifier_id FROM notify_log WHERE session_key = ? AND rating_key = ? AND user_id = ? AND notify_action = ?) AS t ON notifiers.id = t.notifier_id WHERE z = 1 r   r   rR   r   )r   r   r   )r9   r6   notifiedtimestamp_wherer   r   s         r$   get_notify_state_enabledr     sh    51))+J 5B?	 T &-]%;W\=RT[\eTfhu$v  
xF Mr2   c                 <   | r|rt        j                         }|xs i }|rt        j                  |      nd }t	        j
                         |j                  dd       |j                  dd       |j                  dd       | d   | d   |d}|j                  dd       |j                  dd       |j                  d	d       | d
   |||d}	|dk(  r	|d   |	d<   n|dk(  r|d   |	d<   |j                  d||	       |j                         S t        j                  d       y )Nr   r   rR   r<   r   )r   r   r   rR   r5   r   r6   parent_rating_keygrandparent_rating_keyuser
agent_name)r   r   r   r   subject_text	body_textr   rb   update_versionre   rf   tautulli_update_version
notify_log
table_namekey_dict
value_dictz;Tautulli NotificationHandler :: Unable to set notify state.)r   r   jsondumpsr   r   r   upsertlast_insert_idr   rF   )
rN   r6   r   r   r   r9   r=   r   keysr   s
             r$   r   r     s(   M--/
-R1<djj-$$..0&{{=$?%kk,=";;y$7'~$Z0!.0 (/{{3F'M,3KK8PRV,W!++fd3 ( 6")#!,. N*&'78F5M//&'@AF5M\DVT((**RSr2   c                 d    d| i}ddi}t        j                         }|j                  d||       y )Nr<   r   r   r   r   )r   r   r   )r   r   r   r   s       r$   r   r     s8    /"D^F))+JPr2   c                 h    t        j                         }|j                  d| |g      }t        |      S )Nz<SELECT * FROM notify_log WHERE notify_action = ? AND tag = ?)r   r   select_singlebool)r6   re   r   r   s       r$   r{   r{     s:    ))+J%% 'L'4c&:<F <r2   c                 p;   t        j                  t        j                  j                        }t        j                  t        j                  j
                        }t        j                  t        j                  j
                  d      }|r|d   }n|r|d   }t        t              }	|r|j                  d      rqt        j                  |d         }
|
j                  dd        |
j                  dd        |
j                  dd        |
j                  dd        |j                  |
       |	j                  |       |r|	j                  |       i x}}d	|	v rUt        |	d	         d
kD  rD|	d	   d
   }d|v r8t        |d         d
kD  r'|j                  d      }t        d |D        |d
         }d|v r|j                  d      }|D cg c]  }|d   dk(  s| }}|D cg c]  }|d   dk(  s| }}|D cg c]  }|d   dk(  s| }}|r't        d |D        |d
         }|j                  |       |r't        d |D        |d
         }|j                  |       |r't        d |D        |d
         }|j                  |       |	j                  |       |	j                  |       t        j                          j#                        }g x}}|j                  dg       D ]:  }t        j                          j#                  |      }|s*|j%                  |       < |j                  dg       D ]:  }t        j                          j#                  |      }|s*|j%                  |       < |xs i }t'        j(                         }|j+                         }|j+                  |j                  d            }| dk(  rH|D cg c]  }t        |d         |	d   k7  s| }}|D cg c]  }t        |d         |	d   k7  s| }}t        |      }t        |      } t-        d |D              }!||!z
  }"t-        d |D              }#t-        d |D              }$|#|$z   }%|j                  dd      d k(  s|j                  d!d      d k(  rd"}&n/|j                  dd      d#k(  s|j                  d!d      d#k(  rd$}&nd%}&t/        d& |D              }'t/        d' |D              }(| d(k7  rt1        t        j2                         t        j4                  |j                  d)d
            z
  t        j4                  |j                  d*d
            z
        })t        j6                  |)      }*nd
})d
}*t        j8                  |j                  dd
            }+t        j8                  |	d+         },|,|+z
  }-t        j6                  |+      }.t        j6                  |,      }/|/|.z
  }0|	d,   d-k(  r|	d.   }1n|	d   }1d/j;                  t        j                  j<                  t        j                  j>                  |10      |	d1<   |	d,   d2k(  r|	d3   }2n|	d,   d4k(  r|	d5   }2n|	d6   }2|2D ]r  }3d7|3v r|3jA                  d7      d8   |	d9<   d:|3v r|3jA                  d:      d8   |	d;<   ;d<|3v r|3jA                  d<      d8   |	d=<   Wd>|3v s\|3jA                  d>      d8   |	d?<   t d@|	dA   v r,|	dA   jA                  d@      d8   jA                  dB      d8   |	dC<   d7|	dA   v s|	d9   rI|	d9   xs) |	dA   jA                  d7      d8   jA                  dD      d
   |	d9<   dE|	d9   z   |	dF<   dG|	d9   z   |	dH<   dI|	dA   v s|	d=   rn|	d,   dJk(  rdJndK}4|	d=   xs; |	dA   jA                  dI      d8   jA                  dB      d
   jA                  dD      d
   |	d=<   dL|4 dB|	d=    |	dM<   dN|	d=   z   dOz   |	dH<   n^dP|	dA   v rW|	dA   jA                  dP      d8   jA                  dB      d
   jA                  dD      d
   |	d=<   dQ|	d=    |	dM<   dN|	d=   z   dOz   |	dH<   dR|	dA   v s|	d;   r|	d,   dJk(  rM|	d;   xs) |	dA   jA                  dR      d8   jA                  dD      d
   |	d;<   dS|	d;   z   |	dT<   dU|	d;   z   dVz   |	dH<   ne|	d,   dWv r^|	d;   xs; |	dA   jA                  dR      d8   jA                  dB      d
   jA                  dD      d
   |	d;<   dX|	d;   z   |	dT<   dU|	d;   z   dOz   |	dH<   dY|	dA   v rXdBjC                  |	dA   jA                  dY      d8   jA                  dD      d
   jA                  dB      d dZ       |	d[<   d\|	d[   z   |	d]<   d>|	dA   v s|	d?   r3|	d,   d^k(  rd_|	d?   z   |	d`<   n|	d,   dak(  rdb|	d?   z   |	d`<   ndc|	d?   z   |	d`<   dd|	dA   v r[|	dA   jA                  dd      d8   jA                  dB      d
   jA                  dD      d
   jA                  de      d8   |	df<   dg|	df   z   |	dh<   t        j                  jD                  r|	d,   div r|	j                  d;      rY|	d,   d2k(  r|	dj   }5n|	d,   d4k(  r|	d.   }5n|}5tG        |5|	d,   |	d;   k      }6|6j                  d9      r2|6d9   |	d9<   dE|6d9   z   |	dF<   n|	j                  d=      s"|	j                  d9      s|	j                  dC      r|	d,   d2k(  r|	dj   }5|	dl   }7|	dm   }8dn}9n2|	d,   d4k(  r|	d.   }5|	do   }7|	dm   }8dn}9n|}5|	dp   }7|	dm   }8|	d,   dqk(  rdnndJ}9tI        |5|	j                  d=      |	j                  d9      |7|8|9r      }:|:j                  dd        |	j                  |:       |:j                  d9      rdE|:d9   z   |	dF<   |:j                  d;      rdsj;                  |	d;   |9dnk(  rdqndJ      |	dH<   t        j                  jJ                  r|	d,   dWv r
|	j                  d=      s"|	j                  d9      s|	j                  dC      r|	d,   d2k(  r|	dj   }5|	dl   }7n|	d,   d4k(  r|	d.   }5|	do   }7n|}5|	dp   }7tM        |5|	j                  d=      |	j                  d9      |7t      };|;j                  dd        |	j                  |;       |;j                  d=      r"dQ|;d=    |	dM<   dut        |	d=         z   dOz   |	dH<   |;j                  d9      rdE|;d9   z   |	dF<   dG|	d9   z   |	dH<   t        j                  jN                  r|	d,   dvv rd x}<x}=x}>x}?}@|	d,   d^k(  rd^}A|	dp   }<n<|	d,   dak(  rdw}A|	do   }<|	dp   }=|	dx   }?n"dy}A|	dz   xs |	dl   }<|	do   }=|	dp   }>|	dx   }?|	d{   }@tQ        A||<|=|>|?@|      }B|Bj                  dd        |	j                  |B       |	d,   d}v r|	d~   }C|	d   }D|	dp   }E|	d   }Fn|	d,   dv r$|	d~   xs |	d   }C|	d   }D|	do   d|	dp   }E|	d   }Fny|	d,   dv r$|	d   xs |	d   }C|	d.   }D|	dl   d|	do   }E|	d   }FnN|	d,   dk(  r>|	d   r|	d   jS                  dd      xs |	d~   }Cn|	d   xs |	d~   }C|	d   }D|	dp   }E|	d   }Fnd}Cd}Dd}Ed}F|	d,   dJk(  rdF }Gn|	d,   dWv rdF }Gnd}Gt        jT                  d      }H|	d   rdnd}IHdvr,tW        CDEI      }J|Jd   |Jd   d}K|	j                  |K       nqHdk(  rlt        j                  jX                  rRt[        CI      }LEt        j                  jX                  t        j\                  z   dz   |Lz   d}K|	j                  |K       |st        j                  j^                  r{|	d,   dv rt|	dp   }Md}Nd}O|	dp   }Pd}Qd}R|D Scg c]"  }S|Sd.   |k(  rt        j4                  Sd{         $ }T}Sta        |T      \  }U}V|U|V}X}Wd\  }Y}Zd\  }[}\d\  }]}^t        |T      }_d}`|	dm   }an|st        j                  jb                  r|	d,   dv r|	do   }M|	dp   }Nd}O|	do   }P|	dp   }Qd}Rt        |	d{         je                  d8      }Wt        |	d{         je                  dZ      }X|D Scg c]"  }S|Sd.   |k(  rt        j4                  Sd{         $ }b}Sta        |b      \  }U}V|U|V}Z}Y|U|V}^}]d\  }[}\d8}_t        |b      }`|	d   }an|	dl   }M|	do   }N|	dp   }O|	dl   }P|	do   }Q|	dp   }Rt        |	d         je                  d8      }Wt        |	d         je                  dZ      }Xt        |	d{         je                  d8      }Yt        |	d{         je                  dZ      }Zt        |	d         je                  d8      }[t        |	d         je                  dZ      }\t        |	d{         je                  d8      }]t        |	d{         je                  dZ      }^d8}_d8}`|	d   }a|	d   xs |	d   }cd}d|	d   jg                  d      r|	d   rt        jh                  |	d   d      }d|	d   }e|	d   jg                  d      rert        jh                  |	d   d      }e|j                  dt        t0                    }ftk        jl                         }g|gjo                         }hi dtp        jr                  dt        j                  jt                  dt        j                  jv                  dt        jx                  dt        jz                         dt        j                  j|                  dt        j                  j~                  dt        j                  j                  dt        j                  j>                  dt        j                  j                  dt        j                  j                  d| jA                  d      d   d|gj                  d|gj                  d|gj                  d|gj                  d|gj                  i d|gj                  d|hdZ   d|hd8   d|hd8   dt        |g|      dt        |g|      dt        j2                         dt        j                         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|	j                  ddܫ      d|	d)   r"t        tk        j                  |	d)         |      ndd|	d)   r"t        tk        j                  |	d)         |      ndi d|	d)   d|	d   r"t        tk        j                  |	d         |      ndd|	d   r"t        tk        j                  |	d         |      ndd|	d   d|*d|)dt        tk        j                  |)      |      d|0d|-dt        tk        j                  |-      |      d|.d|+dt        tk        j                  |+      |      dt        jh                  |+|,      d|j                  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fd   d|fd   dt        j4                  |fd         dt        j4                  |fd         d|	d   d |	d    d|	d   d|	d   i d|	d   d|	d   d|	d   dn|	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'   d(|	d(   i d)|	d)   d*|	d*   d+|	d+   d,|	d,   d-|	d-   d.|	d.   d/|	d/   d0|	d0   d1|	d1   d2|	d2   d3|	d3   d4|	d4   d5|	d5   d6|	d6   d7|	d7   d8|	d9   d:|	d;   i d<|	d<   d=|	d=   d>|	d>   d?|	d?   d@|	dA   dB|	dB   dC|	dC   dD|	dE   dF|	dF   dG|	dG   d|	d   dH|	dH   dI|	dI   d|	d   dJ|	dJ   d,|	d,   dK|	dK   i dp|	dL   dM|	dM   dNMdONdPOdQPdRQdSRdT|	dz   xs |	dl   dUWdVXdWYdXZdY[dZ\d[]d\^i d]_d^`d_|_d`|`dm|	dm   daadb|	dc   r#t        tk        j                  |	dc         |      nddd|	dc   r#t        tk        j                  |	dc         |      ndde|	df   r,t        tk        j                  t1        |	df               |      nddg|	dh   r,t        tk        j                  t1        |	dh               |      nddi|	dj   r,t        tk        j                  t1        |	dj               |      nddk|	dk   dl|	dl   dmdnjC                  |	dm         dodnjC                  |	do         dpdnjC                  |	dp         dqdnjC                  |	dq         i drdnjC                  |	dr         dsdnjC                  |	ds         dt|	dt   du|	du   dcdvddedw|	dw   d+|/dx|,dy|	d+   dzt        tk        j                  |,      |      d{|	d{   d||	d|   dC|	dC   d1|	d1   d}Fi d~Gd9|	d9   dF|	dF   d=|	d=   dM|	dM   d;|	d;   dT|	dT   d|	d   d|	d   d?|	d?   d`|	d`   df|	df   dh|	dh   d]|	d]   dH|	dH   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   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   d|	d   i d|	d   d|	d   d|	d   d|	d   d|	d   dt        j                  j                  |	d   jS                  dt        j                              dt        j                  |	d         d|	d   d|	d   dA|	dA   d|	d   d|	d   d.|	d.   dj|	dj   d|	d   d~|	d~   d|	d   |	d   Cd}i|	j                  |i       |	S c c}w c c}w c c}w c c}w c c}w c c}Sw c c}Sw (  NT)r]   r   raw_stream_infor<   r   stoppedr\   
media_infor   partsc              3   ,   K   | ]  }|d    s	|  ywselectedNr   )r   ps     r$   r   z,build_media_notify_params.<locals>.<genexpr>/  s     #F!*A#Fr   streamsr   123c              3   ,   K   | ]  }|d    s	|  ywr  r   r   r   s     r$   r   z,build_media_notify_params.<locals>.<genexpr>8        KqQz] Kr   c              3   ,   K   | ]  }|d    s	|  ywr  r   r  s     r$   r   z,build_media_notify_params.<locals>.<genexpr>;  r  r   c              3   ,   K   | ]  }|d    s	|  ywr  r   r  s     r$   r   z,build_media_notify_params.<locals>.<genexpr>>  s     #Q!1Z=A#Qr   )r   
child_keysgrandchild_keysrR   )rR   r^   c              3   2   K   | ]  }|d    dk(  sd  yw)locationlanr   Nr   r  s     r$   r   z,build_media_notify_params.<locals>.<genexpr>_  s     DAQz]e-CaDs   c              3   ^   K   | ]%  }|d    dk(  st        j                  |d          ' ywr  r  	bandwidthNr   r   r  s     r$   r   z,build_media_notify_params.<locals>.<genexpr>b  .     hQRS]Q^bgQg++AkN;h   --c              3   ^   K   | ]%  }|d    dk7  st        j                  |d          ' ywr  r  r  s     r$   r   z,build_media_notify_params.<locals>.<genexpr>c  r  r  stream_video_decisionr   	transcodestream_audio_decision	TranscoderJ   zDirect StreamzDirect Playc              3   &   K   | ]	  }|d      ywtranscode_decisionNr   r  s     r$   r   z,build_media_notify_params.<locals>.<genexpr>m  s     &Q1q)='>&Q   c              3   &   K   | ]	  }|d      ywr$  r   r  s     r$   r   z,build_media_notify_params.<locals>.<genexpr>n  s     +[A.B,C+[r&  r>   startedpaused_counterr]   rX   ra   r   zT{web_url}#!/server/{pms_identifier}/details?key=%2Flibrary%2Fmetadata%2F{rating_key})web_urlpms_identifierr   plex_urlrZ   grandparent_guidsseasonparent_guidsguidszimdb://r   imdb_idztmdb://themoviedb_idztvdb://
thetvdb_idzmbid://musicbrainz_idzplex://guid/plex_id?zhttps://www.imdb.com/title/imdb_urlzhttps://trakt.tv/search/imdb/	trakt_urlz
thetvdb://rY   serieszhttps://thetvdb.com/dereferrer/thetvdb_urlzhttps://trakt.tv/search/tvdb/z
?type=showzthetvdbdvdorder://z&https://thetvdb.com/dereferrer/series/themoviedb://z!https://www.themoviedb.org/movie/themoviedb_urlzhttps://trakt.tv/search/tmdb/z?type=movieshowr.  rZ   zhttps://www.themoviedb.org/tv/z	lastfm://   	lastfm_idzhttps://www.last.fm/music/
lastfm_urlartistzhttps://musicbrainz.org/artist/musicbrainz_urlalbumz https://musicbrainz.org/release/zhttps://musicbrainz.org/track/zhama://-anidb_idzhttps://anidb.net/anime/	anidb_url)rY   r@  r.  rZ   r   r   rX   r2  grandparent_titleyeartvparent_titletitler@  )r   r3  r1  rO  rL  rX   z'https://trakt.tv/search/tmdb/{}?type={})r   r3  r1  rO  zhttps://trakt.tv/search/tvdb/{})rD  rF  ra   releasechildren_count	recordingoriginal_titlemedia_index)musicbrainz_typer   rD  rP  rR  trackstnum)rY   r@  rD  thumbslug)r.  rF  parent_thumbz - parent_slug)rZ   ra   grandparent_thumbgrandparent_slugr[   
extra_typeartz/artz/thumbzhttps://watch.plex.tv/movie/zhttps://watch.plex.tv/show/)include_selflivezposter-liveposter)Nself-hosted)imgr   rO  fallback	img_titleimg_url)poster_title
poster_urlrc  )rd  re  zimage/)r@  rD  )r   r   parent_yearparent_media_indexgrandparent_yearratingaudience_ratingrating_imagerottentomatoes://
   audience_rating_image)rp  r=  markertautulli_versiontautulli_remotetautulli_branchtautulli_commitserver_name	server_ipserver_port
server_urlserver_machine_idserver_platformserver_versionactionon_current_yearcurrent_monthcurrent_daycurrent_hourcurrent_minutecurrent_secondcurrent_weekdaycurrent_weekweek_number	datestampr   unixtimeutctimelan_streamswan_streamsdirect_playszdirect playdirect_streams
transcodestotal_bandwidthlan_bandwidthwan_bandwidthuser_streamsuser_direct_playsuser_direct_streamsuser_transcodesr   friendly_nameusername
user_emailemail
user_thumbdeviceplatformplatform_versionproductproduct_versionplayerrS   zN/Astarted_datestampstarted_timestampstarted_unixtimestopped_datestampstopped_timestampstopped_unixtimestream_durationstream_duration_secstream_timeremaining_durationremaining_duration_secremaining_timeprogress_durationprogress_duration_secprogress_timer   initial_streamr%  container_decisionvideo_decisionaudio_decisionsubtitle_decisionquality_profileoptimized_versionoptimized_version_profilesynced_versionmarker_startstart_time_offset
marker_endend_time_offsetcredits_marker_firstfirstcredits_marker_finalfinalchannel_call_sign
channel_idchannel_identifierchannel_titlechannel_thumbchannel_vcnsecureunknownrelayedstream_locallocalstream_locationr  stream_bandwidthr  stream_containerstream_bitratestream_aspect_ratiostream_video_codecstream_video_codec_levelstream_video_bitratestream_video_bit_depthstream_video_chroma_subsamplingstream_video_color_primariesstream_video_color_rangestream_video_color_spacestream_video_color_trcstream_video_dynamic_rangestream_video_dovi_presentstream_video_dovi_levelstream_video_dovi_profilestream_video_frameratestream_video_full_resolutionstream_video_ref_framesstream_video_resolutionstream_video_scan_typestream_video_heightstream_video_widthstream_video_languagestream_video_language_codestream_audio_bitratestream_audio_bitrate_modestream_audio_codecstream_audio_channelsstream_audio_channel_layoutstream_audio_sample_ratestream_audio_languagestream_audio_language_codestream_subtitle_codecstream_subtitle_containerstream_subtitle_formatstream_subtitle_forcedstream_subtitle_languagestream_subtitle_language_codestream_subtitle_locationtranscode_containertranscode_video_codectranscode_video_widthtranscode_widthtranscode_video_heighttranscode_heighttranscode_audio_codectranscode_audio_channelstranscode_hw_requestedtranscode_hw_decodingtranscode_hw_decode_codectranscode_hw_decodetranscode_hw_decode_titletranscode_hw_encodingtranscode_hw_encode_codectranscode_hw_encodetranscode_hw_encode_titletranscode_hw_full_pipelinetranscode_key
session_idrW   library_name
full_titleedition_title	show_nameseason_nameepisode_nameartist_name
album_name
track_nametrack_artist
season_numseason_num00episode_numepisode_num00disc_num
disc_num00	track_numtrack_num00season_countepisode_countalbum_counttrack_count	show_yearrelease_dateoriginally_available_atair_date
added_dateadded_atupdated_date
updated_atlast_viewed_datelast_viewed_atstudiocontent_rating	directors, writersactorsgenreslabelscollectionssummarytaglinecritic_ratinguser_ratingduration_secduration_msduration_timerh  ri  	plex_slugplex_watch_url	tvmaze_id
tvmaze_url	containerbitrateaspect_ratiovideo_codecvideo_codec_levelvideo_bitratevideo_bit_depthvideo_chroma_subsamplingvideo_color_primariesvideo_color_rangevideo_color_spacevideo_color_trcvideo_dynamic_rangevideo_dovi_presentvideo_dovi_levelvideo_dovi_profilevideo_frameratevideo_full_resolutionvideo_ref_framesvideo_resolutionvideo_scan_typevideo_heightheightvideo_widthwidthvideo_languagevideo_language_codeaudio_bitrateaudio_bitrate_modeaudio_codecaudio_channelsaudio_channel_layoutaudio_sample_rateaudio_languageaudio_language_codesubtitle_codecsubtitle_containersubtitle_formatsubtitle_forcedsubtitle_locationsubtitle_languagesubtitle_language_codefilefilename\	file_sizefile_size_bytesindexes
section_id)r\  poster_thumb)Pr   momentjs_to_arrowr   rk   DATE_FORMATTIME_FORMATr   r   r   r   loadsr   rH   rq   nextr   ri   get_metadata_detailsr   r
   ActivityProcessorget_sessionssumr   r   r   r   seconds_to_minutesconvert_milliseconds_to_secondsr(   PMS_WEB_URLPMS_IDENTIFIERsplitr   THEMOVIEDB_LOOKUPget_themoviedb_infolookup_themoviedb_by_idTVMAZE_LOOKUPlookup_tvmaze_by_idMUSICBRAINZ_LOOKUPlookup_musicbrainz_inforeplaceget_img_serviceget_img_infoHTTP_BASE_URLset_hash_image_info	HTTP_ROOT'NOTIFY_GROUP_RECENTLY_ADDED_GRANDPARENTformat_group_index"NOTIFY_GROUP_RECENTLY_ADDED_PARENTzfillr   rv   arrownowisocalendarr   RELEASE
GIT_REMOTE
GIT_BRANCHCURRENT_VERSIONpms_namePMS_IPPMS_PORTPMS_URLPMS_PLATFORMPMS_VERSIONrL  monthdayhourminutesecondCustomArrowutc_now_isoospathbasenamesephuman_file_size)jr6   r9   r:   r;   rK   date_formattime_formatduration_formatr   notify_paramsr  r  media_part_infor  r
  r   video_streamsaudio_streamssubtitle_streamsvideo_streamaudio_streamsubtitle_streammetadatachild_metadatagrandchild_metadatakeychild
grandchildaprQ   r   stream_countuser_stream_countr  r  r  r  r  r%  transcode_decision_countuser_transcode_decision_countr  r  r  r;  r  r  r]   r  plex_web_rating_keyr0  r5  thetvdb_media_type
lookup_keythemoveidb_jsonlookup_titlelookup_yearlookup_media_typethemoviedb_infotvmaze_inforD  rP  rR  rV  rW  rU  musicbrainz_infors  
poster_keyrh  r>  r?  img_servicere  img_infoposter_infoimg_hashr  r  r  r  r  r  d	child_numnumnum00r  r  r  r  r  r  r  r  child_countgrandchild_countr$  grandchild_numrm  r9  rn  rs  r  now_isoavailable_paramssj                                                                                                             r$   rD   rD     sw-   ++FMM,E,EFK++FMM,E,EFK//0I0ITXYO \*
	l+
$M;;()"jj1B)CDOd+t4	40t4NN?+W%X& $&%J}$]<-H)IA)M"<03
j SG)<%=%ANN7+E"#Fu#FaQOO#!%%i0$+@qqyC/?@@$+@qqyC/?@@'.C!!F)s2BACC KM K][\M]^L""<0 KM K][\M]^L""<0"#Q/?#QScdeSfgO""?3$)$$&;;z;RH+--N(zz,+ )%%'<<<L!!%() zz+R0 3**,AASAQ
&&z23 mG		-	-	/B HOOGKK	,BOCM 	!'a!3q/?+@MR_D`+`Aaa$1kqS=9I5Jm\iNj5jkkx=LM*DDDK,KhXhhMhXhhM#m3O {{*B/;>'++NegiBjnyBy(	,b	1V	;w{{Kbdf?gkq?q,*&&Q&QQ$++[]+[$[!	!!!!#%%gkk)Q&?@A%%gkk2BA&FGH
 "445HI#CCGKKP]_`Dab::=;TUL),AA223HI)),7H!$55 \"g-+,?@+L9 v } }))}}33& !~ !(M* \"i/12	|	$	0n-g& G'+zz)'<Q'?M)$$-1ZZ	-B1-EM/*$*.**Y*?*BM,'$.2jj.CA.FM*+G M&))#0#8#>#>y#I!#L#R#RSV#WXY#Zi M&))]9-E#0#;#v}V?T?Z?Z[d?efg?h?n?nor?stu?vi $AMR[D\$\j!%D}U^G_%_k"}V,,l0K(5l(Cw(NWT\&3L&A  'N]SYEZE`E`amEnopEqEwEwx{E|}~E  FF  FF  GJ  FK  LM  FNl#)HI[H\\]^klx^y]z'{m$%D}UaGb%beq%qk"	v!6	6&3F&;&A&ABV&WXY&Z&`&`ad&efg&h&n&nor&stu&vl#)OP]^jPkOl'mm$%D}UaGb%beq%qk"-//=3Q&'1-:?-K  .M}]cOdOjOjkzO{|}O~  PE  PE  FI  PJ  KL  PMM/*.QTabqTr.rM*+)H=YhKi)ily)yM+&<(,II-:?-K  .[}]cOdOjOjkzO{|}O~  PE  PE  FI  PJ  KL  PM  PS  PS  TW  PX  YZ  P[M/*.NQ^_nQo.oM*+)H=YhKi)ilx)xM+&mF++%(XXmF.C.I.I+.VWX.Y._._`c.def.g.m.mnq.rsutu.v%wk"&B]S^E_&_l#M&))];K-L&(2/PS`aqSr/rM+,<(G3/QTabrTs/sM+,/OR_`pRq/qM+,M&))$1&$9$?$?	$J1$M$S$STW$XYZ$[$a$abe$fgh$i$o$ops$tuv$wj!%?-PZB[%[k" }}&&=+FJp+p_-\*i7*+CD
|,8*+>?
'
1Z=J<=X@Mo@^`O ""9-+:9+Ei(,IO\eLf,fj)|,0A0A)0LP]PaPabkPl\*i7*+CD
,-@A+F3$(!|,8*+>?
,^<+F3$(!'
,W5+F3,9,,G6,QDW^!5ANARARS_A`>K>O>OPY>Z<H;FARTO d3  1""9-,IO\eLf,fj)""?3-V-]-]!/2>OSW>WF]d.fk* }}""}\'BFc'c\*m.?.?	.JmN_N_`iNj\*i7*+CD
,-@A|,8*+>?
,^<'
,W5-9F9J9J<9X6C6G6G	6R4@BK OOL$/  -|,1WXcdpXqWr/sm,-NQTUbcoUpQq-q  uA  .Ak*y),IKXaLb,bj)-L}]fOg-gk* }}''M,,GKg,g7;;;;9;v&(2'"7+F<(G3(">2F#G,G"#34F*"#34ZFY8ZF#N3G%g.I"#34F /D2DTak:@']fou8<> 	\40-.\"&AA$W-"<0
$W-!&)		|	$(;	;$W-N~1N"<0
$1.$A$1'$:<!-0		|	$(<	<$^4ZFY8Z"#67
$12E$F$1.$AC!"45		|	$	.&(/77Ic][bMcL(8RM'<RL"<0
$W-!&)	
	\"g-7	{C	|	$(E	E6ykB))t<K -f 5}8H//LZ|fno'/'<HU^L_`[)		%&--*E*E&<(K'3%+]]%@%@6CSCS%SV^%^ai%ik[)	6==PP,'+==!'*	#G,

 (6_"#;N9OS]9] ((m _	 _'	2
U#&L
%+"]%*!'	;)n!&)	V]]MML)-@@!.1	#G,#N3"7+

}56<<Q?
=78>>qA (6_"#;N9OS]9] "--m _ _'7
U%(%]!$e;	%*~.!-0	 ""56	#N3$W-#$78">2
"7+
';<=CCAF
=)=>?EEaH-67==a@M-89??B}%9:;AA!D';<=CCAF
m45;;A>	-67==a@!"45	8$H6G(HFM^$//0CDh'++M(,CRH#$56O,-889_`!--m<M.NPRSZZ+c"23F
))+CooG[
FNN[
 	6==33[
 	6==33	[

 	611[
 	w'')[
 	V]]))[
 	v}}--[
 	fmm++[
 	V]]99[
 	6==55[
 	&--33[
 	-%%e,R0[
 	[
 	[
  	sww![
" 	#[
$ 	#**%[
& 	#**'[
( 	71:)[
* 	
+[
, 	wqz-[
. 	[k2/[
0 	[k21[
2 	G%%'3[
4 	7&&(5[
8 	<9[
: 	{;[
< 	{=[
> 	0??[
@ 	26:A[
B 	.{;C[
D 	?E[
F 	G[
H 	I[
J 	)K[
L 	:=IM[
N 	<VDO[
P 	8EQ[
R 	o.S[
T 	M&)U[
V 	mG,W[
X 	mL1Y[
Z 	-)[[
\ 	M*-][
^ 	M*<=_[
` 	=+a[
b 	=):;c[
d 	-)e[
f 	m''e<g[
h 	^klu^v[=3K)LkZ|~i[
j 	^klu^v[=3K)LkZ|~k[
l 	M)4m[
n 	^klu^v[=3K)LkZ|~o[
p 	^klu^v[=3K)LkZ|~q[
r 	M)4s[
t 	?u[
v 	2w[
x 	{599-@#A?Sy[
z 	0{[
| 	!"8}[
~ 	+eii0F&GY[
@ 	.A[
B 	 !6C[
D 	UYY/D%EWE[
F 	G//0E|TG[
H 	w{{=!4I[
J 	-(89K[
L 	0M[
N 	m,@AO[
P 	-(89Q[
R 	-(89S[
T 	]+>?U[
V 	=):;W[
X 	]+>?Y[
Z 	$]3N%O[[
\ 	-(89][
^ 	f%_[
` 	23a[
b 	f./c[
d 	 3 3F7O De[
f 	 3 3F7O Dg[
h 	]+>?i[
j 	mL1k[
l 	m,@Am[
n 	7o[
p 	7q[
r 	}]3s[
t 	}X6>)MRZD[u[
v 	=+w[
x 	g.y[
z 	=4{[
| 	M+6}[
~ 	M*<=[
@ 	-(89A[
B 	}-BCC[
D 	m,@AE[
F 	#M2L$MG[
H 	.D EI[
J 	!-0H"IK[
L 	*=9Z+[M[
N 	'6T(UO[
P 	#M2L$MQ[
R 	#M2L$MS[
T 	!-0H"IU[
V 	%m4P&QW[
X 	$]3N%OY[
Z 	"=1J#K[[
\ 	$]3N%O][
^ 	!-0H"I_[
` 	'6T(Ua[
b 	"=1J#Kc[
d 	"=1J#Ke[
f 	!-0H"Ig[
h 	}-BCi[
j 	m,@Ak[
l 	 /F!Gm[
n 	%m4P&Qo[
p 	.D Eq[
r 	$]3N%Os[
t 	m,@Au[
v 	 /F!Gw[
x 	&}5R'Sy[
z 	#M2L$M{[
| 	 /F!G}[
~ 	%m4P&Q[
@ 	 /F!GA[
B 	$]3N%OC[
D 	!-0H"IE[
F 	!-0H"IG[
H 	#M2L$MI[
J 	(7V)WK[
L 	#M2L$MM[
N 	}-BCO[
P 	 /F!GQ[
R 	 /@!AS[
T 	!-0B"CU[
V 	 /F!GW[
X 	#M2L$MY[
Z 	!-0H"I[[
\ 	 /F!G][
^ 	$]3H%I_[
` 	$]3N%Oa[
b 	 /F!Gc[
d 	$]3H%Ie[
f 	$]3N%Og[
h 	%m4P&Qi[
j 	}]3k[
l 	7m[
n 	mL1o[
p 	=+q[
r 	mL1s[
v 	mL1w[
x 	n5y[
z 	|,{[
| 	7}[
~ 	Y[
@ 	{A[
B 	C[
D 	{E[
F 	jG[
H 	jI[
J 	&67]=I\;]K[
L 	jM[
N 	O[
P 	{Q[
R 	S[
T 	HU[
V 	jW[
X 	YY[
Z 	{[[
\ 	][
^ 	)_[
` 	{a[
b 	'c[
d 	f%e[
f 	Yg[
h 	67 $EIIm<U.V$WYde=?k[
l 	67  		-8Q*R SU`a=?o[
p 	Z( "%))Cj0I,J"K[Y.0s[
t 	\* $EIIc-2M.N$OQ\]02w[
x 	-. (		#mDT6U2V(WYde46{[
| 	-)}[
~ 	-(89[
@ 	TYY}[9:A[
B 	499]956C[
D 	$))M(34E[
F 	$))M(34G[
H 	$))M(34I[
J 	tyy}!=>K[
L 	=+M[
N 	=+O[
P 	&Q[
R 	-S[
T 	?U[
V 	}]3W[
X 	HY[
Z 	[[
\ 	}Z0][
^ 	UYY|%<oN_[
` 	n5a[
b 	mL1c[
d 	=+e[
f 	M*-g[
h 	Yi[
j 	.k[
l 	=+m[
n 	M*-o[
p 	mL1q[
r 	}]3s[
t 	7u[
v 	-(89w[
x 	];/y[
z 	mL1{[
| 	-(89}[
~ 	=):;[
@ 	M*-A[
B 	];/C[
D 	mL1E[
F 	];/G[
H 	];/I[
J 	=+K[
L 	n5M[
N 	}]3O[
P 	]+>?Q[
R 	7S[
T 	=):;U[
V 	#M2L$MW[
X 	 /F!GY[
Z 	]+>?[[
\ 	]+>?][
^ 	=):;_[
` 	}-BCa[
b 	m,@Ac[
d 	M*<=e[
f 	m,@Ag[
h 	=):;i[
j 	 /F!Gk[
l 	M*<=m[
n 	M*<=o[
p 	=):;q[
r 	h/s[
t 	}W-u[
v 	-(89w[
x 	}-BCy[
z 	7{[
| 	m,@A}[
~ 	}]3[
@ 	-(89A[
B 	.D EC[
D 	]+>?E[
F 	-(89G[
H 	}-BCI[
J 	-(89K[
L 	m,@AM[
N 	=):;O[
P 	=):;Q[
R 	]+>?S[
T 	]+>?U[
V 	!-0H"IW[
X 	f%Y[
Z 	BGG$$]6%:%B%B4%PQ[[
\ 	W,,];-GH][
^ 	=5_[
` 	=+a[
b 	f%c[
d 	mL1e[
f 	mL1g[
h 	]+>?i[
j 	!-0H"Ik[
l 	}U#m[
n 	w'o[
p 	n5q[
r ++>?$u[
z )*Q A@CJ bkn_4_sU   AvAvAv,Av6AvAvAv$Av$%Av)?Av)'Av.@'Av3c           	         t         j                  j                  j                  dd      }t         j                  j                  j                  dd      }t        j                         j                         }t        t        |j                  di             }t        t        |j                  di             }t        t        |j                  di             }dx}}	|r5|j                  dg       }
|
D ]  }|d   dk(  r|d	   }|d   d
k(  s|d	   }	  t        j                         }|j                         }i dt        j                   dt         j                  j"                  dt         j                  j$                  dt         j&                  dt)        j*                         dt         j                  j,                  dt         j                  j.                  dt         j                  j0                  dt         j                  j2                  dt         j                  j4                  dt         j                  j6                  d| j9                  d      d   d|j:                  d|j<                  d|j>                  d|j@                  d|jB                  i d|jD                  d|d    d!|d"   d#|d"   d$tG        ||      d%tG        ||      d&t)        jH                         d't)        jJ                         d(|d)   d*|d+   d,|d-   d.|d/   d0|d1   d2|d3   d4|d5   d6|d7   d8|d9   i d:|d;   r"tG        t        j                  |d;         |      ndd<|d=k(  rd>nd?d@|dA   dB|dC   dD|dE   dF|dG   dH|dI   dJ|dK   dL|dM   dN|dO   dP|dQ   dR|dS|	dT|dU   dV|dW   dX|j                  dYd      dZ|j                  d[d      d\|d]   i}|S )^NDor   rc   rg   remote_access_infoassetscontent_typez-application/vnd.microsoft.portable-executablebrowser_download_urlz#application/vnd.apple.installer+xmlrt  ru  rv  rw  rx  ry  rz  r{  r}  r~  r|  r  r  r  r  r  r  r  r  r  r  rA  r  r   r  r  r   r  r  remote_access_mapping_statemapping_stateremote_access_mapping_errormapping_errorremote_access_public_addresspublic_addressremote_access_public_portpublic_portremote_access_private_addressprivate_addressremote_access_private_portprivate_portremote_access_reasonreasonr   rd   
update_urldownload_urlupdate_release_dater%  update_channelbetaBetaPublicupdate_platformr  update_distrodistroupdate_distro_buildbuildupdate_requirementsrequirementsupdate_extra_info
extra_infoupdate_changelog_addedchangelog_addedupdate_changelog_fixedchangelog_fixedr   rh   tautulli_update_release_urlhtml_urltautulli_update_exetautulli_update_pkgtautulli_update_tartarball_urltautulli_update_zipzipball_urltautulli_update_commitplexpy_update_committautulli_update_behindplexpy_update_behindtautulli_update_changelogr   )&r   rk   ru  r  rv  r   ri   get_server_update_channelr   r   r   r   r  r  r  r   r  r  r  r  r   r  r  r  r  r  r  r  r  rL  r  r  r  r  r  r  r   r  )r6   rK   r  r  r  rc   rg   r  windows_exe	macos_pkgrelease_assetsassetr  r  r  s                  r$   rE   rE     sA   --++33D<K--++33D<K**,FFHN#C4G)LM&sFJJ7Mr,RS$S&**5I2*NO  K)-11(B?# 	:E^$(WW#$:;~&*OO!"89			: ))+CooG:
FNN:
 	6==33:
 	6==33	:

 	611:
 	w''):
 	V]])):
 	v}}--:
 	fmm++:
 	6==55:
 	&--33:
 	V]]99:
 	-%%e,R0:
 	:
 	:
  	sww!:
" 	#:
$ 	#**%:
& 	#**':
( 	71:):
* 	
+:
, 	wqz-:
. 	[k2/:
0 	[k21:
2 	G%%'3:
4 	7&&(5:
8 	&'9/'J9:
: 	&'9/'J;:
< 	'(:;K(L=:
> 	$%7%F?:
@ 	();<M)NA:
B 	%&8&HC:
D 	 28 <E:
H 	+I6I:
J 	'7K:
L 	 0  +5995F~5V+WYde68O:
P 	Nf$<&(Q:
R 	,Z8S:
T 	*84U:
V 	09W:
X 	0@Y:
Z 	.|<[:
\ 	!"34E"F]:
^ 	!"34E"F_:
b 	"#7
#Cc:
d 	&';J'Ge:
f 	{g:
h 	yi:
j 	3MBk:
l 	3MBm:
n 	!&**-CR"Ho:
p 	!&**-CR"Hq:
r 	$%9&%As:
x r2   c                    |dk(  rdx}}nKt        fdt        j                         D        i       }	|	j                  dd      }|	j                  dd      }t	        | t
              st        j                  d       |} t	        |t
              st        j                  d       |}|j                  d      }
d	}|
d
k(  rGt        j                  |j                  dd      t        j                  t        j                  z        }n|
dk(  rGt        j                  |j                  dd      t        j                  t        j                  z        }n|
dk(  rGt        j                  |j                  dd      t        j                  t        j                  z        }nb|
dk(  rGt        j                  |j                  dd      t        j                  t        j                  z        }n|
dk(  rFt        j                  |j                  dd      t        j                  t        j                  z        }n|
dk(  rFt        j                  |j                  dd      t        j                  t        j                  z        }n|
dk(  rFt        j                  |j                  dd      t        j                  t        j                  z        }n5t        j                  |t        j                  t        j                  z        }t        t        j                  |d|       |      j                  d      } t        t        j                  |d|      |      j                  d      }g }|r| |fS t!        t"        |       }|dk(  r*	 t%        j&                  |       D cg c]
  } ||       }}n|d#k(  s|r|d$k(  rd%nd&}| r	 t/        j0                  |       } | r*	 t/        j4                  t%        j6                  | |            } |r	 t/        j0                  |      }|r=	 t/        j4                  t%        j6                  ||            }n	  ||       } 	  ||      }| ||fS c c}w # t(        $ r$}t        j                  d!|z         g }Y d }~2d }~wt*        $ r$}t        j,                  d"|z         g }Y d }~]d }~ww xY w# t2        $ r)}t        j                  d'|d(|d)       d} Y d }~d }~ww xY w# t(        $ r)}t        j                  d*|d+|d,       d} Y d }~d }~wt*        $ r)}t        j,                  d'|d-|d)       d} Y d }~Nd }~ww xY w# t2        $ r%}t        j                  d.|z         d}Y d }~gd }~ww xY w# t(        $ r%}t        j                  d/|z         d}Y d }~Yd }~wt*        $ r%}t        j,                  d0|z         d}Y d }~d }~ww xY w# t(        $ r>}t        j                  d1|z          t        |      j8                  d5i |} Y d }~d }~wt*        $ r>}t        j,                  d2|z          t        |      j8                  d5i |} Y d }~d }~ww xY w# t(        $ r>}t        j                  d3|z          t        |      j8                  d5i |}Y d }~^d }~wt*        $ r>}t        j,                  d4|z          t        |      j8                  d5i |}Y d }~d }~ww xY w)6N   r   c              3   4   K   | ]  }|d    k(  s|  yw)nameNr   )r   ar6   s     r$   r   z$build_notify_text.<locals>.<genexpr>9  s      sQXYZ`XaerXrqss   r   r   zETautulli NotificationHandler :: Invalid subject text. Using fallback.zBTautulli NotificationHandler :: Invalid body text. Using fallback.rX   z<movie>.*?</movie>|<show>.*?</show>|<season>.*?</season>|<episode>.*?</episode>|<artist>.*?</artist>|<album>.*?</album>|<track>.*?</track>rY   z<movie>.*?</movie>z<movie>|</movie>r@  z<show>.*?</show>z<show>|</show>r.  z<season>.*?</season>z<season>|</season>rZ   z<episode>.*?</episode>z<episode>|</episode>rD  z<artist>.*?</artist>z<artist>|</artist>rF  z<album>.*?</album>z<album>|</album>ra   z<track>.*?</track>z<track>|</track>z 	
)r=   z`Tautulli NotificationHandler :: Unable to parse parameter %s in script argument. Using fallback.z\Tautulli NotificationHandler :: Unable to parse custom script arguments: %s. Using fallback.      MQTTwebhookz7Tautulli NotificationHandler :: Unable to parse custom z json header data: z. Using fallback.z:Tautulli NotificationHandler :: Unable to parse parameter z in z header data. Using fallback.z header data: zbTautulli NotificationHandler :: Unable to parse custom webhook json body data: %s. Using fallback.zbTautulli NotificationHandler :: Unable to parse parameter %s in webhook body data. Using fallback.z]Tautulli NotificationHandler :: Unable to parse custom webhook body data: %s. Using fallback.zeTautulli NotificationHandler :: Unable to parse parameter %s in notification subject. Using fallback.z`Tautulli NotificationHandler :: Unable to parse custom notification subject: %s. Using fallback.zbTautulli NotificationHandler :: Unable to parse parameter %s in notification body. Using fallback.z]Tautulli NotificationHandler :: Unable to parse custom notification body: %s. Using fallback.r   )rx  r   available_notification_actionsr   r   r   r   rF   recompiler  
IGNORECASEDOTALL	strip_tagsubr   r   
str_formatr   r   LookupErrorr   r   r   rw  r   r   traverse_mapr(   )r   r   r6   r=   r   r   r   default_subjectdefault_bodydefault_actionrX   all_tagspatternr   str_formatterargr#   agents     `               r$   r   r   4  s[   2~)++,s)*R*R*Tsuwx(,,Y;%))&"5 gs#\]!dC YZ-JEH
 W**X--.BDVWY[YfYfikirirYrs	v	**X--.@BRSUWUbUbegenenUno	x	**X--.DFZ[]_]j]jmomvmv]vw	y	 **X--.FH^_acananqsqzqzaz{	x	**X--.DFZ[]_]j]jmomvmv]vw	w	**X--.BDVWY[YfYfikirirYrs	w	**X--.BDVWY[YfYfikirirYrs**Xr}}ryy'@A wG4h?EEiPGRVVGR.9??	JDK}J:>M2~	9@9K9KG9TU#=-UKU 
R7"b.i**W- **W%9%9'=%QR zz$' zz'"6"6t]"KL	@#G,G	: &D D+%%{ V 	LL{~  AK 	{~  AK	    CH  JK  L  M    CD  FK  L  M     BG  IJ  "K  L    B  EF  F  G    B  EF  F  G     "A  DE  "E  F  	@LL  A  DE  E  F1c/*11?J?G 	@  CD  D  E1c/*11?J?G	@  	:LL}  AB  B  C+3|$++9j9D 	:|  @A  A  B+3|$++9j9D	:s   =Q Q#Q 9R6 )S+ =U )V  W 	Y- Q 	R3$RR3R..R36	S(?S##S(+	U4TU$UU	U>U99U>	W
V**W6WW	Y*'3X  Y*,3Y%%Y*-	[963Z//[9;3[44[9c                    t        j                  dd |       } |dk(  r2g g g dgdgd}t        j                  | |j	                         |d      } n|d	k(  r_i d
g dg dg dg dg dg dg dg dg ddgdg ddgddgddgdg ddg}t        j                  | |j	                         |d      } n.|dv rn)i }t        j                  | |j	                         |d      } | j                  dd      j                  d d!      S )"Nz{.+?}c                 b    | j                         j                  dd      j                  dd      S )N<%temp_lt_token%>%temp_gt_token%)groupr  )ms    r$   <lambda>zstrip_tag.<locals>.<lambda>  s)    aggi&7&7=N&O&W&WX[]n&o r2      hrefcolor)br   ur  fontT)tags
attributesr      r;  strongr   emr<  insr   strikedelspanclassz
tg-spoilerr  ztg-emojizemoji-idcodepre
blockquote
expandable)rq        r  r2  r1  r4  r3  )r  r#  bleachcleanr   r  )rO   r   	whitelists      r$   r"  r"    s   66(oquvD1}!(%Y	(	
 ||Dy~~'7IUYZ	R

S" 

h 

"

"B

"

#R

 "

 '

 -22

 gY	

 )5b	


 6(

  *

 gY

 B

 "L>

	 ||Dy~~'7IUYZ	%	% 	||Dy~~'7IUYZ <<)3/778I3OOr2   c                 (   t        |       } g }g }t        t        |       d       D ]  \  }}t        t	        t        d      |            }t        |      t        |      }}||k(  rA|j                  dj                  |             |j                  dj                  |             |j                  dj                  ||             |j                  dj                  ||              dj                  |      xs ddj                  |      xs d	fS )
Nc                     | d   | d   z
  S )Nr   r   r   )i_xs    r$   r7  z$format_group_index.<locals>.<lambda>  s    3q6#a&= r2   r   z{0:01d}z{0:02d}z{0:01d}-{1:01d}z{0:02d}-{1:02d},000)sortedr   r   r   mapr   minmaxr   r(   r   )
group_keysr  r  kgr5  g_ming_maxs           r$   r  r    s    
#J
CE	*-/HI 	A1SA*+5z3u:uE>JJy''./LL))%01JJ(//u=>LL*11%?@	A 88C=C%!8D88r2   c	           	         ddd}	|s| s|	S |r8| s6|r#|j                  d      rdj                  |      } ndj                  |      } | j                  d      r1| j                  d      }
dj                  |
d d       } |
d	   }||k7  r|}t	        j
                         }||	S |d
k(  r5|dk(  rd\  }}n|r|j                  d      rd\  }}nd\  }}| |||ddd|d}n| |||||||d}t        j                         } |j                  dd|i|}|r|d   }	n|s| rt        j                         } |j                  dddi|}|rw|d   rrdx}}|dk(  r t	        j                  |d   |||      \  }}n!|d
k(  rt	        j                  |d   |||      }|r&t        di |}|j                  |||||       ||d}	|	d   r,|d
k(  r'||||||||d}t	        j                   di |}|r||	d<   |	S )Nr   )rf  rg  r_  /library/metadata/{}/art/library/metadata/{}/thumb/library/metadatar6        
cloudinarycover)  rh  )i  i8  )rh    d   000000r   rd  r   rZ  rX  opacity
backgroundblurre  servicerefreshTimgur)img_datarf  r   re  )r  rf  rg  delete_hashrp  rg  )r   rZ  rX  rm  rn  ro  re  rf  r   )r   r(   r  r   r   r  r   rs   r  r   ri   	get_imageupload_to_imgurupload_to_cloudinaryr  set_img_infocloudinary_transform)rd  r   rO  rZ  rX  rm  rn  ro  re  r  	img_splitimg_rating_keyrp  wh
image_infor   database_img_infor~   r   rg  rt  r  transformed_urls                           r$   r  r    s   B/Hc#++E2,33J?C.55jAC
~~)*IIcN	hhy!}%"1''J%%'G	L	 wDAq(--e4DAqDAq $.  !!$$,"*,
 !$.$ &!($.""*,
 **,L111P'PZP$Q'3 ++-&&&BtBzBfQi$&&Gk'!'.'>'>q	INJTHP(R$ L(!66q	AFBL@HJ
 .<<))849296A29	 * ; */7C	w,6$.$ &!($.""*#(*
 "66DD"1HYOr2   c	                 B   |s| s|S |r8| s6|r#|j                  d      rdj                  |      } ndj                  |      } | j                  d      r1| j                  d      }	dj                  |	d d       } |	d   }
||
k7  r|
}dj                  t        j
                  j                  | |||||||	      }t        j                  |j                  d	            j                         }|r7d
|i}| |||||||d}t        j                         }|j                  d||       |S )Nr_  ra  rb  rc  r6  rd  re  z{}.{}.{}.{}.{}.{}.{}.{}zutf-8r  rl  image_hash_lookup)r   r   )r   r(   r  r   r   rk   PMS_UUIDhashlibsha256encode	hexdigestr   r   r   )rd  r   rZ  rX  rm  rn  ro  re  	add_to_dbrz  r{  
img_stringr  r   r   dbs                   r$   r  r  O  s-    c#++E2,33J?C.55jAC
~~)*IIcN	hhy!}%"1''J*11ZUY[ceJ~~j//89CCEHH% * "$ *&( %%'
		%	HOr2   c                 Z    t        j                         }d}|j                  || g      }|S )Nz2SELECT * FROM image_hash_lookup WHERE img_hash = ?r   )r   r   r   )r  r  queryr   s       r$   get_hash_image_infor  w  s1    		!	!	#B@Ee8*5FMr2   c                    t        j                         }	 d}|j                  || g      }|si }|r%t	        j                  dj                  |             nK|r%t	        j                  dj                  |             n$t	        j                  dj                  |             |s|r&|rd|ind|i}t        j                  d	|
      \  }	}
}n$|r d|i}t        j                  d|
      \  }	}
}n|S |	r|
s|	j                         }|j                  di       j                  dd      }|j                  di       j                  dd      }|j                  dd      }|j                  dd      }d|i}| |||t        j                  |      d}|j                  d||       |j                  |       |j                  d       |S |
r$t	        j                   dj                  |
             |r$t	        j                  dj                  |             |S # t        $ r$}t	        j
                  d|z         i cY d }~S d }~ww xY w)NzMSELECT imdb_id, tvmaze_id, tvmaze_url FROM tvmaze_lookup WHERE rating_key = ?r   zbTautulli NotificationHandler :: Unable to execute database query for lookup_tvmaze_by_tvdb_id: %s.zKTautulli NotificationHandler :: Looking up TVmaze info for thetvdb_id '{}'.zHTautulli NotificationHandler :: Looking up TVmaze info for imdb_id '{}'.z@Tautulli NotificationHandler :: Looking up TVmaze info for '{}'.thetvdbimdbz"http://api.tvmaze.com/lookup/showsr"   qz)https://api.tvmaze.com/singlesearch/shows	externalsr   r<   urlr@  )r   r3  r1  rA  tvmaze_jsontvmaze_lookupr   r  "Tautulli NotificationHandler :: {}4Tautulli NotificationHandler :: Request response: {})r   r   r   r   r   r   rA   r(   r   request_response2r   r   r   r   rH   r   rF   )r   r3  r1  rO  r  r  r  r#   r"   responseerr_msgreq_msgr  r@  rA  r   s                   r$   r  r  ~  s(   		!	!	#B'&&uJ<&@
 LLfmmnxyzLLcjjkrstLL[bbchij0:i,@QF)0)B)B4V*E&Hgw5\F)0)B)B;F*L&Hgw G"--/K$b9==iLJ!ook26::62FG#b1I$3J+D)3)3&-)3*.**[*A	CK
 II4KIXt$OOM*  AHHQRSZZ[bcde  x{||}	s   H 	H?H:4H?:H?c                 `   t        j                         }	 d}|j                  || g      }|sOi }|r%t	        j                  dj                  |             nL|r%t	        j                  dj                  |             n%t	        j                  dj                  ||             dt        j                  j                  i}
|s|r8|rdnd	|
d
<   t        j                  dj                  |xs |      |
      \  }}}n=|r9|r7|r5||
d<   ||
d<   t        j                  dj                  |      |
      \  }}}n|S |r|s|j                         }|j                  d      r|d   d   d   }n<|j                  d      r|d   d   d   }n|j                  d      r|d   d   d   }nd}|rdj                  ||      }t        | ||      }d|i}| ||xs |j                  d	      |t        j                   |      d}|j#                  d||       |j%                  |       |j'                  d       |S |r$t	        j(                  dj                  |             |r$t	        j                  dj                  |             |S # t        $ r$}	t	        j
                  d|	z         i cY d }	~	S d }	~	ww xY w)NzeSELECT thetvdb_id, imdb_id, themoviedb_id, themoviedb_url FROM themoviedb_lookup WHERE rating_key = ?r   zfTautulli NotificationHandler :: Unable to execute database query for lookup_themoviedb_by_imdb_id: %s.zWTautulli NotificationHandler :: Looking up The Movie Database info for thetvdb_id '{}'.zTTautulli NotificationHandler :: Looking up The Movie Database info for imdb_id '{}'.zQTautulli NotificationHandler :: Looking up The Movie Database info for '{} ({})'.api_keytvdb_idr1  external_sourcez$https://api.themoviedb.org/3/find/{}r  r  rL  z&https://api.themoviedb.org/3/search/{}
tv_resultsr   r<   movie_resultsresultsr    https://www.themoviedb.org/{}/{}rJ  r2  )r   r3  r1  r>  themoviedb_jsonthemoviedb_lookupr   r  r  r  )r   r   r   r   r   r   rA   r(   r   rk   THEMOVIEDB_APIKEYr   r  r   r   r  r   r   rH   r   rF   )r   r3  r1  rO  rL  rX   r  r  r  r#   r"   r  r  r  themoviedb_find_jsonr2  r>  r  r   s                      r$   r  r    s   		!	!	#B'**5
|*D
 LLryy  {E  F  GLLovvw~  ALLlssty{  A  BV]]<<=5?	YF$%)0)B)B6==j>SGT]c*e&Hgwt
#F7O!F6N)0)B)B8??
KTZ*\&Hgw #"G#+==? #''5 4\ B1 Ed K%))/: 4_ Ea H N%)))4 4Y ? B4 H "!C!J!J:Wd!e"5AKDQ#S (71;1;.5.W9L9LY9W5C6:jj6Q	#% 		%84Tc	d&&t,##$56  AHHQRSZZ[bcdC  |  @A  A  	B	s   J   	J-	J("J-(J-c                 ~   |dv rd}t        j                         }	 d}|j                  || g      }|r	 t        j                  |d         S i }t	        j                  dj                  |             dt        j                  j                  i}t        j                  d	j                  ||      |
      \  }	}
}|	r}|
s{|	j                         }|d   }dj                  ||      }d|i}| |j                  d      |t        j                   |      d}|j#                  d||       |j%                  |       |S |
r$t	        j&                  dj                  |
             |r$t	        j                  dj                  |             |S # t        $ r$}t	        j
                  d|z         i cY d }~S d }~ww xY w#  Y oxY w)Nr?  rM  zBSELECT themoviedb_json FROM themoviedb_lookup WHERE rating_key = ?r   z]Tautulli NotificationHandler :: Unable to execute database query for get_themoviedb_info: %s.r  zZTautulli NotificationHandler :: Looking up The Movie Database info for themoviedb_id '{}'.r  z"https://api.themoviedb.org/3/{}/{}r  r<   r  r2  r1  )r   r1  r>  r  r  r   r  r  )r   r   r   r   r   r   r   rw  rA   r(   r   rk   r  r   r  r   r   r   rH   rF   )r   rX   r2  r  r  r   r#   r  r"   r  r  r  r>  r   r  s                  r$   r  r    s   22
		!	!	#B'!!%zl!;
 	::f%6788 O
LLmtt  vC  D  E889F!(!:!:;_;f;fgq  tA  <B  KQ  "RHgw"--/'-;BB:}]/)3&5&9&9)&D-;.2jj.I 			04O	\t$  LL=DDWMNLLOVVW^_`Q  svwwx		s(   F F7 	F4F/)F4/F47F<c           	         t        j                         }	 d}|j                  ||g      }	|	st        j                  t        j                  t        j                  d       | dk(  rKt	        j                  dj                  | |             t        j                  |dd	      }|d
   r|d
   d   }	n| dk(  rNt	        j                  dj                  | ||             t        j                  |||dd      }|d   r^|d   d   }	nU| dk(  rPt	        j                  dj                  | |||             t        j                  |||||dd      }|d   r|d   d   }	|	rf|	d   }d| z   dz   |z   }d|i}||| t!        j"                  |	      d}	|j%                  d||	       |	j'                  |       |	j)                  d       |	S t	        j
                  d       |	S # t        $ r$}
t	        j
                  d|
z         i cY d }
~
S d }
~
ww xY w)NzeSELECT musicbrainz_id, musicbrainz_url, musicbrainz_type FROM musicbrainz_lookup WHERE rating_key = ?r   z\Tautulli NotificationHandler :: Unable to execute database query for lookup_musicbrainz: %s.zhttps://tautulli.comrD  zHTautulli NotificationHandler :: Looking up MusicBrainz info for {} '{}'.Tr   )rD  strictlimitzartist-listr   rP  zMTautulli NotificationHandler :: Looking up MusicBrainz info for {} '{} - {}'.)rD  rP  rV  r  r  zrelease-listrR  zRTautulli NotificationHandler :: Looking up MusicBrainz info for {} '{} - {} - {}'.)rD  rP  rR  rV  rW  r  r  zrecording-listr<   zhttps://musicbrainz.org/r6  r4  )r   rE  rU  musicbrainz_jsonmusicbrainz_lookupr   r  z>Tautulli NotificationHandler :: No match found on MusicBrainz.)r   r   r   r   r   r   musicbrainzngsset_useragentr   PRODUCTr  rA   r(   search_artistssearch_releasessearch_recordingsr   r   r   rH   r   )rU  r   rD  rP  rR  rV  rW  r  r  r  r#   r   r4  rE  r   s                  r$   r  r  :  s=   		!	!	#B'++E+E
 $$NNNN"	
 x'LL $$*F+;V$DF#22&UVWFm$#)-#8#; *LL ))/0@&')RT#3367[a;?qJFn%#).#9!#< ,LL ..4f5EvwXa.bd#55VW`i=C$=ALF &'#)*:#;A#> -d3N8;KKcQTbbO$n5D.83B4D48JJ?O4P R II!5QaIb##D)  !34
  KKXYi  ruvvw	s   G 	H"H;HHc                 r    t               }t        | t              r |j                  t        |       fi |S | S r   )CustomFormatterr   r   r(   )r   r=   custom_formatters      r$   r$  r$  y  s7    &(!S&&&s1v<<<Hr2   c                    | j                  d      } t        t        j                  t        j                  t        j
                  t        j                  t        j                  t        d}|j                  |       t        | dd      }|j                  D ]!  }||vst        dj                  |             t        |di i|      S )N`)r   divmodr   r   rq   roundr   z<string>evalzUse of {name} not allowed)r  __builtins__)r   r   r   helper_divmodr   r   
helper_lenhelper_roundr   rH   r  co_names	NameErrorr(   r  )
field_namerK   allowed_namesrH  r  s        r$   str_evalr    s    !!#&J''&&""!!%%M  :z62D K}$7>>D>IJJK ~r*M::r2   c                   J     e Zd ZddZd Z fdZ fdZ fdZ	 ddZ xZ	S )	r  c                     || _         t        j                  d      | _        t        j                  d      | _        ddd| _        y )Nz`.*?`z{.*(`.*?`).*}z	%%colon%%z%%exclamation%%):!)defaultr  r  
eval_regexeval_replace_regexeval_replace)selfr  s     r$   __init__zCustomFormatter.__init__  s;    **X."$**-=">"
r2   c                    ||S |dk(  rt        |      S |dk(  rt        |      S |dk(  rt        |      j                         S |dk(  rt        |      j                         S |dk(  rt        |      j	                         S |S )Nr   rr<  lr   )r   reprupperr   rO  )r  r   
conversions      r$   convert_fieldzCustomFormatter.convert_field  s    L3u:3;3u:##%%3u:##%%3u:##%%Lr2   c                 Z   |j                  d      r|j                  d      rt        j                  d      }t        j                  ||      }|r|r|j                         }t        |      j                  d      D cg c]  }|j                          }}|d   xs d }|d   xs d }	|t        j                  |      }|	t        j                  |	      }	|d   s|dz   }	d	j                  |t        ||	               }|S 	 t        t        | ?  ||      S c c}w # t         $ r |cY S w xY w)
N[]z/\[(?P<start>-?\d*)(?P<slice>:?)(?P<end>-?\d*)\]rT  r-   endslicer   r1  )r   r   r  r  match	groupdictr   r  r   r   r   r   r  superr  format_fieldr   )r  r   format_specr+  r  groupsr/   itemsr-   r  	__class__s             r$   r  zCustomFormatter.format_field  s!   !!#&;+?+?+Djj!STGHHWk2E*,/J,<,<S,ABqBBw/4Um+t$#//6E?!--c2Cg!)C		%eS(9":;L_d@TT C  s   ?DD D*)D*c                     t        |t              r+|j                  || j                  j	                  |            S t
        t        |   |||      S r   )r   r   r   r  r(   r  r  	get_value)r  r  r   rK   r  s       r$   r  zCustomFormatter.get_value  sC    c3::c4<<#6#6s#;<<$9#tVLLr2   c              #     K   t        j                  | j                  |      D ]J  }|}| j                  j	                         D ]  \  }}|j                  ||      } |j                  ||      }L t        t        | #  |      }|D ]V  \  }}}	}
|r4| j                  j	                         D ]  \  }}|j                  ||      } d}|r||z  }|
r|d|
z   z  }|	r|d|	z   z  }d }d }t        j                  | j                  |      }t        j                  | j                  d|      }|j                  d      }t        |      dk(  r|d   j                  dd	      }|d
   }|j                  d      }t        |      dk(  r|d
   j                  dd	      }|d   }|s|r6d |j                  | z   dz   }t        | j                  |            \  }}}	}
}}|||	|
||f Y y w)Nr   r  r  z{}r1  rA  r   z\n
r   r3  {})r  findallr  r  r  r  r  r  parser  r#  r  rq   r(   rx  )r  format_stringr  replacedr\  r   parsedliteral_textr  r  r  real_format_stringprefixsuffixmatchestemp_format_stringprefix_splitsuffix_split_r  s                      r$   r  zCustomFormatter.parse  s    ZZ 7 7G 	CEH))//1 21#++Aq12)11%BM		C 3MBAG "	T=L*k: --335 :DAq!+!3!3Aq!9J: "$"j0""cJ&66""cK&77"FFjj2DEG!#?Q!R-33C8L< A%%a00=%1!_"-33C8L< A%%a00=%1!_"%(+D+=+D+Dg+N%NQT%T"?CDJJOaDb?c<:{J1
KVVSSE"	Ts   GG!c           	         |dk  rt        d      g }| j                  |      D ]d  \  }}	}
}}}|r|j                  |       |	!|	dk(  r |du rt        d      t        |      }	|dz  }n|	j	                         r|rt        d      d}t
        j                  j                  rA|	j                  d      r0|	j                  d      r	 t        |	|      }|j                  |	       n'| j#                  |	||      \  }}|j                  |       | j%                  ||      }| j'                  |
||||dz
  |	      \  }
}| j)                  ||
      }|s,|r|j                  |       |j                  |       |sT|j                  |       g dj+                  |      |fS # t        t        t         t        f$ r#}t        j                   d|	|       |	}Y d }~d }~ww xY w)
Nr   zMax string recursion exceededr   FzJcannot switch from manual field specification to automatic field numberingr   r  zLTautulli NotificationHandler :: Failed to evaluate notification text %s: %s.)auto_arg_index)r   r  r   r   isdigitr   rk   NOTIFY_TEXT_EVALr   r   r  ro   SyntaxErrorr  	TypeErrorr   rF   	get_fieldr  _vformatr  r   )r  r  r   rK   	used_argsrecursion_depthr  r   r  r  r  r  r  r  objr#   arg_usedformatted_fields                     r$   r  zCustomFormatter._vformat  s   Q<==QUQ[Q[\iQj 9	.ML*k:vvl+ %
 #%.( *5 6 6 "%^!4J"a'N'')%( *5 6 6
 &+N==11j6K6KC6PU_UhUhilUm)&z6:!j1 %)NN:tV$LMCMM(+ ((j9 /3mmvq0#1 /< /3+^ #'"3"3C"E"f-MM/2f-s9	.x wwv..; (J	J )%s%/4()s   FG8GG)z{{{0}}})r   )
__name__
__module____qualname__r  r  r  r  r  r  __classcell__)r  s   @r$   r  r    s*    
 .M,T^ !"A/r2   r  c                   h    e Zd Zd	dej                  j                  dee   fdZdedefdZdefdZ	y)
r  Narrow_valuedefault_formatc                      || _         || _        y r   )r
  r  )r  r
  r  s      r$   r  zCustomArrow.__init__=  s    &,r2   	formatstrreturnc                     t        |      dkD  r| j                  j                  |      S | j                  | j	                  | j                        S t        | j                        S )Nr   )rq   r
  r(   r  
__format__r   )r  r  s     r$   r  zCustomArrow.__format__A  sW    y>A##**955*??4#6#6774##$$r2   c                 $    | j                  d      S )Nr   )r  )r  s    r$   __str__zCustomArrow.__str__J  s    r""r2   r   )
r  r  r  r  Arrowr	   r   r  r  r  r   r2   r$   r  r  <  sC    -EKK$5$5 -xPS} -%C %C %# #r2   r  )r   )NNNNF)NNN)NN)NNNNN)T)r   r   r   NN)NNNFr   )r   r   NNNFF)	NNr   rh  ri  rj  rk  r   N)	NNi  rh  rj  rk  r   NT)NNNN)NNNNNN)NNNNNNN)<rN  r6  r   r   	functoolsr   r  	itertoolsr   r   r   r   r  r  stringr   r*   typingr	   r  r  r   r
   r   r   r   r   r   r   r   r   plexpy.newsletter_handlerr   r   r%   r1   r   rC   rG   r   r   r   r   r{   rD   rE   r   r"  r  r  r  r  r  r  r  r  r$  r  r  r  r   r2   r$   <module>r     s$  $  ,      	 	       %         AR.=f@aHIX/d&,!THQNbSlr&j&PR9( JNDHfR FJKO"&%P9xHV2j jn.2<~;&f/i f/R# #r2   