Ë
    DèÇjj‹  ã            	      óN	  — d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlmZmZ ddlmZ ddlmZ ddlmZ ddlZddlmZmZmZ  ee«      j7                  «       j8                  Z ed	«      Zej8                  j?                  d
d
¬«        ej@                  d«      Z! eeddd¬«      Z"e"jG                  e!«        ejH                  e	jJ                  «      Z&e&jG                  e!«        ejN                  ejP                  e"e&g¬«        ejR                  d«      Z*	 ddl+m,Z,  e,d«       ejt                  jy                  dd«      Z=ejt                  jy                  dd«      ji                  «       Z>ejt                  jy                  dd«      ji                  «       Z?ejt                  jy                  dd«      ji                  «       Z@e>re?s#e*jƒ                  d«        e	j„                  d«       d e=› d!e>› d"�ZCed#z  ZDd$d%d%d$d&œZEd$ZFd'ZG e
j�                  «       ZId(„ ZJd[d)„ZKd\d*„ZLd]d+„ZMd^d,„ZNd_d`d-„ZOdad.„ZPdbd/„ZQdcd0„ZRddd1„ZSded2„ZTdfd3„ZUdgd4„ZVdgd5„ZWdgd6„ZXdgd7„ZYdgd8„ZZdgd9„Z[dgd:„Z\dhd;„Z]did<„Z^did=„Z_did>„Z` eea«      Zbd?Zcd@dAhZddjdB„ZeebjÌ                  dC„ «       ZgebjÑ                  dDdEg¬F«      ebjÑ                  dGdEg¬F«      ebjÑ                  dHdEg¬F«      dI„ «       «       «       Ziebjy                  dJ«      dK„ «       ZjebjÑ                  dHdLdMg¬F«      dN„ «       ZkebjÙ                  dO«      dP„ «       ZmebjÙ                  dG«      dQ„ «       ZnebjÙ                  dD«      dR„ «       Zo eK«        eadSk(  ro epejt                  jy                  dTdU«      «      Zqejt                  jy                  dVdW«      Zre*jç                  dXereqe> ete@«      «       ebjë                  ereqdYd
¬Z«       yy# e-$ r¾ dZ.ej^                  ja                  e.«      r� e1e.d¬«      5 Z2e2D ]w  Z3e3ji                  «       Z5e5re5jm                  d«      sde5vrŒ+e5jo                  dd«      \  Z8Z9ejt                  jw                  e8ji                  «       e9ji                  «       «       Œy 	 ddd«       n# 1 sw Y   nxY wY �Œhw xY w)kak  
Meta CAPI - PX3 Lab (PageView + Purchase)
=========================================

Servico HTTP interno que envia eventos server-side pro pixel Meta
1509133033542161 (PX3 Lab / Cloud PhotoRF / Server PhotoRF).

Endpoints publicos:
  POST/GET  https://track-capi-px3.agentesclimb.us/pageview
  POST      https://track-capi-px3.agentesclimb.us/purchase
  POST      https://track-capi-px3.agentesclimb.us/lead
  POST      https://track-capi-px3.agentesclimb.us/contact
  GET       https://track-capi-px3.agentesclimb.us/health

Porta local: 8918  (Traefik -> 172.18.0.1:8918)

Fluxo /pageview:
  1. Recebe GET ou POST com fbclid, gclid, UTMs, client_ip, client_ua,
     event_source_url.
  2. Dedupe SQLite por fbclid (janela 1h).
  3. Monta payload CAPI padrao Meta (fbc, user_data, event_id).
  4. POST em graph.facebook.com/v22.0/{pixel}/events?access_token=...
  5. Marca (event_type=pageview, key=fbclid) na tabela events_sent.

Fluxo /purchase:
  1. Recebe POST JSON com email, phone, first_name, last_name, city,
     state, zip, country, value, currency, content_name, content_ids,
     num_items, event_id, fbclid (opcional), client_ip (opcional),
     client_user_agent (opcional).
  2. Dedupe por event_id (janela 7 dias) - o N8N garante unicidade
     via padrao vra-<execution_id>.
  3. Monta payload Meta Purchase com user_data hasheado SHA-256
     (em, ph, fn, ln, ct, st, zp, country) + custom_data (value,
     currency, content_*).
  4. Envia pra Graph API e grava dedupe.

Config: /opt/mia/config/meta_capi_px3.env
Log:    /opt/mia/logs/track_capi_px3.log
DB:     /opt/mia/workspace/clientes/px3lab/capi_pageview/dedupe.db
é    )ÚannotationsN)ÚdatetimeÚtimezone)ÚRotatingFileHandler)ÚPath)ÚAny)ÚFlaskÚjsonifyÚrequestz /opt/mia/logs/track_capi_px3.logT)ÚparentsÚexist_okz1%(asctime)s [%(levelname)s] %(name)s: %(message)si    é   úutf-8)ÚmaxBytesÚbackupCountÚencoding)ÚlevelÚhandlersÚcapi_px3)Úload_dotenvz!/opt/mia/config/meta_capi_px3.env)r   ú#ú=é   ÚMETA_API_VERSIONzv22.0ÚMETA_PIXEL_ID_PX3Ú ÚMETA_CAPI_TOKENÚMETA_TEST_EVENT_CODEz=Config incompleta: META_PIXEL_ID_PX3 ou META_CAPI_TOKEN vaziozhttps://graph.facebook.com/ú/z/eventsz	dedupe.dbi  i€:	 )ÚpageviewÚpurchaseÚleadÚcontacti �' c                 óp   — t        j                  t        t        «      d¬«      } | j	                  d«       | S )Ng      @)ÚtimeoutzPRAGMA journal_mode=WAL)Úsqlite3ÚconnectÚstrÚDB_PATHÚexecute)Úconns    ú7/opt/mia/workspace/clientes/px3lab/capi_pageview/app.pyÚ_dbr-   ƒ   s(   € Ü�?‰?œ3œw›<°Ô5€DØ‡L�LÐ*Ô+Ø€Kó    c                 ó  — t         5  t        «       5 } | j                  d«       | j                  d«       | j                  d«       | j                  d«       t        t	        j                  «       «      t
        z
  }| j                  d|f«      j                  }| j                  d|f«      j                  }| j                  «        |s|rt        j                  d||«       d d d «       d d d «       y # 1 sw Y   ŒxY w# 1 sw Y   y xY w)Nzš
            CREATE TABLE IF NOT EXISTS sent (
                fbclid TEXT PRIMARY KEY,
                ts     INTEGER NOT NULL
            )
            z2CREATE INDEX IF NOT EXISTS idx_sent_ts ON sent(ts)a  
            CREATE TABLE IF NOT EXISTS events_sent (
                event_type TEXT NOT NULL,
                event_key  TEXT NOT NULL,
                ts         INTEGER NOT NULL,
                PRIMARY KEY (event_type, event_key)
            )
            z@CREATE INDEX IF NOT EXISTS idx_events_sent_ts ON events_sent(ts)zDELETE FROM sent WHERE ts < ?z$DELETE FROM events_sent WHERE ts < ?z:dedupe cleanup: sent=%d events_sent=%d registros removidos)
