Ë
    ½9j$-  ã                  óœ   — d Z ddlmZ ddlZddlZddlmZ ddlm	Z	m
Z
mZ  ej                  e«      ZdZdZdZd	Zd
ZdZdZdZ G d„ d«      Zy)uÞ   E-mail notifications for status-67 (Dopasowano) leads via SendGrid.

Sends SEPARATE mail per operator address â€” recipients never see each other.
Failures are logged and swallowed so the pipeline continues uninterrupted.
é    )ÚannotationsN)ÚSettings)ÚMatchResultÚ	PartQueryÚPostz#2563ebz#1877F2z#16a34az#6b7280z#f3f4f6z#f9fafbz#e5e7ebz#111827c                  ó¬   — e Zd ZdZdd„Zedd„«       Z	 	 	 	 	 	 	 	 	 	 	 	 dd„Zdd„Z	 	 	 	 	 	 	 	 	 	 dd„Z	dd„Z
edd„«       Zedd	„«       Zedd
„«       Zy)ÚMatchNotifierzDSendGrid notifier for matched leads. Safe to use even without a key.c                óz  — |j                   | _        |j                  | _        |j                  j                  d«      D �cg c]#  }|j                  «       sŒ|j                  «       ‘Œ% c}| _        |j                  | _	        |j                  j                  d«      | _        d| _        t        «       | _        y c c}w )Nú,ú/r   )Úsendgrid_api_keyÚ_api_keyÚnotify_email_fromÚ_from_emailÚnotify_email_toÚsplitÚstripÚ
_to_emailsÚnotify_max_per_cycleÚ_max_per_cycleÚdgred_base_urlÚrstripÚ_dgred_baseÚ_sent_countÚsetÚ_notified_posts)ÚselfÚsettingsÚes      úG/var/www/html/agent.samochodowy/src/agent_samochodowy/dgred/notifier.pyÚ__init__zMatchNotifier.__init__   s“   € Ø ×1Ñ1ˆŒØ#×5Ñ5ˆÔà'×7Ñ7×=Ñ=¸cÓBö
ØÀaÇgÁgÅiˆA�G‰G�Iò
ˆŒð '×;Ñ;ˆÔØ#×2Ñ2×9Ñ9¸#Ó>ˆÔØˆÔÜ),«ˆÕùò
s   Á B8ÁB8c                óH   — t        | j                  xr | j                  «      S )N)Úboolr   r   )r   s    r    ÚenabledzMatchNotifier.enabled*   s   € ä�D—M‘MÒ5 d§o¡oÓ6Ð6ó    c                óœ  — | j                   st        j                  d«       y|j                  | j                  v r!t        j                  d|j                  «       y| j
                  | j                  k\  r7t        j                  d| j
                  | j                  |j                  «       y|j                  r|j                  d   nd}| j                  |«      }| j                  |||||«      }d}	| j                  D ]  }
	 | j                  |
||«       Œ | j                  j                  |j                  «       | xj
                  d	z  c_        t        j!                  d
|j                  t#        | j                  «      | j
                  | j                  «       |	S # t        $ r& t        j                  d|j                  |
