
    g"5                    6   d dl Z d dlmZ d dlm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m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mZ 	 d dlmZ d d	lmZ d d
lm Z  d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'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/ i a0i 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/d0d1d2d3d4d5d6d7d8d9d:d;d<d=d>d?d@dAZ1dBdBg ddCgZ2g dDg dDg dEdFZ3dG Z4ddHZ5ddIZ6ddJZ7ddKZ8ddLZ9ddMZ:ddNZ;ddOZ<ddPZ=ddQZ>dR Z?dS Z@ G dT dUeA      ZB G dV dWeA      ZC G dX dYeC      ZD G dZ d[eC      ZE G d\ d]eC      ZF G d^ d_eC      ZG G d` daeC      ZH G db dceC      ZI G dd deeC      ZJ G df dgeC      ZK G dh dieC      ZL G dj dkeC      ZM G dl dmeC      ZN G dn doeC      ZO G dp dqeC      ZP G dr dseC      ZQ G dt dueC      ZR G dv dweC      ZS G dx dyeC      ZT G dz d{eC      ZU G d| d}eC      ZV G d~ deC      ZW G d deC      ZX G d deC      ZY G d deC      ZZ G d deC      Z[ G d deC      Z\ G d deC      Z] G d deC      Z^ G d deC      Z_d Z`d Zay# e"$ r dZ!Y %w xY w)    N)defaultdict)MIMEMultipart)MIMEText)	urlencode)urlparse)HTTPBasicAuth)hashes)AESGCM)
PBKDF2HMACTF)common)database)helpers)logger)
mobile_app)
pmsconnect)request)usersgrowlprowl   xbmc   plex   
pushbullet   pushover   osx   boxcar	   email
   twitter   ifttt   telegram   slack   scripts   facebook   browser   join                                    )discord	remoteappgroupmemqttzapierwebhookplexmobileapplunaseamicrosoftteamsgotifyntfy )	parameteroperatorvaluetype)isis notzis greater thanzis less than)containszdoes not containrP   rQ   zbegins withzdoes not begin withz	ends withzdoes not end with)floatintstrc                   J   ddt         d   t        ddddt         d   t        ddddt         d   t        ddd	d
t         d
   t        ddddt         d   t
        ddddt         d   t        ddddt         d   t        ddddt         d   t        ddddt         d   t        ddddt         d   t        ddddt         d   t        ddddt         d   t        ddddt         d   t        ddddt         d   t        dddd t         d    t        ddd!d!t         d!   t         ddd"d#t         d#   t"        ddd$d%t         d%   t$        d&dd'd(t         d(   t&        ddd)d*t         d*   t(        ddd+d,t         d,   t*        ddd-d.t         d.   t,        ddd/d0t         d0   t.        ddd1d2t         d2   t0        ddd3d4t         d4   t2        ddd5d6t         d6   t4        ddd7d8t         d8   t6        ddg} t9               j;                         r"| j=                  d9d:t         d:   t8        dd       | S );NTautulli Remote ApprA   )all)labelnameidclassaction_typesBoxcarr!   Browserr1   Discordr@   Emailr#   Facebookr/   GotifyrI   GroupMerB   Growlr   IFTTTr'   Joinr3   Kodir   LunaSearG   Microsoft TeamsrH   MQTTrC   rJ   Plex Home Theaterr   Plex Android / iOS ApprF   )on_play
on_createdon_newdeviceProwlr   
Pushbulletr   Pushoverr   Scriptr-   Slackr+   Telegramr)   Twitterr%   WebhookrE   ZapierrD   zmacOS Notification Centerr   )	AGENT_IDSTAUTULLIREMOTEAPPBOXCARBROWSERDISCORDEMAILFACEBOOKGOTIFYGROUPMEGROWLrf   JOINXBMCLUNASEAMICROSOFTTEAMSrk   NTFYPLEXPLEXMOBILEAPPPROWL
PUSHBULLETPUSHOVERSCRIPTSSLACKTELEGRAMTWITTERWEBHOOKZAPIEROSXvalidateappend)agentss    !/opt/Tautulli/plexpy/notifiers.pyavailable_notification_agentsr   g   s   -"{+)'	 !x('	 " y)'	 " y)'	  w''	 #!z* '	 !x('	 " y)'	  w''	  w''	 v&'	 v&'	 " y)'	 *'/0&'	 v&'	 v&'	 ,v&'	 1&/%H	  w''	 %#|,"'	 #!z* '	 ! y)'	  w''	 #!z* '	 " y)'	 " y)'	 !x('	ybFJ u~~ ;$&u- #'/	 	 M    c                 `   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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d/d%d+dd0d1d2dd3d4ddd5d6d7dd8d9ddd:d;d<dd=d>ddd?d@dAddBdCdddDdEdFddGdHdIddJdKdLddMdNdOddPdQdRddSdNdOddTdUdVddWdNdOddXdYdZdd[dNdOdd\d]d^dd_d`dOddadbdcdddd`dOddedfdgddhdidOdg}t        |       j                         rPt        djk      j                  t	        |       i       j                  dlg       }dm|vr|D cg c]  }|dn   |v s| }}|S c c}w )oNzPlayback Startrn   z0Trigger a notification when a stream is started.zTautulli ({server_name})z*{user} ({player}) started playing {title}.zfa-play)movieepisodetrack)rY   rZ   descriptionsubjectbodyiconmedia_typeszPlayback Stopon_stopz0Trigger a notification when a stream is stopped.z&{user} ({player}) has stopped {title}.zfa-stopzPlayback Pauseon_pausez/Trigger a notification when a stream is paused.z%{user} ({player}) has paused {title}.zfa-pausezPlayback Resume	on_resumez0Trigger a notification when a stream is resumed.z&{user} ({player}) has resumed {title}.zPlayback Erroron_errorz9Trigger a notification when a stream encounters an error.z>{user} ({player}) encountered an error trying to play {title}.zfa-exclamation-trianglezTranscode Decision Change	on_changez@Trigger a notification when a stream changes transcode decision.z={user} ({player}) has changed transcode decision for {title}.zfa-exchange-altzIntro Markeron_introzDTrigger a notification when a video stream reaches any intro marker.z:{user} ({player}) has reached an intro marker for {title}.zfa-bookmark)r   zCommercial Markeron_commercialzITrigger a notification when a video stream reaches any commercial marker.z>{user} ({player}) has reached a commercial marker for {title}.)r   r   zCredits Marker
on_creditszFTrigger a notification when a video stream reaches any credits marker.z;{user} ({player}) has reached a credits marker for {title}.Watched
on_watchedzYTrigger a notification when a stream reaches the specified watched or listened threshold.z&{user} ({player}) has watched {title}.zfa-eyezBuffer Warning	on_bufferzLTrigger a notification when a stream exceeds the specified buffer threshold.z'{user} ({player}) is buffering {title}.z
fa-spinnerzUser Concurrent Streamson_concurrentzKTrigger a notification when a user exceeds the concurrent stream threshold.z-{user} has {user_streams} concurrent streams.zfa-arrow-circle-o-rightzUser New Devicerp   z=Trigger a notification when a user streams from a new device.z0{user} is streaming from a new device: {player}.z
fa-desktopzRecently Addedro   zKTrigger a notification when a media item is added to the Plex Media Server.z#{title} was recently added to Plex.zfa-download)r   showseasonr   artistalbumr   zPlex Server Down
on_intdownzOTrigger a notification when the Plex Media Server cannot be reached internally.zThe Plex Media Server is down.z	fa-server)serverzPlex Server Back Upon_intupz]Trigger a notification when the Plex Media Server can be reached internally after being down.z!The Plex Media Server is back up.zPlex Remote Access Down
on_extdownzOTrigger a notification when the Plex Media Server cannot be reached externally.zEThe Plex Media Server remote access is down. ({remote_access_reason})zPlex Remote Access Back Upon_extupz]Trigger a notification when the Plex Media Server can be reached externally after being down.z/The Plex Media Server remote access is back up.zPlex Update Availableon_pmsupdatezMTrigger a notification when an update for the Plex Media Server is available.zLAn update is available for the Plex Media Server (version {update_version}).z
fa-refreshzTautulli Update Availableon_plexpyupdatezDTrigger a notification when an update for the Tautulli is available.zHAn update is available for Tautulli (version {tautulli_update_version}).zTautulli Database Corruptionon_plexpydbcorruptz`Trigger a notification if Tautulli database corruption is detected when backing up the database.zZTautulli database corruption detected. Automatic cleanup of database backups is suspended.zfa-databaseTreturn_dictr]   rX   rZ   )rU   isdigitget_notify_agentsgetrT   )agent_idactionsr]   as       r   available_notification_actionsr     s   )!Q5D!< )!Q5@!< *"P5?"< +#Q5@!< *"Z5X1< 5#a5W)< ("e5T%+ -'j5X%3 *$g5U%3 #$z5@ < *#m5A$< 3'l5G1< +&^5J$< *$l5=%a ,$p58#* /"~5;#* 3$p5_#* 6"~5I#* 1&n5f$* 5)e5b$* 8,  B5t%*AhGT 8}(T:>>s8}bQUUVdfhi$")GQQvY,-FqGGGN Hs   D+#D+c                     t        |       j                         rBt        d      j                  t	        |       i       j                  dt
              } ||      S y )NTr   r\   config)rU   r   r   r   rT   Notifier)r   r   agents      r   get_agent_classr     sI    
8}!d377HrJNNwX`aF##r   c                     | rt               D ci c]  }|d   |
 c}S t        d t        t               d       D              S c c}w )Nr[   c              3   &   K   | ]	  }|d      ywrZ   N .0r   s     r   	<genexpr>z$get_notify_agents.<locals>.<genexpr>  s     fq6f   c                     | d   S )NrY   r   )ks    r   <lambda>z#get_notify_agents.<locals>.<lambda>  s    Z[\cZd r   )key)r   tuplesortedr   r   s     r   r   r     sD    $A$CDq$
DDfF+H+JPd$efff Es   Ac                 |    | rt               D ci c]  }|d   |
 c}S t        d t               D              S c c}w )NrZ   c              3   &   K   | ]	  }|d      ywr   r   r   s     r   r   z%get_notify_actions.<locals>.<genexpr>  s     Eq6Er   )r   r   r   s     r   get_notify_actionsr     s<    &D&FG&	1GGE$B$DEEE Hs   9c                 (   t               }dx}x}}g }| s|r]d}| r|dz  }|j                  |        |r||v rd|z  }|j                  d       |dj                  ||fD cg c]  }|s|	 c}      z  }t        j                         }|j                  ddj                  |      d	|d
|      }	|	D ]R  }
t        t        t        |
j                               D cg c]  }||v s|
j                  |       c}            |
d<   T |	S c c}w c c}w )NrK   zWHERE znotifiers.id = ?z%s = ?r   z AND zoSELECT notifiers.id, notifiers.agent_id, notifiers.agent_name, notifiers.agent_label, notifiers.friendly_name, , z, MAX(notify_log.timestamp) AS last_triggered, notify_log.success AS last_success FROM notifiers LEFT OUTER JOIN notify_log ON notifiers.id = notify_log.notifier_id z GROUP BY notifiers.idargsactive)r   r   r3   r   MonitorDatabaseselectrT   anylistkeyspop)notifier_idnotify_actionnotify_actionswherewhere_idwhere_actionr   wdbresultitemr   s               r   get_notifiersr     s    ')N&((E(H|Dm**HKK$]n<#m3LKKN8\*BHQaqHII		!	!	#BYY YY~&	/ 6:  	F  cStDIIK7H!`!AQ_L_$((1+!`abXc M# I "as   D

'D

	D%Dc                     t        j                         }t        |       j                         r-t	        j
                  d| z         |j                  d| g      }yy)Nz@Tautulli Notifiers :: Deleting notifier_id %s from the database.z"DELETE FROM notifiers WHERE id = ?r   TF)r   r   rU   r   r   debugaction)r   r   r   s      r   delete_notifierr     sS    		!	!	#B
;!W"# 	$?{mTr   c                 0   t        |       j                         rt        |       } nt        j                  d| z         y t        j                         }|j                  d| g      }|sy 	 t        j                  |j                  dd            }t        |d   |      }|r$t        j                  |j                        |_        t!        d	
      }i }i }	t#        |j%                               D ]  }
|
|v s|j                  |
dz         }|j                  |
dz         }||d   dv rdn||
   d   }||d   dv rdn||
   d   }t        j&                  |j                  |
            ||
<   ||d|	|
<    	 t        j                  |d         |d<   |d   sd|d<   |j                  |d<   |j/                  |      |d<   ||d<   |	|d<   |S # t        $ r"}t        j                  d|z         Y d }~y d }~ww xY w# t(        t*        f$ r t,        |d<   Y w xY w)NzQTautulli Notifiers :: Unable to retrieve notifier config: invalid notifier_id %s.z$SELECT * FROM notifiers WHERE id = ?r   notifier_config{}r   r   r   z@Tautulli Notifiers :: Failed to get notifier config options: %s.Tr   _subject_body
agent_namer-   rE   rK   r   r   )r   r   custom_conditionscustom_conditions_logicr   )mask_passwordsconfig_optionsr   notify_text)rU   r   rT   r   errorr   r   select_singlejsonloadsr   r   	Exceptionr   mask_config_passwordsr   r   r   r   cast_to_int
ValueError	TypeErrorDEFAULT_CUSTOM_CONDITIONSreturn_config_options)r   r  r   r   r   notifier_agenter   notifier_actionsnotifier_textr   r   r   s                r   get_notifier_configr    sL   
;!+&h"# 	$		!	!	#BDK=YFFJJ'8$?@(&2DVT
  ' = =n>S>S T'D9NM&++-  .jjZ0G::a'k*D &| 48N N"TbcdTefoTp|#L15KKrQ_`aQbciQj")"5"5fjjm"DQ+2(, .M!.@&*jj8K1L&M"# +,,.()%,,F8-CCSaCbF(F9)F=MM  WZ[[\6 	" @&?"#@s*   +5G 7G: 	G7G22G7:HHc                 t   t        |       j                         rt        |       } nt        j                  d| z         yt        d      j                  | d       }|st        j                  d| z         yt        |d         }dd i}|d   |d   |d	   d
t        j                  |j                        t        j                  t              d
d}|d   dv r&t               D ]  }d
||d   dz   <   d
||d   dz   <    n+t               D ]  }|d   ||d   dz   <   |d   ||d   dz   <     t        j                         }	 |j                  d||       |j!                         }t        j"                  d|d	   d|d       t%                |S # t&        $ r"}	t        j(                  d|	z         Y d }	~	yd }	~	ww xY w)NzFTautulli Notifiers :: Unable to add new notifier: invalid agent_id %s.FTr   zUTautulli Notifiers :: Unable to retrieve new notification agent: invalid agent_id %s.r[   )r   rZ   rY   rK   r   r   agent_labelfriendly_namer   r   r   r   r   r   r   r   	notifiers
table_namekey_dict
value_dictz4Tautulli Notifiers :: Added new notification agent:  (notifier_id ).z;Tautulli Notifiers :: Unable to add notification agent: %s.)rU   r   rT   r   r  r   r   r   r  dumpsr   r  r   r   r   upsertlast_insert_idinfoblacklist_loggerr  warn)
r   kwargsr   agent_classr   valuesr   r   r   r  s
             r   add_notifier_configr(  G  s   
8}x=]  	!$/33HdCEl  	!!5;7K$<D+!&M"7^!!%K,>,>!?#'::.G#H)+F V}../1 	-A-/F1V9z)**,F1V9w&'	- 01 	4A-.y\F1V9z)**+F)F1V9w&'	4 
	!	!	#B	
		[4F	K'')W~{4 	5 QTUUVs   =AF 	F7F22F7c           
      >   t        |      j                         rt        |      }nt        j                  d|z         yt        d      j                  |d       }|st        j                  d|z         yt               }|d   dz   }t        |j                               D ci c]+  }||v r%|t        j                  |j                  |            - }}t        |j                               D ci c]6  }|j                  |      r#|j                  d      r||j                  |      8 }}t        |j                               D ci c]6  }|j                  |      r#|j                  d	      r||j                  |      8 }	}t        |j                               D ci c]1  }|j                  |      r|t        |      d  |j                  |      3 }
}|
j!                         D ]'  \  }}d
|v s|dk(  st#        |       }|d   |   |
|<   ) t%        |d   |
      }t'        |j                  d            }|du rt        j                  d       yd| i}|d   |d   |d   |j                  dd      t)        j*                  |j,                        t)        j*                  |xs t.              |j                  dd      d}|j1                  |       |j1                  |       |j1                  |	       t3        j4                         }	 |j7                  d||       t        j8                  d|d   d| d       t;                |d   dk(  r
t=                yc c}w c c}w c c}w c c}w # t>        $ r"}t        j@                  d|z         Y d }~yd }~ww xY w)NzKTautulli Notifiers :: Unable to set existing notifier: invalid agent_id %s.FTr   zZTautulli Notifiers :: Unable to retrieve existing notification agent: invalid agent_id %s.rZ   _r   r   passwordz    r   r   r[   r   r   zUTautulli Notifiers :: Unable to update notification agent: Invalid custom conditions.rY   r  rK   r   r  r  r  z2Tautulli Notifiers :: Updated notification agent: r  r  r1   z>Tautulli Notifiers :: Unable to update notification agent: %s.)!rU   r   rT   r   r  r   r   r   r   r   r   r
  r   