Ú_db_lockr-   r*   ÚintÚtimeÚCLEANUP_TTL_SECONDSÚrowcountÚcommitÚlogÚinfo)r+   ÚcutoffÚd1Úd2s       r,   Ú_init_dbr;   ‰   sï   € Ü	ñ (”3“5ð (˜Dð 	�‰ðô	
ð 	�‰ÐIÔJð 	�‰ðô		
ð 	�‰ØNô	
ô
 ”T—Y‘Y“[Ó!Ô$7Ñ7ˆØ�\‰\Ð9¸F¸9ÓE×NÑNˆØ�\‰\Ø2°V°Ió
ç
‰(ð 	ð 	�‰ŒÙ‘Ü�H‰HØLØØô÷I(÷ (÷ (ñ (ú÷ (ð (ús#   ‡C=’CC1Ã C=Ã1C:	Ã6C=Ã=Dc                óD  — |syt         j                  | t        «      }t        t	        j                  «       «      |z
  }t
        5  t        «       5 }|j                  d| ||f«      j                  «       }ddd«       ddd«       duS # 1 sw Y   ŒxY w# 1 sw Y   duS xY w)zETrue se (event_type, event_key) ja foi enviado dentro do TTL do tipo.FzMSELECT ts FROM events_sent WHERE event_type = ? AND event_key = ? AND ts >= ?N)	ÚDEDUPE_TTL_BY_TYPEÚgetÚDEDUPE_TTL_DEFAULTr1   r2   r0   r-   r*   Úfetchone)Ú
event_typeÚ	event_keyÚttlr8   r+   Úrows         r,   Ú_is_duplicaterE   µ   s    € áØÜ
×
 Ñ
  Ô-?Ó
@€CÜ”—‘“Ó Ñ#€FÜ	ñ ”3“5ð ˜DØ�l‰lðAà˜ FÐ+ó
÷ ‰(‹*ð	 	÷÷ ð �dˆ?Ð÷ð ú÷ ð �dˆ?Ðús$   ÁBÁ$BÁ3BÂB	ÂBÂBc                ó4  — |sy t        t        j                  «       «      }t        5  t        «       5 }|j	                  d| ||f«       | dk(  r|j	                  d||f«       |j                  «        d d d «       d d d «       y # 1 sw Y   ŒxY w# 1 sw Y   y xY w)NzOINSERT OR REPLACE INTO events_sent (event_type, event_key, ts) VALUES (?, ?, ?)r    z6INSERT OR REPLACE INTO sent (fbclid, ts) VALUES (?, ?))r1   r2   r0   r-   r*   r5   )rA   rB   Únowr+   s       r,   Ú
_mark_sentrH   Ä   s’   € ÙØÜ
Œd�i‰i‹kÓ
€CÜ	ñ ”3“5ð ˜DØ�‰ð;à˜ CÐ(ô	
ð ˜Ò#Ø�L‰LØHØ˜CÐ ôð 	�‰Œ÷÷ ÷ ñ ú÷ ð ús"   §B²?BÁ1BÂB	ÂBÂBc                 ó²   — t         j                  j                  dd«      } | r"| j                  d«      d   j	                  «       S t         j
                  xs dS )z6Extrai IP real considerando proxies (X-Forwarded-For).zX-Forwarded-Forr   ú,r   )r   Úheadersr>   ÚsplitÚstripÚremote_addr)Úxffs    r,   Ú_client_ip_from_requestrP   Ú   sI   € ä
�/‰/×
Ñ
Ð/°Ó
4€CÙ
Ø�y‰y˜‹~˜aÑ ×&Ñ&Ó(Ð(Ü×ÑÒ$ "Ð$r.   c                óV   — | sy|€t        t        j                  «       «      }d|› d| › �S )z(Formato Meta: fb.1.<ts_ms_or_s>.<fbclid>r   zfb.1.ú.)r1   r2   )ÚfbclidÚtss     r,   Ú
_build_fbcrU   â   s0   € áØØ	€zÜ”—‘“ÓˆØ�2�$�a˜�xÐ Ð r.   c                óˆ   — | r| S |› d|› d|› �j                  d«      }t        j                  |«      j                  «       dd S )z³Se tiver fbclid, ele e o event_id (garante dedupe com pixel browser).
    Senao, hash(ip+ua+minuto) pra permitir dedupe entre chamadas repetidas
    do mesmo user no mesmo minuto.ú|r   Né    )ÚencodeÚhashlibÚsha256Ú	hexdigest)rS   ÚipÚuaÚts_minÚraws        r,   Ú	_event_idra   ë   sL   € ñ ØˆØˆD��"��Q�v�hÐ
×
&Ñ
& wÓ
/€CÜ�>‰>˜#Ó×(Ñ(Ó*¨3¨BÐ/Ð/r.   c                 óH  — i } t         j                  r;t        j                  d¬«      xs i }t        |t        «      r| j                  |«       t         j                  rDt         j                  D ]1  }| j                  |t         j                  j                  |«      «       Œ3 t         j                  D ]1  }| j                  |t         j                  j                  |«      «       Œ3 i }dD ]5  }| j                  |«      }|€Œt        |«      j                  «       dd ||<   Œ7 |S )z1Aceita GET (query string) ou POST (JSON ou form).T©Úsilent)
rS   ÚgclidÚ
utm_sourceÚ
utm_mediumÚutm_campaignÚutm_contentÚutm_termÚ	client_ipÚ	client_uaÚevent_source_urlNi   )r   Úis_jsonÚget_jsonÚ
isinstanceÚdictÚupdateÚformÚ
setdefaultr>   Úargsr(   rM   )ÚsrcÚbodyÚkÚoutÚkeyÚvs         r,   Ú_collect_paramsr|   õ   sð   € à€CÜ‡‚Ü×Ñ tÔ,Ò2°ˆÜ�dœDÔ!Ø�J‰J�tÔÜ‡|‚|Ü—‘ò 	3ˆAØ�N‰N˜1œgŸl™l×.Ñ.¨qÓ1Õ2ð	3ä�\‰\ò /ˆØ�‰�qœ'Ÿ,™,×*Ñ*¨1Ó-Õ.ð/ð €Cðò )ˆð �G‰G�C‹LˆØˆ9ØÜ�q“6—<‘<“> % 4Ð(ˆˆCŠð)ð  €Jr.   c           
     óZ  — t        t        j                  «       «      }| j                  dd«      }| j                  dd«      }||dœ}|rt        ||«      |d<   ddi}d	D ]  }| j                  |«      }	|	sŒ|	||<   Œ |d
z  }
d|d|t	        ||||
«      ||dœ}d|gi}t
        r	t
        |d<   |S )NrS   r   rm   z)https://www.px3lab.com.br/server-photorf/)Úclient_ip_addressÚclient_user_agentÚfbcÚcontent_namezServer PhotoRF©rf   rg   rh   ri   rj   é<   ÚPageViewÚwebsite©Ú
