
    DziH                        d dl Z d dlZd dlmZ d dlZd dlZd dlZd dlZd dlmZ d dl	m
Z
mZ dZdZdZdZ ed	      Zd
Z ed      Zej'                  dd        ed      Zej'                  dd       edz  Zedz  Zedz  Zedz  Zedz  ZdZd ZdedefdZd_dede
e   fdZd_dede
e   fdZ d_dede
e   fdZ!d`ded e
e"   de
e   fd!Z#d`d"ed#ed$e
e   d%e
e   fd&Z$d'efd(Z%d)efd*Z&d+ed'e
e   fd,Z'd-ed'e
e   fd.Z(d'e
e   fd/Z)d'efd0Z*d1ed2ed'e jV                  fd3Z,d4ed'e
e   fd5Z-d6ed7ed'e.fd8Z/d9ed6ed7ed:ed'e
e   f
d;Z0d<ed'e
e   fd=Z1efd>ed$ed?ed'e2fd@Z3d_d4ede
e   d'e2fdAZ4dBed'ee   fdCZ5e6dDk(  rId dl7Z7 e7jp                  dEF      Z9e9ju                  dGdHdIJ       e9ju                  dKdLM       e9jw                         Z<g Z=e<j|                  r.e=j                  e<j|                          e@dN eAe=       dO       ne<j                  rL	  eCe<j                  dPdQR      5 ZD ej                  eD      ZFddd        e5eF      Z= e@dN eAe=       dS       n: e@dW        e@dX        e@dY        e@dZ        e@d[        ej                  d        d ZIe=D ]  ZJ e4eJ      seIdVz  ZI  e@d\eI d] eAe=       d^       yy# 1 sw Y   xY w# e"$ r&ZG e#dTeGU        ej                  dV       Y dZG[G`dZG[Gww xY w)a    N)Path)datetime)OptionalListz#1000.ZNQ17ZU1F48Z6DTTBKPRS8HYYGPU2C*31128c41fe165770eabec0110a9f121b8a9e0846d9 zhttps://www.zoho.comz/var/www/zoho/tokens.jsonz#https://recruit.zoho.com/recruit/v2z/var/www/zoho/attacheTparentsexist_okz/var/www/zoho/Logzreceived.logzsuccess.logz
failed.logz	error.logz	files.logResumec                  L    t        j                         j                         dz   S )NZ)r   utcnow	isoformat     !/var/www/zoho/copytocandidates.py_nowr   '   s    ??&&(3..r   pathobjc                    	 | j                   j                  dd       t        | dd      5 }|j                  t	        j
                  |d      dz          d d d        y # 1 sw Y   y xY w# t        $ r}t        d	| |       Y d }~y d }~ww xY w)
NTr	   autf-8encodingF)ensure_ascii
z [LOG_ERROR] Failed to write log:)parentmkdiropenwritejsondumps	Exceptionprint)r   r   fes       r   _append_json_logr(   *   s    ;$6$g. 	@!GGDJJs7$>?	@ 	@ 	@ ;0$::;s4   +A, *A A,  A)%A, )A, ,	B5BBatsidrawc                 h    t               | d}|||d<   t        t        |       t        d|         y )N)	timestampr)   r*   z[LOG RECEIVED] )r   r(   LOG_RECEIVEDr%   )r)   r*   entrys      r   log_receivedr/   2   s5    &51E
e\5)	OE7
#$r   messagemetac                 h    t               | d}|r||d<   t        t        |       t        d|         y )Nr,   r0   r1   z[LOG SUCCESS] )r   r(   LOG_SUCCESSr%   r0   r1   r.   s      r   log_successr6   9   s3    &W5Ef[%(	N7)
$%r   c                 h    t               | d}|r||d<   t        t        |       t        d|         y )Nr3   r1   z[LOG FAILED] )r   r(   
LOG_FAILEDr%   r5   s      r   
log_failedr9   @   s3    &W5EfZ'	M'
#$r   excc                     t               | d}|r%t        |      |d<   t        j                         |d<   |r||d<   t	        t
        |       t        d|         |rt        t        j                                y y )Nr3   	exception	tracebackr1   z[LOG ERROR] )r   reprr=   