startswithendswithlenitemsr  r   validate_conditionsr  r  r   r  updater   r   r   r"  r#  check_browser_enabledr  r$  )r   r   r%  r   r   config_prefixr   r   subject_text	body_textr   cfgvalold_notifier_configr&  r   r   r'  r   r  s                       r   set_notifier_configr:  x  s{   
8}x=b  	!$/33HdCEq  	!')N&MC'M V[[]+DqN/B '%%fjjm44 DG D "&++-0mALL4PUVU_U_`jUk vzz!}$ mL m v{{}-gn1MRSR\R\]dRe FJJqM! gI g !%V[[] 3Tq||M7R ]+,-vzz!}< TO T $))+ FS"5+"N#6x#@#EOC F "5;OK+FJJ7J,KLE!lm+D+!&M"7^%zz/2>!%K,>,>!?#'::.?.\C\#])/4Mr)RF MM'
MM,
MM)		!	!	#B
		[4F	KW~{4 	5=I%!#]DmgTR  TWXXYs1   #0M0;M";M' 6M,AM1 1	N:NNc                     t        |       }|r<t        |d   |d         } |j                  d	|||j                  d      d   |d|S t	        j
                  d       y )
Nr,  r   r   r   on_)r   r   r   notification_idzITautulli Notifiers :: Notification requested but no notifier_id received.r   )r  r   notifysplitr   r   )r   r   r   r   r>  r%  r   r   s           r   send_notificationrA    su    )kBO)D'6x'@Bu|| &G!%#0#6#6u#=b#A,;& %	& 	& 	`ar   c           
      L   | t         S 	 t        j                  |       }t        |t              st	        j
                  d|z         yg }|D ]  }t         d   j                         }t        |t              st	        j
                  d|z          yt        |j                  dd            j                         }t        |j                  dd            j                         }|j                  d	g       }|rt        j                  j                  |      }|st	        j
                  d
|d|        y|j                         |d<   ||d<   |r=|t        j                  |g       vr t	        j
                  d|d|d|        y||d<   |r[t        |t              s|g}|D ]>  }	t        |	t        t         t"        f      rt	        j
                  d|	d|d|         y ||d	<   |j%                  |        |S # t        $ r t	        j
                  d| z         Y yw xY w)Nz@Tautulli Notifiers :: Unable to parse custom conditions json: %sFzOTautulli Notifiers :: Invalid custom conditions: %s. Conditions must be a list.r   zMTautulli Notifiers :: Invalid custom condition: %s. Condition must be a dict.rL   rK   rM   rN   z)Tautulli Notifiers :: Invalid parameter 'z' in custom condition: rO   z(Tautulli Notifiers :: Invalid operator 'z' for parameter 'z%Tautulli Notifiers :: Invalid value ')r  r  r  r  r   r  
isinstancer   copydictrU   r   lowerr   NOTIFICATION_PARAMETERS_TYPESCUSTOM_CONDITION_TYPE_OPERATORSrT   rS   r   )
r   
conditionsvalidated_conditions	conditionvalidated_conditionrL   rM   r'  parameter_typerN   s
             r   r1  r1    s!    ((ZZ 12

 j$'fisst '9	7:??A)T*LLhkttu	k267==?	y}}Z45;;=w+#AAEEiPN!gpr{|}/8/@,*8'#B#F#F~WY#ZZLL  ~F  HQ  S\  "]  ^ 2:#J/fd+  !!%#sE):;LLz  BK  MV  "W  X !
 ,2(##$78O'9R  g  WZkkls   G? ?!H#"H#c                      t        j                         } | j                  d      }|D ]3  }t        j                  |d   xs d      }t        j                  |       5 y )Nz%SELECT notifier_config FROM notifiersr   r   )r   r   r   r  r  r   blacklist_config)r   r  nr   s       r   r#  r#    sU    		!	!	#B		ABI (A/08D9'(r   c                       e Zd ZddZed        Zed        Zed        Zd Zd Z	ddZ
d	 Zdd
Zd Zd Zed        Zd Zy)PrettyMetadataNc                 Z    |xs i | _         | j                   j                  d      | _        y )N
media_type)
parametersr   rT  )selfrU  s     r   __init__zPrettyMetadata.__init__  s$    $*//--l;r   c                      dddddddS )NrK   Plex WebIMDBThe Movie DatabaseTheTVDBTrakt.tv)rK   plexwebimdb
themoviedbthetvdbtraktr   r   r   r   get_movie_providersz"PrettyMetadata.get_movie_providers  s    %2$# 	r   c                      ddddddddS )	NrK   rY  rZ  r[  r\  TVmazer]  )rK   r^  r_  r`  ra  tvmazerb  r   r   r   r   get_tv_providerszPrettyMetadata.get_tv_providers   s!    %2$"# 	r   c                      dddddS )NrK   rY  Last.fmMusicBrainz)rK   r^  lastfmmusicbrainzr   r   r   r   get_music_providersz"PrettyMetadata.get_music_providers+  s    %#, 	r   c                     | j                   j                  d      }|s0| j                  dv rt        j                  }|S t        j
                  }|S )N
poster_urlr   r   r   )rU  r   rT  r   ONLINE_COVER_THUMBONLINE_POSTER_THUMB)rV  ro  s     r   get_poster_urlzPrettyMetadata.get_poster_url3  sL    __((6
">>#66
  $77
r   c                     d}|dk(  rd}|S |dk(  rd}|S |dk(  rd}|S |dk(  rd	}|S |d
k(  rd}|S |dk(  rd}|S |dk(  rd}|S |dk(  rd}|S )NrK   r^  rY  r_  IMDbra  r\  r`  r[  rf  re  rb  r]  rk  ri  rl  rj  r   rV  providerprovider_names      r   get_provider_namez PrettyMetadata.get_provider_name<  s    y &M, + "M( ' "%M$ # %0M   !$M   &M  !%M  &)M r   c                 z    d}|dk(  r| j                         }|S |r| j                  j                  |dz   d      }|S )NrK   r^  _url)get_plex_urlrU  r   )rV  rw  provider_links      r   get_provider_linkz PrettyMetadata.get_provider_linkW  sM    y  --/M   OO//60A2FM r   c                 .    | j                  |      }d|z   S )NzView on )ry  rv  s      r   get_captionzPrettyMetadata.get_captionf  s    ..x8M))r   c           
         d}| j                   dk(  r$| j                  d   d| j                  d   d}|S | j                   dk(  r$| j                  d   d| j                  d   d}|S | j                   d	k(  r#| j                  d   d
| j                  d   }|S | j                   dk(  r\t        j                  | j                  d         }| j                  d   d
| j                  d   d|d|d| j                  d   d
}|S | j                   dk(  r| j                  d   }|S | j                   dk(  r#| j                  d   d
| j                  d   }|S | j                   dk(  r!| j                  d   d
| j                  d   }|S )NrK   r   titlez (year)r   	show_namer   z - season_namer   episode_name z Eepisode_numr   artist_namer   
album_namer   
track_nametrack_artist)rT  rU  r   short_season)rV  dividerr  r   s       r   	get_titlezPrettyMetadata.get_titlej  s}   ??g%!%!94??6;RSE$ # __&!%!=tv?VWE   __(!%!=t}?]^E  __	)))$//-*HIF-1__[-I-1__^-L-3-4-1__]-K	ME  __(OOM2E
 	 __'!%!?Q]A^_E  __'!%!>P^@_`Er   c                 d    | j                   dk(  r| j                  d   }|S | j                  d   }|S )Nr   r  summary)rT  rU  )rV  r   s     r   get_descriptionzPrettyMetadata.get_description  s:    ??g%//,7K  //)4Kr   c                      | j                   d   S )Nplex_url)rU  rV  s    r   r|  zPrettyMetadata.get_plex_url  s    z**r   c                  |    t         j                  D  ci c]  } | d   D ]  }|d   |d     }} }d|d<   |S c c}} w )NrU  rN   rZ   rK   )r   NOTIFICATION_PARAMETERS)categoryparamrU  s      r   get_parameterszPrettyMetadata.get_parameters  se     !' > >dHUaLbdCH GneFm3 dn d
 d
2ds   8c                    t        j                         j                  | j                  j	                  dd            }|r-|d   r(|d   }dj                  | j                  d         }||dfS t        j                  d       y )	Nposter_thumbrK   )imgr   zposter_{}.png
rating_key	image/pngz@Tautulli Notifiers :: Unable to retrieve image for notification.)r   
PmsConnect	get_imagerU  r   formatr   r  )rV  r   poster_contentposter_filenames       r   r  zPrettyMetadata.get_image  su    &&(22t7J7J>[]7^2_fQi#AYN-44T__\5RSO#^[AAWXr   N)-)__name__
__module____qualname__rW  staticmethodrc  rg  rm  rs  ry  r~  r  r  r  r|  r  r  r   r   r   rR  rR    s    <      6*.+  Yr   rR  c                   X    e Zd ZdZi ZddZddZddZd ZddZ	ddZ
dd	Zdd
Zd Zy)r   rK   Nc                 H    | j                  || j                        | _        y N)r   default)
set_config_DEFAULT_CONFIGr   )rV  r   s     r   rW  zNotifier.__init__  s    ooVT=Q=QoRr   c                 (    | j                  ||      S r  )_validate_config)rV  r   r  s      r   r  zNotifier.set_config  s    $$FG$DDr   c                 \   ||S i }|j                         D ]  \  }}t        |t              r)t        j                  |j                  ||            ||<   ?t        |t              r/|j                  ||      }t        |t              s|g||<   x|||<   ~|j                  ||      ||<    |S r  )r0  rC  rT   r   r
  r   r   )rV  r   r  
new_configr   vcs          r   r  zNotifier._validate_config  s    >N
MMO 
	1DAq!S! ' 3 3FJJq!4D E
1At$JJq!$!!T*%&CJqM$%JqM &

1a 0
1
	1 r   c                 6    | j                   j                         S r  )r  rD  r  s    r   return_default_configzNotifier.return_default_config  s    ##((**r   c                    | j                   dvrf|s?| j                  j                  dd      r#t        j                  d| j                   z         y |s#t        j                  d| j                   z         y  | j
                  d|||d|S )N)rt   rx   incl_subjectTz>Tautulli Notifiers :: %s notification subject cannot be blank.z;Tautulli Notifiers :: %s notification body cannot be blank.r   r   r   r   )NAMEr   r   r   r  agent_notifyrV  r   r   r   r%  s        r   r?  zNotifier.notify  s}    9911t{{~tD]`d`i`iijZ]a]f]ffg t  UtFUfUUr   c                      y r  r   r  s        r   r  zNotifier.agent_notify  s    r   c                 4   t        j                  dj                  | j                               t	        j
                  ||fi |\  }}}|r2|s0t        j                  dj                  | j                               yd}|d|j                  cxk  rdk  rn nd}t        j                  d	j                  || j                  
             |r$t        j                  dj                  |             |r$t        j                  dj                  |             y)N4Tautulli Notifiers :: Sending {name} notification...rZ   /Tautulli Notifiers :: {name} notification sent.TrK   i  i  z5 Verify your notification agent settings are correct.z6Tautulli Notifiers :: {name} notification failed.{msg})msgrZ   zTautulli Notifiers :: {}*Tautulli Notifiers :: Request response: {}F)	r   r"  r  r  r   request_response2status_coder  r   )rV  urlmethodr%  responseerr_msgreq_msg
verify_msgs           r   make_requestzNotifier.make_request  s    JQQW[W`W`Qab%,%>%>sF%Uf%U"'7GKKIPPVZV_V_P`a J#x/C/C(Ic(IT
LLQXX]gnrnwnwXxy7>>wGHIPPQXYZr   c                 T    | j                         }|rt        j                  |       |S r  )_return_config_optionsr   r	  )rV  r  r  s      r   r  zNotifier.return_config_options  s)    446 )).9r   c                 
    g }|S r  r   )rV  r  s     r   r  zNotifier._return_config_options  s    r   r  NNrK   rK   rK   )POSTF)r  r  r  r  r  rW  r  r  r  r?  r  r  r  r  r   r   r   r   r     s<    DOSE&+	V.r   r   c                   2    e Zd ZdZdZdddZd	dZd Zd Zy)
r|   z
    Boxcar notifications
    r^   rK   )tokensoundc                 j    | j                   d   ||| j                   d   d}| j                  d|      S )Nr  r  )user_credentialsznotification[title]znotification[long_message]znotification[sound]z'https://new.boxcar.io/api/notificationsparamsr   r  )rV  r   r   r   r%  datas         r   r  zBOXCAR.agent_notify  sA    $(KK$8'..2'+{{7';   !JSW XXr   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!d"d#d$d%d&d'd(d)d*d+d,d-d.d/}|S )0NrK   z
beep-crispzBeep (Crisp)z	beep-softzBeep (Soft)zbell-modernzBell (Modern)zbell-one-tonezBell (One Tone)zbell-simplezBell (Simple)zbell-triplezBell (Triple)zbird-1zBird (1)zbird-2zBird (2)boingBoingcashCashclangingClangingzdetonator-chargezDetonator Chargezdigital-alarmzDigital AlarmdoneDoneechoEchoflourishFlourishHarpLightzMagic Chimez
Magic CoinzNo SoundzNotifier (1)zNotifier (2)zNotifier (3)zOrchestral (Long)zOrchestral (Short)ScoreSuccessUp)harplightzmagic-chimez
magic-coinzno-soundz
notifier-1z
notifier-2z
notifier-3zorchestral-longzorchestral-shortscoresuccessupr   )rV  soundss     r   
get_soundszBOXCAR.get_sounds  s   "b }   "#4	
     J J 7 & j %&8 "? & &  j!" !" - ,( . . .%8&:"&;> r   c                 x    d| j                   d   ddddd| j                   d   dd	d
| j                         dg}|S )NzBoxcar Access Tokenr  boxcar_tokenzYour Boxcar access token.rY   rN   rZ   r   
input_typeSoundr  boxcar_soundz>Set the notification sound. Leave blank for the default sound.r   rY   rN   rZ   r   r  select_options)r   r  rV  config_options     r   r  zBOXCAR._return_config_options#  sW    #8#';;w#7"0)D(/	 $+#';;w#7"0)i(0,0OO,= r   Nr  	r  r  r  __doc__r  r  r  r  r  r   r   r   r|   r|     s,     D " "OY Dr   r|   c                   *    e Zd ZdZdZddiZddZd Zy)	r}   z
    Browser notifications
    r_   auto_hide_delay   c                 b    t        j                  dj                  | j                               y)Nr  r  T)r   r"  r  r  r  s        r   r  zBROWSER.agent_notify>  s'    ELLRVR[R[L\]r   c                 J    dddddddddd	d
| j                   d   dddd	g}|S )NNotezIYou may need to refresh the page after saving for changes to take effect.helprY   r   r  zAllow Notificationsbrowser_allow_browserzRClick to allow browser notifications. You must click this button for each browser.buttonr  zAuto Hide Delayr  browser_auto_hide_delayzSet the number of seconds for the notification to remain visible. Set 0 to disable auto hiding. (Note: Some browsers have a maximum time limit.)numberr   r  s     r   r  zBROWSER._return_config_optionsB  s[    #))t(. $9#8"9*X(0 $5#';;/@#A";*z(0( r   Nr  r  r  r  r  r  r  r  r  r   r   r   r}   r}   6  s$     D(! Or   r}   c                   B    e Zd ZdZdZddddddddddddddZd
dZd Zy	)r~   z
    Discord Notifications
    r`   rK   r   r   )hookusername
avatar_urlcolorttsr  	incl_cardincl_descriptionincl_thumbnailincl_pmslinkmovie_providertv_providermusic_providerc                    | j                   d   r	|dz   |z   }n|}d|i}| j                   d   r| j                   d   |d<   | j                   d   r| j                   d   |d<   | j                   d   rd|d<   i }| j                   d   rp|j                  d	i       j                  d
      rNt        |d	         }|j                         }	|	rd|	i}|j                  dk(  r| j                   d   }
n>|j                  dv r| j                   d   }
n |j                  dv r| j                   d   }
nd }
|j                         }|j                  |
      }|j                  |
      }|j                  d      }|j                         }|j                         }||j                  d   d}| j                   d   rt        j                  d| j                   d         }|r`|j                  d      j                  d      }t!        |      dk(  rdj#                  d |D              n|}t%        j&                  |      |d<   | j                   d   rd|	rdj)                  |	d         n|i|d<   nd|	rdj)                  |	d         n|i|d <   | j                   d!   r|d d" |d"d  xr d#z   |d$<   g }|r!||d<   |j+                  d%d&|d'|d(dd)       | j                   d*   r|j+                  d%d+|z  dd)       |r||d,<   |g|d-<   d.di}|r<d t-        j.                  |      d/f|d0<   | j1                  | j                   d1   ||2      S | j1                  | j                   d1   ||3      S )4Nr  
contentr  r  r  Tr  rU  rT  zfiles[0]r   r  r   r   r   r  rp  r     ·utctime)r  	timestampr  z^#([0-9a-fA-F]{3}){1,2}$r   #r   rK   c              3   &   K   | ]	  }|d z    yw)r   Nr   )r   hs     r   r   z'DISCORD.agent_notify.<locals>.<genexpr>  s     !5A!a%!5r   r  r  zattachment://{}	thumbnailimager  i  ...r   View Details[z](r  )rZ   rN   inliner  z[Plex Web](%s)fieldsembedswaitapplication/jsonpayload_jsonr  )r  files)r  r  )r   r   rR  r  rT  rs  ry  r~  r  r  r|  rU  rematchgrouplstripr/  r3   r   
hex_to_intr  r   r  r  r  )rV  r   r   r   r%  textr  r4  pretty_metadatar*  rw  ro  rx  r}  r  r   r  
attachment	hex_matchhexr/  r  s                         r   r  zDISCORD.agent_notifyn  s   ;;~&V#d*DD4 ;;z"#{{:6D;;|$!%\!:D;;uDK;;{#