event_nameÚ
event_timeÚaction_sourcerm   Úevent_idÚ	user_dataÚcustom_dataÚdataÚtest_event_code)r1   r2   r>   rU   ra   r   )Úparamsrk   rl   rG   rS   rm   r‹   rŒ   rx   r{   r_   ÚevtÚpayloads                r,   Ú_build_payloadr’     sè   € Ü
Œd�i‰i‹kÓ
€CØ�Z‰Z˜ "Ó%€FØ—z‘zØÐGóÐð
 'Ø&ñ!€Iñ Ü% f¨cÓ2ˆ	�%Ñð 	Ð(ð#€Kð Uò ˆØ�J‰J�q‹MˆÚØˆK˜ŠNðð
 �B‰Y€Fà ØØ"Ø,Ü˜f i°¸FÓCØØ"ñ€Cð  &¨ u˜o€GÝÜ%9ˆÐ!Ñ"Ø€Nr.   c                óÈ   — 	 t        j                  t        dt        i| d¬«      }|j                  |j
                  fS # t         j                  $ r}dd|› �fcY d }~S d }~ww xY w)NÚaccess_tokené   )r�   Újsonr%   éÿÿÿÿzREQ_ERROR: )ÚrequestsÚpostÚMETA_ENDPOINTÚ
META_TOKENÚstatus_codeÚtextÚRequestException)r‘   ÚrÚes      r,   Ú
_send_metar¡   A  sc   € ð	%Ü�M‰MÜØ"¤JÐ/ØØô	
ˆð �}‰}˜aŸf™fÐ$Ð$øÜ×$Ñ$ò %Ø�[  Ð$Ð$Õ$ûð%ús   ‚:= ½A!ÁAÁA!ÁA!c                ód   — | syt        j                  d| «      }dj                  d„ |D «       «      S )z+Remove acentos: 'Sao Paulo' -> 'sao paulo'.r   ÚNFKDc              3  óL   K  — | ]  }t        j                  |«      rŒ|–— Œ y ­w©N)ÚunicodedataÚ	combining)Ú.0Úcs     r,   ú	<genexpr>z!_strip_accents.<locals>.<genexpr>V  s   è ø€ ÒC˜¬+×*?Ñ*?ÀÕ*B”1ÑCùs   ‚$�$)r¦   Ú	normalizeÚjoin)ÚsÚnfkds     r,   Ú_strip_accentsr¯   Q  s/   € áØÜ× Ñ  ¨Ó+€DØ�7‰7ÑC˜dÔCÓCÐCr.   c                óf   — t        j                  | j                  d«      «      j                  «       S )Nr   )rZ   r[   rY   r\   ©Úvalues    r,   Ú_sha256r³   Y  s#   € Ü�>‰>˜%Ÿ,™, wÓ/Ó0×:Ñ:Ó<Ð<r.   c                óF   — | xs dj                  «       j                  «       S )Nr   ©rM   Úlower©r{   s    r,   Ú_norm_emailr¸   ]  s   € ØŠG��?‰?Ó×"Ñ"Ó$Ð$r.   c                ó8   — t        j                  dd| xs d«      S )z:So digitos (Meta espera E.164 sem '+', ex: 5511999999999).ú\Dr   ©ÚreÚsubr·   s    r,   Ú_norm_phoner¾   a  ó   € ä�6‰6�%˜˜QšW "Ó%Ð%r.   c                óX   — t        | xs dj                  «       j                  «       «      S )zFLowercase + strip + remove acentos. Nao remove espaco (nome composto).r   ©r¯   rM   r¶   r·   s    r,   Ú
_norm_namerÂ   f  ó!   € ä˜1š7 Ÿ/™/Ó+×1Ñ1Ó3Ó4Ð4r.   c                ó†   — t        | xs dj                  «       j                  «       «      }t        j                  dd|«      S )z7Lowercase + strip acentos + remove espacos e pontuacao.r   z	[^a-z0-9])r¯   rM   r¶   r¼   r½   )r{   Úbases     r,   Ú
_norm_cityrÆ   k  s3   € ä˜1š7 Ÿ/™/Ó+×1Ñ1Ó3Ó4€DÜ�6‰6�,  DÓ)Ð)r.   c                óX   — t        | xs dj                  «       j                  «       «      S )z-Lowercase (Meta aceita sigla; 'rs' funciona).r   rÁ   r·   s    r,   Ú_norm_staterÈ   q  rÃ   r.   c                ó8   — t        j                  dd| xs d«      S )zSo digitos.rº   r   r»   r·   s    r,   Ú	_norm_ziprÊ   v  r¿   r.   c                óF   — | xs dj                  «       j                  «       S )z$Lowercase ISO 3166-1 alpha-2 ('br').r   rµ   r·   s    r,   Ú_norm_countryrÌ   {  s   € àŠG��?‰?Ó×"Ñ"Ó$Ð$r.   c                ó"   — | rt        | «      gS g S )z|Retorna [sha256(value)] se value for truthy, senao lista vazia.
    Meta CAPI espera array pra em/ph/fn/ln/ct/st/zp/country.)r³   r±   s    r,   Ú_hash_ifrÎ   €  s   € ñ  %ŒG�E‹NÐÐ,¨"Ð,r.   c                ó†  — t        t        j                  «       «      }t        t        | j	                  dd«      «      «      }t        t        | j	                  dd«      «      «      }t        t        | j	                  dd«      «      «      }t        t        | j	                  dd«      «      «      }t        t        | j	                  dd«      «      «      }t        t        | j	                  dd«      «      «      }t        t        | j	                  dd«      «      «      }t        t        | j	                  d	d
