
    g6                        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m	Z	m
Z
 d dlmZmZ dZdZdZdZd	Z e       Zg a e j,                  d
      Z e j,                  d      Z e j,                  d      ZdZd Zd$dZ G d de j:                        Z G d de j:                        Z G d de j:                        Z  G d de j:                        Z! G d de j:                        Z" G d de"      Z# G d de"      Z$ G d de"      Z% G d d e"      Z&d%d!Z'd&d"Z(d# Z)ejT                  Z*ejV                  Z,ejZ                  Z-ej\                  Z.ejV                  Z+ej^                  Z/ejT                  Z0ejV                  Z1ejZ                  Z2ej\                  Z3ejV                  Z4ej^                  Z5ejT                  Z6ejV                  Z7ejZ                  Z8ej\                  Z9ejV                  Z:ej^                  Z;y)'    )handlersN)helpersusers)_BLACKLIST_KEYS_WHITELIST_KEYSztautulli.logztautulli_api.logzplex_websocket.logi@KL    tautullitautulli_apiplex_websocketc                    t               }g d}| j                         D ]  \  }t        |t              st	        |j                               dkD  s4j                         t        vsKj                         |v st        fdt        D              sv|j                  |j                                 t        j                  |       y )N)HOOKAPIKEYKEYPASSWORDTOKENr   c              3   B   K   | ]  }|j                         v   y wN)upper).0bkkeys     /opt/Tautulli/plexpy/logger.py	<genexpr>z#blacklist_config.<locals>.<genexpr>=   s     7dbciik8I7ds   )setitems
isinstancestrlenstripr   r   anyr   add_BLACKLIST_WORDSupdate)config	blacklistblacklist_keysvaluer   s       @r   blacklist_configr(   6   s    ICNlln )
UeS!c%++-&81&<IIK.CIIK>4Q477dTc7d4dMM%++-(	) I&    c                 4   | 4t        j                         j                  d      D cg c]  }|d   	 } }| D ]B  }|j                         dvst	        |      dkD  s%|t
        vs.t
        j                  |       D t        t
        t        d      ay c c}w )NT)include_deletedusername)localguest   )r   reverse)r   Users	get_userslowerr   _FILTER_USERNAMESappendsorted)	new_usersuserr,   s      r   filter_usernamesr9   C   s     27++-2I2IZ^2I2_`$T*%`	` />>#55#h-!:KPX`qPq$$X./ 0c4H as   Bc                   $     e Zd Z fdZd Z xZS )LogLevelFilterc                 8    t         t        |           || _        y r   )superr;   __init__	max_level)selfr?   	__class__s     r   r>   zLogLevelFilter.__init__Q   s    nd,."r)   c                 4    |j                   | j                  k  S r   )levelnor?   r@   records     r   filterzLogLevelFilter.filterV   s    ~~//r)   )__name__
__module____qualname__r>   rF   __classcell__rA   s   @r   r;   r;   P   s    #
0r)   r;   c                   (     e Zd ZdZ fdZd Z xZS )NoThreadFilterz+
    Log filter for the current thread
    c                 8    t         t        |           || _        y r   )r=   rM   r>   
threadName)r@   rO   rA   s     r   r>   zNoThreadFilter.__init__^   s    nd,.$r)   c                 6    |j                   | j                   k(   S r   )rO   rD   s     r   rF   zNoThreadFilter.filterc   s    $$777r)   )rG   rH   rI   __doc__r>   rF   rJ   rK   s   @r   rM   rM   Z   s    %
8r)   rM   c                       e Zd ZdZd Zy)BlacklistFilterz9
    Log filter for blacklisted tokens and passwords
    c                 |   t         j                  j                  syt        D ]  }	 ||j                  v r!|j                  j                  |d      |_        g }|j                  D ]7  }	 t        |      }||v r|j                  |d      }|}|j                  |       9 t        |      |_         y#  Y *xY w#  Y xY w)NT****************)
plexpyCONFIGLOG_BLACKLISTr"   msgreplaceargsr   r5   tuple)r@   rE   itemr[   argarg_strs         r   rF   zBlacklistFilter.filterl   s    }}**$ 	D6::%!'!3!3D(!CFJ!;; %C"%c(7?&-oodH&EG")C KK$% $Dk	& s$   A B7'#B0
#B70B42B77B;N)rG   rH   rI   rQ   rF    r)   r   rS   rS   h   s    r)   rS   c                   &    e Zd ZdZd Zed        Zy)UsernameFilterz"
    Log filter for usernames
    c                 p   t         j                  j                  syt         j                  syt        D ]z  }	 | j                  |j                  |      |_        g }|j                  D ]5  }t        |t              r| j                  ||      }|j                  |       7 t        |      |_        | y#  Y xY wNT)rV   rW   LOG_BLACKLIST_USERNAMES_INITIALIZEDr4   rZ   rY   r[   r   r   r5   r\   )r@   rE   r,   r[   r^   s        r   rF   zUsernameFilter.filter   s    }}44"") 	H
