Ë
    düŽj=Q  ã            
      ó&	  — 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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«      j5                  «       j6                  Z ed	«      Zej6                  j=                  d
d
¬«        ej>                  d«      Z  eeddd¬«      Z!e!jE                  e «        ejF                  e	jH                  «      Z%e%jE                  e «        ejL                  ejN                  e!e%g¬«        ejP                  d«      Z)	 ddl*m+Z+  e+d«        e+d«        e+d«        ejv                  dd«      jg                  «       Z< ejv                  d d!«      jg                  «       Z= ejv                  d"d«      jg                  «       Z> ejv                  d#d$«      jg                  «       Z? ejv                  d%d«      jg                  «       Z@e> ZA ejv                  d&d'«      jg                  «       ZB e ejv                  d( eCed)z  «      «      «      ZD eE ejv                  d*d+«      «      ZF ejv                  d,d-«      ZGd.e?› d/e=› d0�ZHd1d1d1d1d2d2d3d3d4œZI e
j”                  «       ZKd5„ ZLdXd6„ZM	 	 	 	 	 	 dYd7„ZNdZd8„ZOd[d9„ZPd[d:„ZQdZd;„ZRd\d<„ZSdd=œd]d>„ZTd^d?„ZU	 d_	 	 	 d`d@„ZVdadA„ZW eeX«      ZYdbdB„ZZdcdC„Z[eYj¹                  dDdEg¬F«      dG„ «       Z]eYj¹                  dHdIg¬F«      dJ„ «       Z^eXdKk(  r e)j¿                  dL«       e)j¿                  dMe=«       e)j¿                  dNeAeArdOndP«       e)j¿                  dQe<rdPndR«       e)j¿                  dSe@xs dT«       e)j¿                  dUeD«       e)j¿                  dVeGeF«       eYjÁ                  eGeFd
¬W«       yy# e,$ rá dD ]Ø  Z-ej\                  j_                  e-«      sŒ e0e-d¬«      5 Z1e1D ]•  Z2e2jg                  «       Z4e4re4jk                  d«      sde4vrŒ+e4jm                  dd«      \  Z7Z8ejr                  ju                  e7jg                  «       e8jg                  «       jg                  d«      jg                  d«      «       Œ— 	 ddd«       ŒÎ# 1 sw Y   Œ×xY w Y �ŒHw xY w)dum  
Hotmart -> Meta CAPI (Conversions API) â€” Borrello / Passo a Passo da Radiestesia
================================================================================

Endpoint publico:  https://hotmart-webhook.agentesclimb.us/borrello
Porta local:       8950  (Traefik -> 172.18.0.1:8950)

Fluxo:
  1. Recebe POST da Hotmart (postback / webhook 2.0).
  2. Valida HOTTOK (header X-HOTMART-HOTTOK  ou  campo body 'hottok').
  3. Idempotencia por transaction_id em SQLite (dedupe defensivo â€” Hotmart
     reenvia o mesmo evento em caso de retry).
  4. Traduz o payload no evento Meta CAPI equivalente:
        - PURCHASE_APPROVED   -> Purchase (event_id = transaction_id)
        - PURCHASE_COMPLETE   -> Purchase (mesmo event_id -> dedupe local
                                 evita reenvio; se APPROVED nao chegou
                                 antes, este vira o primeiro Purchase)
        - PURCHASE_REFUNDED   -> Purchase com value negativo (opt_out=false)
                                 usando custom event 'Refund' (rec. Meta)
        - PURCHASE_CHARGEBACK -> Custom event 'Chargeback'
        - PURCHASE_CANCELED   -> ignorado (nunca virou venda)
  5. event_id = transaction_id da Hotmart (dedupe com pixel do browser).
  6. Envia pro Meta Graph API v21.0 e loga request+response.

Config em /opt/mia/config/meta_capi_borrello.env
Log em /opt/mia/logs/hotmart_capi_borrello.log
é    )ÚannotationsN)ÚdatetimeÚtimezone)ÚRotatingFileHandler)ÚPath)ÚAny)ÚFlaskÚjsonifyÚrequestz'/opt/mia/logs/hotmart_capi_borrello.logT)ÚparentsÚexist_okz1%(asctime)s [%(levelname)s] %(name)s: %(message)si    é   úutf-8)ÚmaxBytesÚbackupCountÚencoding)ÚlevelÚhandlersÚhotmart_capi)Úload_dotenvú/opt/mia/.envú&/opt/mia/config/meta_capi_borrello.envú$/opt/mia/config/hotmart_borrello.env)r   r   r   )r   ú#ú=é   ú"ú'ÚHOTMART_HOTTOKÚ ÚMETA_PIXEL_ID_BORRELLOÚ464623303880507ÚMETA_CAPI_TOKENÚMETA_API_VERSIONzv21.0ÚMETA_TEST_EVENT_CODEÚEVENT_SOURCE_URLz-https://passoapasso.franciscoborrello.com.br/Ú	DEDUPE_DBz	dedupe.dbÚPORTÚ8950ÚHOSTz0.0.0.0zhttps://graph.facebook.com/ú/z/eventsÚPurchaseÚRefundÚ
Chargeback)ÚAPPROVEDÚPURCHASE_APPROVEDÚCOMPLETEÚPURCHASE_COMPLETEÚREFUNDEDÚPURCHASE_REFUNDEDÚ
CHARGEBACKÚPURCHASE_CHARGEBACKc                 óŒ   — t        j                  t        t        «      «      } | j	                  d«       | j                  «        | S )NaO  
        CREATE TABLE IF NOT EXISTS processed_events (
            event_id       TEXT PRIMARY KEY,
            event_name     TEXT NOT NULL,
            transaction_id TEXT,
            received_at    INTEGER NOT NULL,
            meta_status    INTEGER,
            meta_response  TEXT,
            payload        TEXT
        )
    )Úsqlite3ÚconnectÚstrÚDB_PATHÚexecuteÚcommit)Úconns    ú8/opt/mia/workspace/clientes/borrello/hotmart_capi/app.pyÚ_db_connr@   †   s5   € Ü�?‰?œ3œw›<Ó(€DØ‡L�Lð 
ô 
	ð 	‡K�K„MØ€Kó    c                óÖ   — t         5  t        «       5 }|j                  d| f«      j                  «       }|d ucd d d «       cd d d «       S # 1 sw Y   nxY wd d d «       y # 1 sw Y   y xY w)Nz1SELECT 1 FROM processed_events WHERE event_id = ?)Ú_db_lockr@   r<   Úfetchone)Úevent_idr>   Úrows      r?   Úalready_processedrG   —   se   € Ü	ñ ”8“:ð  Ø�l‰lØ?ØˆKó
÷ ‰(‹*ð 	ð ˜$ˆ÷÷ ÷ ó ú÷ ÷ ñ ús!   ‡A’%A
·	AÁ
A	ÁAÁA(c                ó6  — t         5  t        «       5 }|j                  d| ||t        t	        j                  «       «      ||d d t        j                  |d¬«      d 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)NzËINSERT OR REPLACE INTO processed_events
               (event_id, event_name, transaction_id, received_at,
                meta_status, meta_response, payload)
               VALUES (?, ?, ?, ?, ?, ?, ?)i   F©Úensure_asciii N  )rC   r@   r<   ÚintÚtimeÚjsonÚdumpsr=   )rE   Ú
event_nameÚtransaction_idÚmeta_statusÚmeta_responseÚpayloadr>   s          r?   Úmark_processedrT       s�   € ô 
ñ 
”8“:ð 
 Ø�‰ð/ð �z >´3´t·y±y³{Ó3CØ˜-¨¨Ð.Ü�Z‰Z˜¨eÔ4°V°eÐ<ð>ô	
ð 	�‰Œ÷
÷ 
÷ 
ñ 
ú÷ 
ð 
ús#   ‡B’A BÁ2BÂB	ÂBÂBc                óž   — t        j                  | j                  «       j                  «       j	                  d«      «      j                  «       S )Nr   )ÚhashlibÚsha256ÚstripÚlowerÚencodeÚ	hexdigest©Úvs    r?   rW   rW   ³   s2   € Ü�>‰>˜!Ÿ'™'›)Ÿ/™/Ó+×2Ñ2°7Ó;Ó<×FÑFÓHÐHrA   c                ó@   — | syt        j                  dd| «      }|sy|S )zBMeta espera E.164 sem '+' nem separadores, lowercase, hash SHA256.r    z\D+)ÚreÚsub)ÚrawÚdigitss     r?   Ú
norm_phonerc   ·   s%   € áØÜ�V‰V�F˜B Ó$€FÙØØ€MrA   c                óD   — | sy| j                  «       j                  «       S ©Nr    )rX   rY   )ra   s    r?   Ú
norm_emailrf   Á   s   € ÙØØ�9‰9‹;×ÑÓÐrA   c                óF   — | xs dj                  «       } | syt        | «      S re   )rX   rW   r\   s    r?   Úhash_or_emptyrh   Ç   s"   € Ø	
Šˆb�‰Ó€AÙØÜ�!‹9ÐrA   c                ó.  — t        | j                  d«      t        «      rQ| j                  d«      xs) | d   j                  di «      j                  dd«      xs d}|j                  «       | d   fS | j                  dd«      xs dj                  «       | fS )a(  
    Retorna (status_raw, data).
    Suporta o formato do Postback 2.0 da Hotmart:
      { "id": "...", "event": "PURCHASE_APPROVED",
        "data": { "purchase": {...}, "buyer": {...}, "product": {...} } }
    E o formato de Postback legado (form-encoded flatten com 'prod', 'email', etc).
    ÚdataÚeventÚpurchaseÚstatusr    )Ú
isinstanceÚgetÚdictÚupper)rS   rm   s     r?   Úextract_eventrr   Ñ   s“   € ô �'—+‘+˜fÓ%¤tÔ,Ø—+‘+˜gÓ&ò Ø˜V‘_×(Ñ(¨°RÓ8×<Ñ<¸XÀrÓJòàð 	ð �|‰|‹~˜w v™Ð.Ð.ð �K‰K˜ "Ó%Ò+¨×2Ñ2Ó4°gÐ=Ð=rA   ©Údefaultc               ó˜   — |D ]D  }| }d}|j                  d«      D ]  }t        |t        «      r||vrd} n||   }Œ! |sŒ=|dvsŒB|c S  |S )z=Busca por dot-path aninhado: _get(d, 'purchase.transaction').Tú.Fre   )Úsplitrn   rp   )Údrt   ÚpathsÚpathÚcurÚokÚparts          r?   Ú_getr~   ä   sk   € àò 	ˆØˆØˆØ—J‘J˜s“Oò 	ˆDÜ˜c¤4Ô(¨D¸©OØ�ÙØ�d‘)‰Cð		ò
 �#˜ZÒ'ØŠJð	ð €NrA   c                ój  — | €t        t        j                  «       «      S t        | t         t        f«      r| dkD  rt        | dz  «      S t        | «      S t        | t        «      r?	 t        j                  | j                  dd«      «      }t        |j                  «       «      S t        t        j                  «       «      S # t        $ r Y nw xY wdD ]`  }	 t        j                  | |«      j                  t        j                  ¬«      }t        |j                  «       «      c S # t        $ r Y Œ^w xY w Œ’)z?Aceita ms (Hotmart 2.0), seconds, ISO string, dd/mm/aaaa hh:mm.g   ¢”mBiè  ÚZz+00:00)z%d/%m/%Y %H:%M:%Sz%d/%m/%Y %H:%Mz%d/%m/%Y)Útzinfo)rK   rL   rn   Úfloatr:   r   ÚfromisoformatÚreplaceÚ	timestampÚ	ExceptionÚstrptimer   Úutc)ÚtsÚdtÚfmt_strs      r?   Úto_unixrŒ   ó   s  € à	€zÜ”4—9‘9“;ÓÐÜ�"”sœE�lÔ#à!# d¢Œs�2˜‘9‹~Ð7´°B³Ð7Ü�"”cÔð	Ü×'Ñ'¨¯
