+
    kHàjœž  ã                  ód  € R t ^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	H
t
 ^ RIHt ^ RIHtHtHtHtHt ^ RIHtHt ^ RIHt ^ RIHt ^ R	IHtHtHt ^ R
IHtH t  ^ RI!H"t#H$t%H&t'H(t)H*t* ]PV                  ! ],4      t-]].]/]3,          ,          t0Rt1RRRRRRRR/t2RR/t3RRRut4t5t6Rt7R] Pp                  3R] Pr                  33t:RRRR/t;R R lt<R  R! lt=R" R# lt>R$ R% lt?R& R' lt@R( R) ltAR* R+ ltB ! R, R-]4      tCR.RR/RR0R1/R2 R3 lltDR4 R5 ltER=tFR6 R7 ltG]%! R8R94      tHR:tIR; R< ltJR# )>u  Mattermost gateway adapter â€” REST API v4 + WebSocket via aiohttp (no Mattermost SDK).

Environment variables:
    MATTERMOST_URL              Server URL (e.g. https://mm.example.com)
    MATTERMOST_TOKEN            Bot token or personal-access token
    MATTERMOST_ALLOWED_USERS    Comma-separated user IDs
    MATTERMOST_HOME_CHANNEL     Channel ID for cron/notification delivery
)ÚannotationsN)ÚPath)Úunquote)ÚAnyÚDictÚListÚOptionalÚTuple)ÚPlatformÚPlatformConfig)ÚMessageDeduplicator)Úcancel_task)Úgateway_trust_envÚBasePlatformAdapterÚ
SendResult)ÚMessageEventÚMessageType)Úapply_yaml_bridgeÚenv_is_connectedÚextra_or_secretÚget_scoped_secretÚ
send_errori   ÚDÚdmÚGÚgroupÚPÚOÚchannelÚdisable_mentionsTg       @g      N@gš™™™™™É?zFailed to post with fileúimage/úaudio/ú.pngz.oggc               ó    € V ^8„  d   QhRRRR/# )é   Úpayloadúdict[str, Any]Úreturn© )Úformats   "ÚI/home/ubuntu/.hermes/hermes-agent/plugins/platforms/mattermost/adapter.pyÚ__annotate__r+   4   s   € ÷ ñ  ^ð ¸ñ ó    c                ó†   € V P                  R4      \        r!\        V\        4      '       d   / VCVCM
\        V4      V R&   V # )zDReturn a post payload that prevents Mattermost from firing mentions.Úprops)ÚgetÚ"_MATTERMOST_DISABLE_MENTIONS_PROPSÚ
isinstanceÚdict)r%   r.   Údisables   &  r*   Ú_with_mentions_disabledr4   4   s@   € à—[‘[ Ó)Ô+Mˆ7Ü/9¸%Ä×/FÒ/FÐ+˜%Ð+ 7Ñ+ÌDÐQXËM€GˆGÑØ€Nr,   c               ó    € V ^8„  d   QhRRRR/# )r$   Úrawr   r'   Úsetr(   )r)   s   "r*   r+   r+   ;   s   € ÷ =ñ =˜ð = ñ =r,   c                ó  € \        V \        4      '       d   T M\        V 4      P                  R4      pV Uu0 uF=  p\        V4      P	                  4       '       g   K$  \        V4      P	                  4       kK?  	  up# u upi )zJParse a list or comma-separated string of channel IDs into a stripped set.Ú,)r1   ÚlistÚstrÚsplitÚstrip)r6   ÚitemsÚcs   &  r*   Ú_channel_id_setr@   ;   sR   € ä˜c¤4×(Ò(‰C¬c°#«h¯n©n¸SÓ.A€EÙ$)Ó<¡E˜q¬S°«V¯\©\¯^ŒNŒC�‹F�L‰LŽN¡EÑ<Ð<ùÒ<s   ·!A=ÁA=c               ó$   € V ^8„  d   QhRRRRRR/# )r$   Údatar&   Úerrorr;   r'   r   r(   )r)   s   "r*   r+   r+   A   s!   € ÷ ;ñ ;�~ð ;¨cð ;°jñ ;r,   c                ób   € V '       d   R V 9  d   \        RVR7      # \        RV R ,          R7      # )ÚidF©ÚsuccessrC   T©rG   Ú
message_id)r   )rB   rC   s   &&r*   Ú_post_resultrJ   A   s*   € ß�4˜tÔ#Ü %¨uÔ5Ð5Ü˜d¨t°D­zÔ:Ð:r,   c               ó$   € V ^8„  d   QhRRRRRR/# )r$   Úurlr;   Úfallbackr'   r(   )r)   s   "r*   r+   r+   G   s!   € ÷ <ñ <�sð < cð <¨cñ <r,   c                ót   € V P                  R ^4      R,          P                  R4      ^ ,          ;'       g    T# )Ú/Ú?éÿÿÿÿ)Úrsplitr<   )rL   rM   s   &&r*   Ú_url_filenamerS   G   s0   € Ø�:‰:�c˜1Ó˜bÕ!×'Ñ'¨Ó,¨QÕ/×;Ð;°8Ð;r,   c               ó   € V ^8„  d   QhRR/# )r$   r'   ztuple[str, str]r(   )r)   s   "r*   r+   r+   K   s   € ÷ Zñ Z˜oñ Zr,   c                ó¼   € \        V R/ 4      ;'       g    / pVP                  R4      ;'       g    \        RR4      \        V RR4      ;'       g    \        RR4      3# )zV(server URL, token): ``config`` first, MATTERMOST_URL / MATTERMOST_TOKEN env fallback.ÚextrarL   ÚMATTERMOST_URLÚ ÚtokenNÚMATTERMOST_TOKEN)Úgetattrr/   Ú_get_scoped_secret)ÚconfigrV   s   & r*   Ú_url_and_tokenr^   K   s_   € ä�F˜G RÓ(×.Ð.¨B€EØ�I‰I�eÓ×HÐHÔ 2Ð3CÀRÓ HÜ�F˜G TÓ*×XÐXÔ.@ÐASÐUWÓ.XðZð Zr,   c               ó   € V ^8„  d   QhRR/# ©r$   r'   Úboolr(   )r)   s   "r*   r+   r+   R   s   € ÷ ñ  tñ r,   c                 ó^   €  ^ RI p R#   \         d    \        P                  R4        R# i ; i)zFReturn True if the Mattermost adapter runtime dependency is available.NTz!Mattermost: aiohttp not installedF)ÚaiohttpÚImportErrorÚloggerÚwarning)rc   s    r*   Úcheck_mattermost_requirementsrg   R   s,   € ðÛÙøÜô Ü�‰Ð:Ô;Úðús   ‚ ˆ ,«,c               ó    € V ^8„  d   QhRRRR/# )r$   r]   r   r'   ra   r(   )r)   s   "r*   r+   r+   \   s   € ÷ 	ñ 	 ~ð 	¸$ñ 	r,   c                óÔ   € \        V 4      w  rVP                  4       '       g   \        P                  R4       R# VP                  4       '       g   \        P	                  R4       R# R# )z9Return True when Mattermost has enough config to connect.z$Mattermost: MATTERMOST_TOKEN not setFz"Mattermost: MATTERMOST_URL not setT)r^   r=   re   Údebugrf   )r]   rL   rY   s   &  r*   Úvalidate_mattermost_configrk   \   sG   € ä Ó'�J€CØ�;‰;�=Š=Ü�‰Ð;Ô<ÙØ�9‰9�;Š;Ü�‰Ð;Ô<ÙÙr,   c                  ó  a € ] tR t^htRtRtRtR V 3R lltR R ltR R lt	RIR	 R
 llt
R R ltR R ltR R ltR R ltRIR R lltR R ltRJR R lltRR/R R lltR R ltR R  ltRKR! R" lltR# R$ ltRIR% R& lltR'R/R( R) lltRLR* R+ lltRLR, R- lltRMR. R/ lltRLR0 R1 lltRLR2 R3 lltR4 R5 ltRNR6 R7 lltRKR8 R9 llt R: R; lt!ROR< V 3R= lllt"R> R? lt#R@ RA lt$RB RC lt%RD RE lt&RF RG lt'RHt(V ;t)# )PÚMattermostAdapterz6Gateway adapter for Mattermost (self-hosted or cloud).Tc               ó   € V ^8„  d   QhRR/# )r$   r]   r   r(   )r)   s   "r*   r+   ÚMattermostAdapter.__annotate__n   s   € ÷ ,ñ ,˜~ñ ,r,   c                	óÖ  <€ \         SV `  V\        P                  4       \	        V4      w  V n        V n        V P
                  P                  R 4      V n        R;V n        V n	        RV n
        RV n        RV n        RV n        RV n        VP                  P!                  RR4      ;'       g    \#        RR4      P%                  4       V n        RV n        RV n        \-        4       V n        R# )rO   rX   NFÚ
reply_modeÚMATTERMOST_REPLY_MODEÚoff)ÚsuperÚ__init__r
   Ú
MATTERMOSTr^   Ú	_base_urlÚ_tokenÚrstripÚ_bot_user_idÚ_bot_usernameÚ_sessionÚ_wsÚ_ws_taskÚ_reconnect_taskÚ_closingrV   r/   r\   ÚlowerÚ_reply_modeÚ_last_post_statusÚ_last_post_errorr   Ú_dedup)Úselfr]   Ú	__class__s   &&€r*   ru   ÚMattermostAdapter.__init__n   sÈ   ø€ Ü‰Ñ˜¤×!4Ñ!4Ô5Ü&4°VÓ&<Ñ#ˆŒ˜œØŸ™×.Ñ.¨sÓ3ˆŒØ13Ð3ˆÔ˜DÔ.Ø!ˆŒØˆŒØ04ˆŒØ7;ˆÔØˆŒð �L‰L×Ñ˜\¨2Ó.×dÐdÔ2DÐE\Ð^cÓ2d×fkÑfkÓfmð 	Ôà04ˆÔØ%'ˆÔÜ)Ó+ˆŽr,   c               ó   € V ^8„  d   QhRR/# ©r$   r'   zdict[str, str]r(   )r)   s   "r*   r+   ro   �   s   € ÷ Kñ K˜.ñ Kr,   c                	ó.   € / V P                  4       CR R/C# )úContent-Typeúapplication/json)Ú_auth_header©r†   s   &r*   Ú_headersÚMattermostAdapter._headers�   s   € ØJ�$×#Ñ#Ó%ÐJ ~Ð7IÑJÐJr,   c               ó   € V ^8„  d   QhRR/# rŠ   r(   )r)   s   "r*   r+   ro   „   s   € ÷ :ñ :˜nñ :r,   c                	ó$   € R RV P                    2/# )ÚAuthorizationúBearer )rx   r�   s   &r*   rŽ   ÚMattermostAdapter._auth_header„   s   € Ø 7¨4¯;©;¨-Ð!8Ð9Ð9r,   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r$   Úmethodr;   Úpathr%   zOptional[dict[str, Any]]r'   r&   r(   )r)   s   "r*   r+   ro   ‡   s*   € ÷ ñ  ð ¨Cð Ð:Rð Ð^lñ r,   c           
   ƒ  ó  "  € ^ RI pRV9   d   \        P                  RV4       / # V P                   RVP	                  R4       2pVR8H  pV'       d   RRuV n        V n        RV P                  4       /pVe   W7R	&   VR