!\\&**h?
!;; %C!#s+"ll39KK$% $Dk	 s   A7B11B5c                     |d d dz   |d   z   }t        j                  t        j                  |      || t         j                        S )N   ********)flags)resubescape
IGNORECASE)textmatchmasks      r   rZ   zUsernameFilter.replace   s=    Ray7"U2Y.vvbii&d"--HHr)   N)rG   rH   rI   rQ   rF   staticmethodrZ   r`   r)   r   rb   rb      s"    , I Ir)   rb   c                   @    e Zd ZdZ ej
                  d      Zd Zd Zy)RegexFilterz)
    Base class for regex log filter
     c                    t         j                  j                  sy	 | j                  j	                  |j
                        }|D ]#  }| j                  |j
                  |      |_        % g }|j                  D ]W  }	 t        |      }| j                  j	                  |      }|r|D ]  }| j                  ||      } |}|j                  |       Y t        |      |_        y#  Y (xY w#  Y yxY wrd   )rV   rW   rX   REGEXfindallrY   rZ   r[   r   r5   r\   )r@   rE   matchesrq   r[   r^   r_   s          r   rF   zRegexFilter.filter   s    }}**	jj((4G  =!\\&**e<
= D{{ 
!!#hG"jj009G%, CE&*ll7E&BGC% C 
!  +FK 	s%   AC* <AC#?#C* #C'%C* *C.c                     |S r   r`   )r@   rp   rq   s      r   rZ   zRegexFilter.replace   s    r)   N)	rG   rH   rI   rQ   rl   compilerx   rF   rZ   r`   r)   r   ru   ru      s"     BJJsOE6r)   ru   c                   :    e Zd ZdZ ej
                  d      Zd Zy)PublicIPFilterz,
    Log filter for public IP addresses
    zm(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)[.]){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?!\d*-[a-z0-9]{6})c                 z    t        j                  |      r%|j                  |dj                  dgdz              S |S )N.***   r   is_public_iprZ   joinr@   rp   ips      r   rZ   zPublicIPFilter.replace   s5    #<<CHHeWq[$9::r)   NrG   rH   rI   rQ   rl   r|   rx   rZ   r`   r)   r   r~   r~      s#     BJJ	Er)   r~   c                   :    e Zd ZdZ ej
                  d      Zd Zy)PlexDirectIPFilterz8
    Log filter for IP addresses in plex.direct URL
    z(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)[-]){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?!\d*-[a-z0-9]{6})(?=\.[a-z0-9]+\.plex\.direct)c                     t        j                  |j                  dd            r%|j                  |dj                  dgdz              S |S )N-r   r   r   r   r   s      r   rZ   zPlexDirectIPFilter.replace   s@    

3 45<<CHHeWq[$9::r)   Nr   r`   r)   r   r   r      s#     BJJ	)Er)   r   c                   P    e Zd ZdZ ej
                  dej                        Zd Zy)EmailFilterz(
    Log filter for email addresses
    z0([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)c                     |j                  d      }|d   d d dz   |d   d   z   |d   z   dz   }|j                  ||      S )N@r   rh   ri   rj      )	partitionrZ   )r@   rp   emailemail_partsrr   s        r   rZ   zEmailFilter.replace   sS    ooc*1~bq!G+k!nR.@@;q>QT[[||E4((r)   N)	rG   rH   rI   rQ   rl   r|   ro   rx   rZ   r`   r)   r   r   r      s(     BJJ;
E
)r)   r   c                   :    e Zd ZdZ ej
                  d      Zd Zy)PlexTokenFilterz%
    Log filter for X-Plex-Token
    z&X-Plex-Token(?:=|%3D)([a-zA-Z0-9\-_]+)c                 &    |j                  |d      S )NrU   )rZ   )r@   rp   tokens      r   rZ   zPlexTokenFilter.replace  s    ||E8,,r)   Nr   r`   r)   r   r   r      s!     BJJ1E-r)   r   c                    t         j                  dd t        j                  dd z   t        j                  dd z   t        j
                  j                  j                  dd z   }|D ]  }t        |t        j                        r|j                          n*t        |t        j                        r|j                          t         j                  |       t        j                  |       t        j                  |       t        j
                  j                  j                  |        dt         _        t         j                  |rt        j                   nt        j"                         dt        _        t        j                  |rt        j                   nt        j"                         dt        _        t        j                  |rt        j                   nt        j"                         dt        j
                  j                  _        |rt        j$                  dd      }t&        j(                  j+                  |t,              }t        j                  |t.        t0        d      }|j                  t        j                          |j3                  |       t         j5                  |       t        j
                  j                  j5                  |       t&        j(                  j+                  |t6              }t        j                  |t.        t0        d      }|j                  t        j                          |j3                  |       t        j5                  |       t&        j(                  j+                  |t8              }t        j                  |t.        t0        d      }|j                  t        j                          |j3                  |       t        j5                  |       | r`t        j$                  dd      }t        j                  t:        j<                        }	|	j3                  |       |	j                  t        j                          |	j?                  tA        t        j"                               t        j                  t:        jB                        }