©
°3¸Ó(AÓBˆBÜ�r—|‘|“~Ó&Ð&ô Œt�y‰y‹{ÓÐøô ò 	Ùð	úð Kò 	ˆGðÜ×&Ñ& r¨7Ó3×;Ñ;Ä8Ç<Á<Ð;ÓP�Ü˜2Ÿ<™<›>Ó*Ò*øÜò Ùðúð		øs%   Á%=C  Ã 	CÃCÃAD$Ä$	D0Ä/D0c                ó  — t         j                  | «      }|syt        t        |ddd¬«      «      j	                  «       }|s-t
        j                  dt        j                  |«      dd «       yt        t        |dd	d
dd¬«      «      }t        t        j                  «       «      }||dz
  dz   k  r|dz
  dz   }t        t        t        |ddd¬«      «      «      }t        t        |dddd¬«      «      }t        |«      }	t        t        |ddd¬«      «      j                  d«      d   }
t        t        |ddd¬«      «      j                  d«      dd }|rdj                  |«      nd}t        t        |ddd¬«      «      j!                  «       dd xs d}i }|rt#        |«      g|d<   |	rt#        |	«      g|d<   |
rt#        |
«      g|d<   |rt#        |«      g|d <   |rt#        |«      g|d!<   |xs i }|j                  d"«      xs t        |d#d$d%d¬«      }|j                  d&«      xs t        |d'd(d)d¬«      }|j                  d*«      xs t        |d+d,d¬«      }|j                  d-«      xs t        |d.d¬«      }|r||d"<   |r||d&<   |r||d*<   |r||d-<   t        |d/d0d1d2d¬«      }	 t%        |xs d«      }t        t        |d4d5d6d7¬«      «      j)                  «       dd8 xs d7}t        t        |d9d:d¬«      «      j	                  «       }t        t        |d;d<d¬«      «      j	                  «       }t        t        |d=d>d¬«      «      j	                  «       }|r)|r'|j!                  «       |j!                  «       vr|› d?|› �}|}|d@k(  rdA}t+        |«       }dB|› �}n|dCk(  rdA}t+        |«       }dD|› �}ndA}|}||dEt,        |||t/        |d«      dFœdGœ}|r	|g|dH   dI<   |r||dH   dJ<   dK|dH   dL<   dM|dH   dN<   |S # t&        $ r d3}Y �ŒSw xY w)Oz~
    Constroi 1 evento CAPI a partir do payload Hotmart.
    Retorna None se status nao mapeia (ignorar silenciosamente).
    Núpurchase.transactionÚtransactionr    rs   u'   Payload sem transaction_id â€” skip: %si�  zpurchase.order_datezpurchase.approved_datezpurchase.approvedDateÚpurchase_datei€:	 é<   zbuyer.emailÚemailzbuyer.checkout_phonezbuyer.phoneÚphonez