<(D(H(H(V,VL-ABO#--/E#U+))W4;;'78 ++/LL;;}5 ++/KK;;'78(779J+==hGM+==hGM#--h7E)99;K&335H $)'6'A'A)'LJ {{7#HH%@$++gBVW	#//!,33C8C9<SQ"''!5!55CC*1*<*<S*AJw'{{+,+0X]2C2J2J5QR82Tcm*n
;'',TY.?.F.FuQx.P_i&j
7#{{-.,7,>+deBTB^Y^,_
=)F$1
5!~6C](S)-/ 0 {{>*~(88(C)-/ 0 '-
8$(\DN$%)4::d+;=O$PE.!$$T[[%8u$UU$$T[[%8d$SSr   c                    d| j                   d   ddddd| j                   d   d	d
ddd| j                   d   ddddd| j                   d   ddddd| j                   d   ddddd| j                   d   ddddd| j                   d   d d!ddd"| j                   d#   d$d%ddd&| j                   d'   d(d)ddd*| j                   d+   d,d-ddd.| j                   d/   d0d1d2t               j                         d3d4| j                   d5   d6d7d2t               j                         d3d8| j                   d9   d:d;d2t               j	                         d3g}|S )<NzDiscord Webhook URLr  discord_hookz"Your Discord incoming webhook URL.r  r  zDiscord Usernamer  discord_usernamezUThe Discord username which will be used. Leave blank for webhook integration default.r:  zDiscord Avatarr  z]The image url for the avatar which will be used. Leave blank for webhook integration default.discord_avatar_urlrY   rN   r   rZ   r  zDiscord Colorr  eThe hex color value (starting with '#') for the border along the left side of the message attachment.discord_colorTTSr  discord_ttsz+Send the notification using text-to-speech.checkboxInclude Subject Liner  discord_incl_subject0Include the subject line with the notifications.Include Rich Metadata Infor  discord_incl_cardzGInclude an info card with a poster and metadata with the notifications.Include Summaryr  discord_incl_description1Include a summary for the media on the info card.Include Link to Plex Webr  discord_incl_pmslink@Include a second link to the media in Plex Web on the info card.Use Poster Thumbnailr  discord_incl_thumbnail@Use a thumbnail instead of a full sized poster on the info card.Movie Link Sourcer  discord_movie_providerSelect the source for movie links on the info cards. Leave blank to disable.<br>Note: <a data-tab-destination="3rd_party_apis" data-dismiss="modal" >Metadata Lookups</a> may need to be enabled under the 3rd Party APIs settings tab.r   r  TV Show Link Sourcer  discord_tv_providerSelect the source for tv show links on the info cards. Leave blank to disable.<br>Note: <a data-tab-destination="3rd_party_apis" data-dismiss="modal" >Metadata Lookups</a> may need to be enabled under the 3rd Party APIs settings tab.Music Link Sourcer  discord_music_providerSelect the source for music links on the info cards. Leave blank to disable.<br>Note: <a data-tab-destination="3rd_party_apis" data-dismiss="modal" >Metadata Lookups</a> may need to be enabled under the 3rd Party APIs settings tab.r   rR  rc  rg  rm  r  s     r   r  zDISCORD._return_config_options  s   #8#';;v#6"0)M(/	 $6#';;z#:"4 *A(.	 $4#';;|#< *I"6(.	 $3#';;w#7 *S"1(.	 $)#';;u#5"/)V(2	 $:#';;~#>"8)[(2	 $@#';;{#;"5)r(2	 $5#';;/A#B"<)\(2	 $>#';;~#>"8)k(2	 $:#';;/?#@":)k(2	 $7#';;/?#@":*i )1,:,<,P,P,R $9#';;}#="7*i )1,:,<,M,M,O $7#';;/?#@":*i )1,:,<,P,P,R]Wr r   Nr  r  r   r   r   r~   r~   Z  sJ     D!#%%' "'($%+,)*'()+&()+OQTfZr   r~   c                   D    e Zd ZdZdZddg g g dddddddZdd	Zd
 Zd Zy)r   z
    Email notifications
    ra   TautullirK   i  r   r   )	from_namefromtoccbccsmtp_server	smtp_port	smtp_usersmtp_passwordtlshtml_supportc           	         | j                   d   s"t        j                  d| j                  d       y| j                   d   rt	        d dd      }|j                  dd	       |j                  |j                  d
t        j                  |d            d       t	        |dd      }t        d      }|j                  |       |j                  |       n1t	        d dd      }|j                  dd	       |j                  |d       |j                  dt        j                  j                               }|j                  d      }	||d<   t        j                  j                  d      |d<   ||d<   t        j                  j!                  | j                   d   | j                   d   f      |d<   dj#                  | j                   d         |d<   dj#                  | j                   d         |d<   |	r
|	|d<   |	|d<   | j                   d   | j                   d   z   | j                   d   z   }
d }d}	 | j                   d    d!k(  r1t%        j&                  | j                   d   | j                   d"         }n0t%        j(                  | j                   d   | j                   d"         }|j+                          | j                   d    d#k(  r |j-                          |j+                          | j                   d$   r>|j/                  t1        | j                   d$         t1        | j                   d%                |j3                  | j                   d   |
|j5                                t        j6                  d&j9                  | j                  '             d}|r|j=                          |S # t:        $ r+}t        j                  d| j                  |       Y d }~Cd }~ww xY w# |r|j=                          w w xY w)(Nrh  z0Tautulli Notifiers :: %s notification failed: %szMissing SMTP serverFrm  plainutf-8zContent-Transfer-Encodingzquoted-printable	plaintextT)striphtmlalternativemsg_idreply_msg_idz
Message-ID)	localtimeDateSubjectrc  rd  From,re  Torf  CCzIn-Reply-To
Referencesrg  rl  r   ri  r   rj  rk  r  r  )r   r   r  r  r   replace_headerset_payloadr   bleachcleanr   attachr#   utils
make_msgid
formatdate
formataddrr3   smtplibSMTP_SSLSMTPehlostarttlsloginrU   sendmail	as_stringr"  r  r  quit)rV  r   r   r   r%  ro  rs  r  ru  rv  
recipients
mailserverr  r  s                 r   r  zEMAIL.agent_notify0  sK   {{=)LLK$9;;;~&T7G4E  !<>PQfjjfll4t6TUW^_D&'2D.CJJuJJt4'2C:<NOOOD'*Hekk&<&<&>?zz.1"Lkk,,t,<F Ikk,,dkk+.FTZH[-\]FHHT[[./D	HHT[[./D	!-C ,C[[&T)::T[[=OO

	"{{5!Q&$--dkk-.H$++VaJbc
$\\$++m*DdkkR]F^_
OO{{5!Q&##%!{{;'  T[[%=!>DKKP_D`@abF 3ZQKKIPPVZV_V_P`aG !  	[LLKTYYXYZZ	[ ! s+   /E!N$ $	O-!OO OO O0c                    t        j                         j                         D ci c]  }|d   s	|d   |d    }}| j                  d   D ci c]  }|d }}| j                  d   D ci c]  }|d }}| j                  d   D ci c]  }|d }}|j	                  |       |j	                  |       |j	                  |       |j                         D cg c]
  \  }}||d }}}|j                         D cg c]
  \  }}||d }}}|j                         D cg c]
  \  }}||d }}}|||fS c c}w c c}w c c}w c c}w c c}}w c c}}w c c}}w )Nr#   r  re  rK   rf  rg  rN   r:  )r   Users	get_usersr   r2  r0  )rV  uemailsr  user_emails_touser_emails_ccuser_emails_bccr   s           r   get_user_emailszEMAIL.get_user_emailst  s\   :?++-:Q:Q:SbQWXY`Wa!G*a00bb)-T):;A!R%;;)-T):;A!R%;;*.++e*<=Q1b5==f%f%v&>L>R>R>TUdaAq1UU>L>R>R>TUdaAq1UU?N?T?T?VWtq!Q2WW~>> c;;= VUWs.   
D;D;
E +
E
E
E?E$Ec                     | j                         \  }}}d| j                  d   ddddd| j                  d   d	d
ddd| j                  d   ddd|ddd| j                  d   ddd|ddd| j                  d   ddd|ddd| j                  d   ddddd| j                  d   d d!d"dd#| j                  d$   d%d&ddd'| j                  d(   d)d*d+dd,| j                  d-   d.d/d0d1d2d3d4d5d6| j                  d7   d8d9d:dg}|S );Nz	From Namerc  email_from_namezThe name of the sender.r:  r  rz  rd  
email_fromz The email address of the sender.r|  re  email_toz(The email address(es) of the recipients.	selectizeTrY   rN   rZ   r   r  r   
select_allr}  rf  email_cczThe email address(es) to CC.BCCrg  	email_bcczThe email address(es) to BCC.zSMTP Serverrh  email_smtp_serverzHost for the SMTP server.z	SMTP Portri  email_smtp_portzPort for the SMTP server.r  zSMTP Usernamerj  email_smtp_userzUsername for the SMTP server.zSMTP Passwordrk  email_smtp_passwordzPassword for the SMTP server.r+  
Encryptionrl  	email_tlsz'Send emails encrypted using SSL or TLS.r   Nonez!TLS/STARTTLS (Typically port 587)zSSL/TLS (Typically port 465)r   r   r   r  Enable HTML Supportrm  email_html_supportz$Style your messages using HTML tags.rH  )r  r   )rV  r  r  r  r  s        r   r  zEMAIL._return_config_options  s   :>:N:N:P7#.#';;{#;"3)B(.	 $*#';;v#6".)K(.	 $(#';;t#4",)S(3,:(, $(#';;t#4",)G(3,:(, $)#';;u#5"-)H(3,;(, $1#';;}#="5)D(.	 $/#';;{#;"3)D(0	 $3#';;{#;"3)H(.	 $3#';;#?"7)H(2	 $0#';;u#5"-)R(0060S0N-P $9#';;~#>"6)O(2	KKZ r   Nr  )	r  r  r  r  r  r  r  r  r  r   r   r   r   r     sH     D$.! &($'$&(*'(OBH?"Pr   r   c                   R    e Zd ZdZdZddddddddddd
ZddZddZd	 Zdd
Z	d Z
y)r   z 
    Facebook notifications
    rb   rK   r   r   )
redirect_uriaccess_tokenapp_id
app_secretgroup_idr  r  r  r  r  c                     |t         j                  _        |t         j                  _        |t         j                  _        dt         j                  _        t        j                  ||dg      S )Ntemppublish_to_groups)r  
canvas_urlperms)plexpyCONFIGFACEBOOK_APP_IDFACEBOOK_APP_SECRETFACEBOOK_REDIRECT_URIFACEBOOK_TOKENr/   auth_url)rV  r  r  r  s       r   _get_authorizationzFACEBOOK._get_authorization  sR     )/%,6).:+'-$  ,8(;'<> 	>r   c                 J   t        j                  dj                  | j                               t        j
                  j                  }t        j
                  j                  }t        j
                  j                  }	 t        j                  d      }|j                  ||||      }|d   }t        j                  |d      }|j                  ||      }|d   t        j
                  _        dt        j
                  _        dt        j
                  _        dt        j
                  _        t        j
                  j                  S # t        $ rO}t        j                  d	j                  | j                  |
             dt        j
                  _        Y d }~d }~ww xY w)Nz:Tautulli Notifiers :: Requesting access token from {name}.r  2.12)version)coder  r  r  r  r  r  )r  r  z?Tautulli Notifiers :: Error requesting {name} access token: {e}rZ   r  rK   )r   r"  r  r  r  r  r  r  r  r/   GraphAPIget_access_token_from_codeextend_access_tokenr  r  r  )	rV  r  r  r  r  apir  r  r  s	            r   _get_credentialszFACEBOOK._get_credentials  sQ   PWW]a]f]fWgh..]]66
}}::	.##F3C554CO=CAK 6 MH $N3L ##vNC..f:D / FH ,4N+CFMM( )+%,.).0+}}+++  	.LLZaagkgpgptuavw+-FMM((	.s   ?A2E
 
	F"AFF"c                    | j                   d   rwt        j                  | j                   d   d      }	  |j                  d| j                   d   dd| t	        j
                  dj                  | j                               y	t	        j                  dj                  | j                               y# t        $ r:}t	        j                  d
j                  | j                  |             Y d }~yd }~ww xY w)Nr  r  r  r  feed)parent_objectconnection_namer  r  Tz4Tautulli Notifiers :: Error sending {name} post: {e}r  FzMTautulli Notifiers :: Error sending {name} post: No {name} Group ID provided.r   )
r   r/   r  
put_objectr   r"  r  r  r  r  )rV  r  r  r  s       r   _post_facebookzFACEBOOK._post_facebook  s    ;;z"##^1LV\]CeT[[-DV\e`deMTTZ^ZcZcTde LLhoouyu~u~o  A  SZZ`d`i`imnZops   AB7 7	C: 0C55C:c                    | j                   d   r	|dz   |z   }n|}d|i}| j                   d   r|j                  di       j                  d      rt        |d         }|j                  dk(  r| j                   d   }n>|j                  d	v r| j                   d
   }n |j                  dv r| j                   d   }nd }|j	                  |      |d<    | j
                  di |S )Nr  r   messager  rU  rT  r   r  r"  r  rp  r  linkr   )r   r   rR  rT  r~  r  )	rV  r   r   r   r%  r:  r  r;  rw  s	            r   r  zFACEBOOK.agent_notify&  s    ;;~&V#d*DD4 ;;{#

<(D(H(H(V,VL-ABO))W4;;'78 ++/LL;;}5 ++/KK;;'78*<<XFDL"t""*T**r   c                 2   d| j                   d   ddddd| j                   d   d	d
ddd| j                   d   ddddddddddd| j                   d   ddddd| j                   d   ddddd| j                   d   ddd dd!| j                   d"   d#d$d dd%| j                   d&   d'd(d)t               j                         d*d+| j                   d,   d-d.d)t               j                         d*d/| j                   d0   d1d2d)t               j	                         d*g}|S )3NzOAuth Redirect URIr  facebook_redirect_urizNFill in this address for the "Valid OAuth redirect URIs" in your Facebook App.r:  r  zFacebook App IDr  facebook_app_idzYour Facebook app ID.r  zFacebook App Secretr  facebook_app_secretzYour Facebook app secret.zRequest Authorizationfacebook_facebook_authzFRequest Facebook authorization. (Ensure you allow the browser pop-up).r  zFacebook Access Tokenr  facebook_access_tokenzSYour Facebook access token. Automatically filled in after requesting authorization.zFacebook Group IDr  facebook_group_idzYour Facebook Group ID.rI  r  facebook_incl_subjectrK  rH  rL  r  facebook_incl_cardInclude an info card with a poster and metadata with the notifications.<br>Note: <a data-tab-destination="3rd_party_apis" data-dismiss="modal" data-target="notify_upload_posters">Image Hosting</a> must be enabled under the 3rd Party APIs settings tab.rW  r  facebook_movie_providerrY  r   r  rZ  r  facebook_tv_providerr\  r]  r  facebook_music_providerr_  r`  r  s     r   r  zFACEBOOK._return_config_options?  s   #7#';;~#>"9*A(. $5#';;x#8"3)@(/	 $9#';;|#<"7)D(/	 $;#:":)q(0	 $;#';;~#>"9*c(/ $7#';;z#:"5)B(.	 $:#';;~#>"9)[(2	 $@#';;{#;"6*b )3 $7#';;/?#@";*i )1,:,<,P,P,R $9#';;}#="8*i )1,:,<,M,M,O $7#';;/?#@";*i )1,:,<,P,P,ROPd r   Nr  )rK   )r  r  r  r  r  r  r  r  r  r  r  r   r   r   r   r     sN     D')')!#%'#%'($%)+&()+
O
>,B +2Sr   r   c            
       :    e Zd ZdZdZdddddddddd	Zd
dZd Zy	)r   z
    Gotify notifications
    rc   rK   r   r   )	host	app_tokenpriorityr  incl_posterincl_urlr  r  r  c                    dddii|| j                   d   d}| j                   d   r||d<   d| j                   d	   i}|j                  d
i       j                  d      rt        |d
         }| j                   d   rz|j                  dk(  r| j                   d   }n>|j                  dv r| j                   d   }n |j                  dv r| j                   d   }nd }|j	                  |      }	dd|	ii|d   d<   | j                   d   r,|j                         }
|dxx   dj                  |
      z  cc<   | j                  dj                  | j                   d         ||      S )Nzclient::displaycontentTypeztext/markdownr  )extrasr  r  r  r  zX-Gotify-Keyr  rU  rT  r  r   r  r"  r  rp  r  clickr  r  zclient::notificationr  r  z	

![]({})z
{}/messager  headersr  )r   r   rR  rT  r~  rs  r  r  )rV  r   r   r   r%  r  r  r;  rw  r}  ro  s              r   r  zGOTIFY.agent_notify  ss    "!?$
 J/
 ;;~&#DM!4;;{#;<::lB'++L9,VL-ABO{{:&"--8#{{+;<H$//3PP#{{=9H$//3OO#{{+;<H#H / A A( K:AE=CY9ZX56{{=),;;=