|
j3                  |       |
j                  t        jD                         t         j5                  |	       t         j5                  |
       t        j
                  j                  j5                  |	       t        j
                  j                  j5                  |
       tF        jH                  stF        jJ                  rt         j                  t        j                  z   t        j                  z   t        j
                  j                  j                  z   }|D ]  }|j?                  tM                      |j?                  tO                      |j?                  tQ                      |j?                  tS                      |j?                  tU                      |j?                  tW                       tY                y)a  
    Setup logging for Tautulli. It uses the logger instance with the name
    'tautulli'. Three log handlers are added:

    * RotatingFileHandler: for the file tautulli.log
    * LogListHandler: for Web UI
    * StreamHandler: for console (if console)

    Console logging is only enabled if console is set to True. This method can
    be invoked multiple times, during different stages of Tautulli.
    NFz=%(asctime)s - %(levelname)-7s :: %(threadName)s : %(message)sz%Y-%m-%d %H:%M:%Szutf-8)maxBytesbackupCountencodingz;%(asctime)s - %(levelname)s :: %(threadName)s : %(message)s)-loggerr   
logger_apilogger_plex_websocketcherrypylog	error_logr   RotatingFileHandlercloseloggingStreamHandlerflushremoveHandler	propagatesetLevelDEBUGINFO	Formatterospathr   FILENAMEMAX_SIZE	MAX_FILESsetFormatter
addHandlerFILENAME_APIFILENAME_PLEX_WEBSOCKETsysstdout	addFilterr;   stderrWARNINGrV   DEVrW   rS   r~   r   r   rb   r   	initHooks)consolelog_dirverboselog_handlershandlerfile_formatterfilenamefile_handlerconsole_formatterstdout_handlerstderr_handlers              r   
initLoggerr     sX    ??1%&&q)*(11!45 <<))22156L   
6gx;;<MMO!6!67MMOW%  )++G4,,W5
6 F
OOWGMM',,? JgllC&+#""G7==N',HLL$  **+jl  A 77<<233Hx]fqxygmm,!!.1,')),7 77<<633Hx]fqxygmm,!!.1l+ 77<<)@A33Hx]fqxygmm,!!.1((6 #--.k  nA  B ..szz:##$56.  !=> ..szz:##$560.).))).9)).9
 ::&--!**+,556  ||--667 $ 	1Go/0n./023km,n./o/0	1 Kr)   c                     fd| rt         _        |r6t        j                  j                  fd}|t        j                  _        yy)a  
    This method installs exception catching mechanisms. Any exception caught
    will pass through the exception hook, and will be logged to the logger as
    an error. Additionally, a traceback is provided.

    This is very useful for crashing threads and any other bugs, that may not
    be exposed when running as daemon.

    The default exception hook is still considered, if pass_original is True.
    c                      	 dj                  t        j                  |        }t        j	                  d|       rt        j                  |   y y #  Y xY w)Nrv   zUncaught exception: %s)r   	tracebackformat_exceptionr   errorr   __excepthook__)exception_infomessagepass_originals     r   
excepthookzinitHooks.<locals>.excepthook~  sR    	ggi88.IJGLL17;
 / 		s   7A Ac                 R     | g|i | | j                   fd}|| _         y )Nc                  r    	  | i | y # t         t        f$ r    t        j                           Y y xY wr   )KeyboardInterrupt
SystemExitr   exc_info)r[   kwargsr   old_runs     r   new_runz,initHooks.<locals>.new_init.<locals>.new_run  s:    0T,V,):6 0/s    (6)run)r@   r[   r   r   r   r   old_inits       @r   new_initzinitHooks.<locals>.new_init  s,    T+D+F+hhG0 DHr)   N)r   r   	threadingThreadr>   )global_exceptionsthread_exceptionsr   r   r   r   s     ` @@r   r   r   r  sD    
0 # ##,,	 %-	!# r)   c                  ,    t        j                          y r   )r   shutdownr`   r)   r   r   r     s    r)   r   )FFF)TTT)<r   r   r   r   rl   r   r   r   rV   r   r   plexpy.configr   r   r   r   r   r   r   r   r"   r4   	getLoggerr   r   r   queuer(   r9   Filterr;   rM   rS   rb   ru   r~   r   r   r   r   r   r   infowarningwarnr   debug	exceptionapi_infoapi_warn	api_error	api_debugapi_warningapi_exceptionwebsocket_infowebsocket_warnwebsocket_errorwebsocket_debugwebsocket_warningwebsocket_exceptionr`   r)   r   <module>r      s  $    	 	 
    ! : !. 	5   
		:	&W~.
)))*:;  	
'
I0W^^ 0
8W^^ 
8gnn <IW^^ I@"'.. "J[   ")+ )	-k 	-hV.-b {{~~
..	 ??		  $$ '++&..'--'--)11 +55 r)   