buyer.nameÚnameú r   r   zbuyer.address.country_isozbuyer.address.countryÚBRé   ÚbrÚemÚphÚfnÚlnÚcountryÚfbczpurchase.tracking.fbczpurchase.trackings.fbcÚsrc_fbcÚfbpzpurchase.tracking.fbpzpurchase.trackings.fbpÚsrc_fbpÚclient_ip_addresszpurchase.buyer_ipÚbuyer_ipÚclient_user_agentzpurchase.tracking.user_agentzpurchase.price.valuezpurchase.full_price.valuezpurchase.offer.price.valueÚpriceg        zpurchase.price.currency_valuezpurchase.price.currencyÚcurrencyÚBRLé   ú
product.idÚprodúproduct.nameÚ	prod_namezsubscription.plan.namezpurchase.subscription.plan.namez - r-   r,   Úrefund_r.   Úchargeback_Úwebsite)r¦   Úvalue)rO   Ú
event_timeÚaction_sourceÚevent_source_urlrE   Ú	user_dataÚcustom_datarµ   Úcontent_idsÚcontent_nameÚproductÚcontent_typeÚcurso_onlineÚcontent_category)ÚHANDLED_STATUSro   r:   r~   rX   ÚlogÚwarningrM   rN   rŒ   rK   rL   rf   rc   rw   ÚjoinrY   rW   r‚   r†   rq   Úabsr&   Úround)rm   rj   ÚtrackingrO   Útx_idÚts_unixÚnowr’   Ú	phone_rawr“   Ú
first_nameÚlast_name_partsÚ	last_namer�   r´   rž   r    ÚipÚuar°   r¦   Ú
product_idÚproduct_nameÚ	plan_namer±   Úevent_name_outrE   Úevs                               r?   Úbuild_capi_eventrÑ     sÏ  € ô  ×#Ñ# FÓ+€JÙØä”�TÐ1°=È"ÔMÓN×TÑTÓV€EÙÜ�‰Ð=Ü—J‘J˜tÓ$ T cÐ*ô	,àô ”d˜4Ø0Ø3Ø2Ø*Ø#'ô)ó *€Gô Œd�i‰i‹kÓ
€CØ��}Ñ$ rÑ)Ò)Ø˜Ñ%¨Ñ*ˆô ”sœ4  m°WÀbÔIÓJÓK€EÜ”D˜Ø/Ø&Ø Ø!#ô	%ó &€Iô
 �yÓ!€EÜ”T˜$ ¨f¸bÔAÓB×HÑHÈÓMÈaÑP€JÜœ$˜t \°6À2ÔFÓG×MÑMÈcÓRÐSTÐSUÐV€OÙ-<�—‘˜Ô)À"€IÜ”$�tÐ8Ø.Ø#ô%ó &ç&+¡e£g¨b¨qð2ò :à59ð ð !#€IÙÜ! %›=˜/ˆ	�$‰ÙÜ! %›=˜/ˆ	�$‰ÙÜ! *Ó-Ð.ˆ	�$‰ÙÜ! )Ó,Ð-ˆ	�$‰ÙÜ & w£Ð0ˆ	�)Ñð Š~˜2€HØ