format_excr(   	LOG_ERRORr%   )r0   r:   r1   r.   s       r   	log_errorrA   G   sp    &W5E
!#Yk&113kfY&	L	
"#
i""$% r   	file_namestatuscandidate_idreasonc                 ~    t               | |d}|r||d<   |r||d<   t        t        |       t        d|  d|        y )N)r,   rB   rC   rD   rE   z[LOG FILE] z -> )r   r(   	LOG_FILESr%   )rB   rC   rD   rE   r.   s        r   log_file_statusrH   S   sH    &yFKE ,n hY&	K	{$vh
/0r   returnc            	         	 t         j                         r1t        t         dd      5 } t        j                  |       cd d d        S 	 i S # 1 sw Y   i S xY w# t
        $ r(}t        d|dt        t               i       Y d }~i S d }~ww xY w)Nrr   r   zFailed to load tokens.jsonr   r:   r1   )TOKENS_FILEexistsr    r"   loadr$   rA   str)r&   r'   s     r   load_tokensrQ   _   s    Xk39 $Qyy|$ $  
 I	$ I  X.AVSEU<VWWIXs3   &A A
	A 
AA A 	B BBtokensc           	      ,   	 t         j                  j                  dd       t        t         dd      5 }t	        j
                  | |d       d d d        y # 1 sw Y   y xY w# t        $ r'}t        d|d	t        t               i
       Y d }~y d }~ww xY w)NTr	   wr   r      )indentzFailed to save tokens.jsonr   rL   )	rM   r   r   r    r"   dumpr$   rA   rP   )rR   r&   r'   s      r   save_tokensrX   h   s    X   =+sW5 	+IIfa*	+ 	+ 	+ X.AVSEU<VWWXs4   3A# AA# A A#  A# #	B,BBrefresh_tokenc                    d}| t         t        dd}	 t        j                  ||d      }|j                  d	k(  rd|j                         }t               }|j                  d
      |d
<   d|v r|d   |d<   t        |       t        dddi       |j                  d
      S t        d|j                  |j                  d       y # t        $ r}t        d|d|i       Y d }~y d }~ww xY w)N(https://accounts.zoho.com/oauth/v2/tokenrY   )rY   	client_idclient_secret