8w  d   VP                  ^R7      VR&    \        V P                  VP                  4       4      ! V3/ VB ;_uu_4       GRj  x€L
 pV'       d   VP                  V n        VP                  R8¼  do   VP                  4       G Rj  x€L
 p	V'       d   T	;'       g    RV n        \        P                  RWVP                  V	R,          4       / uuRRR4      GRj  x€L
  # VP                  4       G Rj  x€L
 uuRRR4      GRj  x€L
  #  LÆ L† L3 L L  + GRj  x€L 
 '       g   i     R# ; i  TP                   d<   p
T'       d   \!        T
4      T n        \        P                  RYT
4       / u Rp
?
# Rp
?
ii ; i5i)zN{method} /api/v4/{path}; POST also records _last_post_status/_last_post_error.Nz..z!MM API path traversal blocked: %sz/api/v4/rO   ÚPOSTrX   ÚheadersÚjsonÚPUT©ÚtotalÚtimeouté�  u   MM API %s %s â†’ %s: %sºNéÈ   NzMM API %s %s network error: %s)rc   re   rC   rw   Úlstriprƒ   r„   r�   ÚClientTimeoutr[   r|   r�   ÚstatusÚtextr�   ÚClientErrorr;   )r†   r˜   r™   r%   rc   rL   Úis_postÚkwargsÚrespÚbodyÚexcs   &&&&       r*   Ú_apiÚMattermostAdapter._api‡   s¥  é € ãØ�4Œ<Ü�L‰LÐ<¸dÔCØˆIØ—‘Ð  ¨¯©°SÓ)9Ð(:Ð;ˆØ˜FÑ"ˆßØ<@À"Ð9ˆDÔ" DÔ$9Ø"+¨T¯]©]«_Ð!=ˆØÒØ$�6‰NØ�UŒ?Ø '× 5Ñ 5¸BÐ 5Ó ?ˆF�9Ñð	Ü˜tŸ}™}¨f¯l©l«nÔ=¸cÑLÀV×L×LÒLÐPTßØ-1¯[©[�DÔ*Ø—;‘; #Ô%Ø!%§¡£×,�DßØ04·
°
¸˜Ô-Ü—L‘LÐ!:¸FÈ$Ï+É+ÐW[Ð\`ÕWaÔbØ÷ M×LÒLð "ŸY™Y›[×(÷ M×LÔLñ -ñ	 Mñ )÷ M×L×LÓLûð ×"Ñ"ô 	ßÜ(+¨C«�Ô%Ü�L‰LÐ9¸6ÈÔMØ�Iûð		üsë   ‚AHÁAHÂ7F> ÃFÃF> Ã>F!ÄFÄF!ÄF!Ä(2F!ÅF> Å'FÅ(F> Å,HÅ-F!Æ FÆF!ÆF> ÆFÆF> ÆHÆF> ÆF!ÆF> ÆF!ÆF> Æ!F;	Æ'F*Æ(
F;	Æ3F;	Æ5F> Æ9HÆ;F> Æ>H
Ç0HÇ?H
È HÈH
È
Hc               ó    € V ^8„  d   QhRRRR/# )r$   r™   r;   r'   r&   r(   )r)   s   "r*   r+   ro   §   s   € ÷ ,ñ , 3ð ,¨>ñ ,r,   c              ƒ  	óB   "  € V P                  R V4      G Rj  x€L
 #  L5i)ÚGETN©r¯   )r†   r™   s   &&r*   Ú_api_getÚMattermostAdapter._api_get§   s   é € Ø—Y‘Y˜u dÓ+×+Ð+Ñ+ùó   ‚˜™c               ó$   € V ^8„  d   QhRRRRRR/# )r$   r™   r;   r%   r&   r'   r(   )r)   s   "r*   r+   ro   ª   s!   € ÷ 6ñ 6 Cð 6°.ð 6À^ñ 6r,   c              ƒ  	óB   "  € V P                  R W4      G Rj  x€L
 #  L5i)r›   Nr´   )r†   r™   r%   s   &&&r*   Ú	_api_postÚMattermostAdapter._api_postª   s   é € Ø—Y‘Y˜v tÓ5×5Ð5Ñ5ùr·   c               ó   € V ^8„  d   QhRR/# r`   r(   )r)   s   "r*   r+   ro   ­   s   € ÷ mñ m¸$ñ mr,   c                óz  a€ V P                   ;'       g    RP                  4       oV P                  R9  g	   S'       g   R# \        ;QJ d    V3R lR 4       F  '       g   K   RM	  RM! V3R lR 4       4      ;'       d;    \        ;QJ d    V3R lR 4       F  '       g   K   R# 	  R# ! V3R lR 4       4      # )	zCReturn True only for clear invalid/missing Mattermost thread roots.rX   Fc              3  ó,   <"  € T F	  qS9   x € K  	  R # 5i©Nr(   ©Ú.0Úmarkerr­   s   & €r*   Ú	<genexpr>ÚMMattermostAdapter._last_post_failure_is_broken_thread_root.<locals>.<genexpr>²   s   øé € ÐdÑ1c v˜d–NÓ1cùó   ƒTc              3  ó,   <"  € T F	  qS9   x € K  	  R # 5ir¿   r(   rÀ   s   & €r*   rÃ   rÄ   ³   s   øé € ÐkÑ5j¨6 $žÓ5jùrÅ   >   r¢   é”  )Úroot_idÚrootidzroot idÚthreadÚpost)Úinvalidz	not foundzdoes not existÚmissing)r„   r�   rƒ   Úany)r†   r­   s   &@r*   Ú(_last_post_failure_is_broken_thread_rootÚ:MattermostAdapter._last_post_failure_is_broken_thread_root­   s”   ø€ à×%Ñ%×+Ð+¨×2Ñ2Ó4ˆØ×!Ñ!¨Ô3¿4Ùß“ÔdÑ1cÓd——’ÔdÑ1cÓdÓd÷ lð lß“CÔkÑ5jÓk—C”Cð	mÚð	mØÔkÑ5jÓkÓkð	mr,   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r$   Úchat_idr;   r%   r&   ÚmetadataÚ	_Metadatar'   r(   )r)   s   "r*   r+   ro   µ   s,   € ÷ ;ñ ;Øð;Ø%3ð;Ø?Hð;ØM[ñ;r,   c              ƒ  óP  "  € V P                  RV4      G Rj  x€L
 pV'       gK   RV9  gD   \        V\        4      '       d.   VP                  R4      '       d   V P	                  4       '       g   V# VP                  4        UUu/ uF  w  rVVR8w  g   K  WVbK  	  ppp\        VP                  R4      ;'       g    R4      pV P                  RV,           P                  4       V4      VR&   \        P                  RV4       V P                  RV4      G Rj  x€L
 #  ELu uppi  L5i)	zAPost once, optionally falling back flat for final notify content.ÚpostsNrÈ   ÚnotifyÚmessagerX   uK   âš ï¸� Mattermost thread delivery failed; posting final reply in channel.

zNMattermost: falling back to flat channel delivery for notify-worthy post in %s)rº   r1   r2   r/   rÏ   r>   r;   Úwarning_textr=   re   rf   )	r†   rÒ   r%   rÓ   rB   ÚkÚvÚflat_payloadr­   s	   &&&&     r*   Ú_post_preserving_threadÚ)MattermostAdapter._post_preserving_threadµ   sø   é € ð —^‘^ G¨WÓ5×5ˆß�I WÔ,´ZÀÌ$×5OÒ5OÐT\×T`ÑT`Ðai×TjÒTjØ×DÑD×FÒFØˆKØ)0¯©¬ÔK©¡ ¸AÀ¹Nœ˜š©ˆÑKÜ�<×#Ñ# IÓ.×4Ð4°"Ó5ˆØ"&×"3Ñ"3Ø\Ð_cÕc×jÑjÓlÐnró#tˆ�YÑä�‰ÐgÐipÔqØ—^‘^ G¨\Ó:×:Ð:ò 6ùó Lñ
 ;ùsK   ‚D&˜D™D&¥3D&ÁD&Á/D&ÂDÂDÂD&Â:AD&ÄD$ÄD&ÄD&c               ó0   € V ^8„  d   QhRRRRRRRRRR	R
R/# )r$   rÒ   r;   rØ   Úreply_toúOptional[str]rÓ   rÔ   Úfile_idszOptional[list[str]]r'   r&   r(   )r)   s   "r*   r+   ro   Ã   sA   € ÷ Nñ N¨3ð N¸ð NÈð NÐajð NØ&9ðNØESñNr,   c              ƒ  óŒ  "  € RVRV/pVe   WVR&   \        V4      pV P                  R8X  dz   T;'       gC    \        V\        4      ;'       d+    VP	                  R4      ;'       g    VP	                  R4      pV'       d&   V P                  \        V4      4      G Rj  x€L
 VR&   V P                  WV4      G Rj  x€L
 #  L! L5i)zHBuild a mentions-disabled post payload (+ optional root_id) and post it.Ú
channel_idrØ   Nrâ   rÊ   Ú	thread_idrÈ   )r4   r‚   r1   r2   r/   Ú_resolve_root_idr;   rÝ   )	r†   rÒ   rØ   rà   rÓ   râ   Úbaser%   Ú	candidates	   &&&&&&   r*   Ú_post_messageÚMattermostAdapter._post_messageÃ   sº   é € ð !-¨g°yÀ'ÐJˆØÒØ'�ÑÜ)¨$Ó/ˆØ×Ñ˜xÔ'à ÷ gð gÜ˜8¤TÓ*×eÐe°·±¸[Ó0I×0dÐ0dÈXÏ\É\ÐZcÓMdð çØ+/×+@Ñ+@ÄÀYÃÓ+P×%P�˜	Ñ"Ø×1Ñ1°'ÀHÓM×MÐMñ &QÙMùs:   ‚3C¶CÁCÁ'CÂCÂC ÂCÂ;CÂ<CÃCc               ó0   € V ^8„  d   QhRRRRRRRRRRR	R
/# )r$   rÒ   r;   Úfile_idÚcaptionrá   rà   rÓ   rÔ   r'   r   r(   )r)   s   "r*   r+   ro   Ò   s9   € ÷ 3ñ 3¨Sð 3¸3ð 3Èð 3Ðboð 3Ø(1ð3Ø6@ñ3r,   c           	   ƒ  	óv   "  € \        T P                  Y;'       g    R WEV.4      G Rj  x€L
 \        4      #  L5i)rX   N)rJ   ré   Ú_POST_WITH_FILE_ERROR)r†   rÒ   rì   rí   rà   rÓ   s   &&&&&&r*   Ú_post_with_fileÚ!MattermostAdapter._post_with_fileÒ   s6   é € ä $×"4Ñ"4°W¿m¸mÈÈXÐbiÐajÓ"k×kÜ1ó3ð 	3Ñkùs   ‚'9©7ª9c          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r$   rä   r;   Ú	file_dataÚbytesÚfilenameÚcontent_typer'   rá   r(   )r)   s   "r*   r+   ro   ×   s1   € ÷ 5ñ 5¨Sð 5¸Uð 5Ècð 5Ø),ð5ØN[ñ5r,   c           	   ƒ  óò  "  € ^ RI pVP                  4       pVP                  RV4       VP                  RW#VR7       V P                  P	                  V P
                   R2V P                  4       VVP                  ^<R7      R7      ;_uu_4       GRj  x€L
 pVP                  R8¼  dT   VP                  4       G Rj  x€L
 p\        P                  R	VP                  VR