�,‰,�uÓ
ò =¤ dÐ,CØ&>Ø&/¸ô"=€Cð �,‰,�uÓ
ò =¤ dÐ,CØ&>Ø&/¸ô"=€Cð 
�‰Ð)Ó	*ò 
?¬d°4Ø3FØ3=Ø;=ô/?€Bð 
�‰Ð)Ó	*ò 
?¬d°4Ø3QØ;=ô/?€Bñ Øˆ	�%ÑÙ
Øˆ	�%ÑÙ	Ø)+ˆ	Ð%Ñ&Ù	Ø)+ˆ	Ð%Ñ&ô �Ø'Ø,Ø-ØØô€EðÜ�e’j˜qÓ!ˆô ”4˜Ø7Ø1Ø"Ø %ô	'ó (÷ ).©«°°ð	4ò =ð 8=ð	 ô ”T˜$ ¨f¸bÔAÓB×HÑHÓJ€JÜ”t˜D .°+Ø$&ô(ó )ß).©«ð ô ”D˜Ð7Ø:Ø!#ô%ó &ç&+¡e£gð ñ ™	 i§o¡oÓ&7¸|×?QÑ?QÓ?SÑ&SØ&˜ s¨9¨+Ð6ˆð €JØ�XÒà#ˆÜ�U“�ˆØ˜U˜GÐ$‰Ø	�|Ò	#Ø#ˆÜ�U“�ˆØ   Ð(‰à#ˆØˆð %Ø Ø"Ü,ØØà Ü˜5 !“_ñ
ñ€Bñ Ø,6¨<ˆˆ=Ñ˜-Ñ(ÙØ,8ˆˆ=Ñ˜.Ñ)à(1€B€}Ñ�nÑ%Ø,:€B€}ÑÐ(Ñ)à€Iøôq ò Ø‹ðús   Ê'O; Ï;P
Ð	P
c                ó  — t         rAt        j                  d«       t        j                  dt	        j
                  | d¬«      «       yd| gi}t        r	t        |d<   	 t        j                  t        dt        i|d	¬