«      «      «      }	t        | j	                  dd«      «      j                  «       }
t        | j	                  dd«      «      j                  «       }t        | j	                  dd«      «      j                  «       }t        | j	                  dd«      «      j                  «       }|sd|› dt        |«      dd › �}i }|rt        |«      |d<   |rt        |«      |d<   |rt        |«      |d<   |rt        |«      |d<   |rt        |«      |d<   |rt        |«      |d<   |rt        |«      |d<   |	rt        |	«      |d	<   |r||d<   |r||d<   |
rt        |
|«      |d<   	 t        | j	                  dd«      xs d«      }t        | j	                  dd «      «      j                  «       j%                  «       xs d }t        | j	                  d!d«      «      j                  «       }| j	                  d"«      xs g }t'        |t        «      r|g}	 t        | j	                  d#d«      xs d«      }||d$d%d&œ}|r||d!<   |rt)        |«      |d"<   |r||d#<   d'|d(d)|||d*œ}d+|gi}t        | j	                  d,d«      «      j                  «       }|r||d,<   nt*        r	t*        |d,<   |||||t-        |
«      t-        |«      t-        |«      |j	                  d,d«      d-œ	}||fS # t         t"        f$ r d}Y �Œow xY w# t         t"        f$ r d}Y ŒÚw xY w).z,Retorna (payload_meta, log_info). Nao envia.Úemailr   ÚphoneÚ
first_nameÚ	last_nameÚcityÚstateÚzipÚcountryÚBRrS   rk   r   rŠ   zpurchase-fallback-ú-Né   ÚemÚphÚfnÚlnÚctÚstÚzpr~   r€   r²   r   ç        ÚcurrencyÚBRLr�   Úcontent_idsÚ	num_itemsÚproductÚsoftware_credit)rã   r²   Úcontent_typeÚcontent_categoryÚPurchaseÚsystem_generatedz"https://sistema.app.px3lab.com.br/r†   r�   rŽ   )	rŠ   r²   rã   r�   ræ   Ú
has_fbclidÚhas_ipÚhas_uarŽ   )r1   r2   r¸   r(   r>   r¾   rÂ   rÆ   rÈ   rÊ   rÌ   rM   r³   rÎ   rU   ÚfloatÚ	TypeErrorÚ
ValueErrorÚupperrp   Úlistr   Úbool)rw   rG   rÐ   rÑ   rÒ   rÓ   rÔ   rÕ   Úzip_coder×   rS   rk   rl   rŠ   r‹   r²   rã   r�   rå   ræ   rŒ   r�   r‘   Úbody_test_codeÚlog_infos                            r,   Ú_build_purchase_payloadrù   ‰  s  € ä
Œd�i‰i‹kÓ
€Cäœ˜DŸH™H W¨bÓ1Ó2Ó3€EÜœ˜DŸH™H W¨bÓ1Ó2Ó3€EÜœC §¡¨°rÓ :Ó;Ó<€JÜœ3˜tŸx™x¨°RÓ8Ó9Ó:€IÜ”c˜$Ÿ(™( 6¨2Ó.Ó/Ó0€DÜœ˜DŸH™H W¨bÓ1Ó2Ó3€EÜœ˜TŸX™X e¨RÓ0Ó1Ó2€HÜœC §¡¨°DÓ 9Ó:Ó;€Gä�—‘˜( BÓ'Ó(×.Ñ.Ó0€FÜ�D—H‘H˜[¨"Ó-Ó.×4Ñ4Ó6€IÜ�D—H‘HÐ0°"Ó5Ó6×<Ñ<Ó>€Iä�4—8‘8˜J¨Ó+Ó,×2Ñ2Ó4€HÙà'¨ u¨A¬g°e«n¸R¸aÐ.@Ð-AÐBˆà "€IÙÜ" 5›/ˆ	�$‰ÙÜ" 5›/ˆ	�$‰ÙÜ" :Ó.ˆ	�$‰ÙÜ" 9Ó-ˆ	�$‰ÙÜ" 4›.ˆ	�$‰ÙÜ" 5›/ˆ	�$‰ÙÜ" 8Ó,ˆ	�$‰ÙÜ'¨Ó0ˆ	�)ÑÙØ)2ˆ	Ð%Ñ&ÙØ)2ˆ	Ð%Ñ&ÙÜ% f¨cÓ2ˆ	�%ÑðÜ�d—h‘h˜w¨Ó*Ò/¨aÓ0ˆô �4—8‘8˜J¨Ó.Ó/×5Ñ5Ó7×=Ñ=Ó?ÒHÀ5€HÜ�t—x‘x °Ó3Ó4×:Ñ:Ó<€LØ—(‘(˜=Ó)Ò/¨R€KÜ�+œsÔ#Ø"�mˆðÜ˜Ÿ™ ¨aÓ0Ò5°AÓ6ˆ	ð
 ØØ!Ø-ñ	#€Kñ Ø&2ˆ�NÑ#ÙÜ%)¨+Ó%6ˆ�MÑ"ÙØ#,ˆ�KÑ ð !ØØ+Ø@ØØØ"ñ€Cð  &¨ u˜o€Gô ˜Ÿ™Ð"3°RÓ8Ó9×?Ñ?ÓA€NÙØ%3ˆÐ!Ò"Ý	Ü%9ˆÐ!Ñ"ð ØØØ$ØÜ˜6“lÜ�y“/Ü�y“/Ø"Ÿ;™;Ð'8¸"Ó=ñ
€Hð �HÐÐøôo ”zÐ"ò Ø‹ðûô ”zÐ"ò ØŠ	ðús$   ÊP ÍP, ÐP)Ð(P)Ð,Q Ð?Q c                óš  — t        t        j                  «       «      }t        t        | j	                  dd«      «      «      }t        t        | j	                  dd«      «      «      }t        t        | j	                  dd«      «      «      }t        t        | j	                  dd«      «      «      }t        t        | j	                  dd«      «      «      }t        | j	                  dd«      «      j                  «       }t        | j	                  d	d«      «      j                  «       }t        | j	                  d
d«      «      j                  «       }	t        | j	                  dd«      «      j                  «       }
t        | j	                  dd«      «      j                  «       xs d}t        | j	                  dd«      «      j                  «       }|sd|› dt        |xs |«      dd › �}i }|rt        |«      |d<   |rt        |«      |d<   |rt        |«      |d<   |rt        |«      |d<   |rt        |«      |d<   |	r|	|d<   |
r|
|d<   |rt        ||«      |d<   |r||d	<   t        | j	                  dd«      «      ddœ}dD ]'  }| j	                  |«      }|sŒt        |«      dd ||<   Œ) d|d ||||d!œ}d"|gi}t        | j	                  d#d«      «      j                  «       }|r||d#<   nt        r	t        |d#<   |t        |«      t        |«      t        |«      t        |«      t        |	«      t        |
«      ||j	                  d#d«      d$œ	}||fS )%a  Constroi payload Meta Lead server-side.

    Espera:
      event_id (obrigatorio - MESMO do fbq browser p/ dedupe),
      email, phone, first_name (opcionais mas fortemente recomendados),
      client_ip, client_user_agent, event_source_url,
      fbclid, fbp (cookie _fbp), utms.
    rÐ   r   rÑ   rÒ   rÓ   r×   rØ   rS   Úfbprk   r   rm   zhttps://espera.px3lab.com.br/rŠ   zlead-fallback-rÙ   NrÚ   rÛ   rÜ   rÝ   rÞ   r~   r€   r�   zWaitlist Cloud PhotoRF 2.0Úwaitlist)r�   rê   r‚   é   ÚLeadr…   r†   r�   rŽ   )	rŠ   Ú	has_emailÚ	has_phonerí   Úhas_fbprî   rï   rm   rŽ   )r1   r2   r¸   r(   r>   r¾   rÂ   rÌ   rM   r³   rÎ   rU   r   rõ   )rw   rG   rÐ   rÑ   rÒ   rÓ   r×   rS   rû   rk   rl   rm   rŠ   r‹   rŒ   rx   r{   r�   r‘   r÷   rø   s                        r,   Ú_build_lead_payloadr  ÷  s'  € ô Œd�i‰i‹kÓ