,          4        RRR4      GRj  x€L
  R# VP                  4       G Rj  x€L
 P                  R. 4      p	V	'       d   V	^ ,          R,          MRuuRRR4      GRj  x€L
  #  L¼ L• L^ LF L  + GRj  x€L 
 '       g   i     R# ; i5i)z9Upload a file and return its file ID, or None on failure.Nrä   Úfiles)rõ   rö   ú/api/v4/filesrŸ   )rœ   rB   r¡   r¢   u   MM file upload â†’ %s: %sr£   Ú
file_infosrE   )rc   ÚFormDataÚ	add_fieldr|   rË   rw   rŽ   r¦   r§   r¨   re   rC   r�   r/   )
r†   rä   ró   rõ   rö   rc   Úformr¬   r­   Úinfoss
   &&&&&     r*   Ú_upload_fileÚMattermostAdapter._upload_file×   s;  é € ó 	Ø×ÑÓ!ˆØ�‰�| ZÔ0Ø�‰�w 	È<ˆÔXØ—=‘=×%Ñ%¨¯©Ð(8¸Ð&FÐPT×PaÑPaÓPcÐjnØ.5×.CÑ.CÈ"Ð.CÓ.Mð &÷ O÷ Oô OØRVØ�{‰{˜cÔ!Ø!ŸY™Y›[×(�Ü—‘Ð8¸$¿+¹+ÀtÈDÅzÔRØ÷O÷ Oñ Oð  Ÿ9™9›;×&×+Ñ+¨L¸"Ó=ˆEß%*�5˜•8˜D–>°÷O÷ Oô Oñ )ñOñ '÷O÷ O÷ Oó Oüs–   ‚BE7ÂEÂE7Â%EÂ<EÂ=-EÃ*E7Ã5EÃ6E7Ã<EÄEÄEÄ,EÄ=E7Å
EÅE7ÅEÅE7ÅEÅE7ÅE4	Å E#Å!
E4	Å,E4	Å.	E7Úis_reconnectFc               ó    € V ^8„  d   QhRRRR/# )r$   r  ra   r'   r(   )r)   s   "r*   r+   ro   é   s   € ÷ ñ ¨Tð ¸dñ r,   c             ƒ  ó  "  € ^ RI pV P                  '       d   V P                  '       g   \        P	                  R4       R# VP                  VP                  ^R7      \        4       R7      V n        RV n	        V P                  R4      G Rj  x€L
 pV'       d   RV9  d:   \        P	                  R4       V P                  P                  4       G Rj  x€L
  R# VR,          VP                  R	R