Y=#7#7
#CC  !4!4T[[5H!ISZae ffr   c                    d| j                   d   ddddd| j                   d   d	d
ddd| j                   d   dddddddddddddd| j                   d   ddddd | j                   d!   d"d#ddd$| j                   d%   d&d'ddd(| j                   d)   d*d+dt               j                         dd,| j                   d-   d.d/dt               j                         dd0| j                   d1   d2d3dt               j	                         dg	}|S )4NzGotify Host Addressr  gotify_hostz1Host running Gotify (e.g. http://localhost:8080).r:  r  zGotify App Tokenr  gotify_app_tokenzYour Gotify app token.r  Priorityr  gotify_prioritySet the notification priority.r   r   r   r   r      r  r   r   )r   r   r   r   r  r  r   r   r  rI  r  gotify_incl_subjectrK  rH  Include Poster Imager  gotify_incl_poster(Include a poster with the notifications.z-Open URL on Notification Click (Android Only)r  gotify_incl_urlzHOpen a URL instead of the Gotify app when clicking on the notifications.rW  r  gotify_movie_providerSelect the source for movie links in the notification. Leave blank to disable.<br>Note: <a data-tab-destination="3rd_party_apis" data-dismiss="modal" >Metadata Lookups</a> may need to be enabled under the 3rd Party APIs settings tab.rZ  r  gotify_tv_providerSelect the source for tv show links in the notification. Leave blank to disable.<br>Note: <a data-tab-destination="3rd_party_apis" data-dismiss="modal" >Metadata Lookups</a> may need to be enabled under the 3rd Party APIs settings tab.r]  r  gotify_music_providerSelect the source for music links in the notification. Leave blank to disable.<br>Note: <a data-tab-destination="3rd_party_apis" data-dismiss="modal" >Metadata Lookups</a> may need to be enabled under the 3rd Party APIs settings tab.r`  r  s     r   r  zGOTIFY._return_config_options  s~   #8#';;v#6"/)\(.	 $6#';;{#;"4)A(/	 $.#';;z#:"3)I(001aA!aTUZ[,\ $:#';;~#>"7)[(2	 $:#';;}#="6)S(2	 $S#';;z#:"3)s(2	 $7#';;/?#@"9*i )1,:,<,P,P,R $9#';;}#="6*i )1,:,<,M,M,O $7#';;/?#@"9*i )1,:,<,P,P,Ro@D r   Nr  r  r   r   r   r   r     s=     D!$&#$'(&'#$)+&()+	O%gNCr   r   c                   0    e Zd ZdZdZdddddZd
dZd Zy	)r   z
    GroupMe notifications
    rd   rK   r   r   )r  bot_idr  r  c                    d| j                   d   i}| j                   d   r|dz   |z   |d<   n||d<   | j                   d   r1|j                  d      rt        |j                  d            }|j                         }|r| j                   d   dd	}t	        j
                  d
||d         }	|	j                  dk(  rOt        j                  dj                  | j                               |	j                         }
d|
d   d   dg|d<   nht        j                  dj                  | j                  |	             t        j                  dj                  t        j                  |	d                   | j!                  d|      S )Nr  r  r   r:  r  rU  r  r  )zX-Access-TokenContent-Typez"https://image.groupme.com/picturesr   r  r     z)Tautulli Notifiers :: {name} poster sent.r  r*  payloadpicture_url)rO   r  attachmentszHTautulli Notifiers :: {name} poster failed: [{r.status_code}] {r.reason}rZ   rr  Tz$https://api.groupme.com/v3/bots/post)r  )r   r   rR  r  requestspostr  r   r"  r  r  r  r  r   r   server_messager  )rV  r   r   r   r%  r  r;  r*  r  r  	r_contents              r   r  zGROUPME.agent_notify  sn   $++h/0;;~&"V+d2DLDL;;}%&**\*B,VZZ-EFO#--/E-1[[-H+68 MM"FPW^cde^fg==C'KK K R RX\XaXa R bc !I4;3<Y3G3V,X +YD' LL "@@FDIIYZ@[]LL!M!T!TU\UkUklmosUt!uv  !Gd SSr   c           	          d| j                   d   ddddd| j                   d   d	d
ddd| j                   d   ddddd| j                   d   ddddg}|S )NzGroupMe Access Tokenr  groupme_access_tokenzYour GroupMe access token.r  r  zGroupMe Bot IDr  groupme_bot_idzYour GroupMe bot ID.rI  r  groupme_incl_subjectrK  rH  r  r  groupme_incl_posterr  r   r  s     r   r  zGROUPME._return_config_options;  s    #9#';;~#>"8)E(/	 $4#';;x#8"2)?(/	 $:#';;~#>"8)[(2	 $:#';;}#="7)S(2	%4 r   Nr  r  r   r   r   r   r     s,     D')!#'(&'OT<r   r   c                   ,    e Zd ZdZdZdddZddZd Zy)	r   z(
    Growl notifications, for OS X.
    re   rK   )r  r+  c                    | j                   d   dk(  rd\  }}d| j                   d   v r.| j                   d   j                  dd      \  }}t        |      }n| j                   d   d}}| j                   d   dk(  rd }n| j                   d   }t        j                  j                  dd	gd	g|||
      }	 |j                          t        j                  j!                  t#        t$        j&                        d      }	t)        |	d      5 }
|
j+                         }d d d        	 |j-                  d	||       t        j.                  dj                  | j                               y# t        j                  j                  j                  $ r2 t        j                  dj                  | j                               Y yt        j                  j                  j                  $ r2 t        j                  dj                  | j                               Y yw xY w# 1 sw Y   xY w# t        j                  j                  j                  $ r2 t        j                  dj                  | j                               Y yw xY w)Nr  rK   )	localhostZ  :r   r  r+  rb  z	New Event)applicationNamenotificationsdefaultNotificationshostnameportr+  z?Tautulli Notifiers :: {name} notification failed: network errorr  FzFTautulli Notifiers :: {name} notification failed: authentication error.data/interfaces/default/images/logo-circle.pngrb)noteTyper  r   r   r  T)r   r@  rT   gntpnotifierGrowlNotifierregistererrorsNetworkErrorr   r  r  r  	AuthErrorospathr3   rU   r  PROG_DIRopenreadr?  r"  )rV  r   r   r   r%  r  r   r+  r   
image_filefr*  s               r   r  zGROWL.agent_notifyb  s.   ;;v"$+JD$$++f%%V,223:JD$t9DV,e$D ;;z"b(H{{:.H ++&&-"- , 
	NN WW\\#foo"6<>
 *d# 	qFFHE		LL$ 	   KKIPPVZV_V_P`a- }}##00 	LLZaagkgpgpaqr}}##-- 	LLahhnrnwnwhxy		 	 }}##00 	LLZaagkgpgpaqr	s:   4E& H!AH& &AH>AHHH#&AI?>I?c                 Z    d| j                   d   ddddd| j                   d   d	d
ddg}|S )Nz
Growl Hostr  
growl_hostz"Your Growl hostname or IP address.r:  r  zGrowl Passwordr+  growl_passwordzYour Growl password.r   r  s     r   r  zGROWL._return_config_options  sM    #/#';;v#6".)M(.	 $4#';;z#:"2)?(2	 r   Nr  r  r   r   r   r   r   Y  s&     D!#%O5nr   r   c                   .    e Zd ZdZd ZddddZddZd Zy)	rf   z
    IFTTT notifications
    rK   tautulli)r   eventvalue3c                 X   t        | j                  d         j                  |      }||d}| j                  d   r:t        |d         }|j                  j                  | j                  d   d      |d<   ddi}| j                  d	j                  || j                  d
         ||      S )Nr7  )r   )value1value2r8  rU  rK   Content-typer2  z.https://maker.ifttt.com/trigger/{}/with/key/{}r   r  )rU   r   r  rR  rU  r   r  )	rV  r   r   r   r%  r7  r  r;  r  s	            r   r  zIFTTT.agent_notify  s    DKK()000?!  ;;x ,VL-ABO,77;;DKK<QSUVDN!#56  !Q!X!XY^`d`k`klq`r!s)0t ! = 	=r   c           	          d| j                   d   ddt        j                  d      z   dz   ddd	| j                   d
   ddddd| j                   d   dddt               j	                         dg}|S )NzIFTTT Webhook Keyr   	ifttt_keyz8Your IFTTT webhook key. You can get a key from <a href="z https://ifttt.com/maker_webhooksz," target="_blank" rel="noreferrer">here</a>.r  r  zIFTTT Eventr7  ifttt_eventa  The IFTTT maker event to fire. You can include <span class="inline-pre">{action}</span> to be substituted with the action name. The notification subject and body will be sent as <span class="inline-pre">value1</span> and <span class="inline-pre">value2</span> respectively.r:  zValue 3r8  ifttt_value3zOOptional: Select a parameter to send as <span class="inline-pre">value3</span>.r   r  )r   r   anon_urlrR  r  r  s     r   r  zIFTTT._return_config_options  s    #6#';;u#5"-*68?8H8HIk8l*m)W*X )0 $1#';;w#7"/*e )/
 $-#';;x#8"0)z(0,:,<,K,K,M'8 r   Nr  r  r   r   r   rf   rf     s(     D  *!#O
=r   rf   c            	       >    e Zd ZdZdZdg dddddddZddZd	 Zd
 Zy)r   z
    Join notifications
    rg   rK   r   r   r   )api_keydevice_namesr  r  r  r  r  r  c                 `   | j                   d   dj                  | j                   d         |d}| j                   d   r||d<   |j                  di       j                  d      rt        |d         }|j	                         }|r| j                   d	   r||d
<   |j
                  dk(  r| j                   d   }n>|j
                  dv r| j                   d   }n |j
                  dv r| j                   d   }nd }|j                  |      }	|	r|	|d<   t        j                  d|      }
|
j                  dk(  r|
j                         }|j                  d      r0t        j                  dj                  | j                               y|j                  d      }t        j                  dj                  | j                  |             yt        j                  dj                  | j                  |
             t        j                   dj                  t#        j$                  |
d                   y) NrC  r{  rD  )apikeydeviceNamesr:  r  r  rU  rT  r  r   r   r  r"  r  rp  r  r  z>https://joinjoaomgcd.appspot.com/_ah/api/messaging/v1/sendPushr  r  r  r  r  TerrorMessagez7Tautulli Notifiers :: {name} notification failed: {msg}rZ   r  FzNTautulli Notifiers :: {name} notification failed: [{r.status_code}] {r.reason}r  r  )r   r3   r   rR  rs  rT  r~  r  r  r  r  r   r"  r  r  r  r   r   r  )rV  r   r   r   r%  r  r;  ro  rw  r}  r  response_data	error_msgs                r   r  zJOIN.agent_notify  s   ++i0"xxN(CD ;;~&#DM::lB'++L9,VL-ABO(779Jdkk-8)V))W4;;'78 ++/LL;;}5 ++/KK;;'78+==hGM+UMMZcgh==CFFHM  +MTTZ^ZcZcTde)--n=	V]]cgclclr{]|}LLippvzvv  DEp  F  GLLELLWMcMcdegkMlmnr   c                    | j                   d   D ci c]  }|| }}|j                  ddi       | j                   d   rBd| j                   d   i}	 t        j                  d|      }|j                  dk(  r|j                         }|j                  d      r:|j                  d	g       }|j                  |D ci c]  }|d
   |d
    c}       |S |j                  d      }t        j                  dj                  | j                  |             	 |S t        j                  dj                  | j                  |             t        j                  dj                  t        j                  |d                   	 |S |S c c}w c c}w # t        $ r;}t        j                  dj                  | j                  |             Y d }~|S d }~ww xY w)NrD  rK   rC  rF  zDhttps://joinjoaomgcd.appspot.com/_ah/api/registration/v1/listDevicesr  r  r  records
deviceNamerH  CTautulli Notifiers :: Unable to retrieve {name} devices list: {msg}rI  ZTautulli Notifiers :: Unable to retrieve {name} devices list: [{r.status_code}] {r.reason}r  r  T)r   r2  r  r   r  r  r   r  r  r  r   r   r  r  )	rV  ddevicesr  r  rJ  response_devicesrK  r  s	            r   get_deviceszJOIN.get_devices   s   !%^!<=A1a4==Bx ;;y!I 67FBLL!gpvw==C'$%FFHM$((3+8+<+<Y+K(Rb'cQ,<(H'cd  %2$5$5n$E	%j%q%qw{  xA  xA  GP%q  &Q  R  LL!}  "E  "E  KO  KT  KT  XY  "E  "Z  [LL!M!T!TU\UkUklmosUt!uv
 w3 > (d  Bbiiosoxox~i  A  B  BBs>   
FA(F ;F
F AF A(F 
F 	G0GGc                    d| j                   d   dddddd| j                   d	   d
dd| j                         dd| j                   d   ddddddddddd| j                   d   ddddd| j                   d   d d!ddd"| j                   d#   d$d%dt               j                         dd&| j                   d'   d(d)dt               j	                         dd*| j                   d+   d,d-dt               j                         dg}|S ).NzJoin API KeyrC  join_api_keyz4Your Join API key. Required for group notifications.r  TrY   rN   rZ   r   r  refreshzDevice Name(s)rD  join_device_nameszSelect your Join device(s).r   r  r  r  join_priorityr  r=  r   r   r   r[  r=  r   r   r   rI  r  join_incl_subjectrK  rH  r  r  r  join_incl_posterInclude a poster with the notifications.<br>Note: <a data-tab-destination="3rd_party_apis" data-dismiss="modal" data-target="notify_upload_posters">Image Hosting</a> must be enabled under the 3rd Party APIs settings tab.rW  r  join_movie_providerr  rZ  r  join_tv_providerr   r]  r  join_music_providerr  )r   rT  rR  rc  rg  rm  r  s     r   r  zJOIN._return_config_options<  si   #1#';;y#9"0)_(/%) $4#';;~#>"5)F(0,0,<,<,> $.#';;z#:"1)I(013aA,N $:#';;~#>"5)[(2	 $:#';;}#="4*b )3 $7#';;/?#@"7*i )1,:,<,P,P,R $9#';;}#="4*i )1,:,<,M,M,O $7#';;/?#@"7*i )1,:,<,P,P,Rm?B r   Nr  	r  r  r  r  r  r  r  rT  r  r   r   r   r   r     s>     D"$')#$'(&')+&()+O+Z8Br   r   c                   .    e Zd ZdZdZddddZd	dZd Zy)
r   z
    LunaSea Notifications
    ri   rK   r   )r  profiler  c                    | j                   d   r	|dz   |z   }n|}| j                   d   rt        | j                   d   d      }nd }t        |d         }|||j                  j	                  d      |j                  j	                  d      |j                  j	                  d      |j                         |j                         |j                  j	                  d	      |j                  j	                  d
      |j                  j	                  d      |j                  j	                  d      |j                  j	                  d      |j                  j	                  d      dd}| j                  | j                   d   ||      S )Nr  r   re  rK   rU  useruser_idplayersession_key
session_iduser_streamsremote_access_reasonupdate_versiontautulli_update_version)r  rg  rh  ri  r  ro  rj  rk  rl  rm  rn  ro  )r   r  r  )r  auth)r   r   rR  rU  r   r  rs  r  )	rV  r   r   r   r%  r:  rp  r;  r	  s	            r   r  zLUNASEA.agent_notify  s]   ;;~&V#d*DD;;y! Y!7<DD()=> '2266v>*5599)D)4488B(224-<<>.99==mL-88<<\J / : : > >~ N(7(B(B(F(FG](^"1"<"<"@"@AQ"R+:+E+E+I+IJc+d
$   V!47 NNr   c                     d| j                   d   ddddd| j                   d   d	d
ddd| j                   d   ddddg}|S )NzLunaSea Webhook URLr  lunasea_hookz4Your LunaSea device-based or user-based webhook URL.r  r  zLunaSea Profilere  lunasea_profilez?Your LunaSea profile name. Leave blank for the default profile.r:  rI  r  lunasea_incl_subjectrK  rH  r   r  s     r   r  zLUNASEA._return_config_options  sl    #8#';;v#6"0)_(/	 $5#';;y#9"3)j(.	 $:#';;~#>"8)[(2	( r   Nr  r  r   r   r   r   r     s*     D!"$'(O
OBr   r   c            
       :    e Zd ZdZdZdddddddddd	ZddZd	 Zy
)r   z'
    Microsoft Teams Notifications
    rj   rK   r   r   r   )	r  r  r  r  r  poster_sizer  r  r  c                 F   ddi}ddi}dddd}g }| j                   d	   r|j                  d
dd|d       |j                  d
|dd       | j                   d   r|j                  di       j                  d      rt        |d         }	|	j                  dk(  r| j                   d   }
n>|	j                  dv r| j                   d   }
n |	j                  dv r| j                   d   }
nd }
|	j                         }|	j                  |
      }|	j                  |
      }|	j                  d      }|	j                         }|	j                         }g }|rJ| j                   d   r;|j                  ddd||ddj                  | j                   d   dz        d gd!       |j                  dd"g d!       |d#   d$   j                  d
d|dd%       | j                   d&   r|d#   d$   j                  d
|d'd'dd(       |j                  d)d*d|d+       g }|r$|j                  d,d-j                  |      |d.       | j                   d/   r|j                  d,d0|d.       |r|j                  d1|d2       ||d3<   ||d4<   |g|d5<   d6d7i}| j                  | j                   d8   ||9      S ):NrO   r  r  z'application/vnd.microsoft.card.adaptivez2http://adaptivecards.io/schemas/adaptive-card.jsonAdaptiveCardz1.4)z$schemarO   r  r  	TextBlockLargeBolder)rO   sizeweightr:  T)rO   r:  wrapr  rU  rT  r   r  r"  r  rp  r  r#  rv  ColumnautoImagez{}pxK   )rO   r  altTextr|  height)rO   widthr0  stretchr=  r0  )rO   r}  r:  r~  r  Small)rO   r:  r|  spacingr~  	ColumnSetDefault)rO   paddingr  columnszAction.OpenUrlz
View on {})rO   r  r  r  zView on Plex	ActionSet)rO   r   r   r!  r  r<  r2  r  r  )r   r   r   rR  rT  rs  ry  r~  r  r  r|  r  r  )rV  r   r   r   r%  r  r<  r!  cardr;  rw  ro  rx  r}  r  r   r  r  r   r  s                       r   r  zMICROSOFTTEAMS.agent_notify  s$   I
 D

 L"
 ;;~&KK#"	  	
 	 ;;{#

<(D(H(H(V,VL-ABO))W4;;'78 ++/LL;;}5 ++/KK;;'78(779J+==hGM+==hGM#--h7E)99;K&335HGdkk-8$# %,#-',$+&,mmDKK4NQS4S&T   NN "  BK ''#"	)  {{-.G$++''#& -  KK#$""	  G,)00?(  
 {{>*,+#   '& 
  '
9)l]!#56  V!4gD QQr   c                    d| j                   d   ddddd| j                   d   d	d
ddd| j                   d   ddddd| j                   d   ddddd| j                   d   ddddd| j                   d   ddddddd d!d"d#| j                   d$   d%d&dt               j                         d"d'| j                   d(   d)d*dt               j                         d"d+| j                   d,   d-d.dt               j	                         d"g	}|S )/NzTeams Webhook URLr  microsoftteams_hookz*Your Microsoft Teams incoming webhook URL.r  r  rI  r  microsoftteams_incl_subjectrK  rH  rL  r  microsoftteams_incl_cardr  rN  r  microsoftteams_incl_descriptionrP  rQ  r  microsoftteams_incl_pmslinkrS  zPoster Sizerv  microsoftteams_poster_sizez/Select the size of the poster on the info card.r   r  r  Mediumrz  )r   r   r   r   r  rW  r  microsoftteams_movie_providerrY  rZ  r  microsoftteams_tv_providerr\  r]  r  microsoftteams_music_providerr_  r`  r  s     r   r  z%MICROSOFTTEAMS._return_config_optionsM	  s   #6#';;v#6"7)U(/	 $:#';;~#>"?)[(2	 $@#';;{#;"<*b )3 $5#';;/A#B"C)\(2	 $>#';;~#>"?)k(2	 $1#';;}#=">)Z(0!'!(!)!(	-*
 $7#';;/?#@"A*i )1,:,<,P,P,R $9#';;}#=">*i )1,:,<,M,M,O $7#';;/?#@"A*i )1,:,<,P,P,R}GR r   Nr  r  r   r   r   r   r     s>     D!'($%+,'(&')+&()+	OwRrJr   r   c                   >    e Zd ZdZd Zdddddddddddd	Zdd