«      }t        j                  d|j                  |j                  d d «       |j                  |j                  fS # t        j                  $ r-}t        j                  d|«       dt        |«      fcY d }~S d }~ww xY w)NuL   STUB_MODE ativo (META_CAPI_TOKEN vazio). Nao envia â€” apenas loga o evento.zSTUB event body: %sFrI   )r   Ústubrj   Útest_event_codeÚaccess_tokené   )ÚparamsrM   ÚtimeoutzMeta CAPI response [%s]: %siô  zFalha ao chamar Meta CAPI: %séÿÿÿÿ)Ú	STUB_MODEr½   r¾   ÚinforM   rN   r%   ÚrequestsÚpostÚMETA_GRAPH_URLr#   Ústatus_codeÚtextÚRequestExceptionÚ	exceptionr:   )rk   ÚbodyÚrÚexcs       r?   Úsend_to_metaræ   ¡  sÛ   € ÝÜ�‰ð :ô 	;ä�‰Ð&¬¯
©
°5ÀuÔ(MÔNØà" U GÐ,€DÝÜ"6ˆÐÑðÜ�M‰MÜØ"¤OÐ4ØØô	
ˆô 	�‰Ð.Ø—‘ §¡ t¨ ô	.à�}‰}˜aŸf™fÐ$Ð$øÜ×$Ñ$ò Ü�‰Ð5°sÔ;Ø”3�s“8ˆ|Õûðús   ÁA(C ÃDÃ"DÃ;DÄDc                ó:  — | j                   j                  dd«      j                  «       }|r|S | j                  r4| j	                  d¬«      xs i j                  dd«      j                  «       S | j
                  j                  dd«      xs dj                  «       S )zDHotmart 2.0 = header X-HOTMART-HOTTOK. Legado = campo body 'hottok'.zX-HOTMART-HOTTOKr    T©ÚsilentÚhottok)Úheadersro   rX   Úis_jsonÚget_jsonÚform)ÚreqÚhdrs     r?   Ú_extract_hottokrñ   Á  s~   € à