4      uV n        V n        \        P                  RV P                  V P                  V P                  4       \         P"                  ! V P%                  4       4      V n        V P)                  4        V P+                  R4       R#  Lô L°5i)z7Connect to Mattermost and start the WebSocket listener.Nz'Mattermost: URL or token not configuredFrŸ   )r¡   Ú	trust_envzusers/merE   uP   Mattermost: failed to authenticate â€” check MATTERMOST_TOKEN and MATTERMOST_URLÚusernamerX   z+Mattermost: authenticated as @%s (%s) on %sT)rc   rw   rx   re   rC   ÚClientSessionr¦   r   r|   r€   rµ   Úcloser/   rz   r{   ÚinfoÚasyncioÚcreate_taskÚ_ws_loopr~   Ú_mark_connectedÚ_wire_plugin_handlers)r†   r  rc   Úmes   &$  r*   ÚconnectÚMattermostAdapter.connecté   s#  é € ãØ�~�~ˆ~ T§[§[ [Ü�L‰LÐBÔCÙØ×-Ñ-°g×6KÑ6KÐRTÐ6KÓ6UÔarÓatÐ-ÓuˆŒØˆŒØ—=‘= Ó,×,ˆß�T ”^Ü�L‰LÐkÔlØ—-‘-×%Ñ%Ó'×'Ð'ÙØ02°4µ¸"¿&¹&ÀÈRÓ:PÐ-ˆÔ˜4Ô-Ü�‰Ø9¸4×;MÑ;MÈt×O`ÑO`Ðbf×bpÑbpô	rä×+Ò+¨D¯M©M«OÓ<ˆŒØ×ÑÔØ×"Ñ" 4Ô(Ùñ -ñ (ùs0   ‚(F«A"FÂFÂFÂ9FÃFÃB/FÆFc               ó   € V ^8„  d   QhRR/# ©r$   r'   ÚNoner(   )r)   s   "r*   r+   ro   þ   s   € ÷ 
0ñ 
0 $ñ 
0r,   c              ƒ  	ó:  "  € R V n         \        V P                  4      G Rj  x€L
  V P                  '       d;   V P                  P	                  4       '       g   V P                  P                  4        V P                  '       d*   V P                  P                  4       G Rj  x€L
  RV n        V P                  '       d?   V P                  P                  '       g#   V P                  P                  4       G Rj  x€L
  \        P                  R4       R#  Lò Lt L5i)TNzMattermost: disconnected)r€   r   r~   r   ÚdoneÚcancelr}   r  r|   Úclosedre   r  r�   s   &r*   Ú
disconnectÚMattermostAdapter.disconnectþ   s¾   é € ØˆŒÜ˜$Ÿ-™-Ó(×(Ð(Ø××Ð¨×(<Ñ(<×(AÑ(A×(CÒ(CØ× Ñ ×'Ñ'Ô)Ø�8�8ˆ8Ø—(‘(—.‘.Ó"×"Ð"ØˆDŒHØ�=�=ˆ= §¡×!5×!5Ð!5Ø—-‘-×%Ñ%Ó'×'Ð'Ü�‰Ð.Ö/ñ 	)ñ #ñ (ùsP   ‚ D¢D£D¹DÁ+DÂDÂ"DÂ#DÃ DÃDÃ9DÃ:DÄDÄDc               ó    € V ^8„  d   QhRRRR/# )r$   Úpost_idr;   r'   r(   )r)   s   "r*   r+   ro   
  s   € ÷ Lñ L¨cð L°cñ Lr,   c              ƒ  ó®   "  € V'       g   V# V P                  RV 24      G Rj  x€L
 pV'       d!   VP                  R4      '       d
   VR,          # T#  L.5i)z]Resolve a post_id to its thread root_id (a reply's own ID causes "Invalid RootId parameter").úposts/NrÈ   )rµ   r/   )r†   r  rB   s   && r*   ræ   Ú"MattermostAdapter._resolve_root_id
  sI   é € çØˆNØ—]‘] V¨G¨9Ð#5Ó6×6ˆß"&¨4¯8©8°I×+>Ò+>ˆt�I�ÐKÀGÐKñ 7ùs   ‚"A¤A¥A±AÁAc          
     ó,   € V ^8„  d   QhRRRRRRRRRR	/# )
r$   rÒ   r;   Úcontentrà   rá   rÓ   rÔ   r'   r   r(   )r)   s   "r*   r+   ro     s4   € ÷ 
ñ 
Øð
Ø%(ð
Ø4Að
ØT]ð
Øisñ
r,   c           	   ƒ  ó  "  € V'       g   \        RR7      # \        RR7      pV P                  V P                  V4      \        4       F<  p\	        V P                  WW44      G Rj  x€L
 R4      pVP                  '       d   K;   V# 	  V#  L$5i)zdSend a message (or multiple chunks) to a channel; reply_to / metadata["thread_id"] is the root post.T)rG   NzFailed to create post)r   Útruncate_messageÚformat_messageÚMAX_POST_LENGTHrJ   ré   rG   )r†   rÒ   r   rà   rÓ   ÚresultÚchunks   &&&&&  r*   ÚsendÚMattermostAdapter.send  s}   é € ÷ Ü dÔ+Ð+Ü DÔ)ˆØ×*Ñ*¨4×+>Ñ+>¸wÓ+GÌÖYˆEÜ!¨×(:Ñ(:¸7È8Ó(^×"^Ð`wÓxˆFØ—>—>’>ØØˆñ	 Zð ˆñ #_ùs   ‚A#BÁ%B

Á&BÂBc               ó    € V ^8„  d   QhRRRR/# )r$   rÒ   r;   r'   r&   r(   )r)   s   "r*   r+   ro     s   € ÷ Qñ Q¨3ð Q°>ñ Qr,   c           	   ƒ  	ó  "  € V P                  R V 24      G Rj  x€L
 pV'       g   RVRR/# RVP                  R4      ;'       g    VP                  R4      ;'       g    TR\        P                  VP                  RR4      R4      /#  Ln5i)z	channels/NÚnameÚtyper   Údisplay_namer   )rµ   r/   Ú_CHANNEL_TYPE_MAP)r†   rÒ   rB   s   && r*   Úget_chat_infoÚMattermostAdapter.get_chat_info  s…   é € Ø—]‘] Y¨w¨iÐ#8Ó9×9ˆßØ˜G V¨YÐ7Ð7Ø˜Ÿ™ Ó0×OÐO°D·H±H¸VÓ4D×OÐOÈØÔ)×-Ñ-¨d¯h©h°v¸sÓ.CÀYÓOðQð 	Qñ :ùs    ‚BšB	›B§BÁBÁ+Bc               ó$   € V ^8„  d   QhRRRRRR/# )r$   rÒ   r;   rÓ   rÔ   r'   r  r(   )r)   s   "r*   r+   ro   &  s&   € ÷ [ñ [¨ð [¸	ð [ÈTñ [r,   c              ƒ  	óf   "  € V P                  R V P                   R2RV/4      G Rj  x€L
  R#  L5i)zusers/z/typingrä   N)rº   rz   )r†   rÒ   rÓ   s   &&&r*   Úsend_typingÚMattermostAdapter.send_typing&  s/   é € Ø�n‰n˜v d×&7Ñ&7Ð%8¸Ð@À<ÐQXÐBYÓZ×ZÔZùs   ‚&1¨/©1Úfinalizec          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r$   rÒ   r;   rI   r   r5  ra   r'   r   r(   )r)   s   "r*   r+   ro   )  s8   € ÷ qñ q¨#ð q¸3ð qÈð qÐ[_ð qÐlvñ qr,   c             ƒ  	ó˜   "  € \        R V P                  V4      /4      p\        V P                  RRV R2V4      G Rj  x€L
 R4      #  L	5i)rØ   rž   r  z/patchNzFailed to edit post)r4   r#  rJ   r¯   )r†   rÒ   rI   r   r5  r%   s   &&&&$ r*   Úedit_messageÚMattermostAdapter.edit_message)  sJ   é € Ü)¨9°d×6IÑ6IÈ'Ó6RÐ*SÓTˆÜ $§)¡)¨E°V¸J¸<ÀvÐ3NÐPWÓ"X×XÐZoÓpÐpÑXùs   ‚<A
¾A¿
A
c               ó0   € V ^8„  d   QhRRRRRRRRRRR	R
/# )r$   rÒ   r;   Ú	image_urlrí   rá   rà   rÓ   rÔ   r'   r   r(   )r)   s   "r*   r+   ro   -  sA   € ÷ fñ f¨ð f¸ð fÀmð fØ#0ðfØCLðfØXbñfr,   c              ƒ  	óF   "  € V P                  WW4R V4      G Rj  x€L
 #  L5i)ÚimageN)Ú_send_url_as_file)r†   rÒ   r;  rí   rà   rÓ   s   &&&&&&r*   Ú
send_imageÚMattermostAdapter.send_image-  s$   é € à×+Ñ+¨GÀÐSZÐ\dÓe×eÐeÑeùó   ‚!š›!c               ó0   € V ^8„  d   QhRRRRRRRRRRR	R
/# )r$   rÒ   r;   Ú
image_pathrí   rá   rà   rÓ   rÔ   r'   r   r(   )r)   s   "r*   r+   ro   1  sA   € ÷ fñ f¨Sð f¸cð fÈMð fØ(5ðfØHQðfØ]gñfr,   c              ƒ  	óF   "  € V P                  WW4VR 7      G Rj  x€L
 #  L5i©©rÓ   N©Ú_send_local_file)r†   rÒ   rC  rí   rà   rÓ   s   &&&&&&r*   Úsend_image_fileÚ!MattermostAdapter.send_image_file1  ó$   é € à×*Ñ*¨7ÀÐ\dÐ*Óe×eÐeÑeùrA  c               ó4   € V ^8„  d   QhRRRRRRRRRRRR	R
R/# )r$   rÒ   r;   Ú	file_pathrí   rá   Ú	file_namerà   rÓ   rÔ   r'   r   r(   )r)   s   "r*   r+   ro   5  sM   € ÷ gñ gØðgØ'*ðgØ5BðgØVcðgàðgà2;ðgàGQñgr,   c              ƒ  	óD   "  € V P                  WW5WF4      G R j  x€L
 #  L5ir¿   rG  )r†   rÒ   rM  rí   rN  rà   rÓ   s   &&&&&&&r*   Úsend_documentÚMattermostAdapter.send_document5  s#   é € ð ×*Ñ*¨7¸wÐR[Óf×fÐfÑfùs   ‚ ™š c               ó4   € V ^8„  d   QhRRRRRRRRRRR	R
RR/# )r$   rÒ   r;   Ú
audio_pathrí   rá   rà   rÓ   rÔ   r«   r   r'   r   r(   )r)   s   "r*   r+   ro   :  sJ   € ÷ fñ f¨ð f¸ð fÀ}ð fØ#0ðfØCLðfØ_bðfØgqñfr,   c              ‹  	óF   "  € V P                  WW4VR 7      G Rj  x€L
 #  L5irE  rG  )r†   rÒ   rS  rí   rà   rÓ   r«   s   &&&&&&,r*   Ú
send_voiceÚMattermostAdapter.send_voice:  rK  rA  c               ó0   € V ^8„  d   QhRRRRRRRRRRR	R
/# )r$   rÒ   r;   Ú
video_pathrí   rá   rà   rÓ   rÔ   r'   r   r(   )r)   s   "r*   r+   ro   >  sA   € ÷ fñ f¨ð f¸ð fÀ}ð fØ#0ðfØCLðfØXbñfr,   c              ƒ  	óF   "  € V P                  WW4VR 7      G Rj  x€L
 #  L5irE  rG  )r†   rÒ   rX  rí   rà   rÓ   s   &&&&&&r*   Ú
send_videoÚMattermostAdapter.send_video>  rK  rA  c               ó    € V ^8„  d   QhRRRR/# )r$   r   r;   r'   r(   )r)   s   "r*   r+   ro   B  s   € ÷ Cñ C cð C¨cñ Cr,   c                ó2   € \         P                  ! RRV4      # )zZMattermost renders standard Markdown; reduce ![alt](url) to the bare URL (inline preview).z!\[([^\]]*)\]\(([^)]+)\)z\2)ÚreÚsub)r†   r   s   &&r*   r#  Ú MattermostAdapter.format_messageB  s   € ä�vŠvÐ1°5¸'ÓBÐBr,   c               ó4   € V ^8„  d   QhRRRRRRRRRRRR	R
R/# )r$   rÒ   r;   rL   rí   rá   rà   ÚkindrÓ   rÔ   r'   r   r(   )r)   s   "r*   r+   ro   H  sJ   € ÷ zñ z¨sð z¸ð zÀ}ð zÐ`mð zØ&)ðzØ>GðzØS]ñzr,   c           	   ƒ  óJ  a aaaaa"  € ^ RI Hp R VVVVV V3R llpV! S4      '       g%   \        P                  R4       V! 4       G Rj  x€L
 # ^ RIp	\        ^4       EFM  p
 S P                  P                  SV	P                  ^R7      R7      ;_uu_4       GRj  x€L
 pVP                  R8¼  g   VP                  R	8X  d9   V
^8  d2   \        P                  R
V
^,           SR,          VP                  4       MtVP                  R8¼  d$   V! 4       G Rj  x€L
 uuRRR4      GRj  x€L
  u # VP                  4       G Rj  x€L
 VP                  ;'       g    RrÜ RRR4      GRj  x€L
   MARRR4      GRj  x€L
  \        P                   ! RT
^,           ,          4      G Rj  x€L
  EKP  	  S P#                  SX\%        SV R24      X4      G Rj  x€L
 pV'       d   S P'                  SVSSS4      G Rj  x€L
 # V! 4       G Rj  x€L
 #  ELÃ ELt Lü Lí LÔ L° L   + GRj  x€L 
 '       g   i     L·; i  \        T	P                  3 dI   pT
^8X  d7   \        P                  RST
^,           T4       T! 4       G Rj  x€L 
 u Rp?u #  Rp?ELRp?ii ; i Lô LÈ L¥ L˜5i)zZDownload a URL and upload it as a file attachment (text fallback with the URL on failure).©Úis_safe_urlc               ó   € V ^8„  d   QhRR/# )r$   r'   r   r(   )r)   s   "r*   r+   Ú9MattermostAdapter._send_url_as_file.<locals>.__annotate__M  s   € ÷ 	lñ 	l 
ñ 	lr,   c               “  ó„   <"  € SP                  SS ;'       g    R  RS 2P                  4       SSR7      G Rj  x€L
 #  L5i)rX   Ú
rF  N)r'  r=   )rí   rÒ   rÓ   rà   r†   rL   s   €€€€€€r*   rM   Ú5MattermostAdapter._send_url_as_file.<locals>.fallbackM  s>   øé € ØŸ™ 7¨w¯}¨}¸"¨o¸RÀ¸uÐ,E×,KÑ,KÓ,MÈxÐbj˜Ók×kÐkÑkùs   ƒ6A ¹>ºA z0Mattermost: blocked unsafe URL (SSRF protection)NrŸ   ©r¡   iô  i­  z1Mattermost download retry %d/2 for %s (status %d)ºNéP   Nr¢   úapplication/octet-streamz7Mattermost: failed to download %s after %d attempts: %sg      ø?r"   )Útools.url_safetyre  re   rf   rc   Úranger|   r/   r¦   r§   rj   Úreadrö   ÚTimeoutErrorr©   r	  Úsleeprÿ   rS   rð   )r†   rÒ   rL   rí   rà   rb  rÓ   re  rM   rc   Úattemptr¬   ró   Úctr®   rì   s   fffff&f         r*   r>  Ú#MattermostAdapter._send_url_as_fileH  s  ýé € õ 	1÷	lõ 	lñ ˜3×ÒÜ�N‰NÐMÔNÙ!›×#Ð#ÛÜ˜Q—xˆGð,ØŸ=™=×,Ñ,¨S¸'×:OÑ:OÐVXÐ:OÓ:YÐ,×Z×ZÔZÐ^bØŸ™ sÔ*¨d¯k©k¸SÔ.@ÀgÐPQÄkÜŸ™Ð%XØ%,¨q¥[°#°cµ(¸D¿K¹KõIàŸ™¨Ô+Ù%-£Z×/÷ [×ZÔZð /3¯i©i«k×(9¸4×;LÑ;L×;jÐ;jÐPj 2Ø÷ [×Z×Z×ZÑZô —-’-  w°¥{Õ 3Ó4×4Ó4ñ  ð  ×)Ñ)¨'°9¼mÈCÐTXÐSYÐY]ÐQ^Ó>_ÐacÓd×dˆß\c�T×)Ñ)¨'°7¸GÀXÈxÓX×XÐyÑowÓoy×iyÐyò' $ò [ñ
  0ñ [ñ ):÷ [×Z×ZÔZûô ! '×"5Ñ"5Ð6ô ,Ø˜a”<Ü—N‘NÐ#\Ð^aÐcjÐmnÕcnÐpsÔtÙ!)£×+Ð+×+õ  ûð,úñ 5ÙdÙXÑiyùs]  ˆAJ#Á
HÁJ#Á#9H9ÂH
ÂH9Â A6HÄH
ÄHÄH9Ä'HÄ(H9Ä,J#Ä/HÅH
ÅHÅHÅH9Å(HÅ)H9Å-J#Å/H9Å:HÅ;H9Å?'J#Æ&JÆ'-J#ÇJÇJ#Ç!J#Ç9JÇ:J#ÈJ!È	J#ÈH9ÈHÈH9ÈHÈH9ÈH9ÈH6È#H&È$
H6È/H6È1H9È5J#È6H9È9JÉ0JÊ JÊJÊJÊJ#ÊJÊJ#ÊJ#ÊJ#Ê!J#c               ó4   € V ^8„  d   QhRRRRRRRRRRRR	R
R/# )r$   rÒ   r;   rM  rí   rá   rà   rN  rÓ   rÔ   r'   r   r(   )r)   s   "r*   r+   ro   g  sM   € ÷ Yñ YØðYØ'*ðYØ5BðYØN[ðYà ðYà3<ðYàHRñYr,   c              ƒ  óÂ  "  € \        V4      pVP                  4       '       g$   \        P                  RV4       \	        RRR7      # T;'       g    VP
                  pT P                  YP                  4       T\        P                  ! V4      ^ ,          ;'       g    R4      G Rj  x€L
 p	V	'       g   \	        RRR7      # V P                  WW4V4      G Rj  x€L
 #  L4 L5i)	z,Upload a local file and attach it to a post.z.Mattermost: local file not found, skipping: %sTNrH   rn  FzFile upload failedrF   )r   Úexistsre   rf   r   r+  rÿ   Ú
read_bytesÚ	mimetypesÚ
guess_typerð   )
r†   rÒ   rM  rí   rà   rN  rÓ   ÚpÚfnamerì   s
   &&&&&&&   r*   rH  Ú"MattermostAdapter._send_local_fileg  sº   é € ô �‹OˆØ�x‰x�zŠzÜ�N‰NÐKÈYÔWÜ d°tÔ<Ð<Ø×#Ð#˜QŸV™VˆØ×)Ñ)¨'·<±<³>À5Ü*3×*>Ò*>¸uÓ*EÀaÕ*H×*fÐ*fÐLfóh÷ hˆçÜ eÐ3GÔHÐHØ×)Ñ)¨'¸GÈxÓX×XÐXñ	hñ Yùs7   ‚ACÁACÂ
CÂ&CÂ'CÂ3#CÃCÃCÃCc               ó$   € V ^8„  d   QhRRRRRR/# )r$   r;  r;   ÚindexÚintr'   z Optional[tuple[bytes, str, str]]r(   )r)   s   "r*   r+   ro   v  s'   € ÷ Mñ M°ð M¸Sð MÐEeñ Mr,   c              ƒ  ó.  "  € ^ RI pVP                  R4      '       d˜   \        VR,          4      p\        V4      pVP	                  4       '       g   \
        P                  RV4       R# VP                  4       VP                  \        P                  ! VP                  4      ^ ,          ;'       g    R3# ^ RIHp V! V4      '       g   \
        P                  R4       R#  V P                  P                  WP                  ^R7      R	7      ;_uu_4       GRj  x€L
 pVP                   R
8¼  d<   \
        P                  RVP                   VR,          4        RRR4      GRj  x€L
  R# VP#                  4       G Rj  x€L
 VP$                  ;'       g    Rr˜RRR4      GRj  x€L
  X\)        TRT R24      X	3#  L  LX L@ L  + GRj  x€L 
 '       g   i     L4; i  \&         d*   p
\
        P                  RTR,          T
4        Rp
?
R# Rp
?
ii ; i5i)ud   Read a file:// or remote image for a batch post â†’ (data, filename, content_type), or None to skip.Nzfile://:é   NNz%Mattermost: skipping missing image %sz	image/pngrd  z-Mattermost: blocked unsafe image URL in batchrŸ   rk  r¢   z2Mattermost: failed to download image (HTTP %d): %srl  z&Mattermost: download failed for %s: %sÚimage_r"   )rc   Ú
startswithÚ_unquoter   ry  re   rf   rz  r+  r{  r|  ro  re  r|   r/   r¦   r§   rq  rö   Ú	ExceptionrS   )r†   r;  r�  rc   Ú
local_pathr}  re  r¬   ró   ru  Údl_errs   &&&        r*   Ú_load_batch_imageÚ#MattermostAdapter._load_batch_imagev  s—  é € ãØ×Ñ 	×*Ò*Ü! )¨B¥-Ó0ˆJÜ�ZÓ ˆAØ—8‘8—:’:Ü—‘ÐFÈ
ÔSÙØ—<‘<“> 1§6¡6¬9×+?Ò+?ÀÇÁÓ+GÈÕ+J×+YÐ+YÈkÐYÐYÝ0Ù˜9×%Ò%Ü�N‰NÐJÔKÙð	Ø—}‘}×(Ñ(¨×<QÑ<QÐXZÐ<QÓ<[Ð(×\×\Ô\Ð`dØ—;‘; #Ô%Ü—N‘NÐ#WÐY]×YdÑYdÐfoÐpsÕftÔuØ÷ ]×\Ñ\ð '+§i¡i£k× 1°4×3DÑ3D×3SÐ3SÈ˜2÷	 ]×\ð œ-¨	°V¸E¸7À$Ð3GÓHÈ"ÐLÐLó ]ñ !2÷	 ]×\×\Ò\ûô
 ô 	Ü�N‰NÐCÀYÈsÅ^ÐU[Ô\Ýûð	üsÒ   ‚B.HÂ1HÃ	HÃ!8G ÄF:ÄG Ä;GÅG Å#F<Å$G Å(HÅ*GÅ=F>Å>GÆGÆG Æ"G Æ#G Æ'HÆ:G Æ<G Æ>GÇ G ÇG	ÇGÇ	
G	ÇG	ÇG ÇHÇG ÇHÇ)HÈHÈHÈHc          
     ó,   € V ^8„  d   QhRRRRRRRRR	R
/# )r$   rÒ   r;   Úimageszlist[tuple[str, str]]rÓ   rÔ   Úhuman_delayÚfloatr'   r   r(   )r)   s   "r*   r+   ro   �  s:   € ÷ #gñ #g°#ð #gÐ?Tð #gØ-6ð#gØLQð#gØ\fñ#gr,   c           
   ƒ  óæ  <"  € V'       g   \        RRR7      # \        ^ \        V4      ^4       Uu. uF  qRWU^,            NK  	  ppRp\        V4       EFx  w  r‰V^ 8”  d&   V^ 8”  d   \        P
                  ! V4      G Rj  x€L
  . . rº V	 F~  w  rÍV'       d   VP                  V4       V P                  V\        V
4      4      G Rj  x€L
 pVf   KG  V P                  ! V.VO5!  G Rj  x€L
 ;p'       g   Km  V
P                  V4       K€  	  V
'       g   KÄ  \        P                  R\        V
4      V^,           \        V4      4       V P                  VRP                  V4      RW:4      G Rj  x€L
 pV'       d   RV9   d   RpEK4  \        P                  R	4       \        SV `=  WW4R
7      G Rj  x€L
 pT;'       g    VP                   pEK{  	  \        Yw'       d   RR7      # RR7      # u upi  ELp EL, EL LŠ LJ  \"         dg   p\        P                  RT^,           \        T4      TRR7       \        ST `=  YY4R
7      G Rj  x€L 
 pT;'       g    TP                   p Rp?EK  Rp?ii ; i5i)zŽSend a batch of images as one post; chunked at Mattermost's 5-``file_ids`` cap, each chunk
falling back to the base per-image loop on failure.Fzno images to sendrF   Nz<Mattermost: sending %d image(s) as single post (chunk %d/%d)ri  rE   Tz1Mattermost: multi-image post failed, falling back)r�  zCMattermost: multi-image send failed (chunk %d/%d), falling back: %s)Úexc_infozall images failed to send)r   rp  ÚlenÚ	enumerater	  rs  Úappendr‹  rÿ   re   r  ré   Újoinrf   rt   Úsend_multiple_imagesrG   rˆ  )r†   rÒ   rŽ  rÓ   r�  ÚiÚchunksÚ	deliveredÚ	chunk_idxr&  râ   Úcaption_partsr;  Úalt_textÚloadedÚfidrB   rM   Úer‡   s   &&&&&              €r*   r—  Ú&MattermostAdapter.send_multiple_images�  s  øé € ÷ Ü eÐ3FÔGÐGÜ+0°´C¸³KÀÔ+CÓDÑ+C a˜˜q�5“/Ñ+CˆÐDØˆ	Ü )¨&× 1ÑˆIØ˜QŒ 9¨q¤=Ü—m’m KÓ0×0Ð0Ø&(¨"�mð:Û+0Ñ'�IßØ%×,Ñ,¨XÔ6Ø#'×#9Ñ#9¸)ÄSÈÃ]Ó#S×S�FØÔ)¸D×<MÒ<MÈgÐ<_ÐX^Ó<_×6_Ð/_¨s×/_Ð/_Ø Ÿ™¨Ö,ñ ,1÷  ÙÜ—‘ÐZÜ ›M¨9°q­=¼#¸f»+ôGà!×/Ñ/°¸¿¹À=Ó9QÐSWÐYaÓl×l�ß˜D DœLØ $“Iä—N‘NÐ#VÔWÜ%*¡WÑ%AÀ'ÐRZÐ%AÓ%t×t�HØ )× =Ð =¨X×-=Ñ-=“Iñ+ !2ô6  )¾9°4ÔfÐfÐJeÔfÐfùò; Eò 1ò TÚ6_ñ mñ
  uøäô :Ü—‘ÐdØ(¨1�}¬c°&«k¸1Àtð ô Mä!&¡Ñ!=¸gÈhÐ!=Ó!p×pÐp�Ø%×9Ð9¨×)9Ñ)9—	ûð	:üsÑ   ƒ.I1±G+Á<I1Â G0ÂI1Â	>G=ÃG3ÃG=ÃG=Ã)G6Ã*	G=Ã8G=ÄI1ÄAG=Å.G9Å/G=Å;	G=ÆI1Æ)G=Æ0G;Æ1G=Æ>G=Ç&I1Ç3G=Ç6G=Ç9G=Ç;G=Ç=I.È>I)ÉI	ÉI)ÉI)É"I1É)I.É.I1c               ó   € V ^8„  d   QhRR/# r  r(   )r)   s   "r*   r+   ro   ¶  s   € ÷ "9ñ "9 ñ "9r,   c              ƒ  óN  "  € ^ RI p^ RIp\        pV P                  '       g‘    V P	                  4       G Rj  x€L
  \        pT P                  '       d   R# \
        P                   ! Y3\"        ,          TP                  4       ,          ,           4      G Rj  x€L
  \%        T^,          \&        4      pK¢  R#  L}  \
        P                   d     R# \         dÇ   pT P                  '       d    Rp?R# \        YAP                  4      '       ds   TP                  R	9   db   \        P                  RTP                  4       T P                  RRTP                   R2RR7       T P                  4       G Rj  x€L 
   Rp?R# \        P                  RYC4        Rp?ELXRp?ii ; i EL5i)