«       d}	Y ŒÍw xY w)zBSend notification for a Dopasowano lead. Returns True if all sent.z,Notifier disabled (no API key or recipients)Fz&Already notified for post %s, skippingz7Notification throttle reached (%d/%d), skipping post %sr   NTu/   SendGrid error for post %s to %s â€” continuingé   z8Notification sent for post %s to %d recipient(s) (%d/%d))r$   ÚloggerÚdebugÚpost_idr   r   r   ÚwarningÚoffersÚ_build_subjectÚ_build_htmlr   Ú_send_singleÚ	ExceptionÚ	exceptionÚaddÚinfoÚlen)r   ÚpostÚqueryÚresultÚ	client_idÚ
reply_textÚ	top_offerÚsubjectÚ	body_htmlÚall_okÚ	recipients              r    Únotify_matchzMatchNotifier.notify_match.   s„  € ð �|Š|Ü�L‰LÐGÔHØà�<‰<˜4×/Ñ/Ñ/Ü�L‰LÐAÀ4Ç<Á<ÔPØà×Ñ˜t×2Ñ2Ò2Ü�N‰NØIØ× Ñ  $×"5Ñ"5°t·|±|ôð à(.¯ª�F—M‘M !Ò$¸4ˆ	Ø×%Ñ% eÓ,ˆØ×$Ñ$ T¨5°)¸YÈ
ÓSˆ	àˆØŸ™ò 	ˆIðØ×!Ñ! )¨W°iÕ@ð	ð 	×Ñ× Ñ  §¡Ô.Ø×Ò˜AÑÕÜ�‰ØFØ�L‰Lœ#˜dŸo™oÓ.°×0@Ñ0@À$×BUÑBUô	
ð ˆøô ò Ü× Ñ ØEØ—L‘L )ôð ’ðús   ÄFÆ,GÇ
Gc                óÄ   — |j                   xs d}|j                  |j                  fD �cg c]  }|sŒ|‘Œ	 }}|rdj                  |«      nd}|rd|› d|› �S d|› �S c c}w )Nõ   czÄ™Å›Ä‡ú Ú zNowe dopasowanie: )ÚcategoryÚbrandÚmodelÚjoin)r   r6   ÚpartÚpÚvehicle_partsÚvehicles         r    r-   zMatchNotifier._build_subjecta   sm   € Ø�~‰~Ò+ ˆØ%*§[¡[°%·+±+Ð$>ÖD˜qÂ!šÐDˆÐDÙ-:�#—(‘(˜=Ô)ÀˆÙØ'¨ v¨Q¨w¨iÐ8Ð8Ø# D 6Ð*Ð*ùò	 Es
   «A³Ac                ól  — t         j                  }| j                  j                  dd«      › d|› �} ||j                  xs d«      }|j
                  |j                  fD �	cg c]  }	|	sŒ|	‘Œ	 }
}	|
r |dj                  |
«      «      nd}|› d|› �j                  «       }|j
                  |j                  |j                  fD �	cg c]  }	|	sŒ|	‘Œ	 }}	|r |dj                  |«      «      nd}|j                  r! |dj                  |j                  «      «      nd}|j                  xs d}|r| j                  d|t        «      nd	}|j                  r!| j                  d
|j                  t        «      nd}d}|r�| j!                  |«      }|j"                  xs d}|r| j                  d|t$        «      nd}dt&        › dt(        › dt        › dt*        › d ||j,                  «      › dt*        › d ||«      › d|› d�}dt        › dt.        › dt*        › d ||«      › d�	}dj                  g d‘ ||«      › ‘d‘t0        › ‘d‘t0        › ‘d‘t        › ‘d‘t*        › ‘d‘|› ‘d ‘t(        › ‘d!‘t        › ‘d"‘ ||j2                  «      › ‘d#‘t*        › ‘d‘ ||j4                  «      › ‘d$‘t*        › ‘d%‘ ||j6                  «      › ‘d&‘t        › ‘d'‘|› ‘d(‘|› ‘d)‘|› ‘d*‘|› ‘d+‘t(        › ‘d,‘|› ‘d-‘|› ‘d.‘t(        › ‘d/‘| j                  d0|t.        «      › ‘d1‘t(        › ‘d2‘t        › ‘d3‘«      S c c}	w c c}	w )4Nz/api/v1rC   z/client/rA   rB   u   â€”z, u   OtwÃ³rz post na FacebookuzQ<div style="color:#dc2626;font-size:14px;padding:8px 0">Brak linku do posta</div>zProfil autorau   Zobacz ofertÄ™z}
<!--[if mso]><table width="100%"><tr><td><![endif]-->
<table width="100%" cellpadding="0" cellspacing="0" style="background:z;border:1px solid z–;border-radius:8px;margin:16px 0 8px">
<tr><td style="padding:20px">
  <div style="font-size:12px;text-transform:uppercase;letter-spacing:0.5px;color:za;margin-bottom:10px">Dopasowana oferta</div>
  <div style="font-size:15px;line-height:1.45;color:z+;margin-bottom:12px;word-break:break-word">z:</div>
  <div style="font-size:28px;font-weight:700;color:z;margin-bottom:16px">z	</div>
  z@