�+‰+�/‰/Ð,¨bÓ
1×
7Ñ
7Ó
9€CÙ
Øˆ
Ø
‡{‚{Ø—‘ D�Ó)Ò/¨R×4Ñ4°X¸rÓB×HÑHÓJÐJØ�H‰H�L‰L˜ 2Ó&Ò,¨"×3Ñ3Ó5Ð5rA   c                óì   — | j                   j                  d| j                  xs d«      j                  d«      d   j	                  «       | j                   j                  dd«      j	                  «       dœS )z�Metadados HTTP do request (fbc/fbp normalmente nao vem no postback,
    mas se a landing tiver feito bind server-side, cai aqui).úX-Forwarded-Forr    ú,r   z
User-Agent)r¢   r¤   )rë   ro   Úremote_addrrw   rX   )rï   s    r?   Ú_extract_trackingrö   Ë  sc   € ð !Ÿ[™[Ÿ_™_Ð->Ø-0¯_©_Ò-BÀóDßDIÁEÈ#ÃJÈqñRßRWÑRWÓRYØ Ÿ[™[Ÿ_™_¨\¸2Ó>×DÑDÓFñð rA   z/healthÚGET)Úmethodsc            	     ól   — t        dt        t        t        t        «      t        t
        «      dœ«      dfS )Nr|   )rm   Ú	stub_modeÚpixel_idÚhottok_configuredÚcapi_token_configuredéÈ   )r
   rÚ   ÚMETA_PIXEL_IDÚboolÚHOTTOKr#   © rA   r?   Úhealthr  Õ  s6   € äØÜÜ!Ü!¤&›\Ü!%¤oÓ!6ñó ð 	ðð rA   z	/borrelloÚPOSTc                 óŒ  — t         s%t        j                  d«       t        dddœ«      dfS t	        t
        «      } | t         k7  r]t        j                  d| r| d d dz   nd	t
        j                  j                  d