zHConnect to the WebSocket and listen for events, reconnecting on failure.Nu:   Mattermost WS auth failed (HTTP %d) â€” stopping reconnectÚmattermost_auth_errorz3Mattermost WebSocket authentication rejected (HTTP u   ). The bot token is invalid, revoked, or lacks permission â€” check MATTERMOST_TOKEN and the bot account in the System Console.F)Ú	retryableu1   Mattermost WS error: %s â€” reconnecting in %.0fs>   é‘  é“  )rc   ÚrandomÚ_RECONNECT_BASE_DELAYr€   Ú_ws_connect_and_listenr	  ÚCancelledErrorrˆ  r1   ÚWSServerHandshakeErrorr§   re   rC   Ú_set_fatal_errorÚ_notify_fatal_errorrf   rs  Ú_RECONNECT_JITTERÚminÚ_RECONNECT_MAX_DELAY)r†   rc   r¨  Údelayr®   s   &    r*   r  ÚMattermostAdapter._ws_loop¶  sI  é € ãÛÜ%ˆØ—-—-�-ð`Ø×1Ñ1Ó3×3Ð3Ü-�ð. �}�}ˆ}ÙÜ—-’- Ô0AÕ(AÀFÇMÁMÃOÕ(SÕ SÓT×TÐTÜ˜ �	Ô#7Ó8ŠEñ;  á3øä×)Ñ)ô ÚÜô `Ø—=—=�=Ýô ˜c×#AÑ#A×BÒBÀsÇzÁzÐU_ÔG_Ü—L‘LÐ!]Ð_b×_iÑ_iÔjð ×)Ñ)Ø/ØMÈcÏjÉjÈ\ð Z.ð .à9>ð	 *ô @ð
 ×2Ñ2Ó4×4Ñ4ÝÜ—‘ÐRÐTW×_Ò_ûð'`úò, Uùsˆ   ‚ F%¤B7 ·B5¸
B7 ÁF%ÁAF%ÂF"ÂF%Â5B7 Â7FÃF%ÃFÃFÃFÃ+F%Ã1BFÅ2E5Å3FÅ8F%Å>FÆF%ÆFÆF%c               ó   € V ^8„  d   QhRR/# r  r(   )r)   s   "r*   r+   ro   Ú  s   € ÷ ñ ¨dñ r,   c           	   ƒ  ó„  "  € \         P                  ! RRV P                  4      R,           p\        P	                  RV4       V P
                  P                  VRR7      G Rj  x€L
 V n        V P                  P                  R^R	R