Zd Zy)rk   z
    MQTT notifications
    rK   i[  MQTTv311r6  r   r   <   )brokerr   protocolr  r+  clientidtopicqosretain
keep_aliveas_jsonc                    | j                   d   }|st        j                  d       y  |j                  di |j	                  di       }| j                   d   r*t        j                  |      }t        j                  |      }|||d}i }| j                   d   r| j                   d   |d<   | j                   d   r| j                   d   |d<   t        t        j                  j                  | j                   d         }t        j                  d	j                  | j                  
             t        j                  j                  j                  |t        j                  |      | j                   d   t!        | j                   d         | j                   d   | j                   d   | j                   d   | j                   d   |xs d |
       t        j                  dj                  | j                  
             y)Nr  z/Tautulli Notifiers :: MQTT topic not specified.rU  r  )r   r   r  r  r+  r  r  r  r  r  r  r   r  r  )	r	  r  r  r  r   	client_id	keepaliverp  r  r  Tr   )r   r   r  r  r   r  r  getattrpahorC   clientr"  r  publishsingler  bool)	rV  r   r   r   r%  r  r  rp  r  s	            r   r  zMQTT.agent_notify	  s   G$LLJK<vzz,;<;;y!jj)G::d#D"  ;;z"#{{:6D;;z"#{{:6D499++T[[-DEJQQW[W`W`Qab		  4::d+U1CDQUQ\Q\]eQfLg[[*V1DPTP[P[\fPgkk,/dldX 	! 	
 	ELLRVR[R[L\]r   c                    d| j                   d   ddddd| j                   d   d	d
ddd| j                   d   ddddddddd| j                   d   ddddd| j                   d   ddddd| j                   d   d d!ddd"| j                   d#   d$d%ddd&| j                   d'   d(d)dd*d+d,d-dd.| j                   d/   d0d1d2dd3| j                   d4   d5d6ddd7| j                   d8   d9d:d2dg}|S );NBrokerr  mqtt_brokerz.The hostname or IP address of the MQTT broker.r:  r  Portr   	mqtt_portz3The network port for connecting to the MQTT broker.r  Protocolr  mqtt_protocolzThe MQTT protocol version.r   z3.1z3.1.1z5.0)MQTTv31r  MQTTv5r  z	Client IDr  mqtt_clientidz0The client ID for connecting to the MQTT broker.Usernamer  mqtt_usernamez2The username to authenticate with the MQTT broker.Passwordr+  mqtt_passwordz2The password to authenticate with the MQTT broker.Topicr  
mqtt_topiczThe topic to publish notifications to. You can include <a href="#notify-text-sub-modal" data-toggle="modal">notification parameters</a> to be substituted.zQuality of Servicer  mqtt_qoszEThe quality of service level to use when publishing the notification.r   r   r   r  zRetain Messager  mqtt_retainz2Set the message to be retained on the MQTT broker.rH  z
Keep-Aliver  mqtt_keep_alivezKMaximum period in seconds before timing out the connection with the broker.zSend Message as JSONr  mqtt_as_jsonzGParse and send the subject and body as JSON instead of as a raw string.r   r  s     r   r  zMQTT._return_config_options	  s   #+#';;x#8"/)Y(.	 $*#';;v#6"-)^(0	 $.#';;z#:"1)E(08=9@7<-/	 $/#';;z#:"1)[(.	 $.#';;z#:"1)](.	 $.#';;z#:"1)](2	 $+#';;w#7".*? )/ $8#';;u#5",)p(0010101-/	 $4#';;x#8"/)](2	 $0#';;|#<"3)v(0	 $:#';;y#9"0)r(2	ML\ r   Nr  r  r   r   r   rk   rk   	  sB     D!###-#%#%#- "!"%'"#O"HOr   rk   c                   @    e Zd ZdZdZdddddddddddddZddZd	 Zy
)r   z
    ntfy notifications
    rJ   rK   r  r   r   )r  r  r  r  r  r  r  r  r  r  r  r  c                 p   d}| j                   d    d| j                   d    }i }|j                  d      }| j                   d   d| j                   d    d	d
}	| j                   d   r|j                  d      |	d<   |j                  di       j                  d      rt        |d         }
| j                   d   r)|
j	                         }|r|d| j                  d      z  }| j                   d   r<d}|
j                         \  }}}|r|r||d<   |}||	d<   n|
j                         }||	d<   g }| j                   d   r|
j                  dk(  r| j                   d   }n>|
j                  dv r| j                   d   }n |
j                  dv r| j                   d   }nd }|
j                  |      }|
j                  |      }|j                  d| d| d       | j                   d    r%|
j                         }|j                  d!| d       |rd"j                  |      |	d#<   | j                  |||	||$      S )%Nr  r  /r  rp  r  zBearer r  z'https://tautulli.com/images/favicon.ico)r  AuthorizationIconr  TitlerU  rT  r  z

r  PUTr  FilenameAttachr  r   r  r"  r  rp  r  zview, View on r   z, clear=truer  zview, View on Plex, ;Actions)r  r  r  r  r  )r   encoder   rR  r  r  rs  rT  ry  r~  r   r|  r3   r  )rV  r   r   r   r%  r  r  r  r  r  r;  r   image_file_nameimage_contentimage_file_typero  r   rw  rx  r}  r  s                        r   r  zNTFY.agent_notify5
  s^   V$%Qt{{7';&<={{7#J/&t{{>'B&CD=
 ;;~&&~~g6GG ::lB'++L9,VL-ABO {{-.-==?d;-077@@D {{=)BQB[B[B]?"}(,F9%(D*9GJ' "1!?!?!AJ(2GH% G{{:&"--8#{{+;<H$//3PP#{{=9H$//3OO#{{+;<H#H / A A( K / A A( Kb|\]{{>**779!5hZ|LM%(XXg%6	"  SQW^b ccr   c                    d| j                   d   ddddd| j                   d   d	d
ddd| j                   d   ddddd| j                   d   ddddddddddd| j                   d   ddd dd!| j                   d"   d#d$d dd%| j                   d&   d'd(d dd)| j                   d*   d+d,d dd-| j                   d.   d/d0d dd1| j                   d2   d3d4dt               j                         dd5| j                   d6   d7d8dt               j                         dd9| j                   d:   d;d<dt               j	                         dg}|S )=Nzntfy Host Addressr  	ntfy_hostz-Host running ntfy (e.g. http://localhost:80).r:  r  zntfy Access Tokenr  ntfy_access_tokenzYour ntfy access token.r  z
ntfy Topicr  
ntfy_topicz&The topic to publish notifications to.r  r  ntfy_priorityr  r   r   r   r   r  r  )minlowr  highmaxr  rI  r  ntfy_incl_subjectz+Include a subject line in the notification.rH  r  r  ntfy_incl_posterz7Include a poster of the media item in the notification.rN  r  ntfy_incl_descriptionz8Include a summary of the media item in the notification.z!Include Link to Metadata Providerr  ntfy_incl_urlzNInclude a link to the media item on the metadata provider in the notification.rQ  r  ntfy_incl_pmslinkzAInclude a link to the media item in Plex Web in the notification.rW  r  ntfy_movie_providerr  rZ  r  ntfy_tv_providerzSelect the source for TV show links in the notification. Leave blank to disable.<br>Note: <a data-tab-destination="3rd_party_apis" data-dismiss="modal" >Metadata Lookups</a> may need to be enabled under the 3rd Party APIs settings tab.r]  r  ntfy_music_providerr  r`  r  s     r   r  zNTFY._return_config_optionsy
  s   #6#';;v#6"-)X(.	 $7#';;~#>"5)B(/	 $0#';;w#7".)Q(.	 $.#';;z#:"1)I(0%&%&)*&'%&- $:#';;~#>"5)V(2	 $:#';;}#="4)b(2	 $5#';;/A#B"9)c(2	 $G#';;z#:"1)y(2	 $>#';;~#>"5)l(2	 $7#';;/?#@"7*i )1,:,<,P,P,R $9#';;}#="4*i )1,:,<,M,M,O $7#';;/?#@"7*i )1,:,<,P,P,R_Xt r   Nr  r  r   r   r   r   r   "
  sG     D!') "#,'(+,&'#$'()+&()+OBdH[r   r   c                   P     e Zd ZdZdZddiZd fd	Zd Zd Zd Z	dd	Z
d
 Z xZS )r   z
    macOS notifications
    macOS
notify_appz/Applications/Tautullic                 ~    t         t        |   |       	 t        d      | _        t        d      | _        y #  Y y xY w)Nr   objcAppKit)superr   rW  
__import__r  r  rV  r   	__class__s     r   rW  zOSX.__init__
  s<    c4!!0	"6*DI$X.DK	s    8 <c                 T    	 t        d      | _        t        d      | _        y#  Y yxY w)Nr  r  TF)r  r  r  r  s    r   r   zOSX.validate
  s,    	"6*DI$X.DK	s    # 'c                     |j                  |      fd}| j                  j                  |j                  j                        }| j                  j	                  |||       y )Nc                      | g|i |S r  r   )rV  r   r%  funcold_IMPs      r   wrapperzOSX._swizzle.<locals>.wrapper
  s    g7777r   )selector	signature)instanceMethodForSelector_r  r  r  classAddMethod)rV  clsSELr  r  new_IMPr  s      `  @r   _swizzlezOSX._swizzle
  s[    005	8))$$Ww7G7G/6/@/@ % B		  c73r   c                      y)Nzade.tautulli.osxnotifyr   )rV  originalswizzleds      r   _swizzled_bundleIdentifierzOSX._swizzled_bundleIdentifier
  s    'r   c                 r   |j                  dd      }|j                  dd      }|j                  dd      }	 | j                  | j                  j                  d      d| j                         | j                  j                  d      }| j                  j                  d      }	| j                  j                  d	      }
|r|	sy
|
j                         j                         }|j                         j                         }|j                  |       |r|j                  |       |r|j                  |       |r|j                  d       |rD| j                  j                  j                         j                  |      }|j                  |       |j                  d
       |	j!                         }|j#                  |       t%        j&                  dj)                  | j*                               ~y# t,        $ r:}t%        j.                  dj)                  | j*                  |             Y d }~y
d }~ww xY w)NsubtitlerK   r  r*  NSBundles   bundleIdentifierNSUserNotificationNSUserNotificationCenterNSAutoreleasePoolF"NSUserNotificationDefaultSoundNamer  r  Tz(Tautulli Notifiers :: {name} failed: {e}r  )r   r  r  lookUpClassr  allocinit	setTitle_setSubtitle_setInformativeText_setSoundName_r  NSImageinitByReferencingFile_setContentImage_setHasActionButton_defaultUserNotificationCenterdeliverNotification_r   r"  r  r  r  r  )rV  r   r   r   r%  r  r  r*  r  r  r  poolnotification
source_imgnotification_centerr  s                   r   r  zOSX.agent_notify
  s   ::j"-

7B'

7B'%	MM$))//
;#//1 "&!6!67K!L'+yy'<'<=W'X$ $		 5 56I J%-E$**,113D-335::<L""7+))(3006**+OP![[00668OOPUV
--j9,,U3":"X"X"Z44\BKKIPPVZV_V_P`a 	LLCJJPTPYPY]^J_`	s   BG3 D.G3 3	H6<0H11H6c                 @    d| j                   d   dddddddd	d
dg}|S )NzRegister Notify Appr  osx_notify_appzEnter the path/application name to be registered with the Notification Center. Default is <span class="inline-pre">/Applications/Tautulli</span>.r:  r  zRegister Apposx_notify_registerz/Register Tautulli with the Notification Center.r  r   r  s     r   r  zOSX._return_config_options*  sG    #8#';;|#<"2*n(. $2#1"7)Z(0	 r   r  r  )r  r  r  r  r  r  rW  r   r  r  r  r  __classcell__r  s   @r   r   r   
  s;     D#%= O4(+Zr   r   c                   @    e Zd ZdZdZddddddZd ZddZdd	Zd
 Z	y)r   z)
    Plex Home Theater notifications
    rl   rK   r  hostsr  r+  display_timer*  c                     t        |      }|dz   |z   }| j                  d   r3t        j                  || j                  d   | j                  d   f      S t        j                  |      S Nz/xbmcCmds/xbmcHttp/?r+  r  )rp  r   r   r   request_contentrV  r  commandurl_commandr  s        r   	_sendhttpzPLEX._sendhttpI  d    (++k9;;z"**3dkk*6Mt{{[eOf5ghh**3//r   Nc           	      P   |xs i }dd||dg}ddi}|dz   }| j                   d   rJt        j                  |dt        j                  |      || j                   d	   | j                   d   f
      }n,t        j                  |dt        j                  |      |      }|r|d   d   S y Nr   z2.0)r[   jsonrpcr  r  r  r2  z/jsonrpcr+  r  r  )r  r  r  rp  )r  r  r  r   r   r   request_jsonr  r  rV  r  r  r  r  r  r  r  s           r   	_sendjsonzPLEX._sendjsonR      2UfOP!#56Z;;z"++CTZZPTEU_f26++j2I4;;WaKb1ceH ++CTZZPTEU_fgHA;x(( r   c                    | j                   d   j                  d      D cg c]  }|j                          }}| j                   d   dkD  rd| j                   d   z  }nd}| j                   d   r| j                   d   }nKt        j                  j                  t        j                  t        j                  j                  d            }|D ]  }	t        j                  d	j                  | j                  |	
             	 | j                  |	dddgi      d   d   }