t
        j                  «      «       t        dddœ«      dfS t        j                  d¬«      xs" t
        j                  j                  «       xs i }t        |«      \  }}t        t        |ddd¬«      xs d«      j!                  «       }t        t        |ddd¬«      xs d«      j!                  «       }t        t        |ddd¬«      xs d«      j!                  «       }t        j#                  d|j                  d«      xs |j                  d«      xs |||||j                  d«      t%        t'        j(                  |«      «      «       |st        j#                  d«       y|t*        vr&t        j#                  d|«       t        d|dœ«      dfS t-        t
        «      }t/        |||¬ «      }|st        dd!d"œ«      dfS |d#   }	t1        |	«      r&t        j#                  d$|	«       t        d|	d%œ«      dfS t3        |«      \  }
}t5        |	|d&   t        t        |ddd¬«      «      |
||«       t        d|	|
d'œ«      dfS )(Nu5   HOTMART_HOTTOK nao configurado â€” recusando request.FÚhottok_not_configured)r|   Úerrori÷  z%HOTTOK invalido. Recebido: %r  IP: %sé   z...z(vazio)ró   Úinvalid_hottoki‘  Trè   r©   rª   r    rs   r«   r¬   rŽ   r�   zI[recv] event=%s tx=%s product_id=%s product_name=%r hotmart_id=%s size=%drk   rm   Úidu   Sem status â€” 204.)r    éÌ   z'Status %s nao mapeado, ignorando (200).)r|   Úignoredrþ   )rÂ   Úno_event)r|   ÚskippedrE   u-   Dedupe: event_id %s ja processado â€” 200 OK.)r|   ÚdedupedrO   )r|   rE   rQ   )r  r½   r  r
   rñ   r   r¾   rë   ro   rõ   rí   rî   Úto_dictrr   r:   r~   rX   rÛ   ÚlenrM   rN   r¼   rö   rÑ   rG   ræ   rT   )ÚreceivedrS   rm   rj   Úprod_idr¬   ÚtxrÂ   rk   rE   rß   Úresponse_texts               r?   Úborrello_webhookr  à  s˜  € õ Ü�	‰	ÐIÔJÜ˜eÐ.EÑFÓGÈÐLÐLäœwÓ'€HØ”6ÒÜ�‰Ð;Ù,4�H˜R˜a�L 5Ò(¸)Ü—O‘O×'Ñ'Ð(9¼7×;NÑ;NÓOô	Qô ˜eÐ.>Ñ?Ó@À#ÐEÐEô ×Ñ dÔ+ÒK¬w¯|©|×/CÑ/CÓ/EÒKÈ€Gä  Ó)�L€FˆDÜ”$�t˜\¨6¸2Ô>ÒDÀ"ÓE×KÑKÓM€GÜ”D˜˜~¨{ÀBÔGÒMÈ2ÓN×TÑTÓV€IÜ	ŒT�$Ð.°ÀrÔJÒPÈbÓ	Q×	WÑ	WÓ	Y€BÜ‡H�HÐXØ�[‰[˜Ó!ÒD W§[¡[°Ó%:ÒD¸fØØØØ�[‰[˜ÓÜ”—‘˜GÓ$Ó%ô'ñ Ü�‰Ð&Ô'Øà”^Ñ#Ü�‰Ð:¸FÔCÜ˜d¨vÑ6Ó7¸Ð<Ð<ô !¤Ó)€HÜ˜V T°HÔ=€EÙÜ˜d¨zÑ:Ó;¸SÐ@Ð@à�ZÑ €Hô ˜Ô"Ü�‰Ð@À(ÔKÜ˜d¨xÑ8Ó9¸3Ð>Ð>ä!-¨eÓ!4Ñ€K�Ü�8˜U <Ñ0Ü”t˜DÐ"8¸-Ø$&ô(ó )à ¨wô8ô ØØØ"ñó ð 	ð	ð rA   Ú__main__z=== Hotmart CAPI Borrello ===zPixel:        %sz!STUB_MODE:    %s  (CAPI token %s)ÚvazioÚconfiguradozHOTTOK:       %sÚAUSENTEzTest event:   %sz(prod)zDB dedupe:    %szBind:         %s:%d)ÚhostÚportÚthreaded)rE   r:   Úreturnr   )rE   r:   rO   r:   rP   r:   rQ   z