RRV P                  //4      G Rj  x€L
  \        P	                  R4       V P                    Rj  x€L
  pV P                  '       d    R# VP                  pW3P                  VP                  09   d=    \        P                  ! VP                   4      pT P'                  T4      G Rj  x€L
  Kƒ  W3P(                  VP*                  VP,                  VP.                  09   g   K·  \        P	                  RV4        R#  EL0 Lø LÐ  \        P"                  \$        3 d     Kõ  i ; i L|DõR# 5i)z@Single WebSocket session: connect, authenticate, process events.z^httpÚwsz/api/v4/websocketzMattermost: connecting to %sg      >@)Ú	heartbeatNÚseqÚactionÚauthentication_challengerB   rY   z1Mattermost: WebSocket connected and authenticatedz!Mattermost: WebSocket closed (%s))r^  r_  rw   re   r  r|   Ú
ws_connectr}   Ú	send_jsonrx   r€   r,  ÚTEXTÚBINARYr�   ÚloadsrB   ÚJSONDecodeErrorÚ	TypeErrorÚ_handle_ws_eventÚERRORÚCLOSEÚCLOSINGÚCLOSED)r†   Úws_urlÚraw_msgrb  Úevents   &    r*   rª  Ú(MattermostAdapter._ws_connect_and_listenÚ  s]  é € ä—’˜ $¨¯©Ó7Ð:MÕMˆÜ�‰Ð2°FÔ;ØŸ™×1Ñ1°&ÀDÐ1ÓI×IˆŒØ�h‰h× Ñ  %¨¨HÐ6PÐRXÐ[bÐdh×doÑdoÐZpÐ!qÓr×rÐrÜ�‰ÐGÔHà!ŸXšX÷ 	ð 	�'Ø�}�}ˆ}ÚØ—<‘<ˆDØŸ	™	 4§;¡;Ð/Ô/ðÜ ŸJšJ w§|¡|Ó4�Eð ×+Ñ+¨EÓ2×2Ò2ØŸ*™* d§j¡j°$·,±,ÀÇÁÐLÖLÜ—‘Ð?ÀÔFÚò! JÙrñ	øô ×,Ñ,¬iÐ8ô Úðúá2ò &ùs~   ‚A G Á"FÁ#9G ÂFÂ%G ÃF=ÃFÃF=Ã
?G Ä
 FÄ*G Ä>F;Ä?5G Å9G ÆG ÆF=ÆF8Æ4G Æ7F8Æ8G Æ=G c               ó$   € V ^8„  d   QhRRRRRR/# )r$   rä   r;   Úmessage_textr'   rá   r(   )r)   s   "r*   r+   ro   ð  s!   € ÷ ñ °ð À3ð È=ñ r,   c           
     óB  a€ \        \        V P                  P                  RRRR7      4      pV'       d   W9  d   \        P                  RV4       R# \        \        V P                  P                  RRR	RR7      4      P                  4       R9  p\        \        V P                  P                  R
RRR7      4      pRV P                   2RV P                   2.p\        ;QJ d    V3R lV 4       F  '       g   K   RM	  RM! V3R lV 4       4      pV'       d'   W9  d!   V'       g   \        P                  RV4       R# V'       dT   V FM  p\        P                  ! \        P                  ! V4      RS\        P                  R7      P                  4       oKO  	  S# )záMention-gate a non-DM post; return the cleaned text, or None to ignore it. allowed_channels is a
whitelist checked first (@mentions elsewhere are ignored); require_mention (default true) is
bypassed in free_response_channels.Úallowed_channelsÚMATTERMOST_ALLOWED_CHANNELSF)Úblank_is_unsetz7Mattermost: ignoring message in non-allowed channel: %sNÚrequire_mentionÚMATTERMOST_REQUIRE_MENTIONÚtrueÚfree_response_channelsÚ!MATTERMOST_FREE_RESPONSE_CHANNELSÚ@c              3  ód   <"  € T F%  qP                  4       SP                  4       9   x € K'  	  R # 5ir¿   )r�   )rÁ   ÚpatternrÌ  s   & €r*   rÃ   Ú:MattermostAdapter._apply_channel_gating.<locals>.<genexpr>ý  s%   øé € ÐbÑQaÀgŸ-™-›/¨\×-?Ñ-?Ó-AÖAÓQaùs   ƒ-0TzAMattermost: skipping non-DM message without @mention (channel=%s)rX   )Úflags>   Ú0ÚnoÚfalse)r@   Ú_extra_or_secretr]   rV   re   rj   r;   r�   r{   rz   rÎ   r^  r_  ÚescapeÚ
IGNORECASEr=   )	r†   rä   rÌ  rÎ  rÑ  Úfree_channelsÚmention_patternsÚhas_mentionrØ  s	   &&f      r*   Ú_apply_channel_gatingÚ'MattermostAdapter._apply_channel_gatingð  sd  ø€ ô +Ô+;¸D¿K¹K×<MÑ<MÐOað  dAð  RWô  ,Xó  YÐß 
Ô BÜ�L‰LÐRÐT^Ô_ÙÜÔ.¨t¯{©{×/@Ñ/@ÐBSÐUqÐsyð  KPô  Qó  ß %¡£Ð/CñDˆä'Ü˜TŸ[™[×.Ñ.Ð0HÐJmð  Dô  EóFˆà × 2Ñ 2Ð3Ð4¸¸$×:KÑ:KÐ9LÐ6MÐNÐß“cÔbÑQaÓb—c—c’cÔbÑQaÓbÓbˆß˜zÔ>Ç{Ü�L‰LÐ\Ð^hÔiÙßÛ+�Ü!Ÿvšv¤b§i¢i°Ó&8¸"¸lÔRT×R_ÑR_Ô`×fÑfÓh’ñ ,àÐr,   c               ó    € V ^8„  d   QhRRRR/# )r$   râ   z	list[str]r'   ztuple[list[str], list[str]]r(   )r)   s   "r*   r+   ro     s   € ÷ 'ñ '°Ið 'ÐB]ñ 'r,   c              ƒ  óf  a"  € ^ RI p^ RIHpHpHp . . rvRVRV/pV EF®  p	 V P                  RV	 R24      G Rj  x€L
 p
V
P                  RRV	 24      pV
P                  R	R
4      oV P                  P                  V P                   RV	 2V P                  4       VP                  ^R7      R7      ;_uu_4       GRj  x€L
 pVP                  R8¼  d4   \        P                  RWœP                  4        RRR4      GRj  x€L
  Ké  VP                  4       G Rj  x€L
 p\        V3R lV 4       R4      pV'       dP   TP!                  WŽ,          ! T\#        V4      P$                  ;'       g    \&        V,          4      G Rj  x€L
 4       MTP!                  V! WÛ4      G Rj  x€L
 4       VP!                  S4       RRR4      GRj  x€L
  EK±  	  Wg3#  EL™ EL LÙ LÁ L[ L= L  + GRj  x€L 
 '       g   i     EKá  ; i  \(         d#   p\        P                  RYŸ4        Rp?EK  Rp?ii ; i5i)u`   Download attachments now (URLs need auth headers downstream tools lack) â†’ (paths, mime types).N)Úcache_audio_from_bytes_asyncÚcache_document_from_bytes_asyncÚcache_image_from_bytes_asyncr    r!   zfiles/z/infor+  Úfile_Ú	mime_typern  z/api/v4/files/rŸ   )rœ   r¡   r¢   z/Mattermost: failed to download file %s: HTTP %sc              3  óZ   <"  € T F   pSP                  V4      '       g   K  Vx € K"  	  R # 5ir¿   ©r†  )rÁ   r}  Úmimes   & €r*   rÃ   Ú:MattermostAdapter._download_attachments.<locals>.<genexpr>  s   øé € Ð"N©i¨¸4¿?¹?È1×;M§1¢1«iùs   ƒ+¡
+z)Mattermost: error downloading file %s: %s)rc   Úgateway.platforms.baserè  ré  rê  rµ   r/   r|   rw   rŽ   r¦   r§   re   rf   rq  Únextr•  r   ÚsuffixÚ_INBOUND_CACHE_EXTrˆ  )r†   râ   rc   rè  ré  rê  Ú
media_urlsÚmedia_typesÚ	cache_fnsrŸ  Ú	file_infor~  r¬   ró   Úprefixr®   rï  s   &&              @r*   Ú_download_attachmentsÚ'MattermostAdapter._download_attachments  sö  øé € ã÷	
ñ 	
ð
 #% b�KØÐ;¸XÐGcÐdˆ	ÜˆCðVØ"&§-¡-°&¸¸¸UÐ0CÓ"D×D�	Ø!Ÿ™ f°°c°U¨mÓ<�Ø —}‘} [Ð2LÓM�ØŸ=™=×,Ñ,Ø—~‘~Ð& n°S°EÐ:ÀD×DUÑDUÓDWØ#×1Ñ1¸Ð1Ó;ð -÷ =÷ =ô =à@DØ—{‘{ cÔ)ÜŸ™Ð'XÐZ]×_jÑ_jÔkØ ÷=÷ =ñ =ð '+§i¡i£k× 1�IÜ!Ô"N©iÓ"NÐPTÓU�FßØ"×)Ñ)Ø"+Ö"3°I¼tÀE»{×?QÑ?Q×?oÐ?oÔUgÐhnÕUoÓ"p×põrð #×)Ñ)Ñ0OÐPYÓ0a×*aÔbØ×&Ñ& tÔ,÷=÷ =ò =ñ ð* Ð&Ð&ò' Eô=ñ !2ñ qá*a÷=÷ =÷ =ô =ûô ô VÜ—‘ÐJÈC×UÓUûðVüsú   ƒH1¢HºG»BHÂ=G
Â>HÃ3G#Ã4HÃ?GÄ HÄH1ÄG#ÄG
ÄAG#Å,G#ÆGÆG#Æ!GÆ"G#Æ;HÇG!ÇHÇH1ÇHÇHÇHÇG#ÇG#ÇG#Ç!HÇ#G>Ç)G,Ç*
G>Ç5G>Ç7HÇ;H1Ç>HÈH.ÈH)È"H1È)H.È.H1c               ó    € V ^8„  d   QhRRRR/# )r$   rÉ  r&   r'   r  r(   )r)   s   "r*   r+   ro   '  s   € ÷ (Yñ (Y¨Nð (Y¸tñ (Yr,   c              ƒ  	ó^  a"  € VP                  R 4      R8w  d   R# VP                  R/ 4      p \        P                  ! VP                  R4      ;'       g    R4      pTP                  RR4      TP                  RR4      rTY@P
                  8X  g9   TP                  R4      '       g"   T P                  P                  T4      '       d   R# TP                  R	R4      TP                  R
R4      R8H  rvTP                  RR4      pT'       g   T P                  Yh4      pTf   R# TP                  R4      ;'       g    Rp	T	'       g$   T P                  R8X  d   T'       g   T'       d   Tp	TR,          P                  4       '       d6   TP                  4       P                  R4      '       d   TP                  4       pT P                  TP                  R4      ;'       g    . 4      G Rj  x€L
 w  p