grant_type   paramstimeoutz HTTP error when refreshing tokenurlrL      access_tokenzAccess token refreshedtokenTzFailed to refresh tokenstatus_codetext)	CLIENT_IDCLIENT_SECRETrequestspostr$   rA   rh   r"   rQ   getrX   r6   r9   ri   )rY   rc   ra   respr'   newrR   s          r   refresh_access_tokenrq   p   s    
4C&&%	F}}S<
 3iik!$!8~c!&)/&:F?#F,wo>zz.)),d>N>NX\XaXa.bc  4!5#,Os   C 	C%C  C%	auth_codec                 b   d}| t         t        t        dd}	 t        j                  ||d      }|j                  d	k(  r(|j                         }t        |       t        d
       |S t        d|j                  |j                  d       y # t
        $ r}t        d|d|i       Y d }~y d }~ww xY w)Nr[   authorization_code)coder\   r]   redirect_urir^   r_   r`   z$HTTP error when exchanging AUTH_CODErc   rL   rd   zObtained tokens via AUTH_CODEzFailed to exchange AUTH_CODErg   )rj   rk   REDIRECT_URIrl   rm   r$   rA   rh   r"   rX   r6   r9   ri   )rr   rc   ra   ro   r'   rR   s         r   get_tokens_with_auth_coderx      s    
4C&$*F}}S<
 3F3414CSCS]a]f]f3gh  8auclSs   B 	B.B))B.c                      t               } d| v r| d   S d| v rt        | d         S t        r"t        t              } | r| j	                  d      S t        d       y )Nre   rY   z;No valid token available (access/refresh/AUTH_CODE missing))rQ   rq   	AUTH_CODErx   rn   rA   )rR   s    r   get_valid_access_tokenr{      s_    ]Fn%%& #F?$;<<*95::n--KLr   c                  >    t               } | st        d      dd|  iS )Nz$No valid Zoho access token availableAuthorizationZoho-oauthtoken )r{   RuntimeError)rf   s    r   auth_headersr      s,    "$EABB/w788r   methodrc   c                    |j                  di       }|j                  t                      	 t        j                  | |fd|i|}|j                  dk(  r\t        dd|i       t               }d	|v r?t        |d	         }|r/|j                  d
d| i       t        j                  | |fd|i|}|S # t
        $ r}t        d|| |d        d }~ww xY w)NheaderszHTTP request failed)r   rc   rL   i  z1Access token expired/unauthorized; trying refreshrc   )r1   rY   r}   r~   )
popupdater   rl   requestr$   rA   rh   rQ   rq   )r   rc   kwargsr   responser'   rR   	new_tokens           r   api_requestr      s    jjB'GNN<>"##FCKKFK s"EUTWLYf$,VO-DEI3CI;1OPQ#++FCSSFSO  'Qs5STs   B3 3	C<CCats_idc                 >   t          d|  }	 t        d|d      }|j                  dk(  r4|j                         j                  d	      }|rt        d
d| i       |d   S t        d| |j                  d       y # t        $ r}t        d|| |d       Y d }~y d }~ww xY w)Nz/ATS/GETr_   rb   zFailed to call get_ats_record)r)   rc   rL   rd   datazFetched ATS recordr)   r   zFailed to get ATS record)r)   status_text)
RECRUIT_API_BASEr   r$   rA   rh   r"   rn   r6   r9   ri   )r   rc   ro   r'   r   s        r   get_ats_recordr      s    eF8
,C5#r2
 3yy{v&,w.?@7N)VDII+VW  1qX[?\]s   A8 8	BBBmodule	record_idc           	      ^   t          d|  d| d}	 t        d|d      }|j                  d	k(  r;|j                         j                  d
g       }t        d| |t        |      d       |S t        d| ||j                  d       g S # t        $ r}t        d|| ||d       g cY d }~S d }~ww xY w)N//Attachmentsr   r_   r   zFailed to call get_attachments)r   r   rc   rL   rd   r   zFetched attachments list)r   r   countzFailed to fetch attachments)r   r   r   )r   r   r$   rA   rh   r"   rn   r6   lenr9   ri   )r   r   rc   ro   r'   arrs         r   get_attachmentsr      s    axq<
@C5#r2
 3iikoofb).6PYdghkdl0mn
,ihlhqhq.rsI  26`iru@vw	s   B 	B,B'!B,'B,file_objfolder_pathc           	      ~   | j                  d      xs | j                  d      }| j                  d      }|r|st        d| ||d       y t         d| d| d| }	 t        d|d	d
      }|j                  dk(  rw|j                  d	d	       ||z  }		 t        |	d      5 }