|
dk  r5|dz   |z   dz   t        |      z   }dd|z   dz   d}| j                  |	|      }n||||d}| j                  |	d|      }|st         t        j                  dj                  | j                                yc c}w # t         $ r;}t        j"                  dj                  | j                  |             Y d }~ yd }~ww xY w)Nr  r{  r  r       r*  r!  zETautulli Notifiers :: Sending notification command to {name} @ {host})rZ   r  Application.GetProperties
propertiesr  majorr(   ExecBuiltInNotification(r  r$  rL   r  r  displaytimer*  GUI.ShowNotificationr  r  5Tautulli Notifiers :: {name} notification failed: {e}r  FT)r   r@  rr  r+  r,  r3   r  DATA_DIRabspathr   r"  r  r  r.  rU   r&  r  r  rV  r   r   r   r%  xr  r  r*  r  r  r  notifycommandr   r  r  s                   r   r  zPLEX.agent_notifya  s   $(KK$8$>$>s$CDqDD;;~&*$++n"==LL;;wKK(EGGLL"''//Br2stE 	DKK_fflplulu  }Af  B  C../J\\e[fLghirst{|R<#*S=4#7##=L@Q#QL0=O^jLjmpLp$qM"nnT=AG (/4P\glmF"nnT3I6RG#OKK Q X X^b^g^g X hi#	. G E>  T[[aeajajno[pqs   F+B'F00	G490G//G4c           
          d| j                   d   ddddd| j                   d   d	d
ddd| j                   d   ddddd| j                   d   ddddd| j                   d   ddddg}|S )NzPlex Home Theater Host Addressr  
plex_hostszdHost running Plex Home Theater (eg. http://localhost:3005). Separate multiple hosts with commas (,).r:  r  zPlex Home Theater Usernamer  plex_usernamez?Username of your Plex Home Theater client API (blank for none).zPlex Home Theater Passwordr+  plex_passwordz?Password of your Plex Home Theater client API (blank for none).Notification Durationr  plex_display_timeAThe duration (in seconds) for the notification to stay on screen.r  Notification Iconr*  
plex_image[Full path or URL to an image to display with the notification. Leave blank for the default.r   r  s     r   r  zPLEX._return_config_options  s    #C#';;w#7". *P(.	 $@#';;z#:"1)j(.	 $@#';;z#:"1)j(2	 $;#';;~#>"5)l(0	 $7#';;w#7". *G(.	1@ r   r  r  
r  r  r  r  r  r  r&  r.  r  r  r   r   r   r   r   =  s9     D "#%#%'( "	O0)$L!r   r   c                   J     e Zd ZdZdZdZg ddZd
 fd	ZddZd Z	d	 Z
 xZS )r   z'
    Plex Mobile App Notifications
    rm   z2https://notifications.plex.tv/api/v1/notificationspreplay)user_ids
tap_actionc                 V    t         t        |   |       dddddddddd| _        y )	Nr   mediaz tv.plex.notification.library.new)r7  
identifierz%tv.plex.notification.playback.startedadminztv.plex.notification.device.new)createdplay	newdevice)r  r   rW  configurationsr  s     r   rW  zPLEXMOBILEAPP.__init__  s<    mT+6+: ")8Z[%5\]#*:[\
r   c           	         || j                   vr8|j                  d      s't        j                  d|d| j                  d       y |dk(  rDg }| j                   D ](  }|j                  | j                  ||d|z                * t        |      S |j                  d      d   }| j                   |   d   | j                   |   d	   | j                  d
   dt        j                  j                  t        j                         did}t        |j!                  d            }	|j                  d      r!dddd|d   d<   ddd|d   d<   d||d|d<   n|dv rg|	j"                  d   |	j"                  d   |	j"                  d   d|d   d<   |	j"                  d   |	j"                  d   |	j"                  d    d!|d   d<   n-|d"k(  rn't        j                  d|d#| j                  d       y |d   d$k(  r@|j                  d      s.|	j$                  }
d }|
dk(  r0|
|	j"                  d%   |	j"                  d&   |	j"                  d'   d(}n|
d)k(  r"|
|	j"                  d*   |	j"                  d'   d+}nl|
d,k(  r7d)|	j"                  d*   |	j"                  d'   d+}|	j"                  d-   |d   d.<   n0|
d/k(  rK|
|	j"                  d0   |	j"                  d*   |	j"                  d1   |	j"                  d2   |	j"                  d3   d4}n|
d5k(  r!|
|	j"                  d6   |	j"                  d'   d+}n|
d7k(  r=|
|	j"                  d8   |	j"                  d&   |	j"                  d6   |	j"                  d'   d9}nx|
d:k(  rLd7|	j"                  d8   |	j"                  d&   |	j"                  d6   |	j"                  d;   d9}|	j"                  d<   }n't        j                  d=|
d#| j                  d       y ||d<   d>j'                  t        j                  j                  |xs |	j"                  d?         |d@<   | j                  dA   dBk(  |dB<   dCt        j                  j(                  i}| j+                  | j,                  ||D      S )ENtestz*Tautulli Notifiers :: Notification action z not allowed for .test_r  r=  r7  rS  rO  rw  )rS  r  )r7  rS  re  r  rU  DevicePlatformrb  )r  platformmachineIdentifierr  ri  Userr   )r  r[   rg  r   )rO   r  r  metadata)rV  rW  r_  
machine_idrh  
user_thumb)r  r[   thumbrU  z not supported for rR  r  r  re  )rO   r  r  re  r   r  )rO   r  re  r   episode_countcountr   r  r  
season_numgrandparent_thumb)rO   r  grandparentTitleindexparentIndexgrandparentThumbr   r  r   r  )rO   r  r  parentTitlere  r   parent_thumbparent_rating_keyz!Tautulli Notifiers :: Media type z;server://{}/com.plexapp.plugins.library/library/metadata/{}r  urirP  rV  zX-Plex-Tokenr  )rX  r-  r   r  r  r   r  rX   r@  r   r  r  PMS_IDENTIFIERr   pms_namerR  r   rU  rT  r  	PMS_TOKENr  NOTIFICATION_URL)rV  r   r   r   r%  testsconfigurationconfiguration_actionr  r;  rT  uri_rating_keyrb  r  s                 r   r  zPLEXMOBILEAPP.agent_notify  s   ,,,V5F5Fv5NLL`fhlhqhqrsVE!%!4!4 jT..wTRYZgRg.hiju:%||G4R8 (()=>wG--.BCLQ++j)"(--">">$--/	

 )L)ABV$!&%/&DL"  $DL 
    D ,,(33H=+66zB%4%?%?%M&DL" )33F;%00;(33LA$DL  y  LLbhjnjsjstu=G#F,=,=f,E(33J!NW$&,77@+66v>,77@	 v%&,77D,77@
 x'",77D,77@
 )8(B(B?(SVW%y(&,77G(7(B(B;(O,77F#2#=#=l#K(7(B(BCV(W x'&,77F,77@
 w&&,77E+66v>#2#=#=m#L,77@ w&#,77E+66v>#2#=#=m#L,77G "1!;!;<O!P]gimirirst'DW^^,,n.h@Z@Z[g@hDK  ;;|4>DL!6==#:#:;  !6!6d SSr   c                     t        j                         j                         D ci c]  }|d   s	|d   |d    }}|S c c}w )Nrh  r  )r   r  r  )rV  r  rO  s      r   r  zPLEXMOBILEAPP.get_usersG  sF    >Ckkm>U>U>Wh[\]f[gAiL!O"44hh is   
??c           	          d| j                   d   ddd| j                         dd| j                   d   d	d
dddddg}|S )NzPlex User(s)rO  plexmobileapp_user_idszSelect which Plex User(s) to receive notifications.<br>Note: The user(s) must have notifications enabled for the matching Tautulli triggers in their Plex mobile app.r   r  zNotification Tap ActionrP  plexmobileapp_tap_actionz0Set the action when tapping on the notification.zGo to media pre-play screenzStart playing the media)rN  rV  )r   r  r  s     r   r  z$PLEXMOBILEAPP._return_config_optionsK  sh    #1#';;z#:":*h )1,0NN,< $=#';;|#<"<)[(08U5N-P& r   r  r  )r  r  r  r  r  ru  r  rW  r  r  r  r  r  s   @r   r   r     s9     $DK#%%.O
GTRr   r   c                   ,    e Zd ZdZdZdddZd	dZd Zy)
r   z
    Prowl notifications.
    rq   rK   r   )r   r  c                 v    | j                   d   d||| j                   d   d}ddi}| j                  d||      S )	Nr   rb  r  )rF  applicationr7  r   r  r<  !application/x-www-form-urlencodedz&https://api.prowlapp.com/publicapi/addr  r  )rV  r   r   r   r%  r  r  s          r   r  zPROWL.agent_notifyk  sR    ++e,) # KK
3	5 "#FG  !ISZae ffr   c                 h    d| j                   d   ddddd| j                   d   d	d
ddddddddg}|S )NzProwl API Keyr   	prowl_keyzYour Prowl API key.r  r  r  r  prowl_priorityr  r   r[  r=  r   r   r   r\  r  r   r  s     r   r  zPROWL._return_config_optionsv  s[    #2#';;u#5"-)>(/	 $.#';;z#:"2)I(013aA,N r   Nr  r  r   r   r   r   r   b  s&     D #$O	gr   r   c                   8    e Zd ZdZdZddddddZddZd Zd	 Zy
)r   z"
    Pushbullet notifications
    rr   rK   r   r   )rC  	device_idchannel_tagr  r  c                    d|d}d| j                   d   d}| j                   d   r||d<   | j                   d   r| j                   d   |d	<   n!| j                   d
   r| j                   d
   |d
<   | j                   d   rA|j                  di       j                  d      rt        |d         }|j                         }|r|d   |d   d}	d|i}
t	        j
                  d||	      }|j                         }|j                  d      }t	        j
                  ||
      }|j                  dk(  r)d|d<   |j                  dd        |j                  |       nht        j                  dj                  | j                  |             t        j                  dj                  t        j                   |d                   | j#                  d||      S )Nnote)rO   r   r2  rC  r<  zAccess-Tokenr  r  r  device_idenr  r  rU  rT  r   r   )	file_name	file_typefilez,https://api.pushbullet.com/v2/upload-requestr  
upload_url)r4     rO   r  zTTautulli Notifiers :: Unable to upload image to {name}: [{r.status_code}] {r.reason}r  r  Tz$https://api.pushbullet.com/v2/pushes)r   r   rR  r  r  r  r  r   r  r2  r   r  r  r  r   r   r  r  )rV  r   r   r   r%  r  r  r;  r*  	file_jsonr4  r  file_responser  s                 r   r  zPUSHBULLET.agent_notify  s    $6#';;y#9 ;;~&#DM ;;{#"&++k":D[['"&++m"<D;;}%&**\2*F*J*J<*X,VL-ABO#--/E*/(qJ	MM"PZahqr !*..|<
MM*E:==C'#)DL!%%fd3KK.LL "@@FDIIYZ@[]LL!M!T!TU\UkUklmosUt!uv  !GQX_c ddr   c                    ddi}| j                   d   rd| j                   d   d}	 t        j                  d|      }|j                  dk(  rP|j	                         }|j                  dg       }|j                  |D ci c]  }|d	   s	|d
   |d    c}       |S t        j                  dj                  | j                  |             t        j                  dj                  t        j                  |d                   	 |S |S c c}w # t        $ r;}t        j                  dj                  | j                  |             Y d }~|S d }~ww xY w)NrK   rC  r2  r  z%https://api.pushbullet.com/v2/devices)r  r  rR  r   idennicknamerP  r  r  TrO  rI  )r   r  r   r  r  r2  r   r  r  r  r   r   r  r  )rV  rR  r  r  rJ  pushbullet_devicesrQ  r  s           r   rT  zPUSHBULLET.get_devices  sO   r(;;y!'9'+{{9'=GBLL!HRYZ==C'$%FFHM)6):):9b)I&NNFX#h\]^f\gAfIq}$<#hi  LL "@@FDIIYZ@[]LL!M!T!TU\UkUklmosUt!uv
 w $i  Bbiiosoxox~i  A  B  BBs7   AD >
D
	D
D A(D 
D 	E0EEc           
          d| j                   d   dddddd| j                   d	   d
dd| j                         dd| j                   d   ddddd| j                   d   ddddd| j                   d   ddddg}|S )NzPushbullet Access TokenrC  pushbullet_api_keyzYour Pushbullet access token.r  TrW  r]  r  pushbullet_device_idzdSet your Pushbullet device. If set, will override channel tag. Leave blank to notify on all devices.r   r  Channelr  pushbullet_channel_tagzA channel tag (optional).r:  r  rI  r  pushbullet_incl_subjectrK  rH  r  r  pushbullet_incl_posterr  )r   rT  r  s     r   r  z!PUSHBULLET._return_config_options  s    #<#';;y#9"6)H(/%) $,#';;{#;"8*Q(0,0,<,<,> $-#';;}#=":)D(.	 $:#';;~#>";)[(2	 $:#';;}#=":)S(2	7!F r   Nr  rc  r   r   r   r   r     s5     D"$$&&('(&'	O*eX0$r   r   c                   H    e Zd ZdZdZddddddddddddddZdd	Zd
 Zd Zy)r   z 
    Pushover notifications
    rs   rK   r   r   r?   i  )	api_tokenr   rm  r  r  retryexpirer  r  r  r  r  r  c                    | j                   d   | j                   d   || j                   d   | j                   d   | j                   d   t        j                         d}| j                   d   r||d<   | j                   d   d	k(  r8t        d
| j                   d         |d<   t        d
| j                   d         |d<   ddi}i }| j                   d   r|j	                  di       j	                  d      rt        |d         }|j                  dk(  r| j                   d   }	n>|j                  dv r| j                   d   }	n |j                  dv r| j                   d   }	nd }	|j                  |	      }
|j                  |	      }|
|d<   ||d<   | j                   d   rG|j	                  di       j	                  d      r&t        |d         }|j                         }|rd|i}i }| j                  d|||      S )Nr  r   r  rm  r  )r  rg  r  r  rs  r  r%  r  r  r   r?   r  r  r<  r  r  rU  rT  r   r  r"  r  rp  r  r  	url_titler  r<  z(https://api.pushover.net/1/messages.json)r  r  r4  )r   r   r%  r  r   rR  rT  r~  r  r  r  )rV  r   r   r   r%  r  r  r4  r;  rw  r}  captionr*  s                r   r  zPUSHOVER.agent_notify  s   [1E*W-N3 KK
3$..02 ;;~&#DM;;z"a'DKK$89DM T[[%:;DN!#FG;;z"vzz,'C'G'G'U,VL-ABO))W4;;'78 ++/LL;;}5 ++/KK;;'78+==hGM%11(;G'DK 'D;;}%&**\2*F*J*J<*X,VL-ABO#--/E%u-  !KU\cgot uur   c                 t   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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.dd/d0dg}| j                   d1   |D cg c]  }|d2   	 c}vr.|j                  | j                   d1   | j                   d1   d       |S c c}w )3NrK   r  alienzAlien Alarm (long)bikeBikebugleBuglecashregisterzCash Register	classical	ClassicalclimbzClimb (long)cosmicCosmicr  zPushover Echo (long)fallingFallinggamelanGamelanincomingIncomingintermissionIntermissionmagicMagic
mechanical
MechanicalnonezNone (silent)
persistentzPersistent (long)pianobarz	Piano Barr   zPushover (default)sirenSiren
spacealarmzSpace AlarmtugboatzTug BoatupdownzUp Down (long)vibratezVibrate Onlyr  rN   )r   r   )rV  r  ss      r   r  zPUSHOVER.get_soundsF  s   "%';<f-w/$o>!;7~61&<=33 *5$n=w/"L9o6",?@ +6 *>?w/"M:4(8981
4 ;;wF'Cq'
'CCMMDKK$8$++gBVWX (Ds   5B5c                    d| j                   d   ddddd| j                   d   d	d
ddd| j                   d   ddd| j                         ddd| j                   d   ddddddddddd| j                   d   d d!d"dd#| j                   d$   d%d&d"dd'| j                   d(   d)d*d+dd,| j                   d-   d.d/d+dd0| j                   d1   d2d3d+dd4| j                   d5   d6d7d+dd8| j                   d9   d:d;dt               j                         dd<| j                   d=   d>d?dt               j	                         dd@| j                   dA   dBdCdt               j                         dg}|S )DNzPushover API Tokenr  pushover_api_tokenzYour Pushover API token.r  r  zPushover User or Group Keyr   pushover_keyz Your Pushover user or group key.r  r  pushover_soundz\Select a notification sound or enter a custom sound name. Leave blank for the default sound.r  Fr  r  r  pushover_priorityr  r   r[  r=  r   r   r   r\  r  zRetry Intervalr  pushover_retryzpSet the interval in seconds to keep retrying the notification.<br>Note: For priority 2 only. Minimum 30 seconds.r  zExpire Durationr  pushover_expirezwSet the duration in seconds when the notification will stop retrying.<br>Note: For priority 2 only. Minimum 30 seconds.r  rm  pushover_html_supportzHStyle your messages using these HTML tags: b, i, u, a[href], font[color]rH  zInclude supplementary URLr  pushover_incl_urlz3Include a supplementary URL with the notifications.rI  r  pushover_incl_subjectrK  r  r  pushover_incl_posterr  rW  r  pushover_movie_providerr  rZ  r  pushover_tv_providerr   r]  r  pushover_music_providerr  )r   r  rR  rc  rg  rm  r  s     r   r  zPUSHOVER._return_config_optionsz  s   #7#';;{#;"6)C(/	 $@#';;u#5"0)K(/	 $+#';;w#7"2 *H(3,0OO,=(- $.#';;z#:"5)I(013aA,N $4#';;w#7"2*Z(0 $5#';;x#8"3*Z(0 $9#';;~#>"9)s(2	 $?#';;z#:"5)^(2	 $:#';;~#>"9)[(2	 $:#';;}#="8)S(2	 $7#';;/?#@";*i )1,:,<,P,P,R $9#';;}#="8*i )1,:,<,M,M,O $7#';;/?#@";*i )1,:,<,P,P,Rg\| r   Nr  r  r   r   r   r   r      sO     D$& '( "#$ "!%#$'(&')+&()+O0vdh_r   r   c                   T     e Zd ZdZdZddddZd fd	Zd Zd Zd	 Z	dd
Z
d Z xZS )r   z
    Script notifications
    rt   rK   r?   )script_folderscripttimeoutc           
          t         t        |   |       dddddt        j                  rdnt
        j                  dddd		| _        d
| _        d| _	        dgdgdgddgd| _
        d| _        y )Nr   rK   phpperlz(powershell -executionPolicy bypass -filepythonpythonwruby)	z.batz.cmdz.phpz.plz.ps1.py.pywz.rbz.shnopythonpathTr  r  )r  python2python3r  F)r  r   rW  r  FROZENsys
executablescript_extspythonpath_override
pythonpathprefix_overridesscript_killedr  s     r   rW  zSCRIPTS.__init__  s    gt%V%4 >%}}8#..

 $2 gwwv	!
 #r   c                    | j                   d   }ddi}|r!t        j                  j                  |      s|S t        j                  |      D ]  \  }}}|D ]  }t        j                  j                  |      \  }}|| j                  v s4t        j                  j                  t        j                  j                  ||      |      }	t        j                  j                  ||      }