oTP                  R4      '       d   \        P                  pMAS'       d*   \!        T3R l\"         4       \        P$                  4      pM\        P&                  pT P)                  T\*        P                  TP                  R
R4      R4      YBP                  RR4      P                  R4      ;'       g    TY•R7      p^ RIHp T P1                  \3        Y‹YÃTT
ST! T P4                  P6                  TR4      R7      4      G Rj  x€L
  R#   \        P                  \        3 d     R# i ; i ELA L+5i)rÉ  ÚpostedNrB   rË   rX   Úuser_idrE   r,  rä   Úchannel_typer   r   rØ   rÈ   rÊ   :Né   NrO   râ   c              3  ó´   <a"  € T FL  w  op\         ;QJ d    V3R  lS 4       F  '       g   K   RM	  RM! V3R  lS 4       4      '       g   KH  Vx € KN  	  R# 5i)c              3  óD   <"  € T F  qP                  S4      x € K  	  R # 5ir¿   rî  )rÁ   Úmrù  s   & €r*   rÃ   Ú?MattermostAdapter._handle_ws_event.<locals>.<genexpr>.<genexpr>C  s   øé € ÐItÑhsÐcdÏ,É,ÐW]×J^ÐJ^Óhsùs   ƒ TFN)rÎ   )rÁ   Úmtrù  rö  s   & @€r*   rÃ   Ú5MattermostAdapter._handle_ws_event.<locals>.<genexpr>C  s8   ùé € ÐuÑ2B¡J F¨BÇcÃcÔItÑhsÓItÇcÇcÂcÔItÑhsÓIt×FtŸRšRÓ2Bùs   „A—A®AÁ
Ar   Úsender_namerÖ  )rÒ   Ú	chat_typerÿ  Ú	user_namerå   rI   )Úresolve_channel_prompt)r¨   Úmessage_typeÚsourceÚraw_messagerI   rõ  rö  Úchannel_prompt)r/   r�   r¿  rÀ  rÁ  rz   r…   Úis_duplicaterä  r‚   Úisspacer¥   r†  rú  r   ÚCOMMANDrò  Ú_MEDIA_MSG_TYPESÚDOCUMENTr½  Úbuild_sourcer.  rñ  r  Úhandle_messager   r]   rV   )r†   rÉ  rB   rË   Ú	sender_idr  rä   Úis_dmrÌ  rå   rõ  Úmsg_typer  r  rö  s   &&            @r*   rÂ  Ú"MattermostAdapter._handle_ws_event'  s�  øé € Ø�9‰9�WÓ Ô)ÙØ�y‰y˜ Ó$ˆð	Ü—:’:˜dŸh™h vÓ.×4Ð4°"Ó5ˆDð "ŸX™X i°Ó4°d·h±h¸tÀRÓ6H�7Ø×)Ñ)Ô)¨T¯X©X°f×-=Ò-=ÀÇÁ×AYÑAYÐZa×AbÒAbÙØ ŸH™H \°2Ó6¸¿¹ÀÐQTÓ8UÐY\Ñ8\�EØ—x‘x 	¨2Ó.ˆßØ×5Ñ5°jÓOˆLØÒ#Ùà—H‘H˜YÓ'×/Ð/¨4ˆ	ß˜T×-Ñ-°Ô9Ç%ÏGØˆIØ˜Õ×#Ñ#×%Ò%¨,×*=Ñ*=Ó*?×*JÑ*JÈ3×*OÒ*OØ'×.Ñ.Ó0ˆLØ(,×(BÑ(BÀ4Ç8Á8ÈJÓCW×C]ÐC]Ð[]Ó(^×"^Ñˆ
�KØ×"Ñ" 3×'Ò'Ü"×*Ñ*‰HßÜÔuÕ2BÓuÜ'×0Ñ0ó2‰Hô #×'Ñ'ˆHØ×"Ñ"ØÔ*;×*?Ñ*?ÀÇÁÈÐY\Ó@]Ð_hÓ*iØ¯©°-ÀÓ)D×)KÑ)KÈCÓ)P×)]Ð)]ÐT]Øð #ó 5ˆõ 	BØ×!Ñ!¤,Ø¸VÐbiØ!¨{Ù1°$·+±+×2CÑ2CÀZÐQUÓVô#Xó Y÷ 	Yò 	Yøô? ×$Ñ$¤iÐ0ô 	Úð	úò$ #_ñ	Yùs˜   ƒ+L-¯'L ÁL ÁA	L-Â( L-Ã	A0L-Ä:
L-ÅL-ÅL-Å&L-Æ$L-Æ*2L-Ç
L-Ç'L(Ç(L-ÈL-ÈBL-Ê1AL-Ë?L+Ì L-ÌL%Ì!L-Ì$L%Ì%L-Ì+L-)rw   rz   r{   r€   r…   r„   rƒ   r   r‚   r|   rx   r}   r~   r¿   )rn  )NN)NNN)NNNN)ÚfileN)Ng        )*Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Úsplits_long_messagesÚserial_receive_loopru   r�   rŽ   r¯   rµ   rº   rÏ   rÝ   ré   rð   rÿ   r  r  ræ   r'  r/  r3  r8  r?  rI  rP  rU  rZ  r#  r>  rH  r‹  r—  r  rª  rä  rú  rÂ  Ú__static_attributes__Ú__classcell__)r‡   s   @r*   rm   rm   h   sî   ø† Ù@àÐØÐ÷,ð ,õ&Kõ:÷õ@,õ6õmõ;÷Nõ3÷
5ð$°E÷ õ*
0õL÷
õQ÷[ðqÐbg÷ q÷f÷f÷g÷
f÷fõC÷z÷>YõM÷2#gò #gõN"9õHõ,õ,'÷B(Yó (Yr,   rm   rå   Úmedia_filesÚforce_documentFc               ó0   € V ^8„  d   QhRRRRRRRRRR	R
R/# )r$   rÒ   r;   rØ   rå   rá   r%  zOptional[list]r&  ra   r'   r&   r(   )r)   s   "r*   r+   r+   T  s9   € ÷ 5<ñ 5<¨Sð 5<¸3ð 5<Èmð 5<Ø(6ð5<ØOSð5<Ø`nñ5<r,   c             ƒ  ó	  "  €  ^ RI p\        T 4      w  rxTP	                  R4      TP                  4       r‡T'       d	   T'       g   \        R4      # RRT 2/p	/ T	CRR/Cp
 ^ R	IHpHp T! T! R
R7      4      w  rÞTP                  ! R)RTP                  ^<R7      /TB ;_uu_4       GRj  x€L
 p. pT;'       g    .  EFÊ  p\        T\        4      '       d   TP                  R4      MTpT'       d&   \        P                  P!                  T4      '       g   K\  TP#                  4       pTP%                  RT4       TP%                  R\&        P(                  ! \+        T4      P,                  4      G Rj  x€L
 \        P                  P/                  T4      R7       TP0                  ! T R23RTRT	/TB ;_uu_4       GRj  x€L
 pTP2                  R*9  da   TP5                  4       G Rj  x€L
 p\        RTP2                   RTR,           24      uuRRR4      GRj  x€L
  u uuRRR4      GRj  x€L
  # TP7                  4       G Rj  x€L
 pTP9                  R TP                  R. 4       4       4       RRR4      GRj  x€L
  EKÍ  	  RTRT/pT'       d   TTR&   T'       d   TTR&   TP0                  ! T R23RT
RT/TB ;_uu_4       GRj  x€L
 pTP2                  R*9  d_   TP5                  4       G Rj  x€L
 p\        RTP2                   RTR,           24      uuRRR4      GRj  x€L
  uuRRR4      GRj  x€L
  # TP7                  4       G Rj  x€L
 pRRR4      GRj  x€L
  R R!R"R#R$TR%XP                  R&4      /uuRRR4      GRj  x€L
  #   \         d    \        R4      u # i ; i EL ELE ELú ELÔ EL¤ EL“ EL} ELH  + GRj  x€L 
 '       g   i     EK+  ; i EL Lò LÁ L± Lš LŒ  + GRj  x€L 
 '       g   i     L£; i L€  + GRj  x€L 
 '       g   i     R# ; i  TP:                   d   p\        R'T 24      u Rp?# Rp?i\<         d   p\        R(T 24      u Rp?# Rp?ii ; i5i)+a   Send via the Mattermost v4 REST API without a live gateway adapter (out-of-process cron).