€Cäœ˜DŸH™H W¨bÓ1Ó2Ó3€EÜœ˜DŸH™H W¨bÓ1Ó2Ó3€EÜœC §¡¨°rÓ :Ó;Ó<€JÜœ3˜tŸx™x¨°RÓ8Ó9Ó:€IÜœC §¡¨°DÓ 9Ó:Ó;€Gä�—‘˜( BÓ'Ó(×.Ñ.Ó0€FÜ
ˆd�h‰h�u˜bÓ!Ó
"×
(Ñ
(Ó
*€CÜ�D—H‘H˜[¨"Ó-Ó.×4Ñ4Ó6€IÜ�D—H‘HÐ0°"Ó5Ó6×<Ñ<Ó>€IÜØ�‰Ð#Ð%DÓEóç�eƒgò1à0ð ô �4—8‘8˜J¨Ó+Ó,×2Ñ2Ó4€HÙØ# C 5¨¬'°%².¸5Ó*AÀ"À1Ð*EÐ)FÐGˆà "€IÙÜ" 5›/ˆ	�$‰ÙÜ" 5›/ˆ	�$‰ÙÜ" :Ó.ˆ	�$‰ÙÜ" 9Ó-ˆ	�$‰ÙÜ'¨Ó0ˆ	�)ÑÙØ)2ˆ	Ð%Ñ&ÙØ)2ˆ	Ð%Ñ&ÙÜ% f¨cÓ2ˆ	�%ÑÙ
Øˆ	�%Ñô ˜DŸH™H ^Ð5QÓRÓSØ&ñ#€Kð
 Uò *ˆØ�H‰H�Q‹KˆÚÜ  ›V D S˜\ˆK˜ŠNð*ð ØØ"Ø,ØØØ"ñ€Cð  &¨ u˜o€GÜ˜Ÿ™Ð"3°RÓ8Ó9×?Ñ?ÓA€NÙØ%3ˆÐ!Ò"Ý	Ü%9ˆÐ!Ñ"ð Ü˜%“[Ü˜%“[Ü˜6“lÜ˜“9Ü�y“/Ü�y“/Ø,Ø"Ÿ;™;Ð'8¸"Ó=ñ
€Hð �HÐÐr.   c                ó^  — t        t        j                  «       «      }| j                  d«      xs i }t        |t        «      si }t        |j                  d«      xs | j                  d«      xs d«      j                  «       }t        |j                  d«      xs | j                  d«      xs d«      j                  «       }t        |j                  d«      xs | j                  d«      xs d«      j                  «       }t        |j                  d«      xs | j                  d«      xs d«      j                  «       }t        | j                  dd«      «      j                  «       }|s|rt        ||«      }t        | j                  d	d
«      «      j                  «       xs d
}t        | j                  dd«      «      j                  «       }	|	sd|› dt        |xs |xs |«      dd › �}	i }
|r||
d<   |r||
d<   |r||
d<   |r||
d<   | j                  d«      xs i }t        |t        «      si }dt        |j                  d«      xs | j                  d«      xs d«      dd i}dD ]I  }|j                  |«      �|j                  |«      n| j                  |«      }|sŒ9t        |«      dd ||<   ŒK |j                  «       D ]#  \  }}||v s|€Œ|dv rŒ	 t        |«      dd ||<   Œ% d|d||	|
|dœ}d|gi}t        | j                  dd«      «      j                  «       }|r||d<   nt        r	t        |d<   |	t        |«      t        |«      t        |«      t        |«      |j                  dd«      |j                  dd«      ||j                  dd«      dœ	}||fS # t        $ r Y Œäw xY w)aÏ  Constroi payload Meta Contact server-side (clique no botao WhatsApp).

    O payload vem do browser (JS da landing). Nao exige email/phone;
    o importante aqui e amarrar o clique ao usuario via fbp/fbc + IP/UA
    pra Meta atribuir conversao de volta pro anuncio.

    Espera:
      event_id (obrigatorio - MESMO do fbq browser p/ dedupe),
      event_source_url,
      user_data: { fbp, fbc, client_user_agent },
      custom_data: { content_name, utm_* }
    r‹   rû   r   r€   r   r~   rk   rS   rm   zhttps://oferta.px3lab.com.br/rŠ   zcontact-fallback-rÙ   NrÚ   rŒ   r�   Úwhatsapp_ofertarý   r‚   )r�   ÚContactr…   r†   r�   rŽ   rh   )	rŠ   r  Úhas_fbcrî   rï   r�   rh   rm   rŽ   )r1   r2   r>   rp   rq   r(   rM   rU   r³   ÚitemsÚ	Exceptionr   rõ   )rw   rG   Úud_inrû   r€   rl   rk   rS   rm   rŠ   r‹   Úcd_inrŒ   rx   r{   r�   r‘   r÷   rø   s                      r,   Ú_build_contact_payloadr  T  sÒ  € ô Œd�i‰i‹kÓ