|	||
<     |S )Nr  rK   )	r   r+  r,  existswalksplitextr  r3   relpath)rV  	scriptdirr-   rootdirsr4  r1  rZ   extrfpfps              r   list_scriptszSCRIPTS.list_scripts  s    KK0	r(RWW^^I6N!#!3 	&D$ &GG,,Q/	c$***'',,rwwtY'GKCdA.B"%GBK&	& r   c                 6   t         j                  j                  t         j                  j                  dt	        j
                  d      t         j                  j                  t         j                  z   t         j                  j                  t         j                  t        j                  t        j                  j                  t         j                  j                  d      d	}|r5t!        j"                         j%                  |      }t'        |d         |d<   | j(                  rSt         j*                  d	vrAt        j,                  j                  t.        j                  D cg c]  }|s|	 c}      |d
<   t        j0                  j3                         }|j5                  |       	 t7        j8                  |t6        j:                  t6        j:                  t6        j:                  | j<                  d   |      }| j<                  d   dkD  r0t?        j@                  | j<                  d   | jB                  |f      }nd }	 |r|jE                          |jG                         \  }	}
|jH                  }tK        jL                  d|z         |r|jO                          	 |
rFdj                  |
jU                  d      jW                               }tK        jR                  d|z         |	rFdj                  |	jU                  d      jW                               }tK        jL                  d|z         | jX                  stK        jZ                  d       yy c c}w # |r|jO                          w w xY w# tP        $ r"}tK        jR                  d|z         Y d }~yd }~ww xY w)NrK   r  )r  zplexapi_script.log)	PLEX_URL
PLEX_TOKENPLEX_USER_TOKENTAUTULLI_URLTAUTULLI_PUBLIC_URLTAUTULLI_APIKEYTAUTULLI_ENCODINGTAUTULLI_PYTHON_VERSIONPLEXAPI_LOG_PATH)rh  server_tokenr  )windowsmacos
PYTHONPATHr  )stdinstdoutstderrcwdenvr  r   z>Tautulli Notifiers :: Subprocess returned with status code %s.z.Tautulli Notifiers :: Failed to run script: %sFz
  rp  z)Tautulli Notifiers :: Script error: 
  %sz,Tautulli Notifiers :: Script returned: 
  %sz/Tautulli Notifiers :: Script notification sent.T).r  r  PMS_URLrt  r   get_plexpy_urlHTTP_BASE_URL	HTTP_ROOTAPI_KEYSYS_ENCODINGr   PYTHON_VERSIONr+  r,  r3   LOG_DIRr   r  
get_tokensrU   r  INSTALL_TYPEpathsepr  environrD  r2  
subprocessPopenPIPEr   	threadingTimerkill_scriptstartcommunicate
returncoder   r   cancelOSErrorr  decode
splitlinesr  r"  )rV  r  rh  
custom_envuser_tokenspr
  processtimeroutputr  statusr  errouts                  r   
run_scriptzSCRIPTS.run_script  s    -- --11!#22KH#)==#>#>AQAQ#Q%}}44!'!4!4'-'<'< "V]]-B-BDX Y

 ++-2272CK,/N0K,LJ()??v22:NN')zz3887Qaq7Q'RJ|$jjoo

:	 &&v-7__.8oo.8oo+/;;+G+.0G {{9%)!I(>@P@PSZR\]#KKM ' 3 3 5 ++]`ffgLLN ++ell73>>@ACLLEKL++fmmG4??ABCLLH3NO!!KKIJ "Q 8R2 LLN   	LLIAMN	s>   $M,M*BM- A	M 
M- M**M- -	N6NNc                 |    |j                          d| _        t        j                  d| j                  d   z         y )NTzQTautulli Notifiers :: Script exceeded timeout limit of %d seconds. Script killed.r  )killr  r   r$  r   )rV  r'  s     r   r  zSCRIPTS.kill_scriptO  s5    ! %'+{{9'=> 	?r   c                    | j                   d   st        j                  d       y|j                  d| j                   j                  dd            }t	        j
                  |j                  d|            }|j                  di       j                  d      }t        j                  d	|d
|d|       |r|st        j                  d|z         y|st        j                  d       yt        j                  j                  |      r$|j                  t        | j                              st        j                  d|z         yt        j                  j                  |      \  }}	| j                  j                  |	d      }
|
r|
j                         |gz   }n|g}|
r|r|d   | j                  k(  r
d| _        |d= |
rS|rQ|d   | j"                  v r@|	| j"                  |d      v r|d   |d<   |d= n t        j                  d|d   d|	d       y|j%                  |       t        j                  d|z         t        j                  d       t'        j(                  | j*                  ||f      j-                         }y)z
            Args:
                  subject(string, optional): Subject text,
                  body(string, optional): Body text,
                  action(string): 'play'
        r  z1Tautulli Notifiers :: No script folder specified.Nr  rK   script_argsrU  rh  z3Tautulli Notifiers :: Trying to run notify script: z, arguments: z
, action: zDTautulli Notifiers :: No script selected for action '%s', exiting...z4Tautulli Notifiers :: No script selected, exiting...zDTautulli Notifiers :: Invalid script file '%s' specified, exiting...r   Fz/Tautulli Notifiers :: Invalid prefix override 'z' for 'z' script, exiting...z(Tautulli Notifiers :: Full script is: %sz7Tautulli Notifiers :: Executing script in a new thread.)targetr   T)r   r   r  r   r   
split_argsr   r+  r,  isfiler.  r   r  r  r@  r  r  r  extendr  Threadr-  r  )rV  r   r   r   r%  r  r1  rh  rZ   r  prefixthreads               r   r  zSCRIPTS.agent_notifyU  s    {{?+LLLMHdkkooh&CD((M7)KL**\2.229=V5 	6 &LL_bhhiLLOP'vuTEUEU?V/WLL_bhhiGG$$V,	c!!%%c2.\\^vh.FXF k1~!9!99"'N kk!n8M8M&Md++KN;;'Nq	N +A5 6k"?&HINO!!?PQWWYr   c           	          dddj                  | j                        z   dz   ddd| j                  d   d	d
dddd| j                  d   ddd| j                         dd| j                  d   ddddg}|S )NzSupported File Typesz<span class="inline-pre">r   z</span>r  r  zScript Folderr  scripts_script_folderz*Enter the full path to your script folder.r:  TrW  zScript Filer  scripts_scriptzSelect the script file to run.r   r  zScript Timeoutr  scripts_timeoutzNThe number of seconds to wait before killing the script. 0 to disable timeout.r  r  )r3   r  r   r  r  s     r   r  zSCRIPTS._return_config_options  s    #9)D"ii(8(89*:<E*F(.
 $3#';;#?"9)U(.%) $1#';;x#8"2)I(0,0,=,=,? $4#';;y#9"3)y(0	'6 r   r  r  )r  r  r  r  r  r  rW  r  r-  r  r  r  r  r  s   @r   r   r     s?     D(*!#"$O
#2"=~?<|r   r   c                   B    e Zd ZdZdZddddddddddddddZd
dZd Zy	)r   z
    Slack Notifications
    ru   rK   r   r   )r  channelr  
icon_emojir  r  r  r  r  r  r  r  r  c                    | j                   d   r	|dz   |z   }n|}d|i}| j                   d   r0| j                   d   j                  d      r| j                   d   |d<   | j                   d   r| j                   d   |d<   | j                   d   rJt        | j                   d         j                  dk(  r| j                   d   |d<   n| j                   d   |d	<   | j                   d
   rp|j	                  di       j	                  d      rNt        |d         }|j                  dk(  r| j                   d   }n>|j                  dv r| j                   d   }n |j                  dv r| j                   d   }nd }|j                         }	|j                  |      }
|j                  |      }|j                  d      }|j                         }|j                         }|r
d| d| d}nd| d}| j                   d   r| d| }|d d |dd  xr dz   }dd|dd}| j                   d   r	d|	|d |d!<   |g}g }dd"d}|r,|j                  |       |j                  dd#| d|
 d$d       | j                   d%   r)|j                  |       |j                  dd#| d&d       |rEt        |      d'k  r|j                  d(d)d       |j                  d|d d d'   |d*d d'   z   d+       | j                   d   s|j                  d|	|d        d,|i}| j                   d-   r5t        j                   d.| j                   d-         r| j                   d-   |d-<   |g|d/<   d0d1i}| j#                  | j                   d2   ||3      S )4Nr  
r:  r>  r&  r  r?  rK   icon_urlr  rU  rT  r   r  r"  r  rp  r  r#  z*<|z>**r  i  r+  sectionmrkdwn)rO   r:  r  r*  )rO   	image_urlalt_text	accessoryr,  <>r  z
|Plex Web>r   
plain_textr  r   )rO   r/  blocksr  z^#(?:[0-9a-fA-F]{3}){1,2}$r  r<  r2  r  r  )r   r-  r   schemer   rR  rT  rs  ry  r~  r  r  r|  r   r/  r5  r6  r  )rV  r   r   r   r%  r:  r  r;  rw  ro  rx  r}  r  r   r  rE  rM  r/  field_titler<  r  s                        r   r  zSLACK.agent_notify  s   ;;~&T>D(DD~;;y!dkk)&<&G&G&L"kk)4DO;;z"#{{:6D;;|$L1299R?%)[[%>\"#';;|#<Z ;;{#

<(D(H(H(V,VL-ABO))W4;;'78 ++/LL;;}5 ++/KK;;'78(779J+==hGM+==hGM#--h7E)99;K&335HM?!E7"55'|{{-.r+/ $K4;#859D "# G {{+,#!+ %($
 YFF &K k*$aa@  {{>*k*$z4  v;!#MM , ##  %$SqSkF14a4L8 
 ;;/0#!+ %  &J
 {{7#1NPTP[P[\cPd(e&*kk'&:
7##-,D!#56  V!4gD QQr   c                    d| j                   d   ddddd| j                   d   d	d
ddd| j                   d   ddddd| j                   d   ddddd| j                   d   ddddd| j                   d   ddddd| j                   d   d d!ddd"| j                   d#   d$d%ddd&| j                   d'   d(d)ddd*| j                   d+   d,d-ddd.| j                   d/   d0d1d2t               j                         d3d4| j                   d5   d6d7d2t               j                         d3d8| j                   d9   d:d;d2t               j	                         d3g}|S )<NzSlack Webhook URLr  
slack_hookz Your Slack incoming webhook URL.r  r  zSlack Channelr>  slack_channelzkThe Slack channel name (starting with '#') which will be used. Leave blank for webhook integration default.r:  zSlack Usernamer  slack_usernamezSThe Slack username which will be used. Leave blank for webhook integration default.z
Slack Iconr?  zjThe Slack emoji or image url for the icon which will be used. Leave blank for webhook integration default.slack_icon_emojirC  zSlack Colorr  rD  slack_colorrI  r  slack_incl_subjectrK  rH  rL  r  slack_incl_cardr  rN  r  slack_incl_descriptionrP  rQ  r  slack_incl_pmslinkrS  rT  r  slack_incl_thumbnailrV  rW  r  slack_movie_providerrY  r   r  rZ  r  slack_tv_providerr\  r]  r  slack_music_providerr_  r`  r  s     r   r  zSLACK._return_config_options6  s   #6#';;v#6".)K(/	 $3#';;y#9"1 *Y(.	 $4#';;z#:"2)~(.	 $0#';;|#< *V"4(.	 $1#';;w#7 *S"/(.	 $:#';;~#>"6)[(2	 $@#';;{#;"3*b )3 $5#';;/A#B":)\(2	 $>#';;~#>"6)k(2	 $:#';;/?#@"8)k(2	 $7#';;/?#@"8*i )1,:,<,P,P,R $9#';;}#="5*i )1,:,<,M,M,O $7#';;/?#@"8*i )1,:,<,P,P,RcZx r   Nr  r  r   r   r   r   r     sJ     D!"$#%%' "'($%+,)*'()+&()+OnR`]r   r   c                   4    e Zd ZdZdZddddZddZd	 Zd
 Zy)r{   z+
    Tautulli Remote app notifications
    rW   rK   r   r   )r  r  notification_typeNc                 .   t        j                  | j                  d         }|st        j                  d       y |d   }t        |j                  d            }||||| j                  d   | j                  d   |j                  j                  dd	      |j                  j                  d
d	      |j                  j                  dd	      |j                  j                  dd	      |j                  j                  dd	      d}t        r't        j                  d      }	|d   }
d}d}t        t        j                         ||	|      }|j                  |
j                               }t        j                  d      }t!        |      }|j#                  |t%        j&                  |      j                  d      d       }t         j(                  |d   gddiddt+        j,                  |      t+        j,                  |      t+        j,                  |	      t.        j0                  j2                  dd}nLt        j                  d       t         j(                  |d   gddid|t.        j0                  j2                  dd}dd i}| j5                  d!||"      S )#Nr  )r  z]Tautulli Notifiers :: Unable to send Tautulli Remote app notification: device not registered.r   rU  r  r_  rj  rK   rk  rh  r  r  )r>  r   r   r   r  r_  rj  rk  rh  r  r  r0   device_token    i'	 )	algorithmlengthsalt
iterationsrp  onesignal_idenzTautulli NotificationTr   )	encryptedr  cipher_textnoncere  	server_id)r  include_subscription_idscontentsr  zTautulli Notifiers :: Cryptography library is missing. Tautulli Remote app notifications will be sent unecrypted. Install the library to encrypt the notifications.F)ri  rL  rl  r  r2  z'https://api.onesignal.com/notificationsr  )r   get_mobile_devicesr   r   r$  rR  r   rU  _CRYPTOGRAPHYr+  urandomr   r	   SHA256deriver  r
   encryptr  r  _ONESIGNAL_APP_IDbase64	b64encoder  r  PMS_UUIDr  )rV  r   r   r   r>  r%  devicer;  plaintext_datare  
passphrase
key_lengthrf  kdfr   rk  cipherencrypted_datar	  r  s                       r   r  zTAUTULLIREMOTEAPP.agent_notify  sc   ..[9QRKKwxAYF(L)AB-<%,"&$*&*kk*&=/3{{;N/O)8)C)C)G)GWY)Z(7(B(B(F(F|UW(X%4%?%?%C%CIr%R(7(B(B(F(F|UW(X*9*D*D*H*HY[*\
^ ::b>D/JJJv}}zPTaklC**Z..01C
 JJrNEC[F#^^E4::n3M3T3TU\3]_cdN ",!=!=4:>4J3K$(*A#B-1+,/5/?/?/O)/)9)9%)@(.(8(8(>-3]]-C-C E	G KK L M ",!=!=4:>4J3K$(*A#B-2.<-3]]-C-C EG "#56  !JT[bi jjr   c                     t        j                         }	 d}|j                  |      S # t        $ r$}t	        j
                  d|z         g cY d }~S d }~ww xY w)NzcSELECT * FROM mobile_devices WHERE official = 1 AND onesignal_id IS NOT NULL AND onesignal_id != '')queryzNTautulli Notifiers :: Unable to retrieve Tautulli Remote app devices list: %s.)r   r   r   r  r   r$  )rV  r   r  r  s       r   rT  zTAUTULLIREMOTEAPP.get_devices  sV    %%'	JE9959)) 	KKhkllmI	s   * 	AAAAc                     g }t         sf|j                  ddt        j                  dt        j
                  j                  dt        j
                  j                  d      z   dz   dd       n|j                  d	d