int | NonerR   r:   rS   údict[str, Any])r]   r:   r  r:   )ra   r:   r  r:   )rS   r  r  ztuple[str, dict[str, Any]])rx   rp   )r‰   r   r  rK   )N)rm   r:   rj   r  rÂ   zdict[str, str] | Noner  zdict[str, Any] | None)rk   r  r  ztuple[int, str])r  r:   )r  zdict[str, str])aÚ__doc__Ú
__future__r   rV   rM   ÚloggingÚosr_   r8   ÚsysÚ	threadingrL   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Ú	getLoggerr½   Údotenvr   ÚImportErrorÚenvfilerz   ÚexistsÚopenÚfra   rX   ÚlineÚ
startswithrw   Úkr]   ÚenvironÚ
setdefaultÚgetenvr  rÿ   r#   r$   r%   rÚ   r&   r:   r;   rK   r(   r*   rÞ   r¼   ÚLockrC   r@   rG   rT   rW   rc   rf   rh   rr   r~   rŒ   rÑ   ræ   Ú__name__Úapprñ   rö   Úrouter  r  rÛ   Úrunr  rA   r?   ú<module>rK     sÃ  ðñõ8 #ã Û Û Û 	Û 	Û Û 
Û Û ß 'Ý 0Ý Ý ã ß )Ñ )á�‹>×!Ñ!Ó#×*Ñ*€ñ
 Ð9Ó:€Ø ‡�× Ñ ˜d¨TÐ Ô 2à€g×ÑÐKÓL€Ù" 8Ð6FØ/0¸7ôD€à × Ñ ˜#Ô Ø&�×&Ñ& s§z¡zÓ2€Ø × Ñ ˜CÔ  Ø €× Ñ ˜'Ÿ,™,°,ÀÐ1OÕ PØ€g×Ñ˜Ó'€ð
RÝ"Ù�Ô ÙÐ8Ô9ÙÐ6Ô7ð$ 
ˆ�‰Ð# RÓ	(×	.Ñ	.Ó	0€à�—	‘	Ð2Ð4EÓF×LÑLÓN€Ø�"—)‘)Ð-¨rÓ2×8Ñ8Ó:€Ø�2—9‘9Ð/°Ó9×?Ñ?ÓAÐ Ø �r—y‘yÐ!7¸Ó<×BÑBÓDÐ ð  Ð€	à�2—9‘9ØØ3ó÷ �%ƒ'ð ñ
 ˆyˆr�y‰y˜¡c¨(°[Ñ*@Ó&AÓBÓ
C€Ù
ˆ9ˆ2�9‰9�V˜VÓ$Ó%€Ø€r‡y�y�˜Ó#€ð "Ð"2Ð!3°1°]°OÀ7ÐKð ð Ø#ØØ#ØØ!ØØ'ñ	€ð ˆ9�>‰>Ó€òó"ðØ *ðØ;>ðà*óó&Ióóóó>ð& #'õ óð2 8<ðPØ4ðPØ@UóPólñ: ˆHƒo€ó6óð ‡�ˆ9˜u˜g€Ó&ñó 'ðð ‡�ˆ;  €Ó)ñ<ó *ð<ðD ˆzÒØ‡H�HÐ,Ô-Ø‡H�HÐ Ô/Ø‡H�HÐ0Ø¡9™°-ôAà‡H�HÐ±&¡¸iÔHØ‡H�HÐÐ!5Ò!A¸ÔBØ‡H�HÐ Ô)Ø‡H�HÐ" D¨$Ô/Ø‡G�G�˜D¨4€GÕ0ð øðs ò Rð<ò Rˆð �w‰w�~‰~˜gÔ&ØÙ�' GÔ,ð 	R°Øò R�Ø—y‘y“{�Ù˜tŸ™¨sÔ3°sÀ$±ØØ—z‘z # qÓ)‘��1Ø—
‘
×%Ñ% a§g¡g£i°·±³·±ÀÓ1E×1KÑ1KÈCÓ1PÕQñR÷	R÷ 	Rñ 	RúóRðRús+   Ä)N* Î*0RÏBQ?Ñ6	RÑ?RÒRÒR