|j                  d      D ]  }|s|
j                  |        	 d d d        t        d||d       t        |d       |	S t        d||j                  |j                  d       t        |d|j                         y # t        $ r2}t        d|||d       t        |dt        |             Y d }~y d }~ww xY w# 1 sw Y   xY w# t        $ r:}t        d|dt        |	      i       t        |dt        |             Y d }~y d }~ww xY w)N	File_NamerB   idz"Attachment missing file_name or id)r   r   r   r   z/Attachments/r   T<   )streamrb   z-Failed to download attachment (request error))rB   r   rL   download_failed)rE   rd   r	   wbi    )
chunk_sizezDownloaded attachment)filer   
downloadedz'Failed to write downloaded file to diskr   z$Attachment download failed (non-200))r   rC   ri   )rn   r9   r   r   r$   rA   rH   rP   rh   r   r    iter_contentr!   r6   ri   )r   r   r   r   rB   file_idrc   ro   r'   	file_pathfhchunks               r   download_attachmentr      s   [)FX\\+-FIll4 GG7hZ`ox9yzaxq=	
JC5#dB? 3$6)+		i& ("!..$.? (E(( /)R[1\]I|4 	9IY]YiYisws|s|;}~	#4TYYG/  Aq]fu~O  	A	#4SVD( (  	?QfVYZcVdMefI'8QH	sN   D/ E9  E-9E-$E9 /	E*8(E%%E*-E62E9 9	F<0F77F<
ats_recordc           
      r   t          d}| j                  d      xs( | j                  d      xs | j                  d      xs d}| j                  d      xs | j                  d      xs d }d||| j                  d      xs | j                  d	      xs d
| j                  d      xs | j                  d      xs d
| j                  d      xs | j                  d      xs d
| j                  d      xs d
| j                  d      xs d
dgi}	 t        d||d      }|j
                  dv r	 |j                         j                  dg       }|rlt        |t              r\|d   j                  d      xs i }|j                  d      xs |j                  d      xs d }	|	rt        d|	|d       t        |	      S t        d!|j
                  |j                  d"       y # t        $ r}t	        d|d|i       Y d }~y d }~ww xY w# t        $ r$}t	        d|d |j                  i       Y d }~y d }~ww xY w)#Nz/Candidates	Last_Name	Last_nameCustomModule4_NameUnknown
First_Namer   EmailProfile_urlsr   	Mobile_NoMobilePhone_NoPhoneCityCountry)r   r   r   r   r   r   r   POSTr_   )r"   rb   z*Failed to create candidate (request error)payloadrL   rd      r   detailsr   namezCandidate created)rD   	last_namez)Failed to parse create candidate responseri   zFailed to create candidaterg   )r   rn   r   r$   rA   rh   r"   
isinstancelistr6   rP   ri   r9   )
r   rc   r   
first_namecandidate_payloadro   r'   r   r   rD   s
             r   create_candidate_from_atsr     s   k
*C{+z~~k/Jjnn]qNrvI-]@T1U]Y]J 	(&#0XJNN>4RXVX$..5W9QWUW#
3Tz~~g7NTRT"v.4"%>>)4:

63->K
 :%
	99;??62.D
4.q'++i06B&{{40OGKK4GO4 3laj5kl|,,
 +T=M=MW[W`W`-ab%  >AYXiLjk  	AqPVX\XaXaObc	s1   G# 1BH	 #	H,HH		H6H11H6r   categoryc           	         t          d| d}	 t        | d      5 }|j                         }d d d        | j                  t        j                        f}d|i}d
|i}		 t        d|||	d      }
|
j                  dv r3t        d| j                  ||d       t        | j                  d|       y	 |
j                  }|
j                         }t        d| j                  ||
j                  |xs |d       t        | j                  d||       y	# 1 sw Y   xY w# t        $ rE}t	        d|dt        |       i       t        | j                  d|t        |             Y d }~y	d }~ww xY w# t        $ rG}t	        d|| j                  |d       t        | j                  d|t        |             Y d }~y	d }~ww xY w# t        $ r |
j                  }d }Y w xY w)Nz/Candidates/r   rbzFailed to open file for uploadr   rL   upload_failed)rD   rE   Fattachments_categoryr   Z   )filesr   rb   zUpload request failedr   rD   r   zUploaded file to candidate)r   rD   r   uploaded)rD   Tz"Failed to upload file to candidate)r   rD   rC   r   )r   r    readr$   rA   rP   rH   r   ioBytesIOr   rh   r6   ri   r"   r9   )r   rD   r   rc   r   contentr'   
file_tupler   r   ro   txtjs                r   upload_attachment_to_candidater   <  s   l<.
EC)T" 	 bggiG	  .."**W"56JZ E"H-D63e$K :%09>>[gu}2~	
N	))C		A 	7)..bnz~  {K  {K  YZ  Ya  ^a  :b  	c	l[^_?	  	  2Y@XY	l[^_`[ab  )q	`l7mn	l[^_`[ab  	))CA	sW   D DD E+ /F> DD 	E(#;E##E(+	F;4=F66F;>GGc                 z   t        j                         }t        | |       	 t        |       }|st	        dd| i       yt
        | z  }|j                  dd       ||  dz  }t        |dd	
      5 }t        j                  ||dd       d d d        t        d| t        |      d       t        d|       }g }|r*|D ]$  }	t        |	d| |      }