Token/URL: ``pconfig`` with env fallback. ``media_files`` upload via ``POST /files`` and attach by
file_id; ``thread_id`` becomes ``root_id``. ``force_document`` is signature parity only (unused).
Nz/aiohttp not installed. Run: pip install aiohttprO   zPMattermost standalone send: MATTERMOST_URL and MATTERMOST_TOKEN must both be setr”   r•   rŒ   r�   )Úresolve_proxy_urlÚproxy_kwargs_for_aiohttpÚMATTERMOST_PROXY)Úplatform_env_varr¡   rŸ   r™   rä   rø   )rõ   rù   rB   rœ   zMattermost file upload failed (z): :Ni�  Nc              3  ód   "  € T F&  qP                  R 4      '       g   K  VR ,          x € K(  	  R# 5i)rE   N)r/   )rÁ   r  s   & r*   rÃ   Ú#_standalone_send.<locals>.<genexpr>z  s&   é € Ð#oÑ;\°4×`hÑ`hÐim×`n¤J D¨§J¢JÓ;\ùs   ‚0Ÿ0rú   rØ   rÈ   râ   z/api/v4/postsr�   zMattermost API error (rG   TÚplatformÚ
mattermostrÒ   rI   rE   z"Mattermost send failed (network): zMattermost send failed: r(   >   r¤   éÉ   )rc   rd   r   r^   ry   r=   rñ  r)  r*  r  r¦   r1   r2   r/   Úosr™   ry  rû   rü   r	  Ú	to_threadr   rz  ÚbasenamerË   r§   r¨   r�   Úextendr©   rˆ  )ÚpconfigrÒ   rØ   rå   r%  r&  rc   Úbase_urlrY   Úupload_headersrœ   r)  r*  Ú_sess_kwÚ_req_kwÚsessionrâ   ÚmediarM  rý   Úupload_respr­   Úupload_datar%   r¬   rB   r®   s   &&&$$$                     r*   Ú_standalone_sendr?  T  sþ  é € ðMÛô % WÓ-�O€HØ—o‘o cÓ*¨E¯K©K«MˆeßŸ5ÜÐlÓmÐmØ%¨°°Ð'8Ð9€NØD�ÐD Ð1CÑD€Gð#<çVÙ4Ñ5FÐXjÔ5kÓlÑˆØ×(Ò(Ñ]°×1FÑ1FÈRÐ1FÓ1PÐ]ÐT\×]×]Ò]ÐahØ"$ˆHØ$×*Ð*¨Ó*�Ü1;¸EÄ4×1HÒ1H˜EŸI™I fÔ-Èe�	ß ¬¯©¯©°y×(AÒ(AÙØ×'Ñ'Ó)�Ø—‘˜|¨WÔ5Ø—‘˜w¬g×.?Ò.?ÄÀYÃ×@ZÑ@ZÓ.[×([Ü(*¯©×(8Ñ(8¸Ó(Cð ô Eà"Ÿ<š<¨8¨*°MÐ(Bñ 3Èð 3ÐWeð 3Ø*1÷3÷ 3ò 3Ø6AØ"×)Ñ)°Ô;Ø%0×%5Ñ%5Ó%7×7˜Ü)Ð,KÈK×L^ÑL^ÐK_Ð_bÐcgÐhlÕcmÐbnÐ*oÓp÷	3÷ 3ó 3÷ ^×]Ò]ð )4×(8Ñ(8Ó(:×":�KØ—O‘OÑ#o¸;¿?¹?È<ÐY[Ô;\Ó#oÔo÷3÷ 3ò 3ñ +ð (4°W¸iÈÐ&QˆGßØ%.�˜	Ñ"ßØ&.�˜
Ñ#Ø—|’| x j°Ð$>ÑiÈÐiÐV]ÐiÐah×i×iÒiÐmqØ—;‘; jÔ0Ø!%§¡£×,�DÜ%Ð(>¸t¿{¹{¸mÈ3ÈtÐTXÍzÈlÐ&[Ó\÷ j×iÑi÷- ^×]Ò]ð4 "ŸY™Y›[×(�÷	 j×ið
 ˜t Z°¸yÈ'ÐS_Ðae×aiÑaiÐjnÓaoÐp÷7 ^×]Ò]øô ô MÜÐKÓLÒLðMúò ^ò )\ò3ò  8ò3ò ^ò #;÷3÷ 3÷ 3õ 3úò já,ñ jñ- ^ñ4 )÷	 j×i×iÒiú÷- ^×]×]Ó]ûð8 ×Ñô FÜÐ>¸s¸eÐDÓEÕEûÜô <ÜÐ4°S°EÐ:Ó;Õ;ûð<üsY  ‚Q?„N ˆ<Q?ÁQ?Á A	P2 Â)N4Â*P2 Â-APÃ1$PÄAPÅ2N7Å3APÇ N:ÇPÇ%OÇ)N=Ç*%OÈPÈO ÈPÈ#P2 È0OÈ1P2 È5Q?È6OÉ	OÉ
,OÉ6PÊO	
ÊPÊPÊ&+PËO*ËPË%O7	Ë:O-Ë;%O7	Ì PÌ-O/
Ì.PÌ2P2 Ì?O1Í P2 ÍQ?ÍO7	ÍO3ÍO7	ÍPÍ(O5Í)PÎP2 ÎPÎP2 ÎQ?ÎN1Î.Q?Î0N1Î1Q?Î4P2 Î7PÎ:PÎ=OÏ PÏP2 ÏOÏ	PÏO'ÏOÏ
O'ÏO'Ï PÏ-O7	Ï/PÏ1P2 Ï3O7	Ï5PÏ7PÏ=P Ï>
PÐ	PÐPÐP2 ÐP/	ÐPÐ
P/	Ð'P/	Ð)P2 Ð-Q?Ð/P2 Ð2Q<ÑQÑQ<ÑQ?ÑQ<Ñ#Q<Ñ$Q7Ñ1Q<Ñ2Q?Ñ7Q<Ñ<Q?c               ó   € V ^8„  d   QhRR/# r  r(   )r)   s   "r*   r+   r+   Ž  s   € ÷ +Eñ +E˜4ñ +Er,   c                 ó¨  a€ ^ RI Hp Hp ^ RIHpHpHoHp ^ RIH	p R V3R llpV! R4       V! RRR4      '       d   R	# V! R
RR4       \        4        V! R4      pV'       d   V! RVP                  R4      4       V! RRR7      pV'       g   R	# V! RV4       V! R4       \        4        V! RRR4       \        4        V! R4      p	V	'       d#   V! RV	P                  RR4      4       V! R4       MS! R4       \        4        V! RRR4       V! R 4      P                  4       p
V
'       d   V! R!V
4       MV ! R!4      '       d	   S! R"4       S! R#4       R	# )$zSGuide the user through Mattermost bot setup (URL + token, allowlist, home channel).)Úremove_env_valueÚsave_env_value)ÚpromptÚprint_headerÚ
print_infoÚprint_success)Údeclines_reconfigurec               ó    € V ^8„  d   QhRRRR/# )r$   Úlinesr;   r'   r  r(   )r)   s   "r*   r+   Ú'interactive_setup.<locals>.__annotate__”  s   € ÷ ñ �Sð ˜Tñ r,   c                 ó*   <€ V  F  pS! V4       K  	  R # r¿   r(   )rJ  ÚlinerF  s   * €r*   r  Úinteractive_setup.<locals>.info”  s   ø€ ÛˆDÙ�tÖó r,   Ú
MattermostzReconfigure Mattermost?rZ   Nz/Works with any self-hosted Mattermost instance.uF      1. In Mattermost: Integrations â†’ Bot Accounts â†’ Add Bot Accountz   2. Copy the bot tokenz3Mattermost server URL (e.g. https://mm.example.com)rW   rO   z	Bot tokenT)ÚpasswordzMattermost token savedu,   ðŸ”’ Security: Restrict who can use your botu6      To find your user ID: click your avatar â†’ Profilez'   or use the API: GET /api/v4/users/mez?Allowed user IDs (comma-separated, leave empty for open access)ÚMATTERMOST_ALLOWED_USERSÚ rX   zMattermost allowlist configureduE   âš ï¸�  No allowlist set - anyone who can message the bot can use it!uL   ðŸ“¬ Home Channel: where Hermes delivers cron job results and notifications.uH      To get a channel ID: click channel name â†’ View Info â†’ copy the IDzK   You can also set this later by typing /set-home in a Mattermost channel.z9Home channel ID (leave empty to set later with /set-home)ÚMATTERMOST_HOME_CHANNELzHome channel cleared.z2   Open config in your editor:  hermes config edit)Úhermes_cli.configrB  rC  Úhermes_cli.cli_outputrD  rE  rF  rG  Úhermes_cli.setup_platformsrH  Úprintry   Úreplacer=   )rB  rC  rD  rE  rG  rH  r  Úmm_urlrY   Úallowed_usersÚhome_channelrF  s              @r*   Úinteractive_setupr\  Ž  sB  ø€ çBßUÓUÝ?÷ð ñ �ÔÙ˜LÐ*CÐEW×XÒXÙÙÐ	:Ø	QÐSmôoä	„GÙÐIÓJ€FßÙÐ'¨¯©°sÓ);Ô<Ù�;¨Ô.€EßÙÙÐ% uÔ-ÙÐ*Ô+Ü	„GÙÐ	7Ð9qØ	2ô4ä	„GÙÐ\Ó]€MßÙÐ1°=×3HÑ3HÈÈbÓ3QÔRÙÐ7Õ8áÐZÔ[Ü	„GÙÐ	WØ	SØ	VôXñ ÐUÓV×\Ñ\Ó^€LßÙÐ0°,Õ?Ù	Ð3×	4Ò	4ÙÐ*Ô+ÙÐCÖDr,   c               ó$   € V ^8„  d   QhRRRRRR/# )r$   Úyaml_cfgr2   Úmattermost_cfgr'   zdict | Noner(   )r)   s   "r*   r+   r+   Ä  s!   € ÷ <ñ < ð <°tð <Àñ <r,   c                ó"   € \        V\        4      # )uÉ   ``apply_yaml_config_fn`` (#24836 / #25443): ``config.yaml`` ``mattermost:`` keys â†’ env vars (env wins;
skipped under a multiplexed secondary profile) + ``PlatformConfig.extra`` (extra-first readers).)Ú_apply_yaml_bridgeÚ_YAML_BRIDGE)r^  r_  s   &&r*   Ú_apply_yaml_configrc  Ä  s   € ô ˜n¬lÓ;Ð;r,   rZ   rW   u¸  You are in a Mattermost workspace communicating with your user. Mattermost renders standard Markdown â€” headings, bold, italic, code blocks, and tables all work. You can send media files natively: include MEDIA:/absolute/path/to/file in your response. Images (.jpg, .png, .webp) are uploaded as photo attachments, audio and video as file attachments. Image URLs in markdown format ![alt](url) are rendered as inline previews automatically.c               ó   € V ^8„  d   QhRR/# r  r(   )r)   s   "r*   r+   r+   Ø  s   € ÷ ñ �Tñ r,   c                óB  € ^RI Hp V P                  ! R$/ RRbRRbR\        bRRbR	R
bRR%bR\        bR\
        bR\        bRRR.bRRbR\        bR\        bRRbR\        bR\        bRRbRRbR\        bRR bR!VP                  bR"VP                  bVP                  B  R## )&u:   Plugin entry point â€” called by the Hermes plugin system.)Úgateway_envr+  r0  ÚlabelrO  Úadapter_factoryÚdashboard_descriptionz:Connect Hermes to Mattermost channels and direct messages.Údocs_urlzhttps://mattermost.com/deploy/Údashboard_env_varsrW   rZ   Úcheck_fnÚvalidate_configÚis_connectedÚrequired_envÚinstall_hintzpip install aiohttpÚsetup_fnÚapply_yaml_config_fnÚcron_deliver_env_varrS  Ústandalone_sender_fnÚmax_message_lengthÚemojiu   ðŸ’¬Úallow_update_commandTÚplatform_hintÚdisplay_tierÚmediumÚenv_overridesÚenv_enable_credentialsNr(   )rW   rZ   rQ  )rX   rf  Úregister_platformrm   rg   rk   Ú_is_connectedr\  rc  r?  r$  Ú_PLATFORM_HINTÚENV_OVERRIDESÚENV_ENABLE_CREDENTIALSÚAUTHZ)Úctxrf  s   & r*   Úregisterr„  Ø  s  € åØ×Òò ÙðÙ!-ðÝ?PðáZðñ 2ðñ ^ð	õ
 /ðõ
 A[ðõ #ðð 3CÐDVÑ1Wðñ +ðõ 6Gðõ 0ðñ 7ðõ .ðõ +ðñ 39ðñ PTðõ %ðñ ðð "×/Ò/ðð  +×AÒAÀ[×EVÑEVôr,   ))rÑ  rÒ  r�   )rÔ  rÕ  Úcsv)rÎ  rÏ  r…  )Kr   Ú
__future__r   r	  r�   Úloggingr{  r2  r^  Úpathlibr   Úurllib.parser   r‡  Útypingr   r   r   r   r	   Úgateway.configr
   r   Úgateway.platforms.helpersr   r   rñ  r   r   r   Úgateway.platforms.eventr   r   Úgateway.platforms._sharedr   ra  r   Ú_env_is_connectedr   rÞ  r   r\   r   Ú	getLoggerr  re   r2   r;   rÔ   r$  r.  r0   r©  r±  r¯  rï   ÚPHOTOÚVOICEr  rô  r4   r@   rJ   rS   r^   rg   rk   rm   r?  r\  rb  rc  r~  r  r„  r(   r,   r*   Ú<module>r“     si  ðñõ #ã Û Û Û Û 	Û 	Ý Ý ,ß 3Õ 3ç 3Ý 9Ý 1ß UÑ Uß =÷õ ð 
×	Ò	˜8Ó	$€à�T˜#˜s˜(•^Õ$€	ð €ð ˜$  W¨c°7¸CÀÐKÐ à&8¸$Ð%?Ð "àADÀdÈCÐ >Ð Ð+Ð->à2Ð Ø˜{×0Ñ0Ð1°H¸k×>OÑ>OÐ3PÐQÐ Ø ¨°&Ð9Ð õõ=õ;õ<õZõõ	ôgYÐ+ô gYðX5<Ð^bð 5<Ø9=ð5<ØV[÷5<õt+Eð`@€õ<ñ "Ð"4Ð6FÓG€ð
Að ÷r,   