€Cð �H‰H�[Ó!Ò' R€EÜ�eœTÔ"Øˆä
ˆe�i‰i˜ÓÒ7 $§(¡(¨5£/Ò7°RÓ
8×
>Ñ
>Ó
@€CÜ
ˆe�i‰i˜ÓÒ7 $§(¡(¨5£/Ò7°RÓ
8×
>Ñ
>Ó
@€CÜØ�	‰	Ð%Ó&ò 	Ø�8‰8Ð'Ó(ò	àó÷ �eƒgð	 ô
 Ø�	‰	Ð%Ó&ò 	Ø�8‰8�KÓ ò	àó÷ �eƒgð	 ô �—‘˜( BÓ'Ó(×.Ñ.Ó0€FÙ‘6Ü˜ Ó%ˆäØ�‰Ð#Ð%DÓEóç�eƒgò1à0ð ô �4—8‘8˜J¨Ó+Ó,×2Ñ2Ó4€HÙØ& s e¨1¬W°SÒ5L¸CÒ5LÀ9Ó-MÈbÈqÐ-QÐ,RÐSˆà "€IÙØ)2ˆ	Ð%Ñ&ÙØ)2ˆ	Ð%Ñ&Ù
Øˆ	�%ÑÙ
Øˆ	�%Ñð �H‰H�]Ó#Ò) r€EÜ�eœTÔ"Øˆð 	œØ�I‰I�nÓ%ò !Ø�x‰x˜Ó'ò!à ó
ð ˆ3ð	ð#€Kð Uò *ˆØ!ŸI™I a›LÐ4ˆE�I‰I�aŒL¸$¿(¹(À1»+ˆÚÜ  ›V D S˜\ˆK˜ŠNð*ð —‘“ò ‰ˆˆ1Ø�Ñ˜q˜yØØÐ!Ñ!Øð	Ü  ›V D S˜\ˆK˜ŠNðð  ØØ"Ø,ØØØ"ñ€Cð  &¨ u˜o€GÜ˜Ÿ™Ð"3°RÓ8Ó9×?Ñ?ÓA€NÙØ%3ˆÐ!Ò"Ý	Ü%9ˆÐ!Ñ"ð Ü˜“9Ü˜“9Ü�y“/Ü�y“/Ø#Ÿ™¨¸Ó;Ø#Ÿ™¨¸Ó;Ø,Ø"Ÿ;™;Ð'8¸"Ó=ñ
€Hð �HÐÐøô? ò 	Ùð	ús   ËN Î 	N,Î+N,)z.px3lab.com.brz.agentesclimb.uszhttps://px3lab.com.brzhttps://www.px3lab.com.brc                óž   — | sy| t         v ryt        D ]8  }| j                  |«      sŒ| j                  d«      s| j                  d«      sŒ8 y y)NFTzhttps://zhttp://)Ú_CORS_ALLOWED_EXACTÚ_CORS_ALLOWED_SUFFIXESÚendswithÚ
startswith)ÚoriginÚsufs     r,   Ú_cors_origin_allowedr  Ü  sR   € ÙØØÔ$Ñ$ØÜ%ò ˆØ�?‰?˜3Õà× Ñ  Ô,°×0AÑ0AÀ)Õ0LÙð	ð
 r.   c                óò   — t         j                  j                  dd«      }t        |«      rK|| j                  d<   d| j                  d<   d| j                  d<   d| j                  d<   d	| j                  d
<   | S )NÚOriginr   zAccess-Control-Allow-OriginÚVaryzGET, POST, OPTIONSzAccess-Control-Allow-MethodszContent-TypezAccess-Control-Allow-HeadersÚ86400zAccess-Control-Max-Age)r   rK   r>   r  )Úrespr  s     r,   Ú_cors_headersr  é  so   € ä�_‰_× Ñ  ¨2Ó.€FÜ˜FÔ#Ø6<ˆ�‰Ð2Ñ3Ø'ˆ�‰�VÑØ7Kˆ�‰Ð3Ñ4Ø7Eˆ�‰Ð3Ñ4Ø18ˆ�‰Ð-Ñ.Ø€Kr.   z/contactÚOPTIONS)Úmethodsz/leadz	/pageviewc                  ó   — y)N)r   éÌ   © r  r.   r,   Ú_cors_preflightr  õ  s   € ð
 r.   z/healthc                 óN   — t        ddt        t        t        «      t        dœ«      S )NTÚcapi_pageview_px3)ÚokÚserviceÚpixelÚ	test_modeÚapi_version)r
   ÚMETA_PIXEL_IDrõ   r   r   r  r.   r,   Úhealthr(  ý  s)   € äàØ*Ü"ÜÔ2Ó3Ü+ñ	
óð r.   ÚGETÚPOSTc            
     óL  — t        «       } | j                  d«      xs
 t        «       }| j                  d«      xs  t        j                  j                  dd«      }| j                  dd«      }|rDt        d|«      r8t        j                  d|d d | j                  d	d«      «       t        d
d
dœ«      S t        | ||«      }t        |«      \  }}t        j                  t        j                  «      j                  «       ||r|d d nd| j                  d	d«      | j                  dd«      |t!        t"        «      |d d dœ}t        j                  dt%        j&                  |d¬«      «       d|cxk  rdk  rn nt)        d|«       t        d
|dœ«      S t        d||d d dœ«      dfS )Nrk   rl   ú
User-Agentr   rS   r    z,SKIP dedupe pageview fbclid=%s utm_source=%srX   rf   T)r"  Údeduperh   é�  )rT   ÚstatusrS   rf   rh   r]   r%  r  úCAPI %sF©Úensure_asciiéÈ   é,  )r"  Úmeta_status)r"  r5  r  éö  )r|   r>   rP   r   rK   rE   r6   r7   r
   r’   r¡   r   rG   r   ÚutcÚ	isoformatrõ   r   r–   ÚdumpsrH   )r�   rk   rl   rS   r‘   r/  rw   Úlog_lines           r,   r    r    
  s{  € äÓ€Fð —
‘
˜;Ó'ÒDÔ+BÓ+D€IØ—
‘
˜;Ó'ÒP¬7¯?©?×+>Ñ+>¸|ÈRÓ+P€Ià�Z‰Z˜ "Ó%€Fñ ”- 
¨FÔ3Ü�‰Ø:Ø�3�BˆKØ�J‰J�| RÓ(ô	
ô
 ˜d¨dÑ3Ó4Ð4ä˜V Y°	Ó:€GÜ˜gÓ&�L€FˆDô �l‰lœ8Ÿ<™<Ó(×2Ñ2Ó4ØÙ!'�&˜˜"‘+¨RØ—j‘j ¨rÓ2ØŸ
™
 >°2Ó6ØÜÔ.Ó/Ø�T�c�
ñ	€Hô ‡H�HˆYœŸ
™
 8¸%Ô@ÔAà
ˆfÔ�sÕÜ�:˜vÔ&Ü˜d°6Ñ:Ó;Ð;ä˜%°ÀÀTÀcÀ
ÑKÓLÈcÐQÐQr.   z	/purchasec                 óP  — t        j                  d¬«      xs i } t        | t        «      st	        dddœ«      dfS t        | j                  dd«      «      j                  «       }t        | j                  d	d«      «      j                  «       }t        | j                  d
d«      «      j                  «       }|s|st	        dddœ«      dfS 	 t        | j                  dd«      xs d«      }|dk  rt	        dddœ«      dfS |r1t        d|«      r%t        j                  d|«       t	        dd|dœ«      S t        | «      \  }}t        |«      \  }}t!        j"                  t$        j&                  «      j)                  «       d|t+        t,        «      dœ|¥d|dd i¥}	t        j                  dt/        j0                  |	d¬«      «       d|cxk  rdk  r(n n%t3        d|d   «       t	        d||d   |dd dœ«      S t	        d||d   |dd dœ«      dfS # t        t        f$ r d}Y �Œ:w xY w)ai  Recebe compra real (N8N do PX3) e envia como Purchase server-side.

    Body JSON esperado (campos minimos: email OU phone, value, event_id):
      {
        "email": "...", "phone": "...",
        "first_name": "...", "last_name": "...",
        "city": "...", "state": "...", "zip": "...", "country": "BR",
        "value": 900.00, "currency": "BRL",
        "content_name": "CLOUD PHOTORF",
        "content_ids": ["CLOUD_PHOTORF"],
        "num_items": 10000,
        "event_id": "vra-9436",
        "fbclid": "(opcional)",
        "client_ip": "(opcional)",
        "client_user_agent": "(opcional)"
      }
    Trc   FÚinvalid_json©r"  Úerrorr.  rŠ   r   rÐ   rÑ   Úemail_or_phone_requiredr²   r   râ   Úvalue_requiredr!   z SKIP dedupe purchase event_id=%s©r"  r-  rŠ   rë   ©rT   Úeventr/  r%  r  Nr0  r1  r3  r4  ©r"  r5  rŠ   r  r6  )r   ro   rp   rq   r
   r(   r>   rM   rð   rñ   rò   rE   r6   r7   rù   r¡   r   rG   r   r7  r8  rõ   r   r–   r9  rH   )