dd       |d   dxx   dt        j                  d      z   dz   t        j                  d      z   dz   z  cc<    j                         }|s|j                  dddd       nt        |D ch c]  }|d   	 c}      dk  r|D ci c]  }|d   |d   xs |d    }}nWt        t              }|D ]C  }|d   dk(  rdn|d   j                         }||   j                  |d   |d   xs |d   d       E |j                  d j                  d   ddd|dd        t         fd!|D        d       }|d"k(  rU|j                  d# j                  d$   d%d&dd'd(d)d*d+d,       |j                  d- j                  d.   d/d0dd1d2d3d4d,       |S |dk(  r$|j                  d5 j                  d.   d/d6d7d8       |S c c}w c c}w )9NWarningz<strong>The Cryptography library is missing. The content of your notifications will be sent unencrypted!</strong><br>Please install the library to encrypt the notification contents. Instructions can be found in the <a href="zhttps://github.com/r  z;/wiki/Frequently-Asked-Questions#notifications-cryptographyz+" target="_blank" rel="noreferrer">FAQ</a>.r  r  r
  z]The Cryptography library was found. The content of your notifications will be sent encrypted!r=  r   z.<br><br>Notifications are sent using <a href="zhttps://onesignal.comz" target="_blank" rel="noreferrer">OneSignal</a>. Some user data is collected and cannot be encrypted.<br>Please read the <a href="z$https://onesignal.com/privacy_policyzQ" target="_blank" rel="noreferrer">OneSignal Privacy Policy</a> for more details.r]  a  No mobile devices registered with OneSignal. <a data-tab-destination="remote_app" data-toggle="tab" data-dismiss="modal">Get the Tautulli Remote App</a> and register a device.<br>Note: Only devices registered with a valid OneSignal ID will appear in the list.r_  r   r  r  device_nameiosiOSr  remoteapp_device_idzSelect your mobile device or <a data-tab-destination="remote_app" data-toggle="tab" data-dismiss="modal">register a new device</a> with Tautulli.<br>Note: Only devices registered with a valid OneSignal ID will appear in the list.r   T)rY   rN   rZ   r   r  r   rX  c              3   T   K   | ]  }|d    j                   d    k(  s|d    ! yw)r  r_  Nr   )r   rQ  rV  s     r   r   z;TAUTULLIREMOTEAPP._return_config_options.<locals>.<genexpr>8  s*     f11[>T[[YdMe;e:fs   (
(androidr  r  remoteapp_priorityr  MinimumLowNormalHigh)r   r   r   r  r  zNotification Image Typer_  remoteapp_notification_typez Set the notification image type.zNo notification imagezSmall image (Expandable text)z!Large image (Non-expandable text)r  r  r  rH  r  )rp  r   r   rA  r  r  GIT_USERGIT_REPOrT  r/  r   r   
capitalizer   next)rV  r  rR  rQ  device_selectr_  s   `     r   r  z(TAUTULLIREMOTEAPP._return_config_options  s     " + .5-=-=$*MM$:$:FMM<R<R"T.U	 U XE E %
" 
    [$	"  	b-( .!**+BC.DG(.( +2*:*:6+8.8;=	.= 	>( ""$  ! r %"  73aAjM349ah i\];?1C1WqGW!W i i +D 1  A()*(>uAjMD\D\D^H!(+22!"; !/ 2 Fa6F4    ![1- r '"/"  ffhlmy   #Z0,?& 	#"    2%895A&.6:#" *    /%895I("  { 4 is   8II)rK   rK   rK   Nrc  r   r   r   r{   r{     s1     !D$&#$,-O
IkV	gr   r{   c                   6    e Zd ZdZdZddddddddZd
dZd Zy	)r   z 
    Telegram notifications
    rv   rK   r   r   )	bot_tokenchat_iddisable_web_previewsilent_notificationrm  r  r  c                 B   | j                   d   j                  d      ^}}d|i}|r|d   |d<   | j                   d   r	|dz   |z   }n|}| j                   d   rd|d	<   | j                   d
   r|j                  d      rt        |d         }	|	j	                         }
|
rd|
i}t        |      dkD  rd|d<   n(|j                  d      |d<   | j                   d   rd|d<   | j                  dj                  | j                   d         ||       d|v ry |j                  dd        |d d |dd  xr dz   j                  d      |d<   | j                   d   rd|d<   | j                   d   rd|d<   ddi}| j                  dj                  | j                   d         ||      S )Nr  r  r   message_thread_idr  r   rm  HTML
parse_moder  rU  photoi   Tdisable_notificationrp  r  r  z(https://api.telegram.org/bot{}/sendPhotor  )r  r4  i  r+  r:  r  disable_web_page_previewr<  r  z*https://api.telegram.org/bot{}/sendMessager  )
r   r@  r   rR  r  r/  r  r  r  r   )rV  r   r   r   r%  r  r  r  r:  r;  r*  r4  r  s                r   r  zTELEGRAM.agent_notifyn  s   &*kk)&<&B&B3&G##7#(9!(<D$%;;~&V#d*DD;;~&!'D;;}%&**\*B,VL-ABO#--/E %(t9t#37D/0&*kk'&:DO{{#897;34!!"L"S"STXT_T_`kTl"m'+5 " : $/6UdtDE{'<u=EEgNV;;,-/3D+,;;,-+/D'(!#FG  !M!T!TUYU`U`alUm!n)0t ! = 	=r   c                    d| j                   d   ddt        j                  d      z   dz   ddd	| j                   d
   ddt        j                  d      z   dz   ddd| j                   d   ddddd| j                   d   ddddd| j                   d   ddddd| j                   d   dd ddd!| j                   d"   d#d$ddg}|S )%NzTelegram Bot Tokenr  telegram_bot_tokenz*Your Telegram bot token. Contact <a href="zhttps://telegram.me/BotFatherzI" target="_blank" rel="noreferrer">@BotFather</a> on Telegram to get one.r  r  z2Telegram Chat ID, Group ID, or Channel ID/Usernamer  telegram_chat_idzRYour Telegram Chat ID, Group ID, Channel ID or @channelusername. Contact <a href="zhttps://telegram.me/myidbotz" target="_blank" rel="noreferrer">@myidbot</a> on Telegram to get an ID. For a group topic, append <span class="inline-pre">/topicID</span> to the group ID.r:  rI  r  telegram_incl_subjectrK  rH  r  r  telegram_incl_posterr  r  rm  telegram_html_supportzEnable to style your messages using these HTML tags:<br>b, strong, i, em, u, ins, s, strike, del, span[class], tg-spoiler, a[href], code[class], prezDisable Web Page Previewsr  telegram_disable_web_previewz9Disables automatic link previews for links in the messagezEnable Silent Notificationsr  telegram_silent_notificationz5Send notifications silently without any alert sounds.)r   r   rA  r  s     r   r  zTELEGRAM._return_config_options  s=   #7#';;{#;"6*=?F?O?OPo?p*q*D*D )0 $X#';;y#9"4*=?F?O?OPm?n*o**
 )/	 $:#';;~#>"9)[(2	 $:#';;}#="8)S(2	 $9#';;~#>"9*Q )3 $?#';;/D#E"@)d(2	 $A#';;/D#E"@)`(2	[3j r   Nr  r  r   r   r   r   r   `  s5     D$&"$././'('(&'O0=d6r   r   c                   L    e Zd ZdZdZdZdZdZdZdddddd	d
Z	ddZ
ddZd Zy)r   z
    Twitter notifications
    rw   z+https://api.twitter.com/oauth/request_tokenz*https://api.twitter.com/oauth/access_tokenz'https://api.twitter.com/oauth/authorizez*https://api.twitter.com/oauth/authenticaterK   r   r   )r  access_token_secretconsumer_keyconsumer_secretr  r  Nc                    | j                   d   }| j                   d   }| j                   d   }| j                   d   }t        j                  ||||      }	 |j                  ||       t	        j
                  dj                  | j                               y# t        $ r:}t	        j                  d	j                  | j                  |
             Y d }~yd }~ww xY w)Nr  r  r  r  )rR  r  r  Tr<  r  F)
r   r%   Api
PostUpdater   r"  r  r  r  r  )	rV  r  r<  r  r  r  r  r  r  s	            r   _send_tweetzTWITTER._send_tweet  s    {{>2++&78{{>2"kk*?@ kk,GZ[	NN7*N5KKIPPVZV_V_P`a 	LLPWW]a]f]fjkWlm	s   AB 	C"0CCc                     d}| j                   d   r(|j                  d      r|d   }|j                  dd      }|rt        j                         s|dz  }| j                   d   r| j	                  |dz   |z   |      S | j	                  ||      S )	NrK   r  rU  ro  z.pngr  r   )r<  )r   r   r   get_img_servicer  )rV  r   r   r   r%  ro  rU  s          r   r  zTWITTER.agent_notify  s    
;;}%&**\*B-J#R8J g557& J;;~&##Gf$4t$;
#SS##DZ#@@r   c                     d| j                   d   ddddd| j                   d   d	d
ddd| j                   d   ddddd| j                   d   ddddd| j                   d   ddddd| j                   d   ddddg}|S )NzTwitter Consumer Keyr  twitter_consumer_keyzYour Twitter consumer key.r  r  zTwitter Consumer Secretr  twitter_consumer_secretzYour Twitter consumer secret.zTwitter Access Tokenr  twitter_access_tokenzYour Twitter access token.zTwitter Access Token Secretr  twitter_access_token_secretz!Your Twitter access token secret.rI  r  twitter_incl_subjectrK  rH  r  r  twitter_incl_posterr_  r   r  s     r   r  zTWITTER._return_config_options  s    #9#';;~#>"8)E(/	 $=#';;/@#A";)H(/	 $:#';;~#>"8)E(/	 $A#';;/D#E"?)L(/	 $:#';;~#>"8)[(2	 $:#';;}#="7*b )3='R r   r  r  )r  r  r  r  r  REQUEST_TOKEN_URLACCESS_TOKEN_URLAUTHORIZATION_URL
SIGNIN_URLr  r  r  r  r   r   r   r   r     sN     DECA=J').0')*,'(&'O$A*r   r   c                   ,    e Zd ZdZdZdddZd	dZd Zy)
r   z
    Webhook notifications
    rx   rK   r  )r  r  c                 Z   |j                  d|      }|r	 t        j                  |      }nd }|r	 t        j                  |      }nd }ddi}|r|j                  |       |d   dk(  rd|i}	nd	|i}	 | j                  | j                  d
   f| j                  d   |d|	S # t        $ r:}t	        j
                  dj                  | j                  |             Y d }~yd }~ww xY w# t        $ r:}t	        j
                  dj                  | j                  |             Y d }~yd }~ww xY w)Nr  z:Tautulli Notifiers :: Invalid {name} json header data: {e}r  Fz8Tautulli Notifiers :: Invalid {name} json body data: {e}r  r2  r  r  r  r  )r  r  )r   r  r  r  r   r  r  r  r2  r  r   )
rV  r   r   r   r%  webhook_headersr  webhook_bodyr  r  s
             r   r  zWEBHOOK.agent_notifyA  s.   **Y0"&**W"5
 #O#zz$/
  L!#56NN?+>"&88L)DL)D t  V!4lT[[=R\clgkll1  Y``fjfofost`uv  W^^dhdmdmqr^sts.   B! C' !	C$*0CC$'	D*00D%%D*c                 f    d| j                   d   ddddd| j                   d   d	d
dddddddg}|S )NzWebhook URLr  webhook_hookzYour Webhook URL.r  r  zWebhook Methodr  webhook_methodz The Webhook HTTP request method.r   GETr  r  DELETE)r  r  r  r  r  r   r  s     r   r  zWEBHOOK._return_config_options`  s_    #0#';;v#6"0)<(/	 $4#';;x#8"2)K(0495;497?-A	$ r   Nr  r  r   r   r   r   r   8  s&     D!!'Om>r   r   c                   @    e Zd ZdZdZddddddZd ZddZdd	Zd
 Z	y)r   z
    Kodi notifications
    rh   rK   r  r  c                     t        |      }|dz   |z   }| j                  d   r3t        j                  || j                  d   | j                  d   f      S t        j                  |      S r   r!  r#  s        r   r&  zXBMC._sendhttp  r'  r   Nc           	      P   |xs i }dd||dg}ddi}|dz   }| j                   d   rJt        j                  |dt        j                  |      || j                   d	   | j                   d   f
      }n,t        j                  |dt        j                  |      |      }|r|d   d   S y r)  r+  r-  s           r   r.  zXBMC._sendjson  r/  r   c                    | j                   d   j                  d      D cg c]  }|j                          }}| j                   d   dkD  rd| j                   d   z  }nd}| j                   d   r| j                   d   }nKt        j                  j                  t        j                  t        j                  j                  d            }|D ]  }	t        j                  d	|	z          	 | j                  |	d
ddgi      d   d   }
|
dk  r5|dz   |z   dz   t        |      z   }dd|z   dz   d}| j                  |	|      }n||||d}| j                  |	d|      }|st        t        j                  dj                  | j                                 yc c}w # t        $ r;}t        j"                  dj                  | j                   |             Y d }~ yd }~ww xY w)Nr  r{  r  r   r1  r2  r*  r!  z=Tautulli Notifiers :: Sending notification command to XMBC @ r3  r4  r  r5  r(   r6  r7  r  r8  r9  r;  r  r  r<  r  FT)r   r@  rr  r+  r,  r3   r  r=  r>  r   r"  r.  rU   r&  r  r  r  r  r?  s                   r   r  zXBMC.agent_notify  s   $(KK$8$>$>s$CDqDD;;~&*$++n"==LL;;wKK(EGGLL"''//Br2stE 	DKKWZ^^_../J\\e[fLghirst{|R<#*S=4#7##=L@Q#QL0=O^jLjmpLp$qM"nnT=AG (/4P\glmF"nnT3I6RG#OKK Q X X^b^g^g X hi#	. G E>  T[[aeajajno[pqs   F)B'F	G!0GGc           
          d| j                   d   ddddd| j                   d   d	d
ddd| j                   d   ddddd| j                   d   ddddd| j                   d   ddddg}|S )NzKodi Host Addressr  
xbmc_hostszXHost running Kodi (e.g. http://localhost:8080). Separate multiple hosts with commas (,).r:  r  zKodi Usernamer  xbmc_usernamez2Username of your Kodi client API (blank for none).zKodi Passwordr+  xbmc_passwordz2Password of your Kodi client API (blank for none).rF  r  xbmc_display_timerH  r  rI  r*  
xbmc_imagerK  r   r  s     r   r  zXBMC._return_config_options  s    #6#';;w#7". *D(.	 $3#';;z#:"1)](.	 $3#';;z#:"1)](2	 $;#';;~#>"5)l(0	 $7#';;w#7". *G(.	1@ r   r  r  rL  r   r   r   r   r   v  s9     D "#%#%'( "	O0)$L!r   r   c                   6    e Zd ZdZdZdddddZd Zd	dZd Zy)
r   z
    Zapier notifications
    ry   rK   )r  r  r  r  c                 :    dddddddd}| j                  |	      S )
Nry  BodyActionzhttps://i.imgur.comzProvider Namezhttp://www.imdb.comzhttps://app.plex.tv/desktop)r   r   r   ro  rx  r}  r  )
_test_data)r  )rV  r  s     r   
_test_hookzZAPIER._test_hook  s5    !*$ ($9'6'<"?A
   J 77r   c                 f   |||d}|j                  di       j                  d      rt        |d         }|j                  dk(  r| j                  d   }n>|j                  dv r| j                  d   }n |j                  dv r| j                  d	   }nd }|j	                         }|j                  |      }	|j                  |      }
|j                         }||d
<   |	|d<   |
|d<   ||d<   |j                  d      r|j                  |d          ddi}| j                  | j                  d   ||      S )Nr  rU  rT  r   r  r"  r  rp  r  ro  rx  r}  r  r  r<  r2  r  r  )
r   rR  rT  r   rs  ry  r~  r|  r2  r  )rV  r   r   r   r%  r  r;  rw  ro  rx  r}  r  r  s                r   r  zZAPIER.agent_notify  sF   " " ::lB'++L9,VL-ABO))W4;;'78 ++/LL;;}5 ++/KK;;'78(779J+==hGM+==hGM&335H!+D$1D!$1D!'D::l#KK|,-!#56  V!4gD QQr   c                 B   d| j                   d   ddddddd	d
ddd| j                   d   dddt               j                         dd| j                   d   dddt               j                         dd| j                   d   dddt               j	                         dg}|S )NzZapier Webhook URLr  zapier_hookzYour Zapier webhook URL.r  r  zTest Zapier WebhookzSend Test Datazapier_test_hookzGClick this button when prompted on then "Test Webhooks by Zapier" step.r  rW  r  zapier_movie_providerr  r   r  rZ  r  zapier_tv_providerr   r]  r  zapier_music_providerr  r`  r  s     r   r  zZAPIER._return_config_options  s    #7#';;v#6"/)C(/	 $9#3"4)r(0	 $7#';;/?#@"9*i )1,:,<,P,P,R $9#';;}#="6*i )1,:,<,M,M,O $7#';;/?#@"9*i )1,:,<,P,P,R='R r   Nr  )	r  r  r  r  r  r  r  r  r  r   r   r   r   r     s2     D!)+&()+O	8!RF*r   r   c                      i a t               D ]1  } | d   dk(  s| d   st        | d         }|d   d   t         | d   <   3 y )Nr   r2   r   r[   r   r  )BROWSER_NOTIFIERSr   r  )rP  r   s     r   r3  r3  J  sU    _ VZ=B1X;1!D':O)8)BCT)Uag&Vr   c                      t        j                         } | j                  dt        j                         dz
  g      }g }|D ]6  }|d   |d   t        j                  |d   d      d}|j                  |       8 d|iS )	NzcSELECT notifier_id, subject_text, body_text FROM notify_log WHERE agent_id = 17 AND timestamp >= ? r  r   r5  r6  r   )r5  r6  delayr  )r   r   r   timer  r   r   )r   r   r  r   r  s        r   get_browser_notificationsr  S  s    		!	!	#BYY A!YY[1_-  /F M +(,^(<%)+%6!2!6!6tM7JA!NP 	\*	+ ]++r   r  r  r  )NF)NrK   rK   rK   N)brv  collectionsr   email.mime.multipartr   email.mime.textr   email.utilsr#   r  r+  r5  r  r  r  r  r  urllib.parser   r   r  paho.mqtt.clientr  paho.mqtt.publishr  requests.authr   cryptography.hazmat.primitivesr	   +cryptography.hazmat.primitives.ciphers.aeadr
   )cryptography.hazmat.primitives.kdf.pbkdf2r   rp  ImportErrorgntp.notifierr$  r/   r%   r  r   r   r   r   r   r   r   r   r  rz   r  rH  r   r   r   r   r   r   r   r  r(  r:  rA  r1  r#  objectrR  r   r|   r}   r~   r   r   r   r   r   rf   r   r   r   rk   r   r   r   r   r   r   r   r   r   r{   r   r   r   r   r   r3  r  r   r   r   <module>r     s  $  # . $   	 	   
   " !     '5BDM              Wa aQ Q 1	
  A q b  b  b     R!"  !7	< ,.2TXYZ @> D# nbpfgFD	7t.bCLb9 x(HYV HYVPv PfDX DN!h !HAh AHwH wtzx zzzX zzDh DNOH Od6H 6rZ8 Zz@h @FSX SlE8 EPr8 rjc( cLk8 k\tH tn$H $Nt tnYx YxSh SlaH aHG GTvx vr\h \~;h ;|k8 k\cX cLV,MQ  Ms   J JJ