|
s|j                  |
       & nt        dd| i       t        |      }|r{t!        |      D ]7  \  }}|dk(  rdnd}t#        |||      }|r t	        dt        |      |d       9 t        j                         |z
  j%                         }t        d| ||d       yt	        dd| i       y# 1 sw Y   xY w# t&        $ r}t)        d|d| i       Y d }~yd }~ww xY w)N)r*   zNo ATS record returnedr)   FTr	   z.jsonrT   r   r   rU   )rV   r   zSaved ATS JSON)r)   r   ATSzNo attachments for ATSr   r   Others)r   zOne file failed to uploadr   zProcess completed)r)   rD   duration_secondsz'Candidate not created; skipping uploadsz'Unexpected exception in process_one_atsrL   )r   r   r/   r   r9   OUTPUT_FOLDERr   r    r"   rW   r6   rP   r   r   appendr   	enumerater   total_secondsr$   rA   )r   r*   startrecordrecord_folder	json_filejfattachmentsdownloaded_filesattr   rD   idxr   r   okdurationr'   s                     r   process_one_atsr   d  s   OOES!''/'61BC%.D48!vhe$44	)S73 	@rIIfb?	@$I&OP%eV4" 80eV]S
$++J78
 07F2CD08"+,<"= tY'*ax8X3I|V^_:S^eq<rs	t
 !)E1@@BH+v|qy-z{<w>OP5	@ 	@8  ;'SYIZ[sI   F 2F 1F
AF AF +AF ;F 
FF 	F: F55F:webhook_datac                 j    g }d| v r,| d   D ]$  }d|v s|j                  t        |d                & |S )zk
    Process webhook data and extract ATS IDs
    Modify this function based on your webhook structure
    r   r   )r   rP   )r   processed_idsitems      r   process_webhook_datar     sL    
 M  ( 	6Dt|$$Sd_5	6 r   __main__z%Process ATS records from Zoho Recruit)descriptionz--ids+zList of ATS IDs to process)nargshelpz--webhook-filezPath to webhook data JSON file)r   zProcessing z ATS IDs from command linerK   r   r   z ATS IDs from webhook filezFailed to process webhook file)r:      z1No ATS IDs provided. Waiting for webhook input...zYou can either:z1. Run with --ids ID1 ID2 ID3z/2. Run with --webhook-file path/to/webhook.jsonz03. Set up as webhook endpoint and send POST datazProcessing completed: r   z successful)N)NN)Krl   r"   pathlibr   ossysr   r=   r   typingr   r   rj   rk   rz   rw   rM   r   r   r   LOG_DIRr-   r4   r8   r@   rG   ATTACHMENTS_CATEGORYr   dictr(   rP   r/   r6   r9   r$   rA   rH   rQ   rX   rq   rx   r{   r   Responser   r   r   r   r   r   boolr   r   r   __name__argparseArgumentParserparseradd_argument
parse_argsargsats_ids_to_processidsextendr%   r   webhook_filer    r&   rO   r   r'   exitsuccess_countr   r   r   r   <module>r     sz      	 
 	   !
 2	<	%./8 ,-   D4  0 "
# dT *'%|#
k!	k!	 
/;4 ;d ;% %(4. %& &HTN &% %8D> %
&s 
&)!4 
&8D> 
&1s 1C 1x} 1]efi]j 1T X X  6 $ 0  9d 9 # H4E4E *3 8D>  C C D !$ ! ! !RV ![cdh[i !L'$ '8C= 'R Xl #d ## #QT #pt #P*C *htn * *^t S	 & z$X$$1XYF
s1MN
(/OPD xx!!$((+C 2344NOP 
			d''w? ,1(tyy|,!5l!CK$6 788RST 	AB -.?@@A M$ 6"QM 
"=/37I3J2K;
WXU &, ,  	6A>CHHQKK	s0   K 2K"K KK L!LL