rw   rŠ   rÐ   rÑ   r²   r‘   Úmetar/  Ú	resp_bodyr:  s
             r,   r!   r!   4  s5  € ô& ×Ñ 4Ô(Ò.¨B€DÜ�dœDÔ!Ü˜e¨nÑ=Ó>ÀÐCÐCä�4—8‘8˜J¨Ó+Ó,×2Ñ2Ó4€HÜ�—‘˜ "Ó%Ó&×,Ñ,Ó.€EÜ�—‘˜ "Ó%Ó&×,Ñ,Ó.€EÙ™Ü˜eÐ.GÑHÓIÈ3ÐNÐNðÜ�d—h‘h˜w¨Ó*Ò/¨aÓ0ˆð �‚zÜ˜eÐ.>Ñ?Ó@À#ÐEÐEñ ”M *¨hÔ7Ü�‰Ð3°XÔ>Ü˜d¨dÀÑIÓJÐJä+¨DÓ1�M€GˆTÜ" 7Ó+Ñ€FˆIô �l‰lœ8Ÿ<™<Ó(×2Ñ2Ó4ØØÜÔ.Ó/ñ	ð
 ðð 	�	˜$˜3�ñ€Hô ‡H�HˆYœŸ
™
 8¸%Ô@ÔAà
ˆfÔ�sÕÜ�:˜t JÑ/Ô0ÜàØ%Ø  Ñ,Ø! $ 3˜ñ	ó
ð 	
ô 	àØ%Ø  Ñ,Ø! $ 3˜ñ	ó	
ð 	ð
ð 
øôE ”zÐ"ò Ø‹ðús   ÃH ÈH%È$H%c                 óZ  — t        j                  d¬«      xs i } t        | t        «      st	        dddœ«      dfS t        | j                  dd«      «      j                  «       }t        | j                  d	d«      «      j                  «       }|s|st	        dd
dœ«      dfS t        | j                  dd«      «      j                  «       }| j                  d«      st        «       | d<   | j                  d«      s#t         j                  j                  dd«      | d<   |r1t        d|«      r%t        j                  d|«       t	        dd|dœ«      S t        | «      \  }}t        |«      \  }}t        j                   t"        j$                  «      j'                  «       d|t)        t*        «      dœ|¥d|dd i¥}t        j                  dt-        j.                  |d¬«      «       d|cxk  rdk  r(n n%t1        d|d   «       t	        d||d   |dd dœ«      S t	        d||d   |dd dœ«      dfS )aÈ  Recebe Lead da landing (server-side) e envia ao Meta CAPI.

    Body JSON esperado:
      {
        "event_id": "uuid gerado no browser (fbq eventID)",   # obrigatorio p/ dedupe
        "email":    "...",
        "phone":    "5511987654321",
        "first_name": "...", "last_name": "...",
        "client_ip": "1.2.3.4",           # opcional (senao pega do request)
        "client_user_agent": "...",       # opcional (senao pega do request)
        "event_source_url": "https://espera.px3lab.com.br/",
        "fbclid": "(opcional)",
        "fbp":    "(opcional, cookie _fbp)",
        "utm_source": ..., "utm_medium": ..., "utm_campaign": ...,
        "test_event_code": "(opcional, override)"
      }
    Trc   Fr<  r=  r.  rÐ   r   rÑ   r?  rŠ   rk   r   r,  r"   zSKIP dedupe lead event_id=%srA  rþ   rB  r  Nr0  r1  r3  r4  rD  r6  )r   ro   rp   rq   r
   r(   r>   rM   rP   rK   rE   r6   r7   r  r¡   r   rG   r   r7  r8  rõ   r   r–   r9  rH   )	rw   rÐ   rÑ   rŠ   r‘   rE  r/  rF  r:  s	            r,   r"   r"   ‚  s  € ô& ×Ñ 4Ô(Ò.¨B€DÜ�dœDÔ!Ü˜e¨nÑ=Ó>ÀÐCÐCä�—‘˜ "Ó%Ó&×,Ñ,Ó.€EÜ�—‘˜ "Ó%Ó&×,Ñ,Ó.€EÙ™Ü˜eÐ.GÑHÓIÈ3ÐNÐNä�4—8‘8˜J¨Ó+Ó,×2Ñ2Ó4€Hð �8‰8�KÔ Ü3Ó5ˆˆ[ÑØ�8‰8Ð'Ô(Ü$+§O¡O×$7Ñ$7¸ÀbÓ$IˆÐ Ñ!ñ ”M &¨(Ô3Ü�‰Ð/°Ô:Ü˜d¨dÀÑIÓJÐJä'¨Ó-�M€GˆTÜ" 7Ó+Ñ€FˆIô �l‰lœ8Ÿ<™<Ó(×2Ñ2Ó4ØØÜÔ.Ó/ñ	ð
 ðð 	�	˜$˜3�ñ€Hô ‡H�HˆYœŸ
™
 8¸%Ô@ÔAà
ˆfÔ�sÕÜ�6˜4 
Ñ+Ô,ÜàØ%Ø  Ñ,Ø! $ 3˜ñ	ó
ð 	
ô 	àØ%Ø  Ñ,Ø! $ 3˜ñ	ó	
ð 	ð
ð 
r.   c                 óÖ  — t        j                  d¬«      xs i } t        | t        «      st	        dddœ«      dfS t        | j                  dd«      «      j                  «       }| j                  d	«      }t        |t        «      si }|| d	<   |j                  d
«      st        «       |d
<   |j                  d«      s#t         j                  j                  dd«      |d<   |r1t        d|«      r%t        j                  d|«       t	        dd|dœ«      S t        | «      \  }}t        |«      \  }}t        j                   t"        j$                  «      j'                  «       d|t)        t*        «      dœ|¥d|dd i¥}t        j                  dt-        j.                  |d¬«      «       d|cxk  rdk  r$n n!t1        d|d   «       t	        d|d   |dœ«      S t	        d||d   |dd dœ«      dfS )ag  Recebe clique no botao WhatsApp (browser) e envia Contact ao Meta CAPI.

    Chamado via fetch() do JS da landing. Dedupe por event_id (1h).

    Body JSON esperado:
      {
        "event_id": "uuid gerado no browser (fbq eventID)",   # obrigatorio p/ dedupe
        "event_name": "Contact",                              # ignorado, mantido p/ compat
        "event_source_url": "https://oferta.px3lab.com.br/...",
        "user_data": {
          "fbp": "fb.1.xxx.xxx",            # cookie _fbp
          "fbc": "fb.1.xxx.xxx",            # cookie _fbc (opcional, derivado do fbclid)
          "client_user_agent": "..."
        },
        "custom_data": {
          "content_name": "whatsapp_oferta_cloudphotorf2",
          "utm_source": "facebook", "utm_medium": "paid",
          "utm_campaign": "...", "utm_content": "...", "utm_term": "..."
        }
      }
    Trc   Fr<  r=  r.  rŠ   r   r‹   r~   r   r,  r#   zSKIP dedupe contact event_id=%s)r"  ÚdedupedrŠ   r  rB  r  Nr0  r1  r3  r4  )r"  rŠ   r5  rD  iô  )r   ro   rp   rq   r
   r(   r>   rM   rP   rK   rE   r6   r7   r  r¡   r   rG   r   r7  r8  rõ   r   r–   r9  rH   )rw   rŠ   Úudr‘   rE  r/  rF  r:  s           r,   r#   r#   Ð  sè  € ô. ×Ñ 4Ô(Ò.¨B€DÜ�dœDÔ!Ü˜e¨nÑ=Ó>ÀÐCÐCä�4—8‘8˜J¨Ó+Ó,×2Ñ2Ó4€Hð 