</td></tr>
</table>
<!--[if mso]></td></tr></table><![endif]-->zª
<table width="100%" cellpadding="0" cellspacing="0" style="margin:16px 0 8px">
<tr><td>
  <div style="font-size:12px;text-transform:uppercase;letter-spacing:0.5px;color:zn;margin-bottom:8px">Gotowa propozycja odpowiedzi</div>
  <div style="background:#eff6ff;border-left:3px solid z8;padding:14px 16px;font-size:15px;line-height:1.5;color:z2;border-radius:0 6px 6px 0;word-break:break-word">z</div>
</td></tr>
</table>z‰<!DOCTYPE html>
<html lang="pl"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>z;</title></head>
<body style="margin:0;padding:0;background:zÉ;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Arial,sans-serif;-webkit-text-size-adjust:100%">

<!-- Wrapper -->
<table width="100%" cellpadding="0" cellspacing="0" style="background:aW  ">
<tr><td style="padding:20px 12px" align="center">

<!-- Card -->
<table width="100%" cellpadding="0" cellspacing="0" style="background:#ffffff;border-radius:10px;max-width:560px;overflow:hidden">

  <!-- Header -->
  <tr><td style="padding:24px 24px 20px">
    <div style="font-size:12px;text-transform:uppercase;letter-spacing:0.5px;color:z`;margin-bottom:4px">Nowe dopasowanie</div>
    <div style="font-size:22px;font-weight:700;color:z;line-height:1.3">zj</div>
  </td></tr>

  <!-- Divider -->
  <tr><td style="padding:0 24px"><div style="border-top:1px solid z¡"></div></td></tr>

  <!-- Zapytanie -->
  <tr><td style="padding:20px 24px">
    <div style="font-size:12px;text-transform:uppercase;letter-spacing:0.5px;color:z';margin-bottom:10px">Zapytanie z grupy z</div>
    <div style="background:#fffbeb;border-left:3px solid #f59e0b;padding:14px 16px;font-size:15px;line-height:1.5;color:z‚</div>
    <table width="100%" cellpadding="0" cellspacing="0" style="margin-top:14px">
      <tr><td style="font-size:15px;color:z;padding-bottom:4px"><strong>z></strong></td></tr>
      <tr><td style="font-size:13px;color:z;padding-bottom:14px">Pojazd: z &nbsp;&middot;&nbsp; OE: z</td></tr>
      <tr><td>z1</td></tr>
      <tr><td style="padding-top:6px">z{</td></tr>
    </table>
  </td></tr>

  <!-- Divider -->
  <tr><td style="padding:0 24px"><div style="border-top:1px solid z`"></div></td></tr>

  <!-- Oferta + Propozycja -->
  <tr><td style="padding:8px 24px 20px">
    z
    zd
  </td></tr>

  <!-- Divider -->
  <tr><td style="padding:0 24px"><div style="border-top:1px solid z["></div></td></tr>

  <!-- CTA -->
  <tr><td style="padding:20px 24px" align="center">
    u   OtwÃ³rz lead w dgredzY
  </td></tr>

  <!-- Footer -->
  <tr><td style="padding:16px 24px;border-top:1px solid z(">
    <div style="font-size:12px;color:z¬;text-align:center">Agent Samochodowy &middot; powiadomienie automatyczne</div>
  </td></tr>

</table>
<!-- /Card -->

</td></tr>
</table>
<!-- /Wrapper -->

</body></html>)Úhtml_modÚescaper   ÚreplacerD   rE   rF   rG   r   ÚyearÚ
oe_numbersÚpost_urlÚ
_btn_blockÚ_CLR_FBÚauthor_profile_urlÚ
_CLR_MUTEDÚ_format_priceÚurlÚ
_CLR_GREENÚ	_CLR_CARDÚ_CLR_BORDERÚ	_CLR_TEXTÚtitleÚ_CLR_PRIMARYÚ_CLR_BGÚgroupÚtextÚauthor_name)r   r5   r6   r:   r8   r9   r   Ú
dgred_linkrH   rI   rJ   rK   Úheader_titleÚvehicle_fullÚvehicle_strÚoe_strrR   Úpost_btnÚprofile_btnÚ
offer_htmlÚ	price_strÚ	offer_urlÚsee_btnÚ
reply_htmls                           r    r.   zMatchNotifier._build_htmlm   sq  € ô �O‰OˆØ×(Ñ(×0Ñ0°¸BÓ?Ð@ÀÈÈÐTˆ
á�—‘Ò- :Ó.ˆØ%*§[¡[°%·+±+Ð$>ÖD˜qÂ!šÐDˆÐDÙ0=‘!�C—H‘H˜]Ó+Ô,À2ˆØ˜˜q  	Ð*×0Ñ0Ó2ˆà$)§K¡K°·±¸e¿j¹jÐ#IÖO˜aÊQšÐOˆÐOÙ3?‘a˜Ÿ™ Ó.Ô/ÀUˆØ38×3CÒ3C‘�4—9‘9˜U×-Ñ-Ó.Ô/Èˆð —=‘=Ò& Bˆñ ð �O‰OÐ7¸Ä7ÔKàdð 	ð ×&Ò&ð �O‰O˜O¨T×-DÑ-DÄjÔQØ,.ð 	ð ˆ
ÙØ×*Ñ*¨9Ó5ˆIØ!Ÿ™Ò+¨ˆIÙR[�d—o‘oÐ&6¸	Ä:ÔNÐacˆGðGäGPÀkÐQcÔdoÐcpð qRäR\ÐQ]ð ^5Ü5>°KÐ?jÑklÐmv×m|Ñm|Ók}Ðj~ð 4Ü4=°;Ð>SÑTUÐV_ÓT`ÐSað bØ
€)ð ,ð
/ˆJðRô S]ÐQ]ð ^8Ü8D°~ÐE}ô  Hð  ~Ið  I{ñ  |}ð  ~Hó  |Ið  {Jð J	ð	ˆ
÷>ó >ð ð >á	ˆ,‹Ðð>ð,ð>ô -4¨9ð>ð5Gð>ô HOÀið>ðPTð>ô U_ÐS_ð>ð`6ð>ô 7@°[ð>ð ASð>ð T`ÐR`ð>ðaCð>ô& DOÀ-ð'>ð&PTð'>ô. U_ÐS_ð/>ð. `Gð/>ñ. HIð  JN÷  JTñ  JTó  HUð  GVð/>ð.Vyð/>ô0 zCð  yDð1>ð0 Dvð1>ñ0 wxð  y}÷  yBñ  yBó  wCð  vDð1>ð0D+ð1>ô4 ,5¨+ð5>ð4 6Sð5>ñ4 TUÐUY×UeÑUeÓSfÐRgð5>ð4h+ð5>ô6 ,6¨,ð7>ð6 7Uð7>ð6 VaÐTað7>ð6 b|ð7>ð6 }Cð  |Dð7>ð6Dð7>ð8 ˆjð9>ð8'ð9>ð: (3 mð;>ð:4Cð;>ôD DOÀ-ðE>ðDPðE>ðL €LðM>ðLðM>ðN €LðO>ðNCðO>ôV DOÀ-ðW>ðVPðW>ð^ 
‡_�_Ð+¨Z¼ÓFÐGð_>ð^H9ð_>ôf :E¸ðg>ðfF&ðg>ôh '1 \ði>ðh
2ôi>ð >	ùòc Eùò Ps   Á"L,Á*L,ÃL1ÃL1c                ó  — ddl m} ddlm}m} | j                  | j                  «      } |||||¬«      } || j                  «      }	|	j                  |«      }
|
j                  dk\  r%t        d|
j                  › d|
j                  › �«      ‚y)	z3Send one mail to one recipient via SendGrid v3 API.r   )ÚSendGridAPIClient)ÚEmailÚMail)Ú
from_emailÚ	to_emailsr;   Úhtml_contenti�  zSendGrid HTTP z: N)Úsendgridrp   Úsendgrid.helpers.mailrq   rr   Ú_parse_emailr   r   ÚsendÚstatus_codeÚRuntimeErrorÚbody)r   r>   r;   ru   rp   rq   rr   rs   ÚmessageÚsgÚresponses              r    r/   zMatchNotifier._send_singleî   s�   € å.ß5à×&Ñ& t×'7Ñ'7Ó8ˆ
ÙØ!ØØØ%ô	
ˆñ ˜tŸ}™}Ó-ˆØ—7‘7˜7Ó#ˆØ×Ñ 3Ò&ÜØ  ×!5Ñ!5Ð 6°b¸¿¹¸ÐHóð ð 'r%   c                óú   — ddl m} | j                  «       } d| v rZ| j                  d«      rI| j	                  dd«      \  }} ||j                  d«      j                  «       |j                  «       «      S  || «      S )z@Parse 'Display Name <addr>' or plain 'addr' into SendGrid Email.r   )rq   ú<ú>r'   )rw   rq   r   ÚendswithÚrsplitr   )Úrawrq   ÚnameÚaddrs       r    rx   zMatchNotifier._parse_email  sg   € õ 	0à�i‰i‹kˆØ�#‰:˜#Ÿ,™, sÔ+ØŸ™ C¨Ó+‰JˆD�$Ù˜Ÿ™ SÓ)×/Ñ/Ó1°4·:±:³<Ó@Ð@Ù�S‹zÐr%   c                ó@   — d|› d|› dt        j                  | «      › d�S )uB   Full-width block button â€” works on mobile without media queries.zT<table width="100%" cellpadding="0" cellspacing="0"><tr><td align="center"><a href="z"" style="display:block;background:z¤;color:#ffffff;padding:14px 24px;text-decoration:none;border-radius:6px;font-size:15px;font-weight:600;text-align:center;line-height:1.4;mso-padding-alt:14px 24px">z</a></td></tr></table>)rM   rN   )ÚlabelrX   Úcolors      r    rS   zMatchNotifier._btn_block  s:   € ðØ�uÐ>¸u¸gð F*ô +3¯/©/¸%Ó*@Ð)Að B!ð	"ð	
r%   c                óØ   — | j                   �^| j                  xs d}| j                   t        | j                   «      k(  rt        | j                   «      › d|› �S | j                   d›d|› �S y)NÚPLNrB   z.2fzdo uzgodnienia)ÚpriceÚcurrencyÚint)ÚofferÚcurs     r    rW   zMatchNotifier._format_price  se   € à�;‰;Ð"Ø—.‘.Ò) EˆCØ�{‰{œc %§+¡+Ó.Ò.Ü˜eŸk™kÓ*Ð+¨1¨S¨EÐ2Ð2Ø—k‘k #Ð& a¨ uÐ-Ð-Ør%   N)r   r   ÚreturnÚNone)r’   r#   )r5   r   r6   r   r7   r   r8   ú	int | strr9   Ústrr’   r#   )r6   r   r’   r•   )
r5   r   r6   r   r8   r”   r9   r•   r’   r•   )r>   r•   r;   r•   ru   r•   r’   r“   )r…   r•   r’   z'Email')r‰   r•   rX   r•   rŠ   r•   r’   r•   )r’   r•   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r!   Úpropertyr$   r?   r-   r.   r/   Ústaticmethodrx   rS   rW   © r%   r    r	   r	      sà   „ ÙNó	/ð ò7ó ð7ð-àð-ð ð-ð ð	-ð
 ð-ð ð-ð 
ó-óf+ð{àð{ð ð{ð
 ð{ð ð{ð 
ó{óBð& òó ðð ò	
ó ð	
ð ò ó ñ r%   r	   )r™   Ú
__future__r   ÚhtmlrM   ÚloggingÚagent_samochodowy.configr   Úagent_samochodowy.modelsr   r   r   Ú	getLoggerr–   r(   r^   rT   rY   rV   r_   rZ   r[   r\   r	   rœ   r%   r    ú<module>r£      sf   ðñõ #ã Û å -ß AÑ Aà	ˆ×	Ñ	˜8Ó	$€ð €Ø
€Ø€
Ø€
Ø
€Ø€	Ø€Ø€	÷C ò C r%   