�‰�+Ó	€BÜ�bœ$ÔØˆØˆˆ[ÑØ�6‰6Ð%Ô&Ü"9Ó";ˆÐÑØ�6‰6Ð%Ô&Ü")§/¡/×"5Ñ"5°lÀBÓ"GˆÐÑñ ”M )¨XÔ6Ü�‰Ð2°HÔ=Ü˜d¨tÀÑJÓKÐKä*¨4Ó0�M€GˆTÜ" 7Ó+Ñ€FˆIô �l‰lœ8Ÿ<™<Ó(×2Ñ2Ó4ØØÜÔ.Ó/ñ	ð
 ðð 	�	˜$˜3�ñ€Hô ‡H�HˆYœŸ
™
 8¸%Ô@ÔAà
ˆfÔ�sÕÜ�9˜d :Ñ.Ô/ÜàØ  Ñ,Ø%ñó
ð 	
ô 	àØ%Ø  Ñ,Ø! $ 3˜ñ	ó	
ð 	ð
ð 
r.   Ú__main__ÚPORTÚ8918ÚHOSTz0.0.0.0zkcapi_px3 subindo: host=%s port=%s pixel=%s test_mode=%s routes=[/pageview,/purchase,/lead,/contact,/health]F)ÚhostÚportÚdebugÚthreaded)ÚreturnÚNone)rA   r(   rB   r(   rS  rõ   )rA   r(   rB   r(   rS  rT  )rS  r(   r¥   )rS   r(   rT   z
int | NonerS  r(   )
rS   r(   r]   r(   r^   r(   r_   r1   rS  r(   )rS  údict[str, str])r�   rU  rk   r(   rl   r(   rS  rq   )r‘   rq   rS  ztuple[int, str])r­   r(   rS  r(   )r²   r(   rS  r(   )r{   r(   rS  r(   )r²   r(   rS  z	list[str])rw   zdict[str, Any]rS  ztuple[dict, dict])r  r(   rS  rõ   )vÚ__doc__Ú
__future__r   rZ   r–   ÚloggingÚosr¼   r&   ÚsysÚ	threadingr2   r¦   r   r   Úlogging.handlersr   Úpathlibr   Útypingr   r˜   Úflaskr	   r
   r   Ú__file__ÚresolveÚparentÚBASE_DIRÚLOG_FILEÚmkdirÚ	FormatterÚ_fmtÚ_file_handlerÚsetFormatterÚStreamHandlerÚstdoutÚ_stream_handlerÚbasicConfigÚINFOÚ	getLoggerr6   Údotenvr   ÚImportErrorÚenvfileÚpathÚexistsÚopenÚfr`   rM   Úliner  rL   rx   r{   Úenvironrt   r>   r   r'  r›   r   ÚcriticalÚexitrš   r)   r=   r?   r3   ÚLockr0   r-   r;   rE   rH   rP   rU   ra   r|   r’   r¡   r¯   r³   r¸   r¾   rÂ   rÆ   rÈ   rÊ   rÌ   rÎ   rù   r  r  Ú__name__Úappr  r  r  Úafter_requestr  Úrouter  r(  r    r™   r!   r"   r#   r1   rP  rO  r7   rõ   Úrunr  r.   r,   ú<module>r�     sß  ðñ'õR #ã Û Û Û 	Û 	Û Û 
Û Û Û ß 'Ý 0Ý Ý ã ß )Ñ )á�‹>×!Ñ!Ó#×*Ñ*€ñ
 Ð2Ó3€Ø ‡�× Ñ ˜d¨TÐ Ô 2à€w×ÑÐLÓM€Ù#ØÐ'°QÀô€ð × Ñ ˜4Ô  Ø'�'×'Ñ'¨¯
©
Ó3€Ø × Ñ ˜TÔ "Ø €× Ñ ˜'Ÿ,™,°-ÀÐ1QÕ RØ€g×Ñ˜
Ó#€ð
<Ý"ÙÐ3Ô4ð —:‘:—>‘>Ð"4°gÓ>Ð Ø—
‘
—‘Ð2°BÓ7×=Ñ=Ó?€Ø�Z‰Z�^‰^Ð-¨rÓ2×8Ñ8Ó:€
Ø—z‘z—~‘~Ð&<¸bÓA×GÑGÓIÐ á™JØ‡L�LÐPÔQØ€C‡H�HˆQ„Kð "Ð"2Ð!3°1°]°OÀ7ÐKð ð �[Ñ
 €ð Ø Ø Øñ	Ð ð Ð ð (Ð àˆ9�>‰>Ó€òó)óXóó,%ô!ó0óóH%óP
%ó Dó=ó%ó&ó
5ó
*ó5ó
&ó
%ó
-óhó\Wózqñn ˆHƒo€ðÐ ð
 ØðÐ ó
ð ×Ññó ðð ‡�ˆ: 	˜{€Ó+Ø‡�ˆ7˜Y˜K€Ó(Ø‡�ˆ;  €Ó,ñó -ó )ó ,ðð
 ‡�ˆÓñ	ó ð	ð ‡�ˆ; ¨ €Ó0ñ&Ró 1ð&RðR ‡�ˆ+ÓñJó ðJðZ ‡�ˆ'ÓñJó ðJðZ ‡�ˆ*ÓñLó ðLñd 	„
àˆzÒÙˆr�z‰z�~‰~˜f fÓ-Ó.€DØ�:‰:�>‰>˜& )Ó,€DØ‡H�HØuØØØÙÐ!Ó"ôð ‡G�G�˜D¨¸€GÕ=ð øð] ò 	<Ø1€GØ	‡w�w‡~�~�gÔÙ�' GÔ,ð 	<°Øò <�Ø—y‘y“{�Ù˜tŸ™¨sÔ3°sÀ$±ØØ—z‘z # qÓ)‘��1Ø—
‘
×%Ñ% a§g¡g£i°·±³Õ;ñ<÷	<÷ 	<ñ 	<ýð	<ús+   Ä-O! Ï!,R$ÐA=RÒ	R$ÒR	ÒR$Ò#R$