+
    kHàjõ« ã                   óf  € R t ^ RIt^ RIt^ RIt^ RIt^ RI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 ^ 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H t!H"t#H$t% ^ R	IH&t& R‘R
 lt'R t(]PR                  ! ]*4      t+^ RI,H-t-H.t.H/t/H0t0 ^ RI1H2t2 ^ RI3H4t4H5t5 ^ RI6H7t7 ^ RI8H9t9H:t: ^	t;]<! ];RR04      t=]P|                  ! R4      t?Rt@]P|                  ! R4      tAR R ltB^2tC^tDRtERtFRtGRtHRtI^tJR’tKRtL^xtMR R ltNR R  ltOR!tPRtQR"tRR#tSR$tT]! R%4      P«                  4       tVR&tW]P|                  ! R']W R(2]P°                  4      tY]P|                  ! ]W]P°                  4      tZ]P|                  ! R)]P°                  4      t[R* R+ lt\R, R- lt]R. R/ lt^R0 R1 lt_R2 R3 lt`R4 R5 ltaR6 R7 ltb]a! R84      tc^ R9IdHeteHftfHgtgHhthHitj R: R; ltkR< tlR= R> ltmR? R@ ltnRA RB ltoRC RD ltpRE RF ltqRG RH ltrRI RJ ltsRK RL lttRM RN ltuRO RP ltvR“RR RS lltwR‘RT RU lltxR”tyRV RW ltzR‘RX RY llt{R‘RZ R[ llt|R‘R\ R] llt}R^RQR_RR`]G/Ra Rb llt~RctR‘Rd Re llt€RfR/Rg Rh llt�Ri Rj lt‚Rk Rl ltƒRm Rn lt„Ro Rp lt…Rq Rr lt†Rs Rt lt‡RutˆRv]5EP                  3Rw]5EP                  3Rx]5EP                  33tŒRv]5EP                  Rx]5EP                  Rw]5EP                  Ry]5EP                  /tŽ ! Rz R{]:]-4      t�R| R} lt�R~ R lt‘R€ R� lt’R‚ Rƒ lt“R•t”R„ R… lt•R† R‡ lt–RˆRR‰RRŠR‹/RŒ R� llt—RŽ R� lt˜R� t™R# )–a\  Buzz platform adapter (Block's Nostr-based human+agent community relay).

Outbound and polling go through the ``buzz`` CLI ("JSON in, JSON out", never a shell);
inbound prefers a NIP-42-authenticated WebSocket subscription with a CLI poll fallback.
Config lives in ``gateway.platforms.buzz.extra`` (relay_url, channels, home_channel,
poll_interval, cli_path, credentials_file, allowed_users, reply_in_thread, reaction_only_users)
or the matching ``BUZZ_*`` env vars (env overrides config). The only secret is
BUZZ_PRIVATE_KEY (nsec or hex): it reaches the CLI via the subprocess env and is never logged.
N©ÚOrderedDict)Údatetime)ÚPath)ÚAnyÚDictÚListÚOptionalÚTuple)ÚurlsplitÚ
urlunsplit)Úis_multiplex_active)Úapply_yaml_bridgeÚget_scoped_secretÚprofile_scopedÚseed_extra_from_env)Ú
send_errorc                ó   € \        WRR7      # )zÁBuzz reads consult a one-shot profile-scope build when unscoped: ``check_requirements`` runs at
startup before any scope exists, so Bitwarden-managed keys would otherwise be invisible (#95216).T)Úexternal_fallback)Ú_shared_scoped_secret)ÚnameÚdefaults   &&ÚC/home/ubuntu/.hermes/hermes-agent/plugins/platforms/buzz/adapter.pyÚ_get_scoped_secretr   (   s   € ô ! À$ÔGÐGó    c                ó¦   € \        4       '       d-   \        V 4      pVe   V# T;'       g    / P                  V4      # \        P                  ! V 4      # )uÙ  Raw non-secret setting; in a secondary profile scope ``os.environ`` is the DEFAULT profile's, so the
profile's own secret scope (its ``.env``) stands in for env and ``extra`` is the fallback.

Inside a secondary profile scope ``os.environ`` holds the DEFAULT profile's YAML-to-env bridge output
(#98738), so the profile's ``PlatformConfig.extra`` is authoritative and env is not consulted: a missing
key yields ``None`` and callers fail closed to their default instead of silently borrowing the default
profile's relay, channels, or allowlist. Everywhere else â€” single-profile gateways, the default profile
under multiplexing â€” the legacy ``os.getenv`` read is returned unchanged, so env-over-config precedence
is preserved.
)Ú_profile_scopedr   ÚgetÚosÚgetenv)Úenv_nameÚextraÚkeyÚscopeds   &&& r   Ú_scoped_platform_settingr$   .   sG   € ô ×ÒÜ# HÓ-ˆØÒ+ˆvÐG°%·+°+¸2×1BÑ1BÀ3Ó1GÐGÜ�9Š9�XÓÐr   )ÚBasePlatformAdapterÚCachedMediaÚ
SendResultÚcache_media_bytes_async)Úcancel_task)ÚMessageEventÚMessageType)ÚPlatform)Ú	_SEEN_CAPÚBuzzCursorMixiniÉ¯  iË¯  zBmention '@(?P<name>[^']+)' does not match a current channel memberu   â€‹z[0-9a-f]{64}c                óR   € V ^8„  d   QhR\         R\         R\        \         ,          /# )é   ÚcontentÚerrorÚreturn©Ústrr	   )Úformats   "r   Ú__annotate__r7   W   s&   € ÷ 	&ñ 	&´Sð 	&Äð 	&ÌÔRUÍñ 	&r   c                óF  € \         P                  T;'       g    R4      pV'       d   VP                  R4      MRpV'       g   R# \        P                  ! R\        P
                  ! V4       R2\        P                  4      pVP                  R V 4      w  rVV'       d   V# R# )zÀMake a CLI-rejected ``@name`` presentation-only via an invisible separator after the ``@`` (Buzz
p-tags whitespace-prefixed @tokens at publish, so prose like ``@session:...`` fails preflight).Ú r   Nz(?<!\S)@z(?=$|[^A-Za-z0-9._-])c                 óV   € R \         ,           V P                  ^ 4      R,          ,           # )Ú@ºé   NN)Ú$_BUZZ_PRESENTATION_MENTION_SEPARATORÚgroup)Úms   &r   Ú<lambda>Ú9_escape_unresolved_presentation_mention.<locals>.<lambda>_   s"   € ¨#Ô0TÕ*TÐWX×W^ÑW^Ð_`ÓWaÐbdÕWeÖ*er   )Ú_UNRESOLVED_MENTION_ERROR_REÚsearchr?   ÚreÚcompileÚescapeÚ
IGNORECASEÚsubn)r1   r2   Úmatchr   ÚtokenÚescapedÚcounts   &&     r   Ú'_escape_unresolved_presentation_mentionrN   W   sz   € ô )×/Ñ/°·°¸Ó<€Eß"'ˆ5�;‰;�vÔ¨R€DßÙÜ�JŠJ˜(¤2§9¢9¨T£?Ð"3Ð3HÐIÌ2Ï=É=ÓY€EØ—Z‘ZÑ eÐgnÓo�N€Gßˆ7Ð% Ð%r   g      @ç      ð?ç      >@g      N@g     Àr@c                ó0   € V ^8„  d   QhR\         R\         /# ©r0   Úvaluer3   ©r5   )r6   s   "r   r7   r7   r   s   € ÷ 
2ñ 
2¤Sð 
2¬Sñ 
2r   c                ón  € \        T ;'       g    R4      P                  RR4      P                  R^4      R,          pRP                  R V 4       4      P	                  4       pVR9   d   R# \        \        V4      P                  P                  R4      4      ^8:  d   \        V4      P                  MRpV'       d   VR\        V4      )  MTp\        \        VP                  R4      4      ,
          pVP                  R4      RV P                  RRR	7      P                  R
4      pT;'       g    R V 2# )zAReturn a basename that is safe for cache files and agent context.r9   Ú\Ú/c              3   ó\   "  € T F"  p\        V4      ^ 8¼  g   K  VR8w  g   K  Vx € K$  	  R# 5i)é    ÚN)Úord)Ú.0Úcs   & r   Ú	<genexpr>Ú,_safe_attachment_filename.<locals>.<genexpr>u   s$   é € ÐC™d˜¤c¨!£f°¡l”1°q¸F±{—1’1›dùs   ‚,™,¢
,zattachment.binúutf-8NÚignore©Úerrorsz .Ú
attachmentéÿÿÿÿ>   r9   Ú.ú..)r5   ÚreplaceÚrsplitÚjoinÚstripÚlenr   ÚsuffixÚencodeÚ_MAX_ATTACHMENT_FILENAME_BYTESÚdecodeÚrstrip)rS   r   rm   ÚstemÚbyte_budgetÚ	safe_stems   &     r   Ú_safe_attachment_filenameru   r   s  € äˆu�{ˆ{˜Ó×#Ñ# D¨#Ó.×5Ñ5°c¸1Ó=¸bÕA€DØ�7‰7ÑC™dÓCÓC×IÑIÓK€DØˆÔÙÜ"%¤d¨4£j×&7Ñ&7×&>Ñ&>¸wÓ&GÓ"HÈBÔ"NŒT�$‹Z×ÒÐTV€Fß"(ˆ4�”#�f“+�Ñ¨d€DÜ0´3°v·}±}ÀWÓ7MÓ3NÕN€KØ—‘˜GÓ$ \ kÐ2×9Ñ9¸'È(Ð9ÓS×ZÑZÐ[_Ó`€IØ×'Ð'˜<Ð(¨¨Ð1Ð1r   c                óh   € V ^8„  d   QhR\         R\        \        \         \        3,          ,          /# rR   )r5   r	   ÚtupleÚint)r6   s   "r   r7   r7      s'   € ÷ ñ œcð ¤h¬u´S¼#°X­Õ&?ñ r   c                ó¢  € \        T ;'       g    R4      P                  4       pV'       g   R#  \        RV9   d   TMRV 24      pVP                  ;'       g    RP	                  4       P                  R4      pVP                  ;'       g    RpTP                  '       d   TP                  R9  g	   T'       g   R# Y43#   \         d     R# i ; i)zDNormalize a configured host/URL to an exact HTTPS-equivalent origin.r9   Nz://z//rf   é»  >   ÚwssÚhttps)	r5   rk   r   ÚhostnameÚlowerrq   ÚportÚ
ValueErrorÚscheme)rS   ÚrawÚparsedÚhostr   s   &    r   Ú_attachment_originr…      s¬   € ä
ˆe�kˆk�rÓ
×
 Ñ
 Ó
"€CßÙðÜ ¨#¤™#°R¸°u°:Ó>ˆØ—‘×%Ð% 2×,Ñ,Ó.×5Ñ5°cÓ:ˆØ�{‰{×!Ð!˜cˆð 	��ˆ˜&Ÿ-™-Ð/?Ô?ÏÙØˆ:Ðøô	 ô Úðús   ¯)B? Á2B? ÂB? Â?CÃCg      4@i€„ iD¬  zhermes-buzz-membershipz~/.config/buzzzThttps?://[^\s<>\[\]()]+/media/[0-9a-f]{64}(?:\.[a-z0-9]{1,10})?(?:\?[^\s<>\[\]()]*)?z!!\[(?P<alt>[^\]]*)\]\(\s*(?P<url>z)(?:\s+[\"'][^\"']*[\"'])?\s*\)z:^/media/(?P<sha>[0-9a-f]{64})(?P<ext>\.[a-z0-9]{1,10})?/?$c                ó<   € V ^8„  d   QhR\         P                  RR/# )r0   Útaskr3   N)ÚasyncioÚTask)r6   s   "r   r7   r7   £   s   € ÷ ñ ¤§¡ð °ñ r   c                óÔ   € V P                  4       '       g>   \        P                  ! \        4      ;_uu_ 4        V P	                  4        RRR4       R# R#   + '       g   i     R# ; i)zLRetrieve a detached stalled receive task's result without blocking recovery.N)Ú	cancelledÚ
contextlibÚsuppressÚ	ExceptionÚ	exception)r‡   s   &r   Ú_consume_ws_read_taskr�   £   sA   € à�>‰>×ÒÜ× Ò ¤×+Õ+Ø�N‰NÔ÷ ,Ñ+ñ ß+×+Ð+ús   ¹AÁA'	c                ó:   € V ^8„  d   QhR\         \        ,          /# ©r0   r3   )r	   rx   )r6   s   "r   r7   r7   ª   s   € ÷ Oñ Oœx¬�}ñ Or   c                 ó¤   €  V P                   e   V P                   #  RRRRR^PR^P/P                  T P                  4      #   \         d     R # i ; i)Nr|   rz   r{   ÚhttpÚws)r   r€   r   r�   )rƒ   s   &r   Ú_effective_portr–   ª   s\   € ðØ�;‰;Ò"Ø—;‘;Ðð #ð �S˜%  f¨b°$¸Ð;×?Ñ?ÀÇÁÓNÐNøô ô Úðús   ‚A  Á AÁAc                ó<   € V ^8„  d   QhR\         R\         R\        /# )r0   ÚurlÚ	relay_urlr3   ©r5   Úbool)r6   s   "r   r7   r7   ³   s!   € ÷ ñ œSð ¬Sð ´Tñ r   c                ó²  € \        V 4      \        V4      r2\        VP                  R9   ;'       d¤    VP                  ;'       d�    VP                  ;'       d|    VP                  P	                  4       VP                  P	                  4       8H  ;'       d?    \        V4      \        V4      8H  ;'       d     \        P                  VP                  4      4      # )zDReturn whether *url* is a Buzz media object on the configured relay.)r”   r|   )	r   r›   r�   r}   r~   r–   Ú_MEDIA_PATH_REÚ	fullmatchÚpath)r˜   r™   Ú	candidateÚrelays   &&  r   Ú_is_relay_media_urlr¢   ³   sÃ   € ä “}¤h¨yÓ&9ˆuÜØ×ÑÐ-Ñ-÷ 	nð 	n°)×2DÑ2D÷ 	nð 	nÈÏÉ÷ 	nð 	nØ×Ñ×$Ñ$Ó&¨%¯.©.×*>Ñ*>Ó*@Ñ@÷	nð 	nä˜IÓ&¬/¸%Ó*@Ñ@÷	nð 	näES×E]ÑE]Ð^g×^lÑ^lÓEmóð r   c                ó¶   € V ^8„  d   QhR\         R\         R\        \        \         ,          \        \        \        \        \         3,          ,          3,          /# )r0   Útextr™   r3   )r5   rw   Úlistrx   )r6   s   "r   r7   r7   ½   sC   € ÷ ñ ¤ð ´ð ¼¼tÄC½yÌ$ÌuÔUXÔZ]Ô_bÐUbÕOcÕJdÐ?dÕ9eñ r   c                ó  a€ . p. p. p\         P                  V 4       F   oSP                  R4      p\        WQ4      '       g   K'  VP	                  SP                  4       4       VP	                  . SP                  4       OSP                  R4      P                  4       N54       WR9  g   K�  VP	                  V4       K¢  	  \        P                  V 4       F¦  o\        ;QJ d    V3R lV 4       F  '       g   K   RM	  RM! V3R lV 4       4      '       d   KE  SP                  ^ 4      p\        WQ4      '       g   Ki  VP	                  . SP                  4       ORN54       WR9  g   K•  VP	                  V4       K¨  	  W#3# )z<Find same-relay media URLs and their safe text replacements.r˜   Úaltc              3   ó„   <"  € T F5  w  rVSP                  4       8*  ;'       d    SP                  4       V8*  x € K7  	  R # 5i©N)ÚstartÚend)r\   rª   r«   rJ   s   &  €r   r^   Ú)_find_relay_media_refs.<locals>.<genexpr>Ë   s4   øé € Ð^É~ÁÀˆu˜Ÿ™›Ñ%×<Ð<¨%¯)©)«+¸Ñ*<Ô<Ë~ùs
   ƒ A ¤A TFr9   )	Ú_MARKDOWN_MEDIA_REÚfinditerr?   r¢   ÚappendÚspanrk   Ú_BARE_MEDIA_REÚany)r¤   r™   ÚurlsÚreplacementsÚmarkdown_spansr˜   rJ   s   &&    @r   Ú_find_relay_media_refsr¶   ½   s*  ø€ à€DØ/1€LØ,.€NÜ#×,Ñ,¨TÖ2ˆØ�k‰k˜%Ó ˆÜ" 3×2Ò2ÙØ×Ñ˜eŸj™j›lÔ+Ø×ÑÐG˜eŸj™j›lÐG¨E¯K©K¸Ó,>×,DÑ,DÓ,FÑGÔHØŽ?Ø�K‰K˜Öñ 3ô  ×(Ñ(¨Ö.ˆß‹3Ô^É~Ó^�3�3Š3Ô^É~Ó^×^Ò^ÙØ�k‰k˜!‹nˆÜ" 3×2Ò2ÙØ×ÑÐ/˜eŸj™j›lÐ/¨BÑ/Ô0ØŽ?Ø�K‰K˜Öñ /ð ÐÐr   c                ó~   € V ^8„  d   QhR\         R\        \        \        \        \         3,          ,          R\         /# )r0   r¤   r´   r3   )r5   r¥   rw   rx   )r6   s   "r   r7   r7   Ö   s7   € ÷ Nñ Nœcð N´´e¼CÄÄc¸MÕ6JÕ1Kð NÔPSñ Nr   c           	      óÂ   € \        VR R7       F  w  r#pV RV  V WR  2p K  	  \        P                  ! RR\        P                  ! RRV 4      4      P                  4       # )T)ÚreverseNz\n{3,}z

z[ \t]+\nÚ
)ÚsortedrE   Úsubrk   )r¤   r´   rª   r«   Úreplacements   &&   r   Ú_replace_media_refsr¾   Ö   s^   € Ü#)¨,À×#EÑˆ�KØ�v˜�,� ˜}¨T°$¨Z¨LÐ9Šñ $Fä�6Š6�)˜V¤R§V¢V¨K¸¸tÓ%DÓE×KÑKÓMÐMr   c                ó$   € V ^8„  d   QhR\         /# ©r0   r   rT   )r6   s   "r   r7   r7   Ü   s   € ÷ (ñ (œñ (r   c                ó¤   € ^ RI p \        '       d   VP                  RV  2\        4      # \        V 4      #   \         d    \        T 4      u # i ; i)zaImport a sibling module loader-agnostically (the test loader imports this file as a bare module).Nrf   )Ú	importlibÚ__package__Úimport_moduleÚ_load_sibling_fileÚImportError)r   rÂ   s   & r   Ú_load_siblingrÇ   Ü   sM   € ãð(ßCNÃ;ˆy×&Ñ&¨¨4¨& z´;Ó?ÐlÔTfÐgkÓTlÐløÜô (Ü! $Ó'Ò'ð(ús   †6 ’6 «
6 ¶AÁAc                ó$   € V ^8„  d   QhR\         /# rÀ   rT   )r6   s   "r   r7   r7   å   s   € ÷ ñ œSñ r   c                 ó"  € ^ RI p\        \        4      P                  V  R24      pVP                  P                  RV  2V4      pVe   VP                  f   Q hVP                  P                  V4      pVP                  P                  V4       V# )é    Nz.pyÚplugin_adapter_buzz_)	Úimportlib.utilr   Ú__file__Ú	with_nameÚutilÚspec_from_file_locationÚloaderÚmodule_from_specÚexec_module)r   rÂ   rŸ   ÚspecÚmodules   &    r   rÅ   rÅ   å   s~   € ÛÜ”‹>×#Ñ# t f¨C LÓ1€DØ�>‰>×1Ñ1Ð4HÈÈÐ2OÐQUÓV€DØÒ §¡Ò 7Ð7Ð7Ø�^‰^×,Ñ,¨TÓ2€FØ‡K�K×Ñ˜FÔ#Ø€Mr   Ú
nostr_auth)Ú_BECH32_CHARSETÚ_bech32_hrp_expandÚ_bech32_polymodÚ_convertbitsÚ_npub_to_hexc                óF   € V ^8„  d   QhR\         R\        \         ,          /# )r0   Ú
pubkey_hexr3   r4   )r6   s   "r   r7   r7   ÷   s"   € ÷ 
Jñ 
JœCð 
J¤H¬S¥Mñ 
Jr   c                ó¬  €  \         P                  V 4      p\        T4      ^ 8w  g   \	        T^^4      ;pf   R# \        \        R4      T,           . RO,           4      ^,          p\        ^4       Uu. uF   qC^^T,
          ,          ,	          ^,          NK"  	  ppRRP                  R Y%,            4       4      ,           #   \         d     R# i ; iu upi )u=   Encode a 64-char hex pubkey as an ``npub1â€¦`` bech32 string.NÚnpubÚnpub1r9   c              3   ó<   "  € T F  p\         V,          x € K  	  R # 5ir©   )r×   )r\   Úds   & r   r^   Úhex_to_npub.<locals>.<genexpr>  s   é € ÐI¹°Aœ_¨Q×/Ò/»ùs   ‚)rÊ   rÊ   rÊ   rÊ   rÊ   rÊ   )	ÚbytesÚfromhexr€   rl   rÚ   rÙ   rØ   Úrangerj   )rÝ   r‚   ÚdataÚpolymodÚiÚchecksums   &     r   Úhex_to_npubrë   ÷   s¹   € ðÜ�m‰m˜JÓ'ˆô ˆ3ƒx�2„~¤,¨s°A°qÓ"9Ð9˜$ÒBÙÜÔ0°Ó8¸4Õ?ÒBTÕTÓUÐXYÕY€GÜ7<¸Q´xÓ@±x°!˜A  Q¥�KÕ'¨2×-Ð-±x€HÐ@Ø�R—W‘WÑI¸¾ÓIÓIÕIÐIøô ô Úðüò
 As   ‚B? Á2&CÂ?CÃCc                 óT   € \        V \        4      '       d   V P                  R 4      # T # ©Ú,)Ú
isinstancer5   Úsplit)r‚   s   &r   Ú
_split_csvrñ     s!   € Ü'¨¬S×1Ò1ˆ3�9‰9�S‹>Ð:°sÐ:r   c                ó$   € V ^8„  d   QhR\         /# r’   )Úset)r6   s   "r   r7   r7     s   € ÷ lñ lœñ lr   c                óœ   € \        V 4       Uu0 uF2  p\        V\        4      '       g   K  \        V4      ;p'       g   K0  VkK4  	  up# u upi )zNNormalize a csv string / list of hex pubkeys or npubs to a set of hex pubkeys.)rñ   rï   r5   Ú_normalize_user_ref)r‚   ÚentryÚns   &  r   Ú_pubkey_setrø     s<   € ä% cœ?Ók™?�%¬j¸Ä×.DŒAÔObÐchÓOiÐJiÈ!ÓJi�AˆA™?ÑkÐkùÒks   ŽA	«A	Á A	c                ó<   € V ^8„  d   QhR\         R\        R\         /# )r0   r    r!   r"   ©r5   Údict)r6   s   "r   r7   r7     s!   € ÷ ;ñ ;œ#ð ;¤dð ;´ñ ;r   c                óH   € \        WV4      pVf   VP                  W#4      # T# )zDScoped setting read with an explicit ``None`` -> ``extra`` fallback.)r$   r   )r    r!   r"   r   r‚   s   &&&& r   Ú_setting_orrý     s&   € ä
" 8°CÓ
8€CØ&)¢kˆ5�9‰9�SÓ"Ð:°sÐ:r   c                ó0   € V ^8„  d   QhR\         R\        /# )r0   ÚcacheÚttl)rû   Úfloat)r6   s   "r   r7   r7     s   € ÷ ^ñ ^”Dð ^¤Eñ ^r   c                ó’   € V P                  V4      pVe2   \        P                  ! 4       V^ ,          ,
          V8  d
   V^,          # R# )zRValue of a ``(monotonic_ts, value)`` cache entry if younger than *ttl*, else None.N)r   ÚtimeÚ	monotonic)rÿ   r"   r   Úcacheds   &&& r   Ú_ttl_getr    s<   € à�Y‰Y�s‹^€FØÒ*´·²Ó0@À6È!Å9Õ0LÐPSÔ/Sˆ6�!�9Ð]ÐY]Ð]r   c                ó>   € V ^8„  d   QhR\         \        ,          RR/# )r0   Úbucketr3   N©r¥   r5   )r6   s   "r   r7   r7     s   € ÷ ñ œœS�	ð ¨4ñ r   c                ó’   € \        T;'       g    R4      P                  4       pV'       d   W 9  d   V P                  V4       R# R# R# )z=Append the lowercased pubkey once (empty values are skipped).r9   N)r5   r~   r¯   )r  r‚   Úpks   && r   Ú_add_pubkeyr    s5   € ä	ˆS�YˆY�B‹×	Ñ	Ó	€Bß	ˆbÔØ�‰�bÖñ �rr   c                óF   € V ^8„  d   QhR\         R\        \         ,          /# )r0   Úrefr3   r4   )r6   s   "r   r7   r7      s   € ÷ 5ñ 5œSð 5¤X¬c¥]ñ 5r   c                óè   € T ;'       g    RP                  4       P                  4       p V '       g   R# V P                  R4      '       d   \        V 4      # \        P                  V 4      '       d   V # R# )zANormalize a user reference (hex pubkey or npub) to lowercase hex.r9   Nrà   )rk   r~   Ú
startswithÚnpub_to_hexÚ	_HEX64_RErž   )r  s   &r   rõ   rõ      sZ   € à�9ˆ9�"×
Ñ
Ó
×
#Ñ
#Ó
%€CßÙØ
‡~�~�g×ÒÜ˜3ÓÐÜ×%Ñ% c×*Ò*ˆ3Ð4°Ð4r   c                ó0   € V ^8„  d   QhR\         R\        /# ©r0   r!   r3   ©rû   r5   )r6   s   "r   r7   r7   ,  s   € ÷ jñ j¤$ð j¬3ñ jr   c                ót  € \        4       '       d   \        R4      M\        P                  ! R4      p\	        T;'       g    \        V RR4      ;'       g    R4      P                  4       P                  4       p\        RVRR4      pVe/   \	        V4      P                  4       P                  4       R9   d   R# T# )	znReply mode ("first"/"all" thread, "off" posts flat); env overrides config, ``reply_in_thread: false`` = "off".ÚBUZZ_REPLY_TO_MODEÚreply_to_modeÚfirstÚBUZZ_REPLY_IN_THREADÚreply_in_threadNÚoff©ÚfalseÚ0Únor  )	r   r   r   r   r5   Úgetattrrk   r~   rý   )Úconfigr!   Úmode_envÚmodeÚrits   &&   r   Ú_reply_to_moder&  ,  s˜   € ä;J×;LÒ;LÔ!Ð"6Ô7ÔRT×R[ÒR[Ð\pÓRq€HÜˆx×OÐOœ7 6¨?¸GÓD×OÐOÈÓP×VÑVÓX×^Ñ^Ó`€DÜ
Ð,¨eÐ5FÈÓ
M€CØ’O¬¨C«¯©Ó(8×(>Ñ(>Ó(@ÐD_Ô(_ˆ5ÐiÐeiÐir   c                ó0   € V ^8„  d   QhR\         R\        /# r  r  )r6   s   "r   r7   r7   4  s   € ÷ rñ rœTð r¤cñ rr   c                 ól   € \        R V R4      ;'       g    V P                  RR4      P                  4       # )ÚBUZZ_RELAY_URLr™   r9   )r$   r   rk   ©r!   s   &r   Ú_configured_relayr+  4  s0   € Ü$Ð%5°u¸kÓJ×hÐhÈeÏiÉiÐXcÐegÓNh×oÑoÓqÐqr   c                ó0   € V ^8„  d   QhR\         R\        /# r  r  )r6   s   "r   r7   r7   8  s   € ÷ Eñ E¤Dð E¬Sñ Er   c                 ó–   € \        R V R4      pT;'       g&    \        V P                  RR4      ;'       g    R4      P                  4       # )ÚBUZZ_HOME_CHANNELÚhome_channelr9   )r$   r5   r   rk   ©r!   r‚   s   & r   Ú_configured_home_channelr1  8  s@   € Ü
"Ð#6¸¸~Ó
N€CØ×;Ð;”3�u—y‘y °Ó4×:Ð:¸Ó;×BÑBÓDÐDr   c                ó0   € V ^8„  d   QhR\         R\        /# r  r  )r6   s   "r   r7   r7   =  s   € ÷ ]ñ ]¤ð ]¬ñ ]r   c                 óÎ   € \        R V R4      p\        \        T;'       g    R4      P                  4       ;'       g&    \        V P	                  RR4      ;'       g    R4      4      # )ÚBUZZ_CLI_PATHÚcli_pathr9   )r$   Ú_resolve_cli_pathr5   rk   r   r0  s   & r   Ú_configured_cli_pathr7  =  sP   € Ü
" ?°E¸:Ó
F€CÜœS § ¨›^×1Ñ1Ó3×[Ð[´s¸5¿9¹9ÀZÐQSÓ;T×;ZÐ;ZÐXZÓ7[Ó\Ð\r   c                óF   € V ^8„  d   QhR\         \        ,          R\        /# r  ©r	   rû   r5   )r6   s   "r   r7   r7   B  s"   € ÷ Vñ V¬´­ð V¼3ñ Vr   c                 óê   € \        \        R R4      ;'       g    R4      P                  4       pT;'       g>    \        T ;'       g    / P                  RR4      ;'       g    R4      P                  4       # )ÚBUZZ_CREDENTIALS_FILEr9   Úcredentials_file)r5   r   rk   r   ©r!   Ú
configureds   & r   Ú_configured_credentials_filer?  B  s^   € äÔ'Ð(?ÀÓD×JÐJÈÓK×QÑQÓS€JØ×UÐUœ˜eŸk˜k r×.Ñ.Ð/AÀ2ÓF×LÐLÈ"ÓM×SÑSÓUÐUr   r9   c                ó0   € V ^8„  d   QhR\         R\         /# )r0   r>  r3   rT   )r6   s   "r   r7   r7   H  s   € ÷ 7ñ 7¤#ð 7¬sñ 7r   c                óV  € V '       d=   \        V 4      P                  4       pVP                  4       '       d   \        V4      # R# \        P
                  ! R4      ;p'       d   V# \         P                  ! 4       R,          R,          pVP                  4       '       d   \        V4      # R# )u]   Resolve the buzz binary: explicit config â†’ ``buzz`` on PATH â†’ ``~/bin/buzz``; "" if none.r9   ÚbuzzÚbin)r   Ú
expanduserÚis_filer5   ÚshutilÚwhichÚhome)r>  ÚpÚfoundÚfallbacks   &   r   r6  r6  H  s|   € çÜ�Ó×'Ñ'Ó)ˆØŸ™ŸšŒs�1‹vÐ,¨"Ð,Ü—’˜VÓ$Ð$€uÖ$ØˆÜ�yŠy‹{˜UÕ" VÕ+€HØ$×,Ñ,×.Ò.Œ3ˆx‹=Ð6°BÐ6r   c                ó\   € V ^8„  d   QhR\         \        ,          R\        \        ,          /# r  )r	   rû   r¥   r   )r6   s   "r   r7   r7   S  s"   € ÷ 	ñ 	¤8¬D¥>ð 	¼TÄ$½Zñ 	r   c                 óä   € \        V 4      pV'       d   \        V4      P                  4       .# \        4       '       d   . #  \	        \
        P                  R 4      4      #   \         d    . u # i ; i)z*credentials*.json)r?  r   rD  Ú_is_multiplex_activer»   Ú_DEFAULT_CREDENTIALS_DIRÚglobÚOSErrorr=  s   & r   Ú_credentials_candidatesrR  S  se   € Ü-¨eÓ4€JßÜ�ZÓ ×+Ñ+Ó-Ð.Ð.Ü×ÒØˆ	ðÜÔ.×3Ñ3Ð4HÓIÓJÐJøÜô ØŠ	ðús   ÁA ÁA/Á.A/c                ó0   € V ^8„  d   QhR\         R\        /# )r0   rç   r3   r  )r6   s   "r   r7   r7   b  s   € ÷ ñ œ4ð ¤Cñ r   c                óÂ   € \          FT  pV P                  V4      p\        V\        4      '       g   K,  VP	                  4       '       g   KD  VP	                  4       u # 	  R# )zQFirst non-empty private-key field in a credentials record, stripped ("" if none).r9   )Ú_KEY_FIELDSr   rï   r5   rk   )rç   ÚfieldrS   s   &  r   Ú_credentials_keyrW  b  sA   € çˆØ—‘˜“ˆÜ�eœS×!Ô! e§k¡k§m¤mØ—;‘;“=Ò ñ ñ r   c                óF   € V ^8„  d   QhR\         \        ,          R\        /# r  ©r	   rû   )r6   s   "r   r7   r7   k  s   € ÷ 	ñ 	¤X¬d¥^ð 	¼tñ 	r   c                ó  € \        V 4       FW  p \        P                  ! VP                  RR7      4      p\        T\        4      '       g   KB  \        T4      '       g   KU  Tu # 	  / #   \        \
        3 d     Kq  i ; i)z:Load the first credential record containing a private key.z	utf-8-sig)Úencoding)	rR  ÚjsonÚloadsÚ	read_textrQ  r€   rï   rû   rW  )r!   rŸ   rç   s   &  r   Ú_resolve_credentials_datar_  k  sn   € ä'¨Ö.ˆð	Ü—:’:˜dŸn™n°k˜nÓBÓCˆDô �dœD×!Ô!Ô&6°t×&<Ô&<ØŠKñ /ð €Iøô	 œÐ$ô 	Úð	ús   �&A)Á)A>Á=A>c                óF   € V ^8„  d   QhR\         \        ,          R\        /# r  r9  )r6   s   "r   r7   r7   w  s"   € ÷ Eñ E¤¬¥ð E¼#ñ Er   c                ó˜   € \        \        RR4      ;'       g    R4      P                  4       pT;'       g    \        \	        V 4      4      # )zXResolve the Nostr private key: scoped secret first, then credentials JSON. NEVER log it.ÚBUZZ_PRIVATE_KEYr9   )r5   r   rk   rW  r_  )r!   r"   s   & r   Ú_resolve_private_keyrc  w  s@   € ä
Ô Ð!3°RÓ8×>Ð>¸BÓ
?×
EÑ
EÓ
G€CØ×DÐDÔ"Ô#<¸UÓ#CÓDÐDr   c                óF   € V ^8„  d   QhR\         \        ,          R\        /# r  r9  )r6   s   "r   r7   r7   }  s"   € ÷ 	_ñ 	_œX¤d�^ð 	_´sñ 	_r   c                óŠ  € \        \        RR4      ;'       g    R4      P                  4       pV'       gd   \        \        RR4      ;'       g    R4      P                  4       '       d   \        V 4      '       g   R# R\	        V 4      ;p9  d   R# VR,          p\
        P                  ! \        P                  VR4      RR7      # )z?Resolve and validate the optional NIP-OA owner-attestation tag.ÚBUZZ_AUTH_TAGr9   rb  Úauth_tagzBuzz auth tag©Ú
separators©rî   Ú:)	r5   r   rk   r?  r_  r\  ÚdumpsÚ_nostr_authÚparse_auth_tag)r!   r‚   rç   s   &  r   Ú_resolve_auth_tagro  }  s›   € äÔ% o°rÓ:×@Ð@¸bÓA×GÑGÓI€CßÜÔ!Ð"4°bÓ9×?Ð?¸RÓ@×FÑF×HÒHÔQmÐns×QtÒQtÙØÔ&?ÀÓ&FÐF˜dÔGÙØ�:ÕˆÜ�:Š:”k×0Ñ0°°oÓFÐS]Ô^Ð^r   rg  Ú
input_textÚtimeoutc                óÐ   € V ^8„  d   QhR\         R\        \         ,          R\         R\         R\         R\        \         ,          R\        R\        \
        \         \         3,          /# )	r0   r5  Úargsr™   Úprivate_keyrg  rp  rq  r3   )r5   r¥   r	   r  rw   rx   )r6   s   "r   r7   r7   ‰  sk   € ÷ bñ bÜðbÜœc�ðbÜ25ðbÜDGðbÜSVðbäœ•ðbä/4ðbô Œ3””Sˆ=Õñbr   c             ƒ  ó¤  "  € ^ RI Hp V! 4       pVR,          VR&   W(R&   W8R&   VP                  RR4       V'       d   WHR&   \        P                  ! V .VO5RVe   \        P
                  P                  M\        P
                  P                  R	\        P
                  P                  R
\        P
                  P                  RV/ G Rj  x€L
 p	 Ve   VP                  R4      MRp
\        P                  ! V	P                  V
4      VR7      G Rj  x€L
 w  r¼T	P                   e   T	P                   M^pYëP#                  RRR7      TP#                  RRR7      3#  L� LJ  \         dd    T	P                  4        T	P                  4       G Rj  x€L 
  RRRRT'       d
   T^ ,          MR RT R2/p^|R\        P                  ! T4      3u # i ; i5i)z]Run the buzz CLI (argv, never a shell) -> ``(rc, stdout, stderr)``. Key travels via env only.)Úhermes_subprocess_envÚHERMES_REAL_HOMEÚHOMEr)  rb  rf  NÚstdinÚstdoutÚstderrÚenvr`   ©rq  r2   rq  Úmessagezbuzz r9   z timed out after Úsrh   rb   )Útools.environments.localrv  Úpoprˆ   Úcreate_subprocess_execÚ
subprocessÚPIPEÚDEVNULLrn   Úwait_forÚcommunicateÚTimeoutErrorÚkillÚwaitr\  rl  Ú
returncoderp   )r5  rs  r™   rt  rg  rp  rq  rv  r|  ÚprocÚstdin_bytesrz  r{  ÚdetailÚrcs   &&$$$$$        r   Ú
_exec_buzzr�  ‰  s±  é € õ
 ?Ù
Ó
!€CØÐ(Õ)€Cˆ�KØ%ÐÑØ)ÐÑØ‡G�GˆO˜TÔ"ßØ'ˆOÑÜ×/Ò/ØðØòØ:DÒ:Pœw×1Ñ1×6Ò6ÔV]×VhÑVh×VpÑVpðä×!Ñ!×&Ñ&ðä/6×/AÑ/A×/FÑ/FðàLOñ÷ €Dð+Ø4>Ò4J�j×'Ñ'¨Ô0ÐPTˆÜ&×/Ò/°×0@Ñ0@ÀÓ0MÐW^Ô_×_‰ˆð !ŸO™OÒ7ˆ�Š¸Q€BØ�}‰}˜W¨Yˆ}Ó7¸¿¹ÀwÐW`¸Ó9aÐaÐaññ `øÜô +Ø�	‰	ŒØ�i‰i‹k×ÑØ˜9 i°5ÇD¸¸a¾ÈbÐ8QÐQbÐcjÐbkÐklÐ1mÐnˆØ�BœŸ
š
 6Ó*Ð*Ò*ð	+üs\   ‚C	GÃEÃGÃAE ÄEÄE ÄAGÅE Å.GÆFÆGÆ+GÇ
GÇGÇGi„  c                óR   € V ^8„  d   QhR\         R\        \        ,          R\         /# )r0   r~  Úredact_pathr3   )r5   r	   r   )r6   s   "r   r7   r7   ©  s*   € ÷ pñ p¤#ð p´H¼TµNð pÌcñ pr   c                ó¦   € Ve&   V P                  \        V4      VP                  4      p \        V 4      \        8:  d   V # V R\        ^,
            R2# )zCKeep untrusted CLI detail useful without exposing unbounded output.Nz...)rh   r5   r   rl   Ú_MAX_CLI_MESSAGE_CHARS)r~  r’  s   &&r   Ú_bounded_cli_messager•  ©  sR   € àÒØ—/‘/¤# kÓ"2°K×4DÑ4DÓEˆÜ˜'“lÔ&<Ô<ˆ7ÐoÀWÐMiÔOeÐhiÕOiÐEjÐDkÐknÐBoÐor   r’  c                ó^   € V ^8„  d   QhR\         R\        R\        \        ,          R\         /# )r0   r{  r‹  r’  r3   )r5   rx   r	   r   )r6   s   "r   r7   r7   °  s3   € ÷ 	eñ 	eœsð 	e´ð 	eÄXÌdÅ^ð 	eÔ_bñ 	er   c               ó  € T ;'       g    RP                  4       p\        VR4      p\        V\        4      '       d¯   VP	                  R4      VP	                  R4      re\        V\
        4      '       dx   VP                  4       '       db   \        V\
        4      '       d'   VP                  4       '       d   VP                  4       MRp\        V RVP                  4        RV R2V4      # \        T;'       g    RV 2V4      # )	zEExtract a bounded human-readable message from the CLI error contract.r9   Nr~  r2   z: z (exit Ú)zbuzz CLI failed with exit code )rk   Ú_json_orrï   rû   r   r5   r•  )r{  r‹  r’  r¤   rç   rŽ  ÚcategoryÚlabels   &&$     r   Ú_cli_error_messagerœ  °  sÍ   € à�LˆL�b×ÑÓ!€DÜ�D˜$Ó€DÜ�$œ×ÒØŸ8™8 IÓ.°·±¸Ó0A�Ü�fœc×"Ò" v§|¡|§~¢~Ü(2°8¼S×(AÒ(AÀhÇnÁn×FVÒFV�H—N‘NÔ$Ð\cˆEÜ'¨5¨'°°F·L±L³NÐ3CÀ7È:È,ÐVWÐ(XÐZeÓfÐfÜ × VÐ VÐ*IÈ*ÈÐ(VÐXcÓdÐdr   c                ó~   € V ^8„  d   QhR\         R\        \        \         ,          \        \         ,          3,          /# ©r0   rz  r3   )r5   rw   r	   )r6   s   "r   r7   r7   ¼  s,   € ÷ "ñ "¤ð "¬¬h´s­m¼XÄc½]Ð.JÕ(Kñ "r   c                óô  € \        V R4      p\        V\        4      '       g   R# VP                  R4      RJ d[   VP                  R4      p\        V\        4      '       d   VP                  4       '       g   RpR\        VP                  4       4      3# VP                  R4      pVP                  R4      RJg-   \        V\        4      '       d   VP                  4       '       g   R# VP                  4       R3# )	zGValidate the buzz-cli success receipt and return ``(event_id, error)``.NÚacceptedFr~  zmessage was not acceptedÚevent_idT)Nzinvalid CLI response)r™  rï   rû   r   r5   rk   r•  )rz  rç   rŽ  r¡  s   &   r   Ú_parse_send_receiptr¢  ¼  sÅ   € ä�F˜DÓ!€DÜ�dœD×!Ò!Ø+Ð+Ø‡x�x�
Ó˜uÓ$Ø—‘˜)Ó$ˆÜ˜&¤#×&Ò&¨f¯l©l¯nªnØ/ˆFØÔ)¨&¯,©,«.Ó9Ð9Ð9Ø�x‰x˜
Ó#€HØ‡x�x�
Ó 4Ó'¬z¸(ÄC×/HÒ/HÐPX×P^ÑP^×P`ÒP`Ø+Ð+Ø�>‰>Ó˜TÐ!Ð!r   c                ó$   € V ^8„  d   QhR\         /# )r0   r¤   rT   )r6   s   "r   r7   r7   Ì  s   € ÷ ñ ”3ñ r   c                ó’   €  \         P                  ! T ;'       g    \         P                  ! V4      4      #   \         d    Tu # i ; i)z@``json.loads`` of CLI stdout, or *default* when empty/malformed.)r\  r]  rl  r€   )r¤   r   s   &&r   r™  r™  Ì  s;   € ðÜ�zŠz˜$×5Ð5¤$§*¢*¨WÓ"5Ó6Ð6øÜô ØŠðús   ‚6 ›6 ¶AÁAc                óF   € V ^8„  d   QhR\         R\        \        ,          /# rž  )r5   r¥   rû   )r6   s   "r   r7   r7   Ô  s"   € ÷ _ñ _œSð _¤T¬$¥Zñ _r   c                ó¨   € \        V . 4      p\        V\        4      '       d+   V Uu. uF  p\        V\        4      '       g   K  VNK  	  up# . # u upi )z8Parse CLI stdout expected to be a JSON array of objects.)r™  rï   r¥   rû   )rz  rç   Úitems   &  r   Ú_parse_json_listr¨  Ô  sD   € ä�F˜BÓ€DÜ@JÈ4ÔQU×@VÒ@V™TÓ<™T�T¤Z°´d×%;�DˆD™TÑ<Ð^Ð\^Ð^ùÒ<s   §AÁAc                ó$   € V ^8„  d   QhR\         /# )r0   Úevent©rû   )r6   s   "r   r7   r7   Ú  s   € ÷ Dñ D”4ñ Dr   c              #  ób  "  € V P                  R4      p\        V\        4      '       d„   V F{  p\        V\        \        34      '       g   K!  \	        V4      ^8¼  g   K3  \        V^ ,          4      R8X  g   KL  V^,          \	        V4      ^8”  d   \        V^,          4      MR3x € K}  	  R# R# 5i)zZYield ``(target, marker)`` for each well-formed NIP-10 ``e`` tag (raw values, unstripped).ÚtagsÚer9   N)r   rï   r¥   rw   rl   r5   )rª  r­  Útags   &  r   Ú_e_tagsr°  Ú  s}   é € à�9‰9�VÓ€DÜ�$œ×ÒÛˆCÜ˜#¤¤e˜}×-Ô-´#°c³(¸a¶-ÄCÈÈAÍÃKÐSVÖDVØ˜!•f¬c°#«h¸¬lœs 3 q¥6œ{ÀÐCÔCó ñ ùs   ‚AB/ÁB/ÁB/Á87B/c                óF   € V ^8„  d   QhR\         R\        \        ,          /# ©r0   rª  r3   ©rû   r	   r5   )r6   s   "r   r7   r7   ã  s   € ÷ )ñ )¤$ð )¬8´C­=ñ )r   c                óê   € R;p;r#\        V 4       FJ  w  rE\        T;'       g    R4      P                  4       pV'       g   K2  TpVR8X  d   TpK?  VR8X  g   KH  TpKL  	  T;'       g    T;'       g    T# )z_Direct parent id from NIP-10 ``e`` tags: ``reply`` marker, then ``root``, else last positional.Nr9   ÚreplyÚroot)r°  r5   rk   )rª  Úreply_idÚroot_idÚlast_eÚ
raw_targetÚmarkerÚtargets   &      r   Ú_event_reply_parent_idr½  ã  sx   € à"&Ð&€HÐ&ˆwÜ% ežnÑˆ
Ü�Z×%Ð% 2Ó&×,Ñ,Ó.ˆßÙØˆØ�WÔØŠHØ�vÖØŠGñ -ð ×(Ð(�w×(Ð( &Ð(r   c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r0   rª  Úpubkeyr3   )rû   r5   r›   )r6   s   "r   r7   r7   ò  s&   € ÷ }ñ }”Tð }¤3ð }¬4ñ }r   c                óÊ   a€ V P                  R4      p\        V\        4      ;'       d;    \        ;QJ d    V3R lV 4       F  '       g   K   R# 	  R# ! V3R lV 4       4      # )zMTrue when the event carries a ``p`` tag equal to *pubkey* (case-insensitive).r­  c              3   óú   <"  € T Fp  p\        V\        \        34      ;'       dN    \        V4      ^8„  ;'       d8    V^ ,          R8H  ;'       d$    \	        V^,          4      P                  4       S8H  x € Kr  	  R# 5i)r=   rI  N)rï   r¥   rw   rl   r5   r~   )r\   r¯  r¿  s   & €r   r^   Ú_p_tagged.<locals>.<genexpr>õ  sg   øé € ð *}Ùw{ÐpsŒ
�3œœu˜Ó&×kÐk¬3¨s«8°a©<×kÐk¸CÀ½FÀc¹M×kÐkÌcÐRUÐVWÕRXËk×N_ÑN_ÓNaÐekÑNkÔkÓw{ùs   ƒ!A;¥A;»A;Á,A;TF)r   rï   r¥   r²   )rª  r¿  r­  s   &f r   Ú	_p_taggedrÃ  ò  si   ø€ à�9‰9�VÓ€DÜ�dœDÓ!÷ }ð }§c£cô *}Ùw{ó*}§c¤cð }¢cð } cô *}Ùw{ó*}ó '}ð }r   iô  ÚimageÚaudioÚvideoÚdocumentc            	       ó  a a€ ] tR tRt oRtRtV 3R lt]V3R lR l4       t]	V3R lR l4       t
R	R
/V3R lR lltV3R lR ltRR/V3R lR lltRR/V3R lR lltV3R lR ltV3R lR ltV3R lR ltV3R lR ltR V3R lR lltR¡V3R  lR! lltV3R" lR# ltR$R
/V3R% lR& lltR V3R' lR( lltV3R) lR* ltR+R/V3R, lR- lltV3R. lR/ ltR¢V3R0 lR1 lltR2R
R3R
R4R
R5R/V3R6 lR7 lltR¢V3R8 lV 3R9 llltR£V3R: lR; lltR¢V3R< lR= lltR¢V3R> lR? llt V3R@ lRA lt!V3RB lRC lt"V3RD lRE lt#V3RF lRG lt$]	V3RH lRI l4       t%V3RJ lRK lt&V3RL lRM lt'V3RN lRO lt(V3RP lRQ lt)V3RR lRS lt*V3RT lRU lt+V3RV lRW lt,V3RX lRY lt-V3RZ lR[ lt.V3R\ lR] lt/V3R^ lR_ lt0V3R` lRa lt1V3Rb lRc lt2V3Rd lRe lt3V3Rf lRg lt4]	V3Rh lRi l4       t5]	V3Rj lRk l4       t6]	V3Rl lRm l4       t7V3Rn lRo lt8V3Rp lRq lt9V3Rr lRs lt:V3Rt lRu lt;V3Rv lRw lt<V3Rx lRy lt=V3Rz lR{ lt>V3R| lR} lt?V3R~ lR lt@V3R€ lR� ltAV3R‚ lRƒ ltB]	V3R„ lR… l4       tCV3R† lR‡ ltDRˆtE]	V3R‰ lRŠ l4       tFV3R‹ lRŒ ltGV3R� lRŽ ltHV3R� lR� ltIV3R‘ lR’ ltJ]	V3R“ lR” l4       tK]	V3R• lR– l4       tLR—R˜R™R
RšR
/V3R› lRœ lltMR
R
R
R
RR
R
]NPž                  R
3	V3R� lRž lltPRŸtQVtRV ;tS# )¤ÚBuzzAdapteriÿ  zWBuzz adapter (WebSocket push with poll fallback) for the BasePlatformAdapter interface.Tc           	     óô  <€ \         SV `  V\        R 4      R7       \        VR/ 4      ;'       g    / pW0n        \        V4      V n        \        VP                  R. 4      4      pR V 4       pV Uu0 uF
  qff   K  VkK  	  upV n	        \        V P                  4      pVe   V P                  P                  V4       \        V4      V n        \        \        RVR. 4      4      pV U	u. uFC  p	\        V	\         4      '       g   K  V	P#                  4       '       g   K3  V	P#                  4       NKE  	  up	V n        \'        V4      V n        \+        RVR	4      p
 \-        \.        \1        T
;'       g    VP                  R	\2        4      4      4      V n        \        R
VRR4      p\!        V4      P#                  4       P;                  4       R9  V n        \?        W4      V n        \+        RVR4      pT;'       g&    \!        VP                  RR4      ;'       g    R4      P#                  4       P;                  4       pVR9   d   TMRV n         \C        \        RVR. 4      4      V n"        \C        \        RVR. 4      4      V n#        R;V n$        V n%        R;V n&        ;V n'        V n(        RV n)        RV n*        RV n+        ^ ;V n,        V n-        \]        4       V n/        / V n0        / V n1        \d        Pf                  ! 4       V n4        ^ ;V n5        V n6        / V n7        / V n8        / V n9        / V n:        / V n;        \y        4       V n=        R# u upi u up	i   \6        \8        3 d    \-        \.        \2        4      T n         ELãi ; i)rB  )r"  Úplatformr!   Úattachment_hostsc              3   óh   "  € T F(  p\        V\        4      '       g   K  \        V4      x € K*  	  R # 5ir©   )rï   r5   r…   )r\   Úhs   & r   r^   Ú'BuzzAdapter.__init__.<locals>.<genexpr>
  s%   é € ÐN±%¨Q¼:ÀaÌ×;MÔ(Ô% a×(Ð(³%ùs   ‚2Ÿ2NÚBUZZ_CHANNELSÚchannelsÚBUZZ_POLL_INTERVALÚpoll_intervalÚBUZZ_REQUIRE_MENTIONÚrequire_mentionTÚBUZZ_TRANSPORTÚ	transportÚautoÚBUZZ_ALLOWED_USERSÚallowed_usersÚBUZZ_REACTION_ONLY_USERSÚreaction_only_usersr9   r  )rØ  Ú	websocketÚpoll)>ÚsuperÚ__init__r,   r!  Ú_extrar+  r™   rñ   r   Ú_attachment_originsr…   Úaddr7  r5  rý   rï   r5   rk   rÑ  r1  r/  r$   ÚmaxÚ_MIN_POLL_INTERVALr  Ú_DEFAULT_POLL_INTERVALrÓ  Ú	TypeErrorr€   r~   rÕ  r&  r×  rø   Ú_allowed_pubkeysÚ_reaction_only_pubkeysÚ_private_keyÚ	_auth_tagÚ_self_pubkeyÚ
_self_npubÚ_display_nameÚ
_poll_taskÚ_ws_taskÚ	_ws_readyÚ_membership_sinceÚ_poll_countró   Ú_restricted_channelsÚ_channel_stateÚ_restored_cursorsrˆ   ÚLockÚ_cursor_write_lockÚ_cursor_snapshotsÚ_cursor_writtenÚ_channel_namesÚ_channel_metaÚ_user_namesÚ_member_cacheÚ_profile_name_cacher   Ú_thread_roots)Úselfr"  Úkwargsr!   ÚhostsÚoriginsÚoÚrelay_originÚraw_channelsr]   Ú_pi_rawÚ_rm_cfgÚ_transport_rawÚ
_transportÚ	__class__s   &&,           €r   rà  ÚBuzzAdapter.__init__  s  ø€ Ü‰Ñ ´¸&Ó1AÐÔBÜ˜ ¨Ó,×2Ð2°ˆØŒä*¨5Ó1ˆŒÜ˜5Ÿ9™9Ð%7¸Ó<Ó=ˆÙN±%ÓNˆÙ/6Ó#H©w¨!§A A©wÑ#HˆÔ Ü)¨$¯.©.Ó9ˆØÒ#Ø×$Ñ$×(Ñ(¨Ô6Ü,¨UÓ3ˆŒä!¤+¨o¸uÀjÐRTÓ"UÓVˆÙ7CÓ#h±|°!ÄzÐRSÔUX×GY¤IÐ^_×^eÑ^e×^g¤I A§G¡G¦I±|Ñ#hˆŒÜ4°UÓ;ˆÔÜ*Ð+?ÀÈÓXˆð	QÜ!$Ô%7¼¸w×?|Ð?|È%Ï)É)ÐTcÔe{ÓJ|Ó9}Ó!~ˆDÔô Ð4°eÐ=NÐPTÓUˆÜ" 7›|×1Ñ1Ó3×9Ñ9Ó;ÐC^Ñ^ˆÔÜ#1°&Ó#@ˆÔä1Ð2BÀEÈ;ÓWˆØ$×UÐU¬¨E¯I©I°kÀ6Ó,J×,TÐ,TÈfÓ(U×\Ñ\Ó^×dÑdÓfˆ
Ø'1Ð5RÔ'R™ÐX^ˆŒô &1´Ð=QÐSXÐZiÐkmÓ1nÓ%oˆÔÜ+6´{ÐC]Ð_dÐf{Ð}ó  8Aó  ,BˆÔ#à-/Ð/ˆÔ˜DœNàCEÐEˆÔÐE˜DœO¨dÔ.@Ø26ˆŒØ04ˆŒØ26ˆŒØ45Ð5ˆÔ Ô!1ô *-«ˆÔ!ð 02ˆÔà24ˆÔä")§,¢,£.ˆÔØ89Ð9ˆÔ Ô!5Ø.0ˆÔà.0ˆÔØ+-ˆÔØACˆÔØACˆÔ ä>I»mˆÖùòo $Iùò $iøô
 œ:Ð&ô 	QÜ!$Ô%7Ô9OÓ!PˆD×ð	Qús0   Á1L?Á;L?Ã(MÄMÄMÅ<M	 Í	*M7Í6M7c                ó    <€ V ^8„  d   QhRS[ /# r’   rT   )r6   Ú__classdict__s   "€r   r7   ÚBuzzAdapter.__annotate__E  s   ø€ ÷ ñ ‘cñ r   c                ó   € R # )ÚBuzz© ©r  s   &r   r   ÚBuzzAdapter.nameD  s   € ár   c                ó6   <€ V ^8„  d   QhRS[ RS[S[ ,          /# )r0   Úuser_idr3   r4   )r6   r  s   "€r   r7   r  I  s   ø€ ÷ ,ñ ,¡3ð ,©8±C­=ñ ,r   c                ó   € \        V 4      # )uW  Normalize a user reference (hex or npub) to hex â€” authz_mixin allowlist hook.

Optional hook consumed by ``gateway/authz_mixin`` when matching the profile allowlist carried in
``config.extra.allowed_users`` (#98738): entries may be npubs while inbound ``user_id`` is always
the hex pubkey, so a plain string compare would deny listed users.
)rõ   )r  s   &r   Únormalize_user_idÚBuzzAdapter.normalize_user_idH  s   € ô # 7Ó+Ð+r   rp  Nc          	      óf   <€ V ^8„  d   QhRS[ S[,          RS[S[,          RS[S[S[S[3,          /# )r0   rs  rp  r3   )r¥   r5   r	   rw   rx   )r6   r  s   "€r   r7   r  T  s?   ø€ ÷ Pñ P¡4©¥9ð P¹XÁc½]ð PÑV[Ñ\_ÑadÑfiÐ\iÕVjñ Pr   c          	   ƒ  ó  "  € V P                   '       g5   \        V P                  4      V n         \        V P                  4      V n        \        V P                  WP                  V P                   V P                  VR 7      G Rj  x€L
 #  L5i)©r™   rt  rg  rp  N)rê  rc  rá  ro  rë  r�  r5  r™   )r  rs  rp  s   &&$r   Ú_run_cliÚBuzzAdapter._run_cliT  sk   é € Ø× × Ð Ü 4°T·[±[Ó AˆDÔÜ.¨t¯{©{Ó;ˆDŒNÜ §¡¨t¿~¹~Ð[_×[lÑ[lØ)-¯©ÀJôP÷ Pð 	Pñ Pùs   ‚BBÂB	ÂBc                ó0   <€ V ^8„  d   QhRS[ S[,          /# )r0   rs  r	  )r6   r  s   "€r   r7   r  [  s   ø€ ÷ @ñ @¡D©¥Iñ @r   c              ƒ  ón   "  € V P                  V4      G Rj  x€L
 w  r4pV^ 8X  d   \        WB4      # T#  L5i)z6``_run_cli`` -> parsed stdout on rc 0, else *default*.N)r  r™  )r  rs  r   ÚcodeÚoutÚ_errs   &&&   r   Ú	_cli_jsonÚBuzzAdapter._cli_json[  s5   é € à $§¡¨dÓ 3×3‰ˆ�4Ø)-°¬Œx˜Ó%Ð?¸Ð?ñ 4ùs   ‚5—3˜5Ú	retryableFc          
      ó8   <€ V ^8„  d   QhRS[ RS[ RS[ RS[RS[/# )r0   r"  rŽ  Úlogr'  r3   rš   )r6   r  s   "€r   r7   r  b  s2   ø€ ÷ ñ ¡Cð ±ð ¹3ð ÑVZð Ñgkñ r   c               ó\   € \         P                  ! V.VO5!   V P                  WVR7       R# )z=Log and record a fatal connect() error; always returns False.©r'  F)Úloggerr2   Ú_set_fatal_error)r  r"  rŽ  r)  r'  Úlog_argss   &&&&$*r   Ú_connect_failedÚBuzzAdapter._connect_failedb  s)   € ä�Š�SÐ$˜8Ô$Ø×Ñ˜d°iÐÔ@Ùr   Úis_reconnectc                ó&   <€ V ^8„  d   QhRS[ RS[ /# )r0   r1  r3   ©r›   )r6   r  s   "€r   r7   r  h  s   ø€ ÷ Wñ W©Tð W¹dñ Wr   c          
   ƒ  óx
  "  € V P                   '       g   V P                  RRR4      # V P                  '       g   V P                  RRR4      #  \        V P                  4      V n        \        V P                  4      V n        T P
                  '       g   T P                  RR
R4      # T P                  RR.4      G R	j  x€L
 w  r4pT^ 8w  d/   \        YS4      pT P                  RTRT P                   Yc^8H  R7      # \        T4      pT'       d   T^ ,          P                  R4      '       g   T P                  RRRRR7      # \        T^ ,          R,          4      P                  4       T n        \        T^ ,          P                  R4      ;'       g    R4      P!                  4       T n        \%        T P                  4      ;'       g    RT n        T P)                  RT P                    RT P                   2RT P                  R,           RT P                    24      '       g   R# T P                  RR.4      G R	j  x€L
 w  r4pT^ 8w  d$   \        YS4      pT P                  RTRYc^8H  R7      # / T n        \        T4       Fo  pTP                  R 4      ;p	'       g   K  \        TP                  R!4      ;'       g    T	4      T P*                  \        T	4      &   Y€P,                  \        T	4      &   Kq  	  T P.                  ;'       g    \1        T P*                  4      p
T
'       g   T P                  RR"R#4      # T P3                  4        T
 FF  pY°P4                  9   d   \6        P9                  R$T4       K+  T P;                  TR%R&7      G R	j  x€L
  KH  	  T P=                  RR'7      G R	j  x€L
  T P?                  4        R(pT P@                  R19   da   T PC                  4       G R	j  x€L
 '       d   R)pM?T P@                  R)8X  d/   T PE                  R*R+RR7       T PG                  4       G R	j  x€L
  R# TR(8X  d*   \H        PJ                  ! T PM                  4       4      T n'        T PQ                  4        \6        PS                  R,T P                   T P"                  ;'       g    T P&                  R-,          \U        T PV                  4      YÌR)8X  d   RMR.T PX                  R/ R024       T P[                  R	4       R#   \         d(   pT P                  R\        T4      RT4      u R	p?# R	p?ii ; i ELk ELò EL§ ELŒ ELT EL5i)2z?Verify relay credentials, seed high-water marks, start polling.Úconfig_missingzBUZZ_RELAY_URL must be setz"Buzz: relay URL must be configuredÚcli_missingzbuzz CLI binary not foundzIBuzz: buzz CLI binary not found (set BUZZ_CLI_PATH or put 'buzz' on PATH)Úconfig_invalidu-   Buzz: invalid owner-auth configuration â€” %sNzBUZZ_PRIVATE_KEY must be setzABuzz: no private key (set BUZZ_PRIVATE_KEY or a credentials file)Úusersr   Úconnect_failedu0   Buzz: failed to fetch own profile from %s â€” %sr+  r¿  z"buzz users get returned no profileuP   Buzz: 'users get' returned no profile â€” is the key a member of this community?TÚdisplay_namer9   rB  rk  zBuzz identity ºNé   Nu   â€¦ on FrÑ  r¥   u$   Buzz: failed to list channels â€” %sÚ
channel_idr   zno Buzz channels to watchzFBuzz: no channels to watch (configure BUZZ_CHANNELS or join a channel)zBBuzz: skipping restricted channel %s (relay rejected subscription)r?   ©Ú	chat_type©ÚseedrÞ  rÝ  Úws_auth_failedzCBuzz WebSocket transport did not authenticate (transport=websocket)z<Buzz: connected to %s as %s, watching %d channel(s) via %s%sºNé   Nz, poll interval z.1fr  )rØ  rÝ  ).r™   r/  r5  rc  rá  rê  ro  rë  r€   r5   r  rœ  r¨  r   r~   rì  rk   rî  rë   rí  Ú_acquire_platform_lockrû  rü  rÑ  r¥   Ú_load_cursorsrô  r,  ÚdebugÚ_seed_channelÚ_discover_dmsÚ_save_cursorsr×  Ú_start_websocketr-  Ú
disconnectrˆ   Úcreate_taskÚ
_poll_looprï  Ú_mark_connectedÚinforl   rõ  rÓ  Ú_wire_plugin_handlers)r  r1  Úexcr"  r#  Úerrr~  ÚprofilesÚchÚch_idÚwatchr=  Útransport_useds   &$           r   ÚconnectÚBuzzAdapter.connecth  sÐ  é € à�~�~ˆ~Ø×'Ñ'Ð(8Ð:VÐX|Ó}Ð}Ø�}�}ˆ}Ø×'Ñ'ØÐ:ð  =Hóð ð	zÜ 4°T·[±[Ó AˆDÔÜ.¨t¯{©{Ó;ˆDŒNð × × Ð Ø×'Ñ'Ø Ð"@ð  CFóð ð  $Ÿ}™}¨g°uÐ-=Ó>×>‰ˆ�3Ø�1Œ9Ü(¨Ó3ˆGØ×'Ñ'Ø  'Ð+]Ø—‘ ¸1±9ð (ó ð ô $ CÓ(ˆß˜x¨�{Ÿ™¨x×8Ò8Ø×'Ñ'Ø Ð"FØbÐnrð (ó ð ô   ¨¥¨HÕ 5Ó6×<Ñ<Ó>ˆÔÜ  ¨!¥§¡°Ó!@×!FÐ!FÀBÓG×MÑMÓOˆÔÜ% d×&7Ñ&7Ó8×>Ð>¸BˆŒà×*Ñ*Ø˜4Ÿ>™>Ð*¨!¨D×,=Ñ,=Ð+>Ð?À>ÐRV×RcÑRcÐdfÕRgÐQhÐhoÐpt×p~Ñp~Ðoð  BA÷Bò Báà#Ÿ}™}¨j¸&Ð-AÓB×B‰ˆ�3Ø�1Œ9Ü(¨Ó3ˆGØ×'Ñ'Ø  'Ð+QÐSZÐnoÑfoð (ó ð ð !ˆÔÜ" 3Ö'ˆBØŸ™˜|Ó,Ð,ˆu×,Ð,Ü25°b·f±f¸V³n×6MÐ6MÈÓ2N�×#Ñ#¤C¨£JÑ/Ø13×"Ñ"¤3 u£:Ó.ñ (ð —‘×:Ð:¤ d×&9Ñ&9Ó!:ˆßØ×'Ñ'Ø Ð"=ð  @Hóð ð 	×ÑÔÛˆJØ×6Ñ6Ô6Ü—‘ÐaÐcmÔnÙØ×$Ñ$ Z¸7Ð$ÓC×CÒCñ	  ð
 × Ñ  dÐ Ó+×+Ð+Ø×ÑÔàˆØ�>‰>Ð2Ô2Ø×*Ñ*Ó,×,Ö,Ø!,‘Ø—‘ ;Ô.Ø×%Ñ%Ø$Ð&kÐw{ð &ô ð —o‘oÓ'×'Ð'ÙØ˜VÔ#Ü%×1Ò1°$·/±/Ó2CÓDˆDŒOØ×ÑÔÜ�‰ØJØ�N‰N˜D×.Ñ.×FÐF°$·/±/À#Õ2FÌÈD×L_ÑL_ÓH`Ø°KÔ"?™BÐGWÐX\×XjÑXjÐknÐWoÐopÐEqô	
ð
 	×"Ñ" 4Ô(ÙøôY ô 	zØ×'Ñ'Ð(8¼#¸c»(ÐDsÐuxÓyÕyûð	zúò ?ò* Cò2 DÚ+ò
 -ò (ùsê   ‚7T:ºT:Á4S3 ÂT:Â)T:Â=T(Â>A,T:Ä+A$T:Æ5T:ÇAT:È!T:È9T+È:AT:ÊT:Ê8A
T:ÌT:Ì!A&T:ÎT.ÎT:Î%T1Î&:T:Ï T4Ï!	T:Ï+;T:Ð&T7Ð'A3T:ÒAT:Ó3T%Ó>T ÔT%ÔT:Ô T%Ô%T:Ô+T:Ô.T:Ô1T:Ô4T:Ô7T:c                ó   <€ V ^8„  d   QhRR/# ©r0   r3   Nr  )r6   r  s   "€r   r7   r  Á  s   ø€ ÷ 
ñ 
 $ñ 
r   c              ƒ  ó~  "  € V P                  4        \        P                  ! \        4      ;_uu_ 4        V P	                  4        RRR4       \        V P                  4      G Rj  x€L
  RV n        \        V P                  4      G Rj  x€L
  RV n        / V n        ^ V n	        R#   + '       g   i     Lh; i LR L05i)z2Stop the inbound transport and drop runtime state.N)
Ú_mark_disconnectedrŒ   r�   rŽ   Ú_release_platform_lockr)   rð  rï  rõ  ró  r  s   &r   rL  ÚBuzzAdapter.disconnectÁ  s„   é € à×ÑÔ!Ü× Ò ¤×+Õ+Ø×'Ñ'Ô)÷ ,ä˜$Ÿ-™-Ó(×(Ð(ØˆŒÜ˜$Ÿ/™/Ó*×*Ð*ØˆŒØ ˆÔØˆÖ÷ ,×+úá(á*ùs:   ‚3B=µB&Á B=Á&B9Á'#B=Â
B;ÂB=Â&B6	Â1	B=Â;B=c                ó6   <€ V ^8„  d   QhRS[ RS[S[ ,          /# ©r0   Úchat_idr3   ©r5   r¥   )r6   r  s   "€r   r7   r  Ï  s   ø€ ÷ ñ ±Sð ¹TÁ#½Yñ r   c           	   ƒ  ó¤  "  € V P                   p\        V\        V4      \        4      ;pe   \	        V4      # . pV P                  RRR\        V4      .. 4      G Rj  x€L
  F6  p\        T\        V\        4      '       d   VP                  R4      MT4       K8  	  V'       d/   \        P                  ! 4       \	        V4      3V\        V4      &   V# . pV P                  RRR\        V4      RR	.. 4      G Rj  x€L
  F•  p\        WgP                  R4      4       VP                  R
4      ;'       g    .  FY  p\        V\        4      '       g   K  \        V4      ^8”  g   K-  V^ ,          R8X  g   K=  \        V\        V^,          4      4       K[  	  K—  	  V'       d-   \        P                  ! 4       \	        V4      3V\        V4      &   V#  ELo LÖ5i)uÀ   Mention candidates: ``channels members`` (a non-member ``--mention`` is rejected by the CLI), else
recent traffic, which over-approximates â€” ``send()`` recovers by retrying without mentions.NrÑ  Úmembersú	--channelr¿  Úmessagesr   ú--limitÚ50r­  rI  )rþ  r  r5   Ú_MEMBER_CACHE_TTLr¥   r%  r  rï   rû   r   r  r  rl   )	r  rc  rÿ   r  ÚpksÚrowÚ
candidatesÚmsgÚts	   &&       r   Ú_channel_member_pubkeysÚ#BuzzAdapter._channel_member_pubkeysÏ  sx  é € ð ×"Ñ"ˆÜ˜u¤c¨'£lÔ4EÓFÐFˆFÒSÜ˜“<ÐØˆØŸ™¨°YÀÌSÐQXË\Ð(ZÐ\^Ó_×_Ò_ˆCÜ˜´*¸SÄ$×2GÒ2G˜SŸW™W XÔ.ÈSÖQñ `çÜ#'§>¢>Ó#3´T¸#³YÐ"?ˆE”#�g“,ÑØˆJØ "ˆ
ØŸ™¨°U¸KÌÈWËÐW`ÐbfÐ(gÐikÓl×lÒlˆCÜ˜
§G¡G¨HÓ$5Ô6Ø—W‘W˜V“_×*Ð*¨Ò*�Ü˜a¤×&Ô&¬3¨q«6°A®:¸!¸A½$À#¾+Ü 
¬C°°!µ«IÖ6ó +ñ m÷
 Ü#'§>¢>Ó#3´T¸*Ó5EÐ"FˆE”#�g“,ÑØÐò `ñ mùsE   ‚AGÁGÁAGÂ#AGÃ7GÃ8AGÅGÅ!GÅ1+GÆ/GÇGc                ó&   <€ V ^8„  d   QhRS[ RS[ /# ©r0   r¿  r3   rT   )r6   r  s   "€r   r7   r  å  s   ø€ ÷ ñ ±#ð ¹#ñ r   c              ƒ  ó¨  "  € V P                   p\        W!\        4      ;pe   V# RpV P                  RRRV.. 4      G Rj  x€L
 pV'       dè   \	        V^ ,          ;p\
        4      '       dÉ   \        VP                  R4      ;'       g    VP                  R4      ;'       g    R4      P                  4       pV'       gv   VP                  R4      '       d_   \        VR,          / 4      p\        VP                  R4      ;'       g    VP                  R4      ;'       g    R4      P                  4       p\        P                  ! 4       V3W!&   V#  EL5i)	ziDisplay name via ``users get --pubkey`` (bare ``users get`` may return only our own profile), TTL-cached.Nr9   r8  r   ú--pubkeyr:  r   r1   )rÿ  r  Ú_PROFILE_NAME_TTLr%  rï   rû   r5   r   rk   r™  r  r  )r  r¿  rÿ   r  r   rT  Úp0Úprofs   &&      r   Ú_profile_display_nameÚ!BuzzAdapter._profile_display_nameå  s	  é € à×(Ñ(ˆÜ˜uÔ.?Ó@Ð@ˆFÒMØˆMØˆØŸ™¨°%¸ÀVÐ(LÈbÓQ×Qˆßœ
¨°!­Ð#4 2´d×;Ò;Ü�r—v‘v˜nÓ-×EÐE°·±¸³×EÐEÀ2ÓF×LÑLÓNˆDß˜BŸF™F 9×-Ò-Ü  9¥¨rÓ2�Ü˜4Ÿ8™8 NÓ3×MÐM°t·x±xÀÓ7G×MÐMÈ2ÓN×TÑTÓV�ÜŸšÓ)¨4Ð0ˆ‰Øˆò Rùs;   ‚>EÁ EÁEÁ;EÂ	EÂ"EÂ?EÃ/EÄEÄ1Ec                ó<   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          /# )r0   rc  r1   r3   rd  )r6   r  s   "€r   r7   r  ô  s&   ø€ ÷ ñ ±#ð Áð ÉÉSÍ	ñ r   c              ƒ  ó  "  € RV9  d   . # / p/ p\        V RR4      pV P                  V4      G Rj  x€L
  Fx  pWe8X  d   K  V P                  V4      G Rj  x€L
 pV'       g   K.  VP                  4       pVP	                  V. 4      p	Wi9  d   V	P                  V4       VP	                  W‡4       Kz  	  . p
Tp\        V\        RR7       F¹  p\        P                  ! R\        P                  ! WH,          4      ,           R,           \        P                  4      pVP                  V4      '       g   Ki  W8,          p	\        V	4      ^8X  d'   V	^ ,          V
9  d   V
P                  V	^ ,          4       VP                  RV4      pK»  	  V
#  ELV EL55i)	a  Resolve ``@Name`` tokens to member pubkeys so genuine mentions notify while @-prose stays text.
Word-bounded ("email@Fizz", "@@Fizz", "@FizzBuzz" don't wake Fizz; "@Riley!!" does); longer names
match first and consume their span; ambiguous names tag nobody.r;   rì  NT)r"   r¹   ú(?<![\w@])@z(?!\w)Ú )r!  rq  rz  r~   Ú
setdefaultr¯   r»   rl   rE   rF   rG   rH   rD   r¼   )r  rc  r1   Úby_nameÚdisplayÚself_pkr  r   r"   rl  rJ  r¤   Úpatterns   &&&          r   Ú_mention_pubkeys_forÚ BuzzAdapter._mention_pubkeys_forô  sM  é € ð �gÔØˆIØ(*ˆØ"$ˆÜ˜$ °Ó5ˆØ×4Ñ4°WÓ=×=Ò=ˆBØŒ}ÙØ×3Ñ3°BÓ7×7ˆDßÙØ—*‘*“,ˆCØ×$Ñ$ S¨"Ó-ˆCØŒ}Ø—
‘
˜2”Ø×Ñ˜sÖ)ñ >ð ˆØˆÜ˜'¤s°D×9ˆCÜ—j’j ´"·)²)¸G½LÓ2IÕ!IÈIÕ!UÔWY×WdÑWdÓeˆGØ�~‰~˜d×#Ô#Ø•l�Ü�s“8˜q”= S¨¥V°5Ô%8Ø—L‘L  Q¥Ô(ð —{‘{ 6¨4Ó0’ñ :ð ˆò- >ò 8ùs/   ‚/F±F²#FÁF
ÁFÁ"C
FÄ1AFÆ
Fc                ó\   <€ V ^8„  d   QhRS[ S[,          RS[RS[S[ S[,          ,          /# )r0   rs  r1   Úmention_pubkeys)r¥   r5   r	   )r6   r  s   "€r   r7   r    s3   ø€ ÷ ñ ©D±­Ið Áð ÑV^Ñ_cÑdgÕ_hÕViñ r   c              ƒ  ó„  "  € . pT;'       g    .  F  pVRV.,          pK  	  V P                  W,           VR7      G Rj  x€L
 w  rgpV^ 8X  d   WgV3# V'       d:   RT;'       g    R9   d)   V P                  WR7      G Rj  x€L
 w  rgpV^ 8X  d   WgV3# \        W(4      p	V	e>   \        P                  R4       V P                  WR7      G Rj  x€L
 w  rgpV^ 8X  d   WgV3# RT;'       g    R9   dE   \	        V RR4      '       d2   V P                  VRV P
                  .,           VR7      G Rj  x€L
 w  rgpWgV3#  Lø L¹ Lo L5i)	uÇ  Send with bounded recovery (each rung once): explicit ``--mention``s; on "not channel members" retry
without; escape an unresolvable ``@token`` and retry; finally ``--mention <self>`` (downgrades @names to text).

1. publish with explicit ``--mention`` pubkeys resolved from the content (#83414) so genuine member
mentions carry p-tags and mention-subscribed agents actually wake; 2. if the CLI rejects because a
resolved pubkey is no longer a member (membership drift), retry without the explicit mentions â€”
deliver the message rather than lose it; 3. if the CLI's preflight rejects an unresolvable
presentation ``@token`` in prose, escape exactly that token with an invisible separator and retry
(#82646 / #78797); 4. if the error persists and we know our own pubkey, retry once with ``--mention
<self>`` â€” supplying any explicit identity downgrades unresolvable @names to presentation-only text
(#83414); the echo de-dupe already suppresses self-notification.
z	--mention)rp  Nznot channel membersr9   zFBuzz: retrying message after unresolved presentation-mention preflightz'does not match a current channel memberrì  )r  rN   r,  rP  r!  rì  )
r  rs  r1   rˆ  Úmention_argsr  r"  r#  rS  rL   s
   &&&&      r   Ú_run_message_sendÚBuzzAdapter._run_message_send  sF  é € ð #%ˆØ!×'Ð' RÒ'ˆBØ˜[¨"Ð-Õ-ŠLñ (à#Ÿ}™}¨TÕ-@ÈW˜}ÓU×U‰ˆ�3Ø�1Œ9Ø˜c�>Ð!ßÐ1°c·i°i¸RÔ@Ø#'§=¡=° =Ó#J×J‰NˆD�sØ�qŒyØ #�~Ð%Ü9¸'ÓGˆØÒÜ�K‰KÐ`ÔaØ#'§=¡=° =Ó#J×J‰NˆD�sØ�qŒyØ #�~Ð%Ø4¸¿¸ÀÔCÌÐPTÐVdÐfj×HkÒHkØ#'§=¡=°¸Àd×FWÑFWÐ8XÕ1XÐel =Ó#m×m‰NˆD�sØ˜#ˆ~Ðñ Vñ Kñ Kñ nùsZ   ‚=E ¿D8Á E Á	E Á$E Â D:ÂAE ÃD<ÃE Ã)AE Ä,D>Ä-E Ä:E Ä<E Ä>E c                ón   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          RS[S[S[ S[3,          ,          RS[/# )r0   rc  r1   Úreply_toÚmetadatar3   ©r5   r	   rû   r   r'   )r6   r  s   "€r   r7   r  6  sL   ø€ ÷ ñ ¡#ð ±ð ¹xÉ½}ð Ñ_gÑhlÑmpÑruÐmuÕhvÕ_wð ñ  DNñ r   c              ƒ  ó"  "  € V'       g   \        R RR7      # T;'       g    / pRRR\        V4      RR.pY`P                  VP                  R4      ;'       g    VP                  R	4      ;'       g    T4      ,          pV P	                  W4      G R
j  x€L
 pV P                  WbV4      G R
j  x€L
 w  r‰p
V P                  WWš4      pVP                  '       d2   V P                  \        V4      VP                  V P                  V4       V#  Lx L`5i)FúEmpty message©Úsuccessr2   rh  Úsendrg  ú	--contentÚ-Ú	thread_idÚreply_to_message_idN)r'   r5   Ú_reply_argsr   r…  r‹  Ú_send_resultr”  Ú_remember_event_metaÚ
message_idrì  )r  rc  r1   rŽ  r�  Úmetars  rˆ  r"  r#  rS  Úresults   &&&&&       r   r•  ÚBuzzAdapter.send6  sç   é € ßÜ e°?ÔCÐCà�~ˆ~˜2ˆØ˜F K´°W³¸{ÈCÐPˆØ× Ñ  §¡¨+Ó!6×!eÐ!e¸$¿(¹(ÐCXÓ:Y×!eÐ!eÐ]eÓfÕfˆØ $× 9Ñ 9¸'Ó K×KˆØ#×5Ñ5°dÀ_ÓU×U‰ˆ�3Ø×"Ñ" 7°#Ó;ˆØ�>�>ˆ>à×%Ñ%¤c¨'£l°F×4EÑ4EÀt×GXÑGXÐZaÔbØˆñ LÙUùs5   ‚D¡6DÁDÁ1!DÂDÂDÂ,DÂ-ADÄDc                óF   <€ V ^8„  d   QhRS[ S[,          RS[S[,          /# ©r0   Úanchorr3   )r	   r5   r¥   )r6   r  s   "€r   r7   r  E  s'   ø€ ÷ jñ j¡(©3¥-ð j±D¹µIñ jr   c                ót   € V P                  V4      pV'       d   V P                  R8w  d   R\        V4      .# . # )zA``--reply-to`` CLI args for *anchor*, honoring ``reply_to_mode``.r  ú
--reply-to)Ú_resolve_reply_anchorr&  r5   )r  r£  Úreply_targets   && r   rš  ÚBuzzAdapter._reply_argsE  s8   € à×1Ñ1°&Ó9ˆß4@ÀT×EXÑEXÐ\aÔEa�œc ,Ó/Ð0ÐiÐgiÐir   r’  c                óN   <€ V ^8„  d   QhRS[ RS[RS[ RS[ RS[S[,          RS[/# )r0   rc  r"  r#  rS  r’  r3   )r5   rx   r	   r   r'   )r6   r  s   "€r   r7   r  J  s?   ø€ ÷ =ñ =¡Cð =©sð =¹ð =Á3ð =ÑX`ÑaeÕXfð =Ñr|ñ =r   c          	     óè   € V^ 8w  d   \        R\        WBVR7      V^8H  R7      # \        V4      w  rgV'       d   \        RVR7      # Vf   Q hV P                  \	        V4      V4       \        RVR7      # )zf``messages send`` result -> SendResult; marks the verified id seen (echo suppression belt-and-braces).F©r’  ©r”  r2   r'  r“  T)r”  r�  )r'   rœ  r¢  Ú
_mark_seenr5   )r  rc  r"  r#  rS  r’  r¡  Úreceipt_errors   &&&&&$  r   r›  ÚBuzzAdapter._send_resultJ  sr   € à�1Œ9Ü eÔ3EÀcÐ]hÔ3iÐuyÐ}~Ñu~ÔÐÜ"5°cÓ":ÑˆßÜ e°=ÔAÐAØÒ#Ð#Ð#ð 	�‰œ˜G› hÔ/Ü $°8Ô<Ð<r   c                ó$   <€ V ^8„  d   QhRS[ RR/# )r0   rc  r3   NrT   )r6   r  s   "€r   r7   r  X  s   ø€ ÷ :ñ :©ð :Àñ :r   c              ƒ  ó   "  € R# 5i)u+   Buzz has no typing indicator API â€” no-op.Nr  )r  rc  r�  s   &&&r   Úsend_typingÚBuzzAdapter.send_typingX  s   é ‚ ùs   ‚c                ó2   <€ V ^8„  d   QhRS[ RS[ RS[ RS[/# )r0   rc  r�  Úemojir3   rš   )r6   r  s   "€r   r7   r  [  s*   ø€ ÷ ñ ©3ð ¹Cð Éð ÑPTñ r   c           	   ƒ  ó  "  € V P                   '       d   V'       d	   V'       g   R# V P                  RRR\        V4      RV.4      G Rj  x€L
 w  rEpV^ 8w  d)   \        P	                  RVR,          V\        Wd4      4       V^ 8H  #  L;5i)	zEBest-effort reaction via buzz-cli; failures are logged, never raised.FÚ	reactionsrã  ú--eventz--emojiNu5   Buzz: reaction add failed for message %s in %s â€” %sºNé   N)r5  r  r5   r,  rG  rœ  )r  rc  r�  rµ  r"  Ú_outrS  s   &&&&   r   Úsend_reactionÚBuzzAdapter.send_reaction[  s‚   é € à�}�}ˆ}§E·Ùà $§¡¨{¸EÀ9ÌcÐR\ËoÐ_hÐjoÐ.pÓ q×q‰ˆ�CØ�1Œ9Ü�L‰LÐPÐR\Ð]`ÕRaÐcjÔl~ð  @Có  mJô  KØ�q‰yÐñ rùs   ‚B�B¥%BÁ
BÁ<BÚfinalizec          
      ó8   <€ V ^8„  d   QhRS[ RS[ RS[ RS[RS[/# )r0   rc  r�  r1   r¾  r3   )r5   r›   r'   )r6   r  s   "€r   r7   r  e  s9   ø€ ÷ sñ s©#ð s¹3ð sÉð sÑ[_ð sÑlvñ sr   c             ƒ  óþ  "  € V'       g   \        RRR7      # V'       g   \        RRR7      # RRR\        V4      RV 2.pV P                  V4      G R	j  x€L
 w  rgpV^ 8w  d   \        R\        W†4      V^8H  R
7      # \	        V/ 4      p	V	P                  R4      '       d,   V P                  \        V4      \        V	R,          4      4       \        \        V	P                  RR4      4      \        V4      V	R7      #  L¦5i)z¦Edit a sent message (streamed replies). The CLI reports a NEW event id but the stream consumer
keeps addressing the original, so return the given id, never the CLI's.FzBuzz edit needs a message idr“  r’  rh  Úeditr¸  z
--content=Nr¬  r¡  r   T)r”  r�  Úraw_response)r'   r5   r  rœ  r™  r   r­  r›   )
r  rc  r�  r1   r¾  rs  r"  r#  rS  rç   s
   &&&&$     r   Úedit_messageÚBuzzAdapter.edit_messagee  sÞ   é € ÷ Ü eÐ3QÔRÐRßÜ e°?ÔCÐCð ˜F I¬s°:«À*ÈWÈIÐ@VÐWˆØ#Ÿ}™}¨TÓ2×2‰ˆ�3Ø�1Œ9Ü eÔ3EÀcÓ3PÐ\`ÐdeÑ\eÔfÐfÜ˜˜RÓ ˆØ�8‰8�J×Òà�O‰OœC ›L¬#¨d°:Õ.>Ó*?Ô@Ü¤$ t§x¡x°
¸DÓ'AÓ"BÌsÐS]ËÐmqÔrÐrñ 3ùs   ‚C= 4C=ÁC;ÁB'C=c                ó,   <€ V ^8„  d   QhRS[ RS[ RS[/# )r0   rc  r�  r3   rš   )r6   r  s   "€r   r7   r  x  s"   ø€ ÷ 0ñ 0©Cð 0¹Sð 0ÁTñ 0r   c              ƒ  ó¦  "  € V'       g   R# V P                  RRR\        V4      .4      G Rj  x€L
 w  r4pV^ 8w  d   R#  \        P                  ! T;'       g    R4      pTP                  R4      '       d,   T P                  \        T4      \        TR,          4      4       \        TP                  R	R4      4      #  LŽ  \         d     R# i ; i5i)
zCDelete a sent message (stream consumer's fresh-final cleanup path).Frh  Údeleter¸  Nz{}Tr¡  r   )r  r5   r\  r]  r€   r   r­  r›   )r  rc  r�  r"  r#  r$  rç   s   &&&    r   Údelete_messageÚBuzzAdapter.delete_messagex  s¯   é € çÙØ $§¡¨z¸8ÀYÔPSÐT^ÓP_Ð.`Ó a×a‰ˆ�4Ø�1Œ9Ùð	Ü—:’:˜cŸk˜k TÓ*ˆDð �8‰8�J×ÒØ�O‰OœC ›L¬#¨d°:Õ.>Ó*?Ô@Ü�D—H‘H˜Z¨Ó.Ó/Ð/ñ bøô
 ô 	Úð	üs@   ‚,C®B=¯CÁ B? ÁB? Á CÁ7ACÂ?CÃ
CÃCÃCc                ó„   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          RS[S[ ,          RS[S[S[ S[3,          ,          RS[/# )r0   rc  Ú	image_urlÚcaptionrŽ  r�  r3   r�  )r6   r  s   "€r   r7   r  ‡  s\   ø€ ÷ 	Tñ 	TÙð	TÙ'*ð	TÙ5=¹cµ]ð	TÙU]Ñ^aÕUbð	Tá™4¡¡S �>Õ*ð	Tá6@ñ	Tr   c           	   ƒ  ó<  "  € VP                  R4      '       g   \        V4      P                  4       MRpVe4   VP                  4       '       d   V P	                  WW4VRR7      G Rj  x€L
 # V'       d   V RV 2MTpV P                  WWER7      G Rj  x€L
 #  L0 L5i)z@Send an image: local files upload via --file, URLs go as a link.NF©rÌ  rŽ  r�  Úproberº   )rŽ  r�  )zhttp://zhttps://)r  r   rD  rE  Ú_send_file_attachmentr•  )r  rc  rË  rÌ  rŽ  r�  Úlocalr¤   s   &&&&&&  r   Ú
send_imageÚBuzzAdapter.send_image‡  sŸ   é € ð 5>×4HÑ4HÐI`×4aÒ4a”�Y“×*Ñ*Ô,ÐgkˆØÒ §¡§¢Ø×3Ñ3°GÈGÐqyð  BGÐ3ó  H÷  Hð  Hç,3�'�˜"˜Y˜KÑ(¸ˆØ—Y‘Y˜w°x�YÓS×SÐSñ Hñ Tùs0   ‚ABÁBÁ'BÁ(BÁ4BÂBÂBÂBrÌ  rŽ  r�  rÏ  c                óŠ   <€ V ^8„  d   QhRS[ RS[RS[S[ ,          RS[S[ ,          RS[S[S[ S[3,          ,          RS[RS[/# )r0   rc  Ú	file_pathrÌ  rŽ  r�  rÏ  r3   )r5   r   r	   rû   r   r›   r'   )r6   r  s   "€r   r7   r  ’  sg   ø€ ÷ Mñ MÙðMÙ'+ðMÙ9AÁ#½ðMÙYaÑbeÕYfðMá™4¡¡S �>Õ*ðMá:>ðMñ 
ñMr   c             ƒ  ó¶  "  € \        V4      P                  4       pV'       d$   VP                  4       '       g   \        RRR7      # RRR\	        V4      R\	        V4      RR	.pY€P                  T;'       g    / P                  R
4      ;'       g    T4      ,          pT P                  Yƒ;'       g    R4      G Rj  x€L
 w  ršpV P                  WW«VR7      #  L5i)z†Upload a local file as a native attachment; ``probe=False`` when the caller already verified it (a re-probe could race).

See #74999.
FzMedia file not foundr“  rh  r•  rg  ú--filer–  r—  r˜  r9   Nr«  )	r   rD  rE  r'   r5   rš  r   r‹  r›  )r  rc  rÕ  rÌ  rŽ  r�  rÏ  rÑ  rs  r"  r#  rS  s   &&&$$$$     r   rÐ  Ú!BuzzAdapter._send_file_attachment’  s»   é € ô �Y“×*Ñ*Ó,ˆß˜Ÿ™Ÿšä eÐ3IÔJÐJØ˜F K´°W³¸xÌÈUËÐU`ÐbeÐfˆØ× Ñ  (§. .¨b×!5Ñ!5°kÓ!B×!NÐ!NÀhÓOÕOˆØ#×5Ñ5°d¿M¸MÀrÓJ×J‰ˆ�3Ø× Ñ  °ÀeÐ ÓLÐLñ Kùs#   ‚7CºACÂ CÂ1
CÂ;CÂ<Cc                ó„   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          RS[S[ ,          RS[S[S[ S[3,          ,          RS[/# )r0   rc  Ú
image_pathrÌ  rŽ  r�  r3   r�  )r6   r  s   "€r   r7   r  £  s\   ø€ ÷ 
Vñ 
VÙð
VÙ(+ð
VÙ6>¹sµmð
VÙV^Ñ_bÕVcð
Vá™4¡¡S �>Õ*ð
Vá@Jñ
Vr   c              ‹  óð   <"  € \        V4      P                  4       pVP                  4       '       d   V P                  WW4VRR7      G Rj  x€L
 # \        SV `  ! R	RVRVRVRVRV/VB G Rj  x€L
 #  L& L5i)
zwUpload a local image via ``--file``; missing paths keep the Base fallback so host paths never reach chat.

See #74999.
FrÎ  Nrc  rÚ  rÌ  rŽ  r�  r  )r   rD  rE  rÐ  rß  Úsend_image_file)	r  rc  rÚ  rÌ  rŽ  r�  r  rÑ  r  s	   &&&&&&, €r   rÜ  ÚBuzzAdapter.send_image_file£  s´   øé € ô �ZÓ ×+Ñ+Ó-ˆØ�=‰=�?Š?Ø×3Ñ3°GÈGÐqyð  BGÐ3ó  H÷  Hð  HÜ‘WÒ,ñ  V°Wð  VÈð  VÐ]dð  VÐowð  Vð  CKð  Vð  OUñ  V÷  Vð  	Vñ Hñ Vùs$   ƒAA6ÁA2Á!A6Á-A4Á.A6Á4A6c                óš   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          RS[S[ ,          RS[S[ ,          RS[S[S[ S[3,          ,          RS[/# )r0   rc  rÕ  rÌ  Ú	file_namerŽ  r�  r3   r�  )r6   r  s   "€r   r7   r  ¯  si   ø€ ÷ Añ AÙðAÙ'*ðAÙ5=¹cµ]ðAÙV^Ñ_bÕVcðAá™3•-ðAá2:¹4ÁÁSÀ½>Õ2JðAá`jñAr   c              ‹  óZ   "  € V P                  V\        V4      W5VR7      G Rj  x€L
 #  L5i)z>Upload a local document through Buzz's native ``--file`` path.©rÌ  rŽ  r�  N©rÐ  r   )r  rc  rÕ  rÌ  rß  rŽ  r�  r  s   &&&&&&&,r   Úsend_documentÚBuzzAdapter.send_document¯  s9   é € ð ×/Ñ/°¼¸i»ÐRYÐwÐ/ó  A÷  Að  	Añ  Aùó   ‚"+¤)¥+c                ó„   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          RS[S[ ,          RS[S[S[ S[3,          ,          RS[/# )r0   rc  Ú
video_pathrÌ  rŽ  r�  r3   r�  )r6   r  s   "€r   r7   r  µ  ó\   ø€ ÷ Bñ BÙðBÙ(+ðBÙ6>¹sµmðBÙV^Ñ_bÕVcðBá™4¡¡S �>Õ*ðBá@JñBr   c              ‹  óZ   "  € V P                  V\        V4      W4VR7      G Rj  x€L
 #  L5i)z;Upload a local video through Buzz's native ``--file`` path.rá  Nrâ  )r  rc  rç  rÌ  rŽ  r�  r  s   &&&&&&,r   Ú
send_videoÚBuzzAdapter.send_videoµ  ó>   é € ð ×/Ñ/°¼¸jÓ9IÐSZð  yAÐ/ó  B÷  Bð  	Bñ  Bùrå  c                ó„   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          RS[S[ ,          RS[S[S[ S[3,          ,          RS[/# )r0   rc  Ú
audio_pathrÌ  rŽ  r�  r3   r�  )r6   r  s   "€r   r7   r  »  rè  r   c              ‹  óZ   "  € V P                  V\        V4      W4VR7      G Rj  x€L
 #  L5i)z@Upload a local audio file through Buzz's native ``--file`` path.rá  Nrâ  )r  rc  rî  rÌ  rŽ  r�  r  s   &&&&&&,r   Ú
send_voiceÚBuzzAdapter.send_voice»  rì  rå  c                ó<   <€ V ^8„  d   QhRS[ RS[S[ S[3,          /# rb  )r5   rû   r   )r6   r  s   "€r   r7   r  Á  s'   ø€ ÷ oñ o©3ð o±4¹¹S¸µ>ñ or   c              ƒ  óÞ  "  € \        V4      pV P                  P                  V4      pV P                  P                  V4      ;pf~   V P                  '       dl   V P                  RRRV./ 4      G R j  x€L
 p\        V\        4      '       d8   VP                  R4      '       d!   \        VR,          4      ;q0P                  V&   RT;'       g    TRV'       d   VR,          RV/# RRV/#  Lw5i)	NrÑ  r   rg  r   Útyper?  r?   rc  )r5   rõ  r   rû  r5  r%  rï   rû   )r  rc  Ústater   rç   s   &&   r   Úget_chat_infoÚBuzzAdapter.get_chat_infoÁ  sÓ   é € Ü�g“,ˆØ×#Ñ#×'Ñ'¨Ó0ˆØ×'Ñ'×+Ñ+¨GÓ4Ð4ˆDÒ=À$Ç-Ç-À-ØŸ™¨°U¸KÈÐ(QÐSUÓV×VˆDÜ˜$¤×%Ò%¨$¯(©(°6×*:Ò*:Ü69¸$¸v½,Ó6GÐG�×*Ñ*¨7Ñ3Ø˜Ÿ˜ ¨Çu°°{Õ1CÐ[dÐfmÐnÐnÐRYÐ[dÐfmÐnÐnñ Wùs*   ‚AC-ÁC-Á3C+Á40C-Â%)C-Ã
C-ÃC-c                ó    <€ V ^8„  d   QhRS[ /# r’   rT   )r6   r  s   "€r   r7   r  Ð  s   ø€ ÷ Xñ X¡ñ Xr   c                óR  € \        V P                  P                  4       4      pR RRR/P                  VP                  VP                  4      pVR9  g   VP
                  '       g   \        R4      h\        Y!P
                  VP                  ;'       g    RVP                  R34      # )r”   r•   r|   r{   z(Buzz relay URL must use http(s) or ws(s)r9   )r•   r{   )
r   r™   rk   r   r�   Únetlocr€   r   rŸ   Úquery)r  rƒ   r�   s   &  r   Ú_websocket_urlÚBuzzAdapter._websocket_urlÐ  s�   € Ü˜$Ÿ.™.×.Ñ.Ó0Ó1ˆØ˜$ ¨Ð/×3Ñ3°F·M±MÀ6Ç=Á=ÓQˆØ˜Ô&¨f¯m¯m¨mÜÐGÓHÐHÜ˜6§=¡=°&·+±+×2CÐ2CÀÀVÇ\Á\ÐSUÐVÓWÐWr   c                ó    <€ V ^8„  d   QhRS[ /# r’   r3  )r6   r  s   "€r   r7   r  ×  s   ø€ ÷ ñ ©ñ r   c              ƒ  ó†  "  €  ^ RI pV P                  4        \
        P                  ! 4       T n        \        \        P                  ! 4       4      T n
        \
        P                  ! T P                  4       4      T n         \
        P                  ! T P                  P                  4       \         ^,           R7      G Rj  x€L
  R#   \         d"   p\        P	                  RT4        Rp?R# Rp?ii ; i L5  \"         d?    \        P%                  R4       \'        T P                  4      G Rj  x€L 
  RT n         R# i ; i5i)zAStart the WS loop; True when it authenticates within the timeout.NzCBuzz: WebSocket transport unavailable (%s); falling back to pollingFr}  Tz,Buzz: WebSocket did not authenticate in time)Ú
websocketsrü  rŽ   r,  rP  rˆ   ÚEventrñ  rx   r  rò  rM  Ú_websocket_looprð  r†  rŠ  Ú_WS_AUTH_TIMEOUTrˆ  Úwarningr)   )r  r   r®  s   &  r   rK  ÚBuzzAdapter._start_websocket×  sê   é € ð	ÛØ×ÑÔ!ô !Ÿš›ˆŒÜ!$¤T§Y¢Y£[Ó!1ˆÔÜ×+Ò+¨D×,@Ñ,@Ó,BÓCˆŒð	Ü×"Ò" 4§>¡>×#6Ñ#6Ó#8ÔBRÐUVÕBVÔW×WÐWÙøô ô 	Ü�K‰KÐ]Ð_`ÔaÝûð	úñ Xøäô 	Ü�N‰NÐIÔJÜ˜dŸm™mÓ,×,Ñ,Ø ˆDŒMÚð		üsp   ‚E„C ˜A&EÁ?>C5 Â=C3Â>C5 ÃEÃC0ÃC+Ã%EÃ+C0Ã0EÃ3C5 Ã58D>Ä-D0Ä.D>Ä:EÄ=D>Ä>Ec                ó   <€ V ^8„  d   QhRR/# r\  r  )r6   r  s   "€r   r7   r  ë  s   ø€ ÷ Gñ G¸$ñ Gr   c              ƒ  ó’  "  € \         P                  ! \        P                  ! VP	                  4       \
        R7      G Rj  x€L
 4      p\        V\        4      '       d   \        V4      ^8  g   V^ ,          R8w  d   \        R4      h\        V RR4      ;'       g    RpV'       g    \        \        V RR4      4      p\        P                  V P                  \!        V^,          4      V P#                  4       VR7      pVP%                  \         P&                  ! RV.RR	7      4      G Rj  x€L
   \         P                  ! \        P                  ! VP	                  4       \
        R7      G Rj  x€L
 4      p\        V\        4      '       d	   V'       g   Kg  V^ ,          R8X  dJ   \        V4      ^8¼  d:   V^,          VR,          8X  d%   V^,          R
J d   R# \        RV^,           24      hV^ ,          R9   g   KÎ  \        R\        V4      ^8”  d   VR,           24      hR 24      h ELë  \         d    Rp EL€i ; i EL LÖ5i)zjNIP-42: await the AUTH challenge, answer with a signed kind-22242 event (+ optional NIP-OA tag), await OK.r}  NÚAUTHz/Buzz relay did not send a NIP-42 AUTH challengerë  r9   rá  )rt  Ú	challenger™   Úauth_tag_jsonrh  TÚOKÚidzBuzz WebSocket AUTH rejected: zBuzz WebSocket AUTH failed: zauthentication failedrj  )ÚNOTICEÚCLOSEDre   )r\  r]  rˆ   r†  Úrecvr  rï   r¥   rl   ÚConnectionErrorr!  ro  r€   rm  Úbuild_auth_eventrê  r5   rü  r•  rl  )r  rÝ  r~  rg  rª  Úresponses   &&    r   Ú_authenticate_websocketÚ#BuzzAdapter._authenticate_websocketë  s	  é € ä—*’*¤7×#3Ò#3°I·N±NÓ4DÔN^Ô#_×_Ó`ˆÜ˜'¤4×(Ò(¬C°«L¸1Ô,<ÀÈÅ
ÈfÔ@TÜ!Ð"SÓTÐTô ˜4 ¨bÓ1×7Ð7°RˆßðÜ,¬W°T¸8ÀTÓ-JÓK�ô ×,Ñ,¸×9JÑ9JÔVYÐZaÐbcÕZdÓVeÐqu÷  rEñ  rEó  rGð  W_Ð,ó  `ˆØ�n‰nœTŸZšZ¨°¨ÀJÔOÓP×PÐPØÜ—z’z¬×(8Ò(8¸¿¹Ó9IÔScÔ(d×"dÓeˆHÜ˜h¬×-Ò-·XÙØ˜�{˜dÔ"¤s¨8£}¸Ô'9¸hÀq½kÈUÐSWÍ[Ô>XØ˜A•; $Ó&ÙÜ%Ð(FÀxÐPQÅ{ÀmÐ&TÓUÐUØ˜�{Ð2Ö2Ü%Ð(DÔUXÐYaÓUbÐefÔUfÀXÈbÅ\ð  EEð  'Fó  Gð  Gð  mDð  EEð  'Fó  Gð  Gò9 `øô ô Ø“ðúò 	Qá"dùsi   ‚>IÁ H+ÁAIÂ
IÂ(H. Â>A-IÄ+IÄ,AIÅ.IÅ/%IÆA$IÇ>.IÈ.H?È;IÈ>H?È?IÉIc                ó*   <€ V ^8„  d   QhRS[ RS[RR/# )r0   Úsubscription_idÚrequest_filterr3   Nrú   )r6   r  s   "€r   r7   r    s(   ø€ ÷ jñ j±Cð jÉð jÐRVñ jr   c              ƒ  ót   "  € V P                  \        P                  ! R W.RR7      4      G Rj  x€L
  R#  L5i)ÚREQrh  Nrj  )r•  r\  rl  )rÝ  r  r  s   &&&r   Ú	_send_reqÚBuzzAdapter._send_req  s(   é € à�n‰nœTŸZšZ¨°Ð(PÐ]gÔhÓi×iÔiùs   ‚-8¯6°8c                ó*   <€ V ^8„  d   QhRS[ RS[ RR/# )r0   r  r=  r3   NrT   )r6   r  s   "€r   r7   r    s)   ø€ ÷ Iñ IÉ3ð IÑ\_ð IÐdhñ Ir   c              ƒ  óP  "  € V P                   P                  V4      ;'       g    / p\        VP                  R 4      ;'       g    ^ 4      pR\        \        4      RV./pV'       d   \        V^,
          ^ 4      VR&   M	\        VR&   V P                  WV4      G Rj  x€L
  R#  L5i)Úlast_tsÚkindsz#hÚsinceÚlimitN)rõ  r   rx   r»   Ú_DISPATCH_KINDSrä  Ú_FETCH_LIMITr  )r  rÝ  r  r=  rõ  r  r  s   &&&&   r   Ú_send_channel_subscriptionÚ&BuzzAdapter._send_channel_subscription  s�   é € Ø×#Ñ#×'Ñ'¨
Ó3×9Ð9°rˆÜ�e—i‘i 	Ó*×/Ð/¨aÓ0ˆð "¤6¬/Ó#:¸DÀ:À,ÐOˆßä&)¨'°A­+°qÓ&9ˆN˜7Ò#ô '3ˆN˜7Ñ#Ø�n‰n˜Y¸ÓH×HÔHùs   ‚AB&ÁAB&ÂB$ÂB&c                óF   <€ V ^8„  d   QhRS[ S[S[S[,          3,          /# r’   ©rû   r5   r	   )r6   r  s   "€r   r7   r  !  s"   ø€ ÷ ñ ±t¹CÁÉ#ÅÐ<NÕ7Oñ r   c           	   ƒ  ó°  "  € / p\        \        V P                  4      4       F<  w  r4W@P                  9   d   K  WBRV 2&   V P	                  VRV 2V4      G Rj  x€L
  K>  	  V P
                  '       d\   R\        .RV P
                  .R\        V P                  ^,
          ^ 4      /pV P                  V\        V4      G Rj  x€L
  RV\        &   V#  Lw L5i)zlSubscribe to every watched conversation plus membership events (kind 44100 p-tagged to us) for DM discovery.zhermes-buzz-Nr  z#pr   )Ú	enumerater¥   rõ  rô  r$  rì  Ú_WS_MEMBERSHIP_KINDrä  rò  r  Ú_WS_MEMBERSHIP_SUB_ID)r  rÝ  ÚsubscriptionsÚindexr=  Ú
memberships   &&    r   Ú_subscribe_websocketÚ BuzzAdapter._subscribe_websocket!  så   é € à24ˆÜ!*¬4°×0CÑ0CÓ+DÖ!EÑˆEØ×6Ñ6Ô6ÙØ4>˜L¨¨Ð0Ñ1Ø×1Ñ1°)¸|ÈEÈ7Ð=SÐU_Ó`×`Ò`ñ	 "Fð
 ××ÐØ!Ô$7Ð#8¸$À×ARÑARÐ@SÐU\Ô^aÐbf×bxÑbxÐ{|Õb|Ð~ó  _Að  BˆJØ—.‘. Ô,AÀ:ÓN×NÐNØ37ˆMÔ/Ñ0ØÐñ añ Oùs+   ‚ACÁCÁCÁ5ACÃCÃCÃCc                óJ   <€ V ^8„  d   QhRS[ S[S[S[,          3,          RR/# ©r0   r,  r3   Nr'  )r6   r  s   "€r   r7   r  /  s1   ø€ ÷ 
Oñ 
OÉÉSÑRZÑ[^ÕR_ÐM_ÕH`ð 
OÐeiñ 
Or   c              ƒ  ó@  "  € \        V P                  4      pV P                  RR7      G Rj  x€L
  \        V P                  4       FM  pWC9   d   K  R\	        V4       2pWBV&   V P                  WV4      G Rj  x€L
  \        P                  RV4       KO  	  R#  Ll L"5i)zbRediscover conversations and subscribe to any adopted since (fresh DMs dispatch from their start).Fr@  Nzhermes-buzz-dm-z'Buzz: subscribed to new conversation %s)ró   rõ  rI  r¥   rl   r$  r,  rP  )r  rÝ  r,  Úbeforer=  r  s   &&&   r   Ú_rediscover_and_subscribeÚ%BuzzAdapter._rediscover_and_subscribe/  s”   é € ä�T×(Ñ(Ó)ˆØ× Ñ  eÐ Ó,×,Ð,Ü˜t×2Ñ2Ö3ˆJØÔ#ÙØ /´°MÓ0BÐ/CÐDˆOØ-7˜/Ñ*Ø×1Ñ1°)ÈjÓY×YÐYÜ�K‰KÐAÀ:ÖNó 4ñ 	-ñ Zùs"   ‚+B­B®ABÁ9BÁ:!BÂBc                óJ   <€ V ^8„  d   QhRS[ S[S[S[,          3,          RR/# r2  r'  )r6   r  s   "€r   r7   r  ;  s/   ø€ ÷ Xñ XÁÁcÉ8ÑTWÍ=ÐFXÕAYð XÐ^bñ Xr   c              ƒ  ó^  "  € ^ RI Hp \        V P                  \        ,          \
        4      p \        P                  ! V4      G Rj  x€L
   V P                  W4      G Rj  x€L
  K;   L  L  \        P                  T3 d    h \         d    \        P                  RRR7        K{  i ; i5i)u®  Periodic discovery on the poll cadence: relays don't guarantee a kind-44100 event for every new
conversation. Failures retry next tick, except a closed socket: that is the same dead connection the
read loop may still be parked on, so it propagates and tears the connection down (#112049).

The kind-44100 membership subscription is the fast path, but relays do not guarantee a membership
event for every conversation that materializes mid-session (#93557) â€” some emit none at all for new
DM-shaped conversations. The poll transport papers over this by re-running discovery every
``_DM_DISCOVERY_EVERY`` sweeps; this loop gives the WS transport the same guarantee on the same
cadence.
)ÚConnectionClosedTNz&Buzz: WebSocket discovery sweep failed©Úexc_info)Úwebsockets.exceptionsr9  rä  rÓ  Ú_DM_DISCOVERY_EVERYrå  rˆ   Úsleepr5  ÚCancelledErrorrŽ   r,  r  )r  rÝ  r,  r9  Úintervals   &&&  r   Ú_ws_discovery_loopÚBuzzAdapter._ws_discovery_loop;  s“   é € õ 	;ä�t×)Ñ)Ô,?Õ?ÔASÓTˆØÜ—-’- Ó)×)Ð)ðXØ×4Ñ4°YÓN×NÒNñ *áNøÜ×*Ñ*Ð,<Ð=ô ØÜô XÜ—‘ÐGÐRV�×WðXüsN   ‚AB-ÁA)Á	B-ÁA- Á"A+Á#A- Á'B-Á+A- Á- B*ÂB*Â&B-Â)B*Â*B-c                ó   <€ V ^8„  d   QhRR/# r\  r  )r6   r  s   "€r   r7   r  R  s   ø€ ÷ ,1ñ ,1 tñ ,1r   c           
   ƒ  ó:  "  € ^ RI pRpRp  VP                  V P                  4       \        ^^^\        RR7      ;_uu_4       GRj  x€L
 pV P                  V4      G Rj  x€L
  V P                  V4      G Rj  x€L
 pV P                  e   V P                  P                  4        V'       d   RpV P                  4        Rp\        P                  ! V P                  WE4      4      \        P                  ! V P                  WE4      4      0p \        P                  ! V\        P                  R7      G Rj  x€L
 w  rxV F  p	V	P!                  4        K  	  V F  p
V
P#                  4        K  	  \        P$                  ! VRR/ G Rj  x€L
  RRR4      GRj  x€L
  EK•   ELY ELC EL- Lr L"  T F  p
T
P#                  4        K  	  \        P$                  ! TRR/ G Rj  x€L 
  i ; i LQ  + GRj  x€L 
 '       g   i     EKü  ; i  \        P&                   d    h \(         do   pT'       g   RpT P+                  4        \,        P/                  R	Y+4       \        P0                  ! T4      G Rj  x€L 
  \3        T^,          R
4      p Rp?EKˆ  Rp?ii ; i5i)zjPersistent authenticated subscription with bounded reconnect backoff; `since` filters resume on reconnect.NrO   FTg      Ð?)Úopen_timeoutÚclose_timeoutÚping_intervalÚping_timeoutÚmax_sizeÚhappy_eyeballs_delay)Úreturn_whenÚreturn_exceptionsz3Buzz: WebSocket disconnected; retrying in %.1fs: %srP   )r   rY  rü  r  Ú_WS_MAX_MESSAGE_BYTESr  r/  rñ  ró   rO  rˆ   rM  Ú_ws_read_looprA  rŠ  ÚFIRST_COMPLETEDrŸ  ÚcancelÚgatherr?  rŽ   Ú_mark_degradedr,  r  r>  Úmin)r  r   ÚbackoffÚreconnectingrÝ  r,  ÚtasksÚdoneÚ_Úfinishedr‡   r®  s   &           r   r  ÚBuzzAdapter._websocket_loopR  s  é € ãØˆØˆØð&1Ø%×-Ñ-Ø×'Ñ'Ó)Ô8HÐXYØ"$°2Ô@UØ)-ð .÷ ÷ ô ð Ø×6Ñ6°yÓA×AÐAØ*.×*CÑ*CÀIÓ*N×$N�MØ—~‘~Ò1ØŸ™×*Ñ*Ô,ß#à',˜Ø×,Ñ,Ô.Ø!�Gô  ×+Ò+¨D×,>Ñ,>¸yÓ,XÓYÜ×+Ò+¨D×,CÑ,CÀIÓ,]Ó^ð�EðMÜ(/¯ª°UÌ×H_ÑH_Ô(`×"`™˜Û(,˜HØ$ŸO™OÖ-ñ )-ó %*˜DØ ŸK™KžMñ %*ä%Ÿnšn¨eÐLÀtÑL×LÐL÷7÷ õ ò
 BÚ$Nñ #añ Møó %*˜DØ ŸK™KžMñ %*ä%Ÿnšn¨eÐLÀtÑL×LÒLú÷7÷ ÷ ô ûô8 ×)Ñ)ô ØÜô 1ç#Ø#'�LØ×'Ñ'Ô)Ü—‘ÐTÐV]ÔaÜ—m’m GÓ,×,Ñ,Ü˜g¨�k¨4Ó0—ûð1üs  ‚
J�:H
 ÁF ÁH
 ÁG,Á F#Á!G,Á9F&Á:3G,Â.AG,Ä)F-Ä6F)Ä7F-Å2G,ÆF+Æ	G,ÆH
 ÆG*ÆH
 ÆJÆ H
 Æ#G,Æ&G,Æ)F-Æ+G,Æ-3G'Ç G#Ç!G'Ç'G,Ç*H
 Ç,H	Ç2G5Ç3
H	Ç>H	È H
 ÈJÈH
 È
JÈ)JÈ*A	JÉ3I6É4JÊJÊJÊJc                óJ   <€ V ^8„  d   QhRS[ S[S[S[,          3,          RR/# r2  r'  )r6   r  s   "€r   r7   r  €  s.   ø€ ÷ Qñ Q¹DÁÁhÉsÅmÐASÕ<Tð QÐY]ñ Qr   c              ƒ  óz  "  € VP                  4       p \        P                  ! VP                  4       4      p \        P                  ! V0\
        \        P                  R7      G Rj  x€L
 w  rVV'       g   \        R\
        R R24      hVP                  4       p TP                  4       '       g&   TP                  4        TP                  \        4        \        P                  ! T4      p\)        T\*        4      '       g   Kó  T'       g   Ký  T P-                  YT4      G Rj  x€L
  EK   LÄ  \         d    \        R4      Rhi ; i  TP                  4       '       g'   TP                  4        TP                  \        4       i i ; i  \         \"        3 d    \$        P'                  R4        EK¢  i ; i L“5i)z`Read frames until the relay closes; a close or an idle read raises ConnectionError to reconnect.)rq  rK  Nzno WebSocket frame for z.0fz&s; assuming the connection went silentzrelay closed the WebSocketz(Buzz: ignoring malformed WebSocket frame)Ú	__aiter__rˆ   Úensure_futureÚ	__anext__rŠ  Ú_WS_READ_IDLE_TIMEOUTrO  r  rŸ  ÚStopAsyncIterationrW  rP  Úadd_done_callbackr�   r\  r]  r€   rç  r,  r  rï   r¥   Ú_handle_ws_message)	r  rÝ  r,  Ú
frame_iterÚ	read_taskrW  rX  r‚   r~  s	   &&&      r   rN  ÚBuzzAdapter._ws_read_loop€  sw  é € à×(Ñ(Ó*ˆ
ØÜ×-Ò-¨j×.BÑ.BÓ.DÓEˆIðGÜ '§¢Ø�KÔ)>ÌG×LcÑLcô!÷ ‘�÷ ô *Ø1Ô2GÈÐ1LÐLrÐsóð ð  ×&Ñ&Ó(‘ð !—~‘~×'Ò'Ø×$Ñ$Ô&Ø×/Ñ/Ô0EÔFðÜŸ*š* S›/�ô ˜'¤4×(Ô(¯W©WØ×-Ñ-¨iÈÓP×PÓPñ3øô &ô Nô &Ð&BÓCÈÐMðNûð
 !—~‘~×'Ò'Ø×$Ñ$Ô&Ø×/Ñ/Ô0EÕFð (ûô
 ¤	Ð*ô Ü—‘ÐIÔJÛðúñ Qùs|   ‚6F;¹/D/ Á(D-Á)2D/ ÂF;Â2%F;ÃF Ã.F;ÄF;ÄF;Ä%F9Ä&F;Ä-D/ Ä/EÅE
 Å
>FÆF;Æ&F6Æ1F;Æ5F6Æ6F;c                óP   <€ V ^8„  d   QhRS[ S[S[S[,          3,          RS[RR/# )r0   r,  r~  r3   N)rû   r5   r	   r¥   )r6   r  s   "€r   r7   r  ¡  s8   ø€ ÷ Bñ BÁÁcÉ8ÑTWÍ=ÐFXÕAYð BÑdhð BÐmqñ Br   c              ƒ  óÂ  a"  € V^ ,          R8X  Ed	   \        V4      ^8¼  dù   \        V^,          4      V^,          rT\        V\        4      '       g   R# V\        8X  dY   \        V P                  \        VP                  R4      ;'       g    ^ 4      4      V n        V P                  W4      G Rj  x€L
  R# VP                  V4      pV P                  P                  T;'       g    R4      pV'       d$   Ve   V P                  WgV.4      G Rj  x€L
  R# R# R# V^ ,          R8X  Ed   \        V4      ^8”  d
   VR,          MRo\        V4      ^8”  d   \        V^,          4      MRpVP                  V4      p	\        ;QJ d    V3R lR 4       F  '       g   K   RM	  R	M! V3R lR 4       4      p
V
'       d	   V	'       g   \        \        S4      4      h\        P                  R
V	S4       V P                   P#                  V	4       W( V P                  P%                  V	R4       R# V^ ,          R8X  d    \        P                  RVR,          4       R# R#  EL¨ ELL5i)z7Route one parsed relay frame (EVENT / CLOSED / NOTICE).ÚEVENTNÚ
created_atr9   r  zsubscription closedc              3   óZ   <"  € T F   q\        S4      P                  4       9   x € K"  	  R # 5ir©   )r5   r~   )r\   r@   rŽ  s   & €r   r^   Ú1BuzzAdapter._handle_ws_message.<locals>.<genexpr>µ  s#   øé € ÐuÑ=t¸¤ F£× 1Ñ 1Ó 3Ö3Ó=tùs   ƒ(+TFuM   Buzz: relay permanently rejected channel %s (%s) â€” removing from watch listr  zBuzz: relay notice: %sre   )Ú
restrictedznot a channel memberzauth-required)rl   r5   rï   rû   r+  rä  rò  rx   r   r5  rõ  Ú_handle_eventsr²   r  r,  r  rô  rã  r�  )r  rÝ  r,  r~  r  rª  r=  rõ  Úsub_idÚclosed_channelÚrejectedrŽ  s   &&&&       @r   rc  ÚBuzzAdapter._handle_ws_message¡  sß  øé € à�1�:˜Õ ¤S¨£\°QÔ%6Ü%(¨°­£_°g¸aµj˜UÜ˜e¤T×*Ò*ÙØÔ"7Ô7ä),¨T×-CÑ-CÄSÈÏÉÐS_ÓI`×IeÐIeÐdeÓEfÓ)g�Ô&Ø×4Ñ4°YÓN×NÐNÙØ&×*Ñ*¨?Ó;ˆJØ×'Ñ'×+Ñ+¨J×,<Ð,<¸"Ó=ˆEß˜eÒ/Ø×)Ñ)¨*¸e¸WÓE×EÒEñ 0‰zà�Q�Z˜8Õ#Ü$'¨£L°1Ô$4�W˜R–[Ð:OˆFÜ(+¨G«°qÔ(8”S˜ �”_¸bˆFØ*×.Ñ.¨vÓ6ˆNç“sÔuÑ=tÓu—s—s’sÔuÑ=tÓuÓuˆHß§Ü%¤c¨&£kÓ2Ð2Ü�N‰NÐjÐlzð  }Cô  DØ×%Ñ%×)Ñ)¨.Ô9ØÐ%Ø×Ñ×#Ñ# N°DÖ9Ø�Q�Z˜8Ô#Ü�N‰NÐ3°W¸Rµ[ÖAñ $ò% Oò
 FùsP   ƒB	IÂ$IÂ1IÂ24IÃ'IÃ6IÄIÄA3IÆIÆIÆ<IÇBIÉIc                ó   <€ V ^8„  d   QhRR/# r\  r  )r6   r  s   "€r   r7   r  Á  s   ø€ ÷ Iñ I $ñ Ir   c              ƒ  óò  "  €  \         P                  ! V P                  4      G Rj  x€L
  V ;P                  ^,          un         V P                  \        ,          ^ 8X  d   V P                  RR7      G Rj  x€L
  \        V P                  4       F  pV P                  V4      G Rj  x€L
  K  	  K°   L‹ L= L  \         P                   d    h \         d    \        P                  RRR7        Kð  i ; i5i)z:Poll every watched channel for new events until cancelled.TNFr@  zBuzz: poll sweep failedr:  )rˆ   r>  rÓ  ró  r=  rI  r¥   rõ  Ú_poll_channelr?  rŽ   r,  r  )r  r=  s   & r   rN  ÚBuzzAdapter._poll_loopÁ  sÊ   é € àÜ—-’- × 2Ñ 2Ó3×3Ð3Ø×Ò Õ!ÕðIØ×#Ñ#Ô&9Õ9¸QÔ>Ø×,Ñ,°%Ð,Ó8×8Ð8Ü"& t×':Ñ':Ö";�JØ×,Ñ,¨ZÓ8×8Ò8ó #<ñ 4ñ 9á8øÜ×)Ñ)ô ØÜô IÜ—‘Ð8À4�×HðIüs]   ‚%C7§B3¨C7Á1B9 Á7B5Á80B9 Â(B7Â)B9 Â1C7Â5B9 Â7B9 Â9C4ÃC4Ã0C7Ã3C4Ã4C7c                ó&   <€ V ^8„  d   QhRS[ RS[/# )r0   r?  r3   rú   )r6   r  s   "€r   r7   r  Ð  s   ø€ ÷ jñ j©Cð j±Dñ jr   c           	     ó6   € R VR^ R\        4       R\        4       /# )r?  r  ÚseenÚ
event_metar   )r  r?  s   &&r   Ú_new_channel_stateÚBuzzAdapter._new_channel_stateÐ  s   € Ø˜Y¨	°1°f¼k»mÈ\Ô[fÓ[hÐiÐir   c                ó,   <€ V ^8„  d   QhRS[ RS[ RS[/# )r0   r=  r?  r3   rš   )r6   r  s   "€r   r7   r  Ó  s"   ø€ ÷ ñ ±ð Áð Éñ r   c                óú   € V P                   P                  VR4      pVf   R# T P                  VR,          ;'       g    T4      pVR,          VR&   \        R VR,           4       4      VR&   W@P                  V&   R# )a;  Install a persisted cursor (True when one existed): seeding would mark downtime arrivals as seen.

Restoring is what closes the restart gap: seeding from current history instead would mark everything
that arrived while the gateway was down as already seen, so the relay's durable copy is never
dispatched (#90464).
NFr?  r  c              3   ó(   "  € T F  qR 3x € K
  	  R # 5ir©   r  )r\   r¡  s   & r   r^   Ú5BuzzAdapter._restore_channel_state.<locals>.<genexpr>ß  s   é € Ð#VÑEU¸¨tÕ$4ÓEUùs   ‚ry  T)rö  r�  r{  r   rõ  )r  r=  r?  Úrestoredrõ  s   &&&  r   Ú_restore_channel_stateÚ"BuzzAdapter._restore_channel_stateÓ  s{   € ð ×)Ñ)×-Ñ-¨j¸$Ó?ˆØÒÙØ×'Ñ'¨°Õ(=×(JÐ(JÀÓKˆØ# IÕ.ˆˆiÑÜ#Ñ#VÀXÈfÖEUÓ#VÓVˆˆf‰Ø*/×Ñ˜JÑ'Ùr   c                ó*   <€ V ^8„  d   QhRS[ RS[ RR/# )r0   r=  r?  r3   NrT   )r6   r  s   "€r   r7   r  ã  s"   ø€ ÷ ñ ©cð ¹cð Àdñ r   c           
   ƒ  óÌ  "  € V P                  W4      '       d   R# V P                  V4      ;q0P                  V&   V P                  RRRVR\	        \
        4      .4      G Rj  x€L
 w  rEpV^ 8w  dD   \        P                  RV\        Wd4      4       \        \        P                  ! 4       4      VR&   R# \        V4       FŒ  pVP                  R4      ;p'       d   RVR	,          \	        V4      &   \        VR,          \        VP                  R
4      ;'       g    ^ 4      4      VR&   V P                  W74       V P                  WV4       KŽ  	  V P!                  V4       R#  Lÿ5i)z>Initialize a channel's high-water mark from its newest events.Nrh  r   rg  ri  u&   Buzz: could not seed channel %s â€” %sr  r  ry  rj  )r‚  r{  rõ  r  r5   r#  r,  r  rœ  rx   r  r¨  r   rä  Ú_remember_eventÚ_maybe_latch_dmÚ
_trim_seen)	r  r=  r?  rõ  r"  r#  rS  rª  r¡  s	   &&&      r   rH  ÚBuzzAdapter._seed_channelã  s-  é € à×&Ñ& z×=Ò=ÙØ26×2IÑ2IÈ)Ó2TÐTˆ×#Ñ# JÑ/Ø#Ÿ}™}¨j¸%ÀÈjÐZcÔehÔiuÓevÐ-wÓx×x‰ˆ�3Ø�1Œ9Ü�N‰NÐCÀZÔQcÐdgÓQnÔoä"¤4§9¢9£;Ó/ˆE�)ÑÙÜ% cÖ*ˆEØ Ÿ9™9 T›?Ð*ˆxÖ*Ø/3��f•œc (›mÑ,Ü" 5¨Õ#3´S¸¿¹À<Ó9P×9UÐ9UÐTUÓ5VÓWˆE�)Ñð × Ñ  Ô.Ø× Ñ  °EÖ:ñ +ð 	�‰˜Öñ yùs   ‚A E$Á"E"Á#B6E$ÄA	E$c                ó$   <€ V ^8„  d   QhRS[ RR/# )r0   rA  r3   Nr3  )r6   r  s   "€r   r7   r  ø  s   ø€ ÷ &xñ &x©4ð &x°Dñ &xr   c          	   ƒ  óâ  "  € V P                  RR.4      G Rj  x€L
 w  r#pV^ 8X  d   \        V4      M.  FŠ  p\        VP                  R4      ;'       g    R4      pV'       g   K1  W`P                  9  g   KC  W`P
                  9  g   KU  V P                  Wa4      G Rj  x€L
  V P                  P                  VR4       KŒ  	  V P                  RR.4      G Rj  x€L
 w  r#pV^ 8w  d   R# \        V4       EFf  p\        VP                  R4      ;'       g    R4      ;p'       g   K2  WpP                  V&   V P                  P                  T\        VP                  R	4      ;'       g    T4      4       W€P
                  9   d   K�  V P                  V4      '       dD   W€P                  9   d   R
V P                  V,          R&   KÏ  V P                  W�4      G Rj  x€L
  Kê  W€P                  9  g   Kü  V'       d   EK  V P                  '       d   EK  V P                  VRR7      G Rj  x€L
  \        P                  RW€P                  P                  Wˆ4      4       EKi  	  R#  ELI ELÇ EL� L’ LE5i)a�  Watch DMs: startup ones are seeded, mid-run ones dispatch from their start. ``dms list`` is best-effort
(some relays return ``[]``); the fallback shape is a ``channels list`` entry named "DM" with empty
description. Named rooms and missing metadata fail closed as groups.

``dms list`` is only a best-effort source: on some hosted relays it returns ``[]`` even when DM
conversations exist (#68871).
Údmsr¥   NÚdm_idr9   ÚDMrÑ  r=  r   Údmr?  r?   r>  z*Buzz: adopted newly joined channel %s (%s))r  r¨  r5   r   rõ  rô  Ú_adopt_conversationrû  r€  rü  Ú_may_reclassify_as_dmrÑ  rH  r,  rP  )	r  rA  r"  r#  r$  r�  r�  rU  rV  s	   &$       r   rI  ÚBuzzAdapter._discover_dmsø  sð  é € ð !%§¡¨u°f¨oÓ >×>‰ˆ�4Ø+/°1¬9Ô" 3Ô'¸"Ò<ˆBÜ˜Ÿ™˜w›×-Ð-¨2Ó.ˆEß‰u˜×&9Ñ&9Ö9¸e×KdÑKdÖ>dØ×.Ñ.¨uÓ;×;Ð;Ø×#Ñ#×.Ñ.¨u°dÖ;ñ	 =ð
 !%§¡¨z¸6Ð.BÓ C×C‰ˆ�4Ø�1Œ9ÙÜ" 3×'ˆBÜ  §¡¨Ó!5×!;Ð!;¸Ó<Ð<�EÖ<ÙØ(*×Ñ˜uÑ%Ø×Ñ×*Ñ*¨5´#°b·f±f¸V³n×6MÐ6MÈÓ2NÔOØ×1Ñ1Ô1ÙØ×)Ñ)¨%×0Ò0ð ×/Ñ/Ô/Ø>B�D×'Ñ'¨Õ.¨{Ó;à×2Ñ2°5Ó?×?Ò?Ø×1Ñ1Ö1¿$º$ÀtÇ}Ç}Ã}ð ×(Ñ(¨¸'Ð(ÓB×BÐBÜ—‘ÐHÈ%×QdÑQd×QhÑQhÐinÓQv×wó+ (ò ?ò <âCñ  @ñ Cùsš   ‚I/™I"š:I/ÁI/Á&I/Á8I/Â
I/ÂI%Â:I/ÃI(Ã;I/ÄI/Ä%AI/Å(3I/Æ<I/ÇI+ÇI/Ç1I/Ç<I/ÈI/È'I-È(;I/É%I/É(I/É+I/É-I/c                ó*   <€ V ^8„  d   QhRS[ RS[RR/# )r0   r=  rA  r3   Nrš   )r6   r  s   "€r   r7   r     s'   ø€ ÷ Lñ L±Cð L¹tð LÈñ Lr   c              ƒ  óÌ   "  € V'       d   V P                  VRR7      G Rj  x€L
  R# V P                  VR4      '       g!   V P                  R4      V P                  V&   R# R#  L@5i)zOStart watching a DM conversation: seed at startup, else restore or start fresh.r�  r>  N)rH  r‚  r{  rõ  )r  r=  rA  s   &&&r   r�  ÚBuzzAdapter._adopt_conversation   sZ   é € çØ×$Ñ$ Z¸4Ð$Ó@×@Ò@Ø×,Ñ,¨Z¸×>Ò>Ø.2×.EÑ.EÀdÓ.KˆD×Ñ 
Ó+ñ ?ñ Aùs   ‚A$¡A"¢A$Á #A$c                ó$   <€ V ^8„  d   QhRS[ RR/# )r0   r=  r3   NrT   )r6   r  s   "€r   r7   r  '  s   ø€ ÷ Lñ L©cð L°dñ Lr   c              ƒ  ó¦  "  € V P                   P                  V4      pVf   R # RRRVR\        \        4      .pVR,          '       d   VR\        VR,          4      .,          pV P	                  V4      G R j  x€L
 w  rEpV^ 8w  d#   \
        P                  RV\        Wd4      4       R # V P                  W\        V4      4      G R j  x€L
  R #  LU L5i)Nrh  r   rg  ri  r  z--sinceu&   Buzz: poll of channel %s failed â€” %s)
rõ  r   r5   r#  r  r,  rG  rœ  rn  r¨  )r  r=  rõ  rs  r"  r#  rS  s   &&     r   ru  ÚBuzzAdapter._poll_channel'  s¼   é € Ø×#Ñ#×'Ñ'¨
Ó3ˆØŠ=ÙØ˜E ;°
¸IÄsÌ<ÓGXÐYˆØ�×Ôà�Y¤ E¨)Õ$4Ó 5Ð6Õ6ˆDØ#Ÿ}™}¨TÓ2×2‰ˆ�3Ø�1Œ9Ü�L‰LÐAÀ:ÔOaÐbeÓOlÔmÙØ×!Ñ! *Ô5EÀcÓ5JÓK×KÒKñ	 3ñ 	Lùs%   ‚A5CÁ7CÁ8ACÃCÃCÃCc                ó@   <€ V ^8„  d   QhRS[ RS[RS[S[,          RR/# )r0   r=  rõ  Úeventsr3   N)r5   rû   r¥   )r6   r  s   "€r   r7   r  5  s4   ø€ ÷ Lñ L©sð L¹4ð LÉÉdÍð LÐX\ñ Lr   c              ƒ  ó  "  € V P                  V4      pV F  pV P                  WV4      G Rj  x€L
  K  	  V P                  V4       V P                  V4      V8w  d'   ^ RIHp V! W P                  4       4      G Rj  x€L
  R# R#  LW L
5i)zdHandle a batch, trim, and persist only when the cursor moved (idle channels don't rewrite the file).N)Úwhen_returned_inputs_durable)Ú_cursor_markÚ_handle_eventrˆ  Úgateway.session_ingress_burstrœ  Ú_cursor_writer)r  r=  rõ  rš  r4  rª  rœ  s   &&&&   r   rn  ÚBuzzAdapter._handle_events5  s~   é € à×"Ñ" 5Ó)ˆÛˆEØ×$Ñ$ Z¸Ó>×>Ò>ñ à�‰˜ÔØ×Ñ˜UÓ# vÔ-ÝRÙ.¨t×5HÑ5HÓ5JÓK×KÒKñ .ñ ?ñ Lùs"   ‚,B
®B¯AB
Á=BÁ>	B
ÂB
c                óL   <€ V ^8„  d   QhRS[ RS[S[S[ ,          S[3,          /# r²  )rû   rw   r¥   rx   )r6   r  s   "€r   r7   r  @  s(   ø€ ÷ $%ñ $%©ð $%±±t¹DµzÁ3°Õ1Gñ $%r   c                ó¨  € V P                  R4      p\        V\        4      '       g   . ^ 3# . p^ ;r4V EF÷  p\        V\        \        34      '       d   V'       d   V^ ,          R8w  d   K8  \	        V4      \
        8¼  d   V^,          pKW  / pR VR,           4        F*  w  rxp	V'       g   K  Wv9  g   K  V	P                  4       Wg&   K,  	  VP                  RR4      VP                  RR4      P                  4       rº \        VP                  RR4      4      p\        V
4      pVP                  pVP                   TP                  R	8w  g�   T'       dy   TP                  '       gg   TP                   '       gU   TP"                  '       gC   \$        P'                  T4      '       d(   ^ Tu;8  d   \(        8:  d   M MYL,           \(        8”  d   T^,          pEK¤  YL,          pTP+                  RT
R
TRTR\-        TP                  RR4      4      RTP                  RR4      R,          /4       EKú  	  W#3#   \        \        3 d    T^,          p EK  i ; i)zAReturn accepted NIP-94 metadata and the rejected ``imeta`` count.r­  Úimetac              3   ót   "  € T F.  p\        V\        4      '       g   K  VP                  R 4      x € K0  	  R# 5i)Ú N)rï   r5   Ú	partition)r\   Úfs   & r   r^   Ú7BuzzAdapter._parse_imeta_attachments.<locals>.<genexpr>N  s*   é € Ð)bÁG¸qÌzÐZ[Ô]`×OaÔ*:¨!¯+©+°c×*:Ð*:ÃGùs   ‚8Ÿ8r<   r˜   r9   ÚxÚsizer|   Úsha256ÚfilenameÚ	mime_typer@   :Néÿ   N)r   rï   r¥   rw   rl   Ú_MAX_INBOUND_ATTACHMENTSrk   r~   rx   r   r}   r   rç  r€   r�   ÚusernameÚpasswordÚfragmentr  rž   Ú_MAX_INBOUND_ATTACHMENT_BYTESr¯   ru   )rª  r­  Úattachmentsrq  Útotal_declared_bytesr¯  Úfieldsr"   Ú	separatorrS   r˜   Údigestr«  rƒ   Úparsed_hostnames   &              r   Ú_parse_imeta_attachmentsÚ$BuzzAdapter._parse_imeta_attachments?  s
  € ð �y‰y˜Ó ˆÜ˜$¤×%Ò%Ø�q�5ˆLØ"$ˆØ*+Ð+ˆÜˆCÜ˜c¤D¬% =×1Ò1¿ÀÀAÅÈ'Ô@QÙÜ�;ÓÔ#;Ô;Ø˜A•�ÙØ%'ˆFÙ)bÀCÈÆGÖ)bÑ%� ß‘9 Ö!2Ø"'§+¡+£-�F“Kñ *cð !Ÿ*™* U¨BÓ/°·±¸CÀÓ1D×1JÑ1JÓ1L�ðÜ˜6Ÿ:™: f¨bÓ1Ó2�Ü! #›�Ø"(§/¡/�Ø—’ð
 —‘ Ô(·À6Ç?Ç?À?ÐV\×Ve×VeÐVeÐio×ix×ixÐixÜ ×*Ñ*¨6×2Ò2¸!¸dÖ:cÔFc×:cØ'Õ.Ô1NÔNà˜A•�ÚØ Õ(Ð Ø×Ñ  s¨H°f¸fÀdØ *Ô,EÀfÇjÁjÐQ[Ð]_ÓF`Ó,aÐcnÐpv×pzÑpzÐ{~ð  ACó  qDð  EIõ  qJð K÷ Lñ7 ð: Ð$Ð$øô œzÐ*ô Ø˜A•�Ûðús   Ã<>H2È2IÉIc                ó6   <€ V ^8„  d   QhRS[ RS[S[ ,          /# r²  )rû   r¥   )r6   r  s   "€r   r7   r  g  s   ø€ ÷ >ñ >¡$ð >©4±­:ñ >r   c                ó:   € \         P                  V 4      ^ ,          # )z>Return bounded, structurally valid NIP-94 attachment metadata.)rÉ  r»  )rª  s   &r   Ú_imeta_attachmentsÚBuzzAdapter._imeta_attachmentsf  s   € ô ×3Ñ3°EÓ:¸1Õ=Ð=r   c                ó&   <€ V ^8„  d   QhRS[ RS[/# )r0   rq  r3   )rx   r5   )r6   r  s   "€r   r7   r  l  s   ø€ ÷ wñ w©Sð w±Sñ wr   c                ó&   € RV R8:  d   V  R2# R R2# )zAReturn a fixed-width diagnostic for malformed or excess metadata.Ú[iç  z999+z: Buzz attachment(s) rejected as malformed or over limits.]r  )rq  s   &r   Ú_attachment_rejection_noteÚ&BuzzAdapter._attachment_rejection_notek  s)   € ð ˜x¨3œ�8Ð;Ð;uÐvÐv°FÐ;Ð;uÐvÐvr   c                ó6   <€ V ^8„  d   QhRS[ RS[S[,          /# )r0   r�  r3   )rû   r	   r&   )r6   r  s   "€r   r7   r  p  s    ø€ ÷ /ñ /±4ð /¹HÁ[Õ<Qñ /r   c              ƒ  óÐ	  "  € VR,          p \        V4      pVP                  ;'       g    RP                  4       P                  R4      VP                  ;'       g    R3pVe"   VP                  R8w  g   W@P                  9  d2   \        P                  RV^ ,          ;'       g    RV^,          4       R# ^ RI
p VP                  \        4      p\        P                  ! \        4      ;_uu_4       GRj  x€L
  VP                  R	VR
R/R7      ;_uu_4       GRj  x€L
 pVP!                  RV4      ;_uu_4       GRj  x€L
 pVP"                  ^È8w  dT   \        P                  RVP"                  4        RRR4      GRj  x€L
  RRR4      GRj  x€L
  RRR4      GRj  x€L
  R# VP$                  P'                  R4      ;p	'       db    \)        V	4      p
Y¡R,          8w  dI   \        P                  R4        RRR4      GRj  x€L
  RRR4      GRj  x€L
  RRR4      GRj  x€L
  R# \+        4       pVP-                  4         Rj  x€L
  pVP/                  V4       \1        V4      VR,          8”  g   K4  \        P                  R4        RRR4      GRj  x€L
  RRR4      GRj  x€L
  RRR4      GRj  x€L
  R#   \
         d    RRrC ELti ; i ELâ EL¾ ELž EL_ ELR ELE  \
         d8     RRR4      GRj  x€L 
  RRR4      GRj  x€L 
  RRR4      GRj  x€L 
  R# i ; i EL) EL EL Lì L� L� L�DóRRR4      GRj  x€L 
  M  + GRj  x€L 
 '       g   i     M; iRRR4      GRj  x€L 
  M  + GRj  x€L 
 '       g   i     M; iRRR4      GRj  x€L 
  Ma  + GRj  x€L 
 '       g   i     MH; i  \2        TP4                  \6        \
        3 d"   p\        P                  RT4        Rp?R# Rp?ii ; i\1        X4      TR,          8g  R3\8        P:                  ! T4      P=                  4       TR,          8g  R33 F&  w  rïT'       g   K  \        P                  RT4        R# 	   \?        \A        T4      TR,          TR,          R7      G Rj  x€L 
 #   \6        \
        3 d"   p\        P                  RT4        Rp?R# Rp?ii ; i5i)zDDownload, integrity-check, and cache one authorized Buzz attachment.r˜   r9   rf   rz   Nr|   z5Buzz: refusing attachment from untrusted origin %s:%sz	<missing>FzAccept-EncodingÚidentity)Úfollow_redirectsrq  ÚheadersÚGETz*Buzz: attachment download returned HTTP %szcontent-lengthr«  z9Buzz: attachment Content-Length does not match imeta sizez+Buzz: attachment exceeded its declared sizez$Buzz: attachment download failed: %sr¬  zSHA-256z(Buzz: attachment %s does not match imetar­  r®  ©r­  r®  z'Buzz: attachment cache write failed: %s)r9   rÊ   )!r   r}   r~   rq   r   r€   r�   râ  r,  r  ÚhttpxÚTimeoutÚ_ATTACHMENT_DOWNLOAD_TIMEOUTrˆ   rq  ÚAsyncClientÚstreamÚstatus_coderÊ  r   rx   Ú	bytearrayÚaiter_bytesÚextendrl   rˆ  Ú	HTTPErrorrQ  Úhashlibr¬  Ú	hexdigestr(   rä   )r  r�  r˜   Ú
parsed_urlÚoriginrÍ  rq  Úclientr  Úcontent_lengthÚdeclared_response_sizerç   ÚchunkrR  ÚbadÚwhats   &&              r   Ú_download_attachmentÚ BuzzAdapter._download_attachmentp  s×  é € à�u�oˆð	/Ü! #›ˆJØ!×*Ñ*×0Ð0¨b×7Ñ7Ó9×@Ñ@ÀÓEÀzÇÁ×G]ÐG]ÐZ]Ð^ˆFð Ò ×!2Ñ!2°gÔ!=À×OgÑOgÔAgÜ�N‰NÐRÐTZÐ[\ÕT]×TlÐTlÐalÐntÐuvÕnwÔxÙÛð	Ø—m‘mÔ$@ÓAˆGä—’Ô <×=×=Õ=Ø×!Ñ!°5À'ÐTeÐgqÐSrÐ!×s×sÔsÐw}Ø—‘˜e S×)×)Ô)¨Xà×'Ñ'¨3Ô.Ü—N‘NÐ#OÐQY×QeÑQeÔfØ÷	 *×)÷ t×s÷ >×=Ñ=ð &.×%5Ñ%5×%9Ñ%9Ð:JÓ%KÐK�>ÖKð$Ü14°^Ó1DÐ.ð .¸&Õ1AÔAÜŸ™Ð'bÔcØ#÷ *×)÷ t×s÷ >×=Ñ=ô !“{�Ø#+×#7Ñ#7Ô#9÷ $ð $˜%Ø—K‘K Ô&Ü˜4“y 8¨FÕ#3Ö3ÜŸ™Ð'TÔUØ#÷% *×)÷ t×s÷ >×=Ñ=øô ô 	/Ø!% w›ð	/úò >ÚsÝ)ò tò >øô &ô $Ø#÷ *×)Ð)÷ t×sÐs÷ >×=Ò=ð$úò *ò tò >ñ $ñ *ñ tñ >ð  $:÷ *×)×)×)×)Ò)ú÷ t×s×s×s×sÒsú÷ >×=×=×=×=Ò=ûô* ˜eŸo™o¬w¼
ÐCô 	Ü�N‰NÐAÀ3ÔGÝûð	úô ˜t›9¨°Õ(8Ñ8¸&ÐAÄGÇNÂNÐSWÓDX×DbÑDbÓDdÐhpÐqyÕhzÑDzð  }Fð  DGó  H‰IˆCß‰sÜ—‘ÐIÈ4ÔPÚñ Hð	Ü0´°t³ÀxÐPZÕG[ÐgoÐp{Õg|Ô}×}Ð}Ð}øÜœÐ$ô 	Ü�N‰NÐDÀcÔJÝûð	üs  ‚
S&�AK ÁK Á!AS&Â&S&Â<;O Ã7KÃ8O Ã;#N0ÄKÄN0Ä"N	ÅKÅN	Å3MÅ8N	ÆK"ÆN	ÆN0ÆK%ÆN0ÆO Æ#K(Æ$O Æ(S&Æ*"MÇK+Ç#MÇ<N	ÈL0ÈN	ÈN0ÈL3ÈN0ÈO È'L6È(O È,S&È.MÉMÉL9ÉMÉ'MÉ<MÊN	ÊL;ÊN	Ê"N0Ê-L=Ê.N0Ê2O Ê=L?Ê>O ËS&ËKËS&ËKËS&ËO ËN0ËN	Ë"N	Ë%N0Ë(O Ë+L-Ë6MË7N	ÌLÌN	ÌN0ÌLÌN0ÌO Ì$L'Ì%O Ì*S&Ì,L-Ì-MÌ0N	Ì3N0Ì6O Ì9MÌ;N	Ì=N0Ì?O ÍMÍN	ÍMÍN	ÍM-ÍMÍ
M-Í&M-Í(N	Í0N0Í;M>Í<N0ÎNÎNÎ	
NÎNÎN0ÎO Î)N,Î*O Î/S&Î0O		Î6N9Î7
O		ÏO		ÏO ÏS&Ï	O Ï!PÏ-P	ÐS&Ð	PÐAS&Ñ'S&Ò(R1 Ò+R.Ò,R1 Ò0S&Ò1S#ÓSÓS&ÓS#Ó#S&c                óF   <€ V ^8„  d   QhRS[ S[,          RS[ S[,          /# )r0   Úmetadata_itemsr3   )r¥   rû   r&   )r6   r  s   "€r   r7   r  ¡  s)   ø€ ÷ dñ d¹tÁD½zð dÉdÑS^ÕN_ñ dr   c              ƒ  óx   "  € V Uu. uF#  q P                  V4      G R j  x€L
 ;pf   K!  VNK%  	  up#  Lu upi 5ir©   )rá  )r  rä  r@   Úas   &&  r   Ú_cache_inbound_attachmentsÚ&BuzzAdapter._cache_inbound_attachments¡  s6   é € Ù)Óc™>�a×9RÑ9RÐSTÓ9U×3UÐ.U¨a—�™>ÑcÐcÑ3UùÒcùs    ‚:‡5Ÿ3
 5ª5°:³5µ:c                ó0   <€ V ^8„  d   QhRS[ RS[RS[RR/# ©r0   r=  rõ  rª  r3   Nrú   )r6   r  s   "€r   r7   r  ¤  s*   ø€ ÷ >
ñ >
©cð >
¹$ð >
Átð >
ÐPTñ >
r   c              ƒ  óÔ	  "  € \        VP                  R4      ;'       g    R4      p\        VP                  R4      ;'       g    ^ 4      pV'       d   WBR,          9   d   R# RVR,          V&   \        VR,          V4      VR&   \        VP                  R4      ;'       g    ^ 4      \        9  d   R# \        VP                  R4      ;'       g    R4      P                  4       pVP                  R	4      pV P                  V4      w  r‰V'       d=   \        V\         4      '       d'   VP                  4       '       g   V'       g   V	'       g   R# V P                  W#4       W`P                  8X  d   R# V P                  WV4       VR
,          R8H  p
\        V4      pV'       d   V P                  W+4      MRp\        VRJ;'       d    V^ ,          V P                  8H  4      pV
'       g4   V P                  '       d"   V P!                  V4      '       g   V'       g   R# V P"                  '       dŒ   W`P"                  9  d|   W`P$                  9   dM   \'        W0P                  4      '       d2   V P)                  V4      '       d   V P+                  WR4      G Rj  x€L
  \,        P/                  RVR,          4       R# V P1                  V4      pV P3                  V4      pV P5                  WC4       V
'       d   RMRp\        V4      ;'       d    V P7                  VVV4      RJ pV'       d   V P9                  V4      G Rj  x€L
 M. pV	'       d%   V RV P;                  V	4       2P                  4       pV'       d:   \=        V4      \=        V4      ,
          ;p'       d   V RV R2P                  4       p\>        P@                  pV'       dr   V Uu0 uF  pVPB                  kK  	  pp\=        V4      ^8X  d7   \D        P                  \G        \I        V4      4      \>        PJ                  4      M\>        PJ                  pT PM                  YáTTV PO                  V4      G Rj  x€L
 TY_TV'       d
   V^,          MRV'       d
   V^ ,          MRTV Uu. uF  pVPP                  NK  	  upV Uu. uF  pVPR                  NK  	  upVVR7      G Rj  x€L
  R#  EL: EL–u upi  L~u upi u upi  L5i)z>De-dupe, filter, and dispatch a single ``messages get`` event.r  r9   rj  ry  Nr  Úkindr¿  r1   r?  r�  õ   ðŸ‘€u5   Buzz: ignoring message from unauthorized pubkey %sâ€¦r;  r?   Trº   z
[zH Buzz attachment(s) could not be downloaded or failed integrity checks.])r¤   rc  r?  r  Ú	user_namer�  rj  r˜  r™  Úreply_to_textÚreply_to_author_idÚreply_to_is_own_messageÚ
media_urlsÚmedia_typesÚmessage_typeÚraw_message)*r5   r   rx   rä  r"  r~   r»  rï   rk   r†  rì  r‡  r½  Ú_lookup_event_metar›   rÕ  Ú_is_addressedrè  ré  rÃ  Ú_is_mentionedr¼  r,  rG  Ú_strip_mentionÚ_extract_thread_rootÚ_record_thread_rootÚ_is_sender_authorizedrç  rÄ  rl   r+   ÚTEXTrì  Ú_ATTACHMENT_KIND_TYPESÚnextÚiterÚDOCUMENTÚ_dispatch_messageÚ_resolve_user_namerŸ   Ú
media_type)r  r=  rõ  rª  r¡  rj  r¿  r1   Úattachment_metadataÚrejected_attachmentsÚis_dmÚreply_parent_idÚ
reply_metaÚreply_to_is_ownÚdispatch_textr˜  r?  Úfetch_allowedrµ  Úfailedrô  rd   r  s   &&&&                   r   rž  ÚBuzzAdapter._handle_event¤  s%  é € ä�u—y‘y “×,Ð,¨"Ó-ˆÜ˜Ÿ™ <Ó0×5Ð5°AÓ6ˆ
ß˜8¨V¥}Ô4ÙØ"&ˆˆf��hÑÜ˜u YÕ/°Ó<ˆˆiÑÜˆu�y‰y˜Ó ×%Ð% AÓ&¬oÔ=ÙÜ�U—Y‘Y˜xÓ(×.Ð.¨BÓ/×5Ñ5Ó7ˆØ—)‘)˜IÓ&ˆØ48×4QÑ4QÐRWÓ4XÑ1ÐßœZ¨´×5Ò5¸g¿m¹m¿oºo×Qd×h|Ùà×Ñ˜UÔ*à×&Ñ&Ô&Ùà×Ñ˜Z°Ô6Ø�kÕ" dÑ*ˆÜ0°Ó7ˆßHW�T×,Ñ,¨UÔDÐ]aˆ
Ü˜z°Ð5×\Ð\¸*ÀQ½-È4×K\ÑK\Ñ:\Ó]ˆ÷ ˜×-×-Ð-°d×6HÑ6HÈ×6OÒ6O×XgÙà× × Ð  V×3HÑ3HÔ%HØ×4Ñ4Ô4¼À5×J[ÑJ[×9\Ò9\Ðae×asÑasÐt{×a|Òa|Ø×(Ñ(¨¸vÓF×FÐFÜ�L‰LÐPÐRXÐY[ÕR\Ô]Ùà×+Ñ+¨GÓ4ˆà×-Ñ-¨eÓ4ˆ	Ø× Ñ  Ô1÷ "‘D wˆ	ÜÐ0Ó1×wÐw°d×6PÑ6PÐQWÐYbÐdnÓ6oÐswÐ6wˆßTa˜D×;Ñ;Ð<OÓP×PÐPÐgiˆßØ,˜o¨R°×0OÑ0OÐPdÓ0eÐ/fÐg×mÑmÓoˆMß¬Ð,?Ó(@Ä3À{ÓCSÕ(SÐS˜fÖSØ,˜o¨S°°ð  9Að  B÷  Hñ  Hó  JˆMÜ"×'Ñ'ˆßá7BÓC±{¨�Z—_”_±{ˆEÐCÜbeÐfkÓblÐpqÔbqÔ1×5Ñ5´d¼4À»;Ó6GÌ×I]ÑI]Ô^ô  xC÷  xLñ  xLˆLØ×$Ñ$Ø¸iÐQWØ ×3Ñ3°FÓ;×;ÈØ!ÈOß+5˜* Qž-¸4×eoÐT^Ð_`ÖTaÐuyØ$3ÑcnÓ@oÑcnÐU_ÀÇÄÑcnÑ@oÙALÓMÁ°:˜×.Ô.ÁÑMÐ\hÐv{ð %ó 
÷ 	
ò 	
ò- Gò Qùò Dñ <ùò ApùÚMñ	
ùsë   ‚AS(ÁS(ÁAS(Â!.S(ÃA,S(Ä=S(ÅS(ÅA8S(Ç"S(Ç)S(Ç;S(ÈS(ÈS(È.AS(Ê S(ÊSÊA3S(Ì
S(Ì(S(Ì<SÌ=S(Í+S(Í7AS(ÏS(ÏSÏ!A:S(ÑSÑS(Ñ<S(ÒS Ò S(Ò&S!"Ò;S(ÓS&Ó	S(ÓS(ÓS(ÓS(c                ó&   <€ V ^8„  d   QhRS[ RS[/# )r0   r=  r3   rš   )r6   r  s   "€r   r7   r  ì  s   ø€ ÷ nñ n±ð n¹ñ nr   c                ó,  € V P                   P                  V4      pVf   R# \        VP                  R4      ;'       g    R4      P                  4       R8H  ;'       d8    \        VP                  R4      ;'       g    R4      P                  4       '       * # )zhTrue when metadata does not rule out a DM (name "DM", empty description); missing metadata fails closed.Fr   r9   rŽ  Údescription)rü  r   r5   rk   )r  r=  rž  s   && r   r‘  Ú!BuzzAdapter._may_reclassify_as_dmì  sv   € à×!Ñ!×%Ñ% jÓ1ˆØŠ<ÙÜ�4—8‘8˜FÓ#×)Ð) rÓ*×0Ñ0Ó2°dÑ:×mÐmÄ3ÀtÇxÁxÐP]ÓG^×GdÐGdÐbdÓCe×CkÑCkÓCmÔ?mÐmr   c                ó&   <€ V ^8„  d   QhRS[ RS[/# r²  ©rû   r›   )r6   r  s   "€r   r7   r  ó  s   ø€ ÷ Oñ O¡tð O±ñ Or   c                óf   € \        V P                  4      ;'       d    \        WP                  4      # )z=True when the signed event addresses this identity by pubkey.)r›   rì  rÃ  )r  rª  s   &&r   Ú_p_tagged_to_selfÚBuzzAdapter._p_tagged_to_selfó  s&   € ä�D×%Ñ%Ó&×NÐN¬9°U×<MÑ<MÓ+NÐNr   c                ó,   <€ V ^8„  d   QhRS[ RS[RS[/# )r0   r=  rª  r3   )r5   rû   r›   )r6   r  s   "€r   r7   r  ÷  s"   ø€ ÷ 
ñ 
±3ð 
¹tð 
Éñ 
r   c                ó(  € \        VP                  R4      ;'       g    R4      P                  4       pVP                  R4      p\        V P                  ;'       d´    V P                  V4      ;'       d›    \        VP                  R4      ;'       g    ^ 4      \        8H  ;'       dh    T;'       d^    W0P                  8g  ;'       dH    V P                  V4      ;'       d/    \        V\         4      ;'       d    V P                  V4      '       * 4      # )um   Kind-9 from another user, p-tagged to us, text NOT mentioning us â€” structural DM addressing, not a typed @.r¿  r9   r1   rì  )r5   r   r~   r›   rì  r‘  rx   Ú
_CHAT_KINDr  rï   rø  )r  r=  rª  r¿  r1   s   &&&  r   Ú_is_direct_message_eventÚ$BuzzAdapter._is_direct_message_event÷  s  € ä�U—Y‘Y˜xÓ(×.Ð.¨BÓ/×5Ñ5Ó7ˆØ—)‘)˜IÓ&ˆÜØ×Ñ÷ Mð M $×"<Ñ"<¸ZÓ"H÷ Mð MÌSÐQV×QZÑQZÐ[aÓQb×QgÐQgÐfgÓMhÔlvÑMv÷ Mð MØ÷Mð MØ!×%6Ñ%6Ñ6÷Mð MØ;?×;QÑ;QÐRWÓ;X÷Mð Mä˜7¤CÓ(÷Mð Mà15×1CÑ1CÀGÓ1LÔ-Ló
ð 	
r   c                ó0   <€ V ^8„  d   QhRS[ RS[RS[RR/# rê  rú   )r6   r  s   "€r   r7   r    s/   ø€ ÷ gñ g©#ð g±dð gÁ4ð gÈDñ gr   c                óÂ   € VR,          R8X  g   V P                  W4      '       g   R# RVR&   V P                  P                  VR4       \        P	                  RV4       R# )zLLatch a group conversation to "dm" once a direct message is seen; it sticks.r?  r�  NrŽ  zCBuzz: conversation %s reclassified as DM (message p-tagged to self))r  rû  r€  r,  rP  )r  r=  rõ  rª  s   &&&&r   r‡  ÚBuzzAdapter._maybe_latch_dm  sR   € à�Õ Ô%¨T×-JÑ-JÈ:×-]Ò-]ÙØ!ˆˆkÑØ×Ñ×&Ñ& z°4Ô8Ü�‰ÐYÐ[eÖfr   c                ó&   <€ V ^8„  d   QhRS[ RS[/# ©r0   r1   r3   rš   )r6   r  s   "€r   r7   r  	  s   ø€ ÷ 
<ñ 
<¡Sð 
<©Tñ 
<r   c                óÈ  a€ VP                  4       o. pV P                  '       dY   \        P                  V P                  4      '       d4   VP	                  R\
        P                  ! V P                  4       R24       V P                  '       dB   VP	                  R\
        P                  ! V P                  P                  4       4       R24       V P                  '       dH   VP	                  R\
        P                  ! V P                  P                  4       4       2R,           4       \        ;QJ d    V3R lV 4       F  '       g   K   R# 	  R	# ! V3R lV 4       4      # )
zETrue when text explicitly addresses this agent (npub, hex, or @name).z(?<![0-9a-f])ú(?![0-9a-f])z(?<![a-z0-9])ú(?![a-z0-9])r~  ú(?=$|[\s,;.!?:)\]}])c              3   óR   <"  € T F  p\         P                  ! VS4      x € K  	  R # 5ir©   )rE   rD   )r\   rI  Úlowereds   & €r   r^   Ú,BuzzAdapter._is_mentioned.<locals>.<genexpr>  s   øé € Ð;±(¨Q”2—9’9˜Q ×(Ð(³(ùs   ƒ$'TF)
r~   rì  r  rž   r¯   rE   rG   rí  rî  r²   )r  r1   Úpatternsr'  s   && @r   rø  ÚBuzzAdapter._is_mentioned	  s÷   ø€ à—-‘-“/ˆØˆØ××Ð¤×!4Ñ!4°T×5FÑ5F×!GÒ!GØ�O‰O˜}¬R¯YªY°t×7HÑ7HÓ-IÐ,JÈ,ÐWÔXØ�?�?ˆ?Ø�O‰O˜}¬R¯YªY°t·±×7LÑ7LÓ7NÓ-OÐ,PÐP\Ð]Ô^Ø××ÐØ�O‰O˜{¬2¯9ª9°T×5GÑ5G×5MÑ5MÓ5OÓ+PÐ*QÐRÐUlÕlÔmß‹sÔ;±(Ó;�sŒsÐ;ŠsÐ;ˆsÔ;±(Ó;Ó;Ð;r   c                ó&   <€ V ^8„  d   QhRS[ RS[/# r²  r  )r6   r  s   "€r   r7   r    s   ø€ ÷ kñ k¡4ð k©Dñ kr   c                ó¨   € VP                  R4      p\        V\        4      ;'       d+    V P                  V4      ;'       g    V P	                  V4      # )zBTrue when a group event carries an explicit text or p-tag address.r1   )r   rï   r5   rø  r  )r  rª  r1   s   && r   r÷  ÚBuzzAdapter._is_addressed  sD   € à—)‘)˜IÓ&ˆÜ˜'¤3Ó'×jÐj¨T×-?Ñ-?ÀÓ-H×-iÐ-iÈD×LbÑLbÐchÓLiÐjr   c                ó&   <€ V ^8„  d   QhRS[ RS[ /# r!  rT   )r6   r  s   "€r   r7   r    s   ø€ ÷ nñ n¡cð n©cñ nr   c                óx  € VP                  4       p. pV P                  '       d:   VP                  R\        P                  ! V P                  4       2R,           4       V P
                  '       d4   VP                  R\        P                  ! V P
                  4       R24       V P                  '       d4   VP                  R\        P                  ! V P                  4       R24       V'       g   V# \        P                  ! RRP                  V4       R2R	V^\        P                  R
7      P                  4       # )zfStrip a LEADING @mention of this agent so ``is_command()`` sees "/whoami"; mid-sentence mentions stay.r;   r%  z@?r$  r#  z^(?:Ú|z)[\s:,]*r9   )rM   Úflags)
rk   rî  r¯   rE   rG   rí  rì  r¼   rj   rH   )r  r1   r¤   rn  s   &&  r   rù  ÚBuzzAdapter._strip_mention  sì   € à�}‰}‹ˆàˆ
Ø××ÐØ×Ñ ¤2§9¢9¨T×-?Ñ-?Ó#@Ð"AÐBÐE\Õ\Ô]Ø�?�?ˆ?Ø×Ñ ¤B§I¢I¨d¯o©oÓ$>Ð#?¸|ÐLÔMØ××ÐØ×Ñ ¤B§I¢I¨d×.?Ñ.?Ó$@Ð#AÀÐNÔOßØˆKÜ�vŠv˜˜cŸh™h zÓ2Ð3°8Ð<¸bÀ$ÈaÔWY×WdÑWdÔe×kÑkÓmÐmr   c                ó&   <€ V ^8„  d   QhRS[ RS[ /# rt  rT   )r6   r  s   "€r   r7   r  )  s   ø€ ÷ ñ ©sð ±sñ r   c              ƒ  óª  "  € V P                   P                  V4      ;pe   V# V P                  RRRV.4      G Rj  x€L
 w  r4pV^ 8X  d   \        V4      M. pV'       d:   \	        V^ ,          P                  R4      ;'       g    R4      P                  4       MRpT;'       g    \        V4      ;'       g    TR,          ;qpP                   V&   V#  L”5i)znPubkey -> display name, cached (negatively too, so profile-less pubkeys don't re-query); npub prefix fallback.Nr8  r   rv  r:  r9   rC  )rý  r   r  r¨  r5   rk   rë   )r  r¿  r  r"  r#  r$  rT  r   s   &&      r   r  ÚBuzzAdapter._resolve_user_name)  s½   é € à×&Ñ&×*Ñ*¨6Ó2Ð2ˆFÒ?ØˆMØ $§¡¨w¸¸zÈ6Ð.RÓ S×S‰ˆ�4Ø,0°A¬IÔ# CÔ(¸2ˆßEMŒs�8˜A•;—?‘? >Ó2×8Ð8°bÓ9×?Ñ?ÔAÐSUˆØ*.×*VÐ*V´;¸vÓ3F×3PÐ3PÈ&ÐRUÕ2VÐVˆ×Ñ Ñ'Øˆñ	 Tùs'   ‚:C¼C½"CÁ #CÂCÂ$CÂ7Cc                ó$   <€ V ^8„  d   QhRS[ RR/# )r0   rõ  r3   Nr«  )r6   r  s   "€r   r7   r  4  s   ø€ ÷ )ñ )™$ð ) 4ñ )r   c                ó
  € V R ,          p\        V4      \        8”  d   VP                  RR7       K(  V P                  R4      p\	        V\
        4      '       d+   \        V4      \        8”  d   VP                  RR7       K(  R# R# )ry  F©Úlastrz  N)rl   r-   Úpopitemr   rï   r   )rõ  ry  rž  s   &  r   rˆ  ÚBuzzAdapter._trim_seen3  sd   € à�V�}ˆÜ�$‹iœ)Ô#Ø�L‰L˜eˆLÖ$Ø�y‰y˜Ó&ˆÜ�dœK×(Ò(Ü�d“)œiÔ'Ø—‘ %�Ö(ñ (ñ )r   c                ó*   <€ V ^8„  d   QhRS[ RS[ RR/# )r0   r=  r¡  r3   NrT   )r6   r  s   "€r   r7   r  =  s"   ø€ ÷ #ñ #¡Sð #±Cð #¸Dñ #r   c                ó‚   € V P                   P                  V4      pVe    R VR,          V&   V P                  V4       R # R # )Nry  )rõ  r   rˆ  )r  r=  r¡  rõ  s   &&& r   r­  ÚBuzzAdapter._mark_seen=  s=   € Ø×#Ñ#×'Ñ'¨
Ó3ˆØÒØ&*ˆE�&�M˜(Ñ#Ø�O‰O˜EÖ"ñ r   i   c                ó6   <€ V ^8„  d   QhRS[ RS[S[,          /# r²  r³  )r6   r  s   "€r   r7   r  J  s   ø€ ÷ ñ ¡Dð ©X±c­]ñ r   c                óî   € R;r\        V 4       FX  w  r4VP                  4       pVR8X  d   \        V4      pK)  VR8X  d   \        V4      pK=  V'       d   KG  Ve   KM  \        V4      pKZ  	  T;'       g    T# )zAReturn the NIP-10 thread root of ``event``, or None if top-level.Nr¶  rµ  )r°  r~   r5   )rª  r¶  rµ  r¼  r»  s   &    r   rú  Ú BuzzAdapter._extract_thread_rootI  si   € ð ÐˆÜ% ežn‰NˆFØ—\‘\“^ˆFØ˜ÔÜ˜6“{’Ø˜7Ô"Ü˜F›’ß‘V ¤Ü˜F›’ñ -ð �}ˆ}�uÐr   c                ó*   <€ V ^8„  d   QhRS[ RS[RR/# )r0   r¡  rª  r3   Nrú   )r6   r  s   "€r   r7   r  X  s"   ø€ ÷ &ñ &©Cð &¹ð &Àñ &r   c                óÖ   € V'       g   R# V P                   pV P                  V4      W1&   VP                  V4       \        V4      V P                  8”  d   VP                  RR7       K.  R# )z0Cache the thread root for an inbound message id.NFr8  )r   rú  Úmove_to_endrl   Ú_THREAD_ROOT_CACHEr:  )r  r¡  rª  Úrootss   &&& r   rû  ÚBuzzAdapter._record_thread_rootX  sX   € çÙØ×"Ñ"ˆØ×3Ñ3°EÓ:ˆ‰Ø×Ñ˜(Ô#Ü�%‹j˜4×2Ñ2Ô2Ø�M‰M˜uˆMÖ%ñ 3r   c                óF   <€ V ^8„  d   QhRS[ S[,          RS[ S[,          /# r¢  )r	   r5   )r6   r  s   "€r   r7   r  b  s'   ø€ ÷ Uñ U©H±S­Mð U¹hÁs½mñ Ur   c                ór   € V'       d/   V P                   P                  \        V4      4      ;'       g    T# T# )z]Thread root when the trigger was inside a thread (reply joins it), else the anchor unchanged.)r   r   r5   )r  r£  s   &&r   r¦  Ú!BuzzAdapter._resolve_reply_anchorb  s,   € çBH�×"Ñ"×&Ñ&¤s¨6£{Ó3×=Ð=°vÐTÈfÐTr   c                ó*   <€ V ^8„  d   QhRS[ RS[ RR/# )r0   rõ  rª  r3   Nr«  )r6   r  s   "€r   r7   r  f  s'   ø€ ÷ eñ e¡Tð e±$ð e¸4ñ er   c           	     óL  € \        VP                  R4      ;'       g    R4      pVP                  R4      pV'       dg   \        V\         4      '       d
   VR\         MRpT P	                  Y\        VP                  R4      ;'       g    R4      P                  4       V4       R# R# )z?Record author + content snippet for later NIP-10 parent lookup.r  r9   r1   Nr¿  )r5   r   rï   Ú_EVENT_META_CONTENT_CAPÚ_store_event_metar~   )r  rõ  rª  r¡  r1   Úsnippets   &&&   r   r†  ÚBuzzAdapter._remember_eventf  s�   € ä�u—y‘y “×,Ð,¨"Ó-ˆØ—)‘)˜IÓ&ˆßÜ;EÀgÌs×;SÒ;S�gÐ6Ô6Ñ7ÐY[ˆGØ×"Ñ" 5´C¸¿	¹	À(Ó8K×8QÐ8QÈrÓ4R×4XÑ4XÓ4ZÐ\cÖdñ r   c          
      ó6   <€ V ^8„  d   QhRS[ RS[ RS[ RS[ RR/# )r0   r=  r¡  r¿  r1   r3   NrT   )r6   r  s   "€r   r7   r  n  s9   ø€ ÷ fñ f©sð f¹cð fÉ3ð fÑY\ð fÐaeñ fr   c           
     óŒ   € V P                   P                  V4      pVe%   T P                  TRTRTRT;'       g    R/4       R # R # )Nr  r¿  r1   r9   )rõ  r   r†  )r  r=  r¡  r¿  r1   rõ  s   &&&&& r   rœ  Ú BuzzAdapter._remember_event_metan  sJ   € Ø×#Ñ#×'Ñ'¨
Ó3ˆØÒØ× Ñ  ¨¨x¸À6È9ÐV]×VcÐVcÐacÐ(dÖeñ r   c          
      ó6   <€ V ^8„  d   QhRS[ RS[RS[RS[RR/# )r0   rõ  r¡  r¿  rO  r3   Nr  )r6   r  s   "€r   r7   r  t  s1   ø€ ÷ &ñ &¡ð &±ð &¹cð &ÉCð &ÐTXñ &r   c                ó   € V P                  R \        4       4      p\        V\        4      '       g   \        V4      ;q@R &   W#3WA&   VP                  V4       \	        V4      \
        8”  d   VP                  RR7       K(  R# )rz  Fr8  N)r€  r   rï   rD  rl   r-   r:  )rõ  r¡  r¿  rO  rÿ   s   &&&& r   rN  ÚBuzzAdapter._store_event_metas  sl   € à× Ñ  ¬{«}Ó=ˆÜ˜%¤×-Ò-Ü*5°eÓ*<Ð<ˆE˜,Ñ'Ø!Ð+ˆ‰Ø×Ñ˜(Ô#Ü�%‹jœ9Ô$Ø�M‰M˜uˆMÖ%ñ %r   c          	      ób   <€ V ^8„  d   QhRS[ RS[S[,          RS[S[S[S[3,          ,          /# )r0   rõ  r¡  r3   )rû   r	   r5   rw   )r6   r  s   "€r   r7   r  ~  s6   ø€ ÷ 8ñ 8¡$ð 8±(¹3µ-ð 8ÁHÉUÑSVÑX[ÐS[Í_ÕD]ñ 8r   c                ó:  € V'       d+   V P                  R 4      ;'       g    / P                  V4      MRpV'       d'   \        V\        4      '       d   \        V4      ^8  d   R# \	        V^ ,          ;'       g    R4      \	        V^,          ;'       g    R4      3# )rz  Nr9   )r   rï   rw   rl   r5   )rõ  r¡  rö   s   && r   rö  ÚBuzzAdapter._lookup_event_meta}  sl   € çAI�—‘˜<Ó(×.Ð.¨B×3Ñ3°HÔ=ÈtˆßœJ u¬e×4Ò4¼¸E»
ÀQ¼ÙÜ�5˜•8—>�>˜rÓ"¤C¨¨a­¯¨°BÓ$7Ð7Ð7r   r  r9   r?  rc  c                óœ   <€ V ^8„  d   QhRS[ RS[ RS[ RS[S[ ,          RS[S[ ,          RS[S[ S[S[ ,          S[S[ ,          S[3,          /# )r0   r¤   r�  r  r?  rc  r3   )r5   r	   rw   r¥   r+   )r6   r  s   "€r   r7   r  „  sf   ø€ ÷ 1Cñ 1CÙð1CÙ%(ð1CÙ69ð1CÙKSÑTWÍ=ð1CÙjrÑsvÕjwð1Cá	‰s‘D™•I™t¡C�y©+Ð5Õ	6ñ1Cr   c             ƒ  ó’  a"  € \        WP                  4      w  rgV'       g   V. . \        P                  3# V P	                  W4V4      RJdN   \
        P                  R\        V4      VR,          T;'       g    RR,          4       V. . \        P                  3# \        W4      p. p	. p
. o^ RI	H
pHp V EF$  p\        P                  \        V4      P                  4      pVf   K2  VP!                  R4      R,           VP!                  R	4      ;'       g    R
P#                  4        2p \$        P&                  ! RR7      ;_uu_ 4       p\)        V4      RV 2,          pV P+                  RRR\-        V4      V.4      G Rj  x€L
 w  pppV^ 8w  g   VP/                  4       '       g$   \
        P                  RVV4        RRR4       EK  V! VP1                  4       P2                  RR7       \4        P6                  ! VP8                  4      ^ ,          ;'       g    Rp\:        P<                  ! VP>                  4      G Rj  x€L
 pV! VVP8                  VR7      G Rj  x€L
 pRRR4       Xf   \
        P                  RT4       EKÓ  T	PG                  TP                  4       T
PG                  TPH                  4       SPG                  TPJ                  4       EK'  	  V	'       d(   \
        PM                  R\        V	4      VR,          4       S'       g   \        P                  M'\O        V3R l\P         4       \        PR                  4      pV'       g   V	'       d   RMRpW‰V
V3#  ELä EL( EL  + '       g   i     EL; i  \@         d7   p\
        P                  RT\C        T4      PD                  4        Rp?EK
  Rp?ii ; i5i)z¸Authenticate and cache same-relay media refs in *text* (failures skipped per object). Spends our
credentials on a sender-chosen URL, so it runs only on the gateway's explicit ``True``.Tuf   Buzz: not localizing %d media reference(s) in message %s â€” sender %sâ€¦ is not explicitly authorizedr¹  Ú?r;  )r(   Úvalidate_inbound_media_sizeNÚshaÚextz.binzhermes-buzz-media-)ÚprefixÚbuzz_Úmediar   z-oz3Buzz: failed to localize inbound media %s (exit %d)z
Buzz media)r  zapplication/octet-streamrÌ  z.Buzz: failed to localize inbound media %s (%s)z'Buzz: rejected invalid inbound media %sz=Buzz: localized %d inbound media attachment(s) for message %sc              3   ó>   <"  € T F  w  rVS9   g   K  Vx € K  	  R # 5ir©   r  )r\   ÚkÚmtÚmedia_kindss   &  €r   r^   Ú6BuzzAdapter._localize_inbound_media.<locals>.<genexpr>²  s    øé € ÐEÑVjÉUÈQÐnoÐs~Ñn~ÇbÂbÓVjùs   ƒ“
z(attachment)z#(Buzz media attachment unavailable))*r¶   r™   r+   rý  rü  r,  r  rl   r¾   Úgateway.platforms.baser(   r]  r�   rž   r   rŸ   r?   r~   ÚtempfileÚTemporaryDirectoryr   r  r5   rE  ÚstatÚst_sizeÚ	mimetypesÚ
guess_typer   rˆ   Ú	to_threadÚ
read_bytesrŽ   rô  Ú__name__r¯   r  rì  rP  rÿ  Ú_MEDIA_KIND_PRIORITYr  )r  r¤   r�  r  r?  rc  r³   r´   Úcleaned_textrò  ró  r(   r]  r˜   Ú
path_matchr›  Útemp_dirÚdownload_pathr"  r»  r$  r®  rç   r  rR  rô  rf  s   &&&$$$                    @r   Ú_localize_inbound_mediaÚ#BuzzAdapter._localize_inbound_media„  s#  øé € ô
 4°D¿.¹.ÓIÑˆßØ˜˜R¤×!1Ñ!1Ð1Ð1Ø×%Ñ% g¸'ÓBÈ$ÓNÜ�N‰Nð  DÜ˜t›9 j°¥o¸¿¸À3ÈÕ7KôMà˜˜R¤×!1Ñ!1Ð1Ð1Ü*¨4Ó>ˆØ "ˆ
Ø!#ˆØ!#ˆß_ÜˆCÜ'×1Ñ1´(¸3³-×2DÑ2DÓEˆJØÒ!ÙØ!×'Ñ'¨Ó.¨sÕ3Ð4°j×6FÑ6FÀuÓ6M×6WÐ6WÐQW×5^Ñ5^Ó5`Ð4aÐbˆEðÜ×0Ò0Ð8L×MÕMÐQYÜ$(¨£N°u¸U¸G°_Õ$D�MØ-1¯]©]¸GÀUÈDÔRUÐVcÓRdÐfiÐ;jÓ-k×'kÑ$�D˜$ Ø˜q”y¨×(=Ñ(=×(?Ò(?ÜŸ™Ð'\Ð^cÐeiÔjØ ÷ NÒMñ 0°×0BÑ0BÓ0D×0LÑ0LÐYeÕfÜ )× 4Ò 4°]×5GÑ5GÓ HÈÕ K× iÐ iÐOi�Iä!(×!2Ò!2°=×3KÑ3KÓ!L×L�DÙ#:¸4È-×J\ÑJ\ÐhqÔ#r×r�F÷ Nð Š~Ü—‘ÐHÈ%ÔPÚØ×Ñ˜fŸk™kÔ*Ø×Ñ˜v×0Ñ0Ô1Ø×Ñ˜vŸ{™{×+ñ3 ÷4 Ü�K‰KÐWÔY\Ð]gÓYhÐjtÐuxÕjyÔzç/:”{×'Ò'ÄÔEÕVjÓEô  BM÷  BVñ  BVó  AWˆßß-7™>Ð=bˆLØ¨°lÐBÐBò1 (lò MÚr÷ N×MÐMûô ô Ü—‘ÐOÐQVÔX\Ð]`ÓXa×XjÑXjÔkÞûðüsÏ   ƒA4OÁ8BOÄOÄ+NÅ
8M/ÆM&
Æ$M/Æ(M/Ç NÇOÇAM/È&M/ÉM)
ÉM/ÉM,
ÉM/É#NÉ+A:OË&.OÌ?OÍOÍ	OÍ&M/Í)M/Í,M/Í/N Í:NÍ>OÎ NÎOÎ*N?Î8OÎ?OÏOc          "      óþ   <€ V ^8„  d   QhRS[ RS[ RS[ RS[ RS[ RS[ RS[RS[S[ ,          R	S[S[ ,          R
S[S[ ,          RS[S[ ,          RS[RS[S[S[ ,          ,          RS[S[S[ ,          ,          RS[RS[RR/# )r0   r¤   rc  r?  r  rî  r�  rj  r˜  r™  rï  rð  rñ  rò  ró  rô  rõ  r3   N)r5   rx   r	   r›   r¥   r+   r   )r6   r  s   "€r   r7   r  ·  sã   ø€ ÷ )añ )aÙð)aÙ"%ð)aÙ25ð)aÙ@Cð)aÙPSð)aáð)aá%(ð)aá5=¹cµ]ð)añ &¡c�]ð)añ CKÉ3Å-ð)añ %¡S�Mð	)añ LPð	)añ
 ™T¡#�YÕ'ð)añ
 >FÁdÉ3ÅiÕ=Pð)añ "ð)añ DGð)að 
ñ)ar   c              ƒ  óæ  "  € V P                   '       g   R# \        T;'       g    . 4      p\        T;'       g    . 4      pV P                  WWCVR7      G Rj  x€L
 pVw  pppp\        VV4       F1  w  ppVV9  g   K  VP	                  V4       VP	                  V4       K3  	  V\
        P                  8X  d   TpM/V'       d(   VV\
        P                  39  d   \
        P                  pV P                  W P                  P                  W"4      VWEW†R7      p\        YTTT\        V4      \        V4      R.\        V4      ,          V'       d   \        P                  ! V4      M\        P                  ! 4       WšW¼R7      pV P!                  V4      G Rj  x€L
   V P#                  W&R4      G Rj  x€L
  R#  ELa L$ L  \$         d$    \&        P)                  RTR,          R	R
7        R# i ; i5i)z;Build a MessageEvent and hand it to the base class handler.N)r  r?  rc  )rc  Ú	chat_namer?  r  rî  r˜  r�  F)r¤   rô  Úsourcerõ  r�  rò  ró  Úmedia_text_inlinedÚ	timestampr™  rï  rð  rñ  rí  z$Buzz: reaction failed for message %sr¹  Tr:  )Ú_message_handlerr¥   rw  Úzipr¯   r+   rý  r  Úbuild_sourcerû  r   r*   rl   r   ÚfromtimestampÚnowÚhandle_messager¼  rŽ   r,  rG  )r  r¤   rc  r?  r  rî  r�  rj  r˜  r™  rï  rð  rñ  rò  ró  rô  rõ  Ú	localizedÚlocalized_urlsÚlocalized_typesÚlocalized_typerŸ   Úmimer|  rª  s   &&&&&&&&&&&&&&&&&        r   r  ÚBuzzAdapter._dispatch_message·  sÃ  é € ð ×$×$Ð$ÙÜ˜*×*Ð*¨Ó+ˆ
Ü˜;×,Ð,¨"Ó-ˆà×6Ñ6°tÐQXÐw~Ð6Ó×ˆ	Ø@IÑ=ˆˆn˜o¨~Ü˜n¨oÖ>‰JˆD�$Ø˜:Ö%Ø×!Ñ! $Ô'Ø×"Ñ" 4Ö(ñ ?ð œ;×+Ñ+Ô+Ø)‰Lß °|Ä[×EUÑEUÐ6VÔ Vä&×/Ñ/ˆLØ×"Ñ"Ø×':Ñ':×'>Ñ'>¸wÓ'PÐ\eØ¸Ið #ó 
ˆô Ø¸È[ÐeoÜ˜JÓ'´T¸+Ó5FÐ\aÐ[bÔehÐisÓetÕ[tß<F”h×,Ò,¨ZÔ8ÌHÏLÊLËNØ 3Ø1ô
ˆð ×!Ñ! %Ó(×(Ð(ð	aØ×$Ñ$ W¸&ÓA×AÒAò3 @ñ, 	)ñ BøÜô 	aÜ�L‰LÐ?ÀÈCÅÐ[_ˆL×`ð	aüsq   ‚"G1¥G1ºG1ÁF9Á!G1Á?AG1ÃCG1ÆF<ÆG1ÆG  Æ2F>Æ3G  Æ7G1Æ<G1Æ>G  Ç *G.Ç*G1Ç-G.Ç.G1)"rè  râ  rë  rü  rû  rõ  rù  rø  rú  rî  rá  rþ  rò  ró  rï  rê  rÿ  ré  r&  rö  rô  rí  rì  r   rý  rñ  rð  rÑ  r5  r/  rÓ  r™   rÕ  r×  r©   )NN)NNN)NNNN)Trq  Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Úserial_receive_looprà  Úpropertyr   Ústaticmethodr  r  r%  r/  rY  rL  rq  rz  r…  r‹  r•  rš  r›  r²  r¼  rÃ  rÈ  rÒ  rÐ  rÜ  rã  rê  rð  rö  rü  rK  r  r  r$  r/  r5  rA  r  rN  rc  rN  r{  r‚  rH  rI  r�  ru  rn  r»  r¿  rÄ  rá  rç  rž  r‘  r  r  r‡  rø  r÷  rù  r  rˆ  r­  rE  rú  rû  r¦  r†  rœ  rN  rö  rw  r+   rý  r  Ú__static_attributes__Ú__classdictcell__Ú__classcell__)r  r  s   @@r   rÉ  rÉ  ÿ  s  ù‡ € ÙaàÐõ?LðB ÷ó ðð ÷,ó ð,ðPÈT÷ Pò P÷@ð @ðÐ]b÷ ò ðW°E÷ Wò W÷r
ð 
÷ð ÷,ð ÷ð ÷Bò ÷Bò ÷jð jð
=Ðim÷ =ò =÷:ò :÷ð ðsÐbg÷ sò s÷&0ð 0÷	Tò 	TðMØIMðMØimðMà-1ðMàAE÷Mò M÷"
Võ 
V÷Aò A÷Bò B÷Bò B÷oð o÷Xð X÷ð ÷(Gð Gð@ ÷jó ðj÷Ið I÷$ð ÷
Oð 
O÷Xð X÷.,1ð ,1÷\Qð Q÷BBð B÷@Ið I÷jð j÷ð ÷ ð ÷*&xð &x÷PLð L÷Lð L÷Lð Lð ÷$%ó ð$%ðL ÷>ó ð>ð ÷wó ðw÷/ð /÷bdð d÷>
ð >
÷Pnð n÷Oð O÷
ð 
÷gð g÷
<ð 
<÷kð k÷
nð n÷ð ð ÷)ó ð)÷#ð #ð Ðà÷ó ð÷&ð &÷Uð U÷eð e÷fð fð
 ÷&ó ð&ð ÷8ó ð8ð1CØ<>ð1CØ[_ð1CØz~÷1Cò 1Cðj FJØ-1ÐRVØ,0ÐRWØ*.ÐSWØ$/×$4Ñ$4È÷)a÷ )aò )ar   rÉ  c                ó$   € V ^8„  d   QhR\         /# r’   r«  )r6   s   "r   r7   r7   å  s   € ÷ 4ñ 4œTñ 4r   c                 óÌ  € \        4       '       g   / #  ^ RIHp  ^ RIHp ^ RIHp V! \        V! 4       4      R,          4      p\        T\        4      '       g   / # T ! TRTP                  R4      ;'       g    / P                  R4      4      w  rE\        T\        4      '       d   TP                  RT4      MR	p\        T\        4      '       d   T# / #   \         d    / u # i ; i)
zq``buzz.extra`` from the scoped profile's config.yaml for ``check_requirements``; failures yield {} (fail closed).)Úplatform_section)Úget_hermes_home)Úread_user_config_rawzconfig.yamlrB  ÚgatewayÚ	platformsr!   N)r   Úgateway.config_loaderr—  Úhermes_constantsr˜  Úhermes_cli.configr™  r   rŽ   rï   rû   r   )r—  r˜  r™  ÚcfgrB  rX  r!   s          r   Ú_profile_buzz_extrar   å  sÂ   € ä×ÒØˆ	ðÝ:Ý4Ý:Ù"¤4©Ó(9Ó#:¸]Õ#JÓKˆô �cœ4× Ò Øˆ	ñ ˜s F¨S¯W©W°YÓ-?×-EÐ-EÀ2×,JÑ,JÈ;Ó,WÓX�G€DÜ'1°$¼×'=Ò'=ˆD�H‰H�W˜dÔ#À4€EÜ˜u¤d×+Ò+ˆ5Ð3°Ð3øô ô ØŠ	ðús   ”/C ÃC#Ã"C#c                ó$   € V ^8„  d   QhR\         /# r’   r3  )r6   s   "r   r7   r7   ù  s   € ÷ 	kñ 	kœDñ 	kr   c                 ó  € \        4       '       d2   \        4       p \        \        V 4      ;'       d    \	        V 4      4      # \        \        RR4      ;'       g    RP                  4       4      ;'       d    \        \	        4       4      # )z?Check if Buzz is configured: a relay URL plus a resolvable key.r)  r9   )r   r   r›   r+  rc  r   rk   r*  s    r   Úcheck_requirementsr£  ù  sj   € ä×Òô $Ó%ˆÜÔ% eÓ,×LÐLÔ1EÀeÓ1LÓMÐMäÔ#Ð$4°bÓ9×?Ð?¸R×FÑFÓHÓI×jÐjÌdÔSgÓSiÓNjÐjr   c                ó$   € V ^8„  d   QhR\         /# r’   r3  )r6   s   "r   r7   r7     s   € ÷ 
7ñ 
7œtñ 
7r   c                ó$  € \        V R/ 4      ;'       g    / p\        4       '       d'   \        RVR4      pVe   TMVP                  RR4      pM&\	        RR4      ;'       g    VP                  RR4      p\        T;'       d    \        V4      4      # )zDValidate that the platform config has enough information to connect.r!   r)  r™   r9   )r!  r   r$   r   r   r›   rc  )r"  r!   r¡   s   &  r   Úvalidate_configr¦    s�   € ä�F˜G RÓ(×.Ð.¨B€Eä×Òä(Ð)9¸5À+ÓNˆØÒ*‘°·	±	¸+ÀrÓ0J‰ä"Ð#3°RÓ8×VÐV¸E¿I¹IÀkÐSUÓ<VˆÜ�×5Ð5Ô.¨uÓ5Ó6Ð6r   c                ó$   € V ^8„  d   QhR\         /# r’   r3  )r6   s   "r   r7   r7     s   € ÷ #ñ #œDñ #r   c                ó   € \        V 4      # )z6Check whether Buzz is configured (env or config.yaml).)r¦  )r"  s   &r   Úis_connectedr©    s   € ä˜6Ó"Ð"r   c                óR   € V ^8„  d   QhR\         R\         R\        \         ,          /# )r0   Úyaml_cfgÚbuzz_cfgr3   )rû   r	   )r6   s   "r   r7   r7   "  s%   € ÷ 3ñ 3¤ð 3´ð 3¼(Ä4½.ñ 3r   c                óŠ   € VP                  RV4      ;'       g    / p\        V\        4      '       g   R# \        V\        4      # )a  ``apply_yaml_config_fn``: bridge ``buzz.extra`` into ``BUZZ_*`` env (env wins; skipped under a
secondary profile's scope, #98738) and seed the same keys into the returned ``extra`` so each profile's
adapter reads its own. ``BUZZ_PRIVATE_KEY`` is never sourced from config.yaml.r!   N)r   rï   rû   Ú_apply_yaml_bridgeÚ_YAML_BRIDGE)r«  r¬  r!   s   && r   Ú_apply_yaml_configr°  "  s9   € ð �L‰L˜ (Ó+×1Ð1¨r€EÜ�eœT×"Ò"ÙÜ˜e¤\Ó2Ð2r   c                ó:   € V ^8„  d   QhR\         \        ,          /# r’   rY  )r6   s   "r   r7   r7   ,  s   € ÷ 0ñ 0œ¤$�ñ 0r   c                 ó0  € \        \        RR4      ;'       g    R4      P                  4       p V '       d   \        4       '       g   R# \	        RRR 3RR\
        3R34      p\	        RR	VP                  R4      ;'       g    R.^ ,          R
7      pRV /VCVC# )uy  ``env_enablement_fn``: seed ``PlatformConfig.extra`` from the owning profile's env so env-only setups
show in gateway status; None if unconfigured. Reads go through the profile scope: a served secondary sees
only its own ``.env`` (#98738 â€” the process env is the DEFAULT profile's and must not fabricate Buzz here).
Cron delivery target defaults to the first watched channel.r)  r9   NrÐ  rÑ  c                 ó˜   € V P                  R 4       Uu. uF*  qP                  4       '       g   K  VP                  4       NK,  	  up# u upi rí   )rð   rk   )Úvr]   s   & r   rA   Ú!_env_enablement.<locals>.<lambda>5  s/   € ÀAÇGÁGÈCÄLÓ0^ÁL¸q×T[ÑT[×T]´°·±¶ÁLÒ0^ùÒ0^s
   ”A°ArÒ  rÓ  r.  )Úhome_envÚhome_defaultr™   )r4  r5  Nr  )r5   r   rk   rc  Ú_seed_extra_from_envr  r   )r¡   rA  rH  s      r   Ú_env_enablementr¹  ,  s£   € ô
 Ô"Ð#3°RÓ8×>Ð>¸BÓ?×EÑEÓG€EßÔ,×.Ò.ÙÜØ	˜*Ñ&^Ð_Ø	˜´Ð6Ð8[ð!ó €Dô   Ð-@ÐPT×PXÑPXÐYcÓPd×PlÐPlÐikÐhlÐnoÕOpÔq€DØ˜Ð/ $Ð/¨$Ð/Ð/r   r˜  Úmedia_filesÚforce_documentFc                óÄ   € V ^8„  d   QhR\         R\         R\        \         ,          R\        \        \        ,          ,          R\        R\
        \         \        3,          /# )r0   rc  r~  r˜  rº  r»  r3   )r5   r	   r¥   r   r›   rû   )r6   s   "r   r7   r7   <  sS   € ÷ ,ñ ,Üð,Ü$'ð,Ü7?Äµ}ð,äœ$œs�)Õ$ð,ä=Að,ô 
Œ#Œsˆ(…^ñ,r   c          
   ƒ  óâ  "  € \        V R/ 4      ;'       g    / p\        V4      p\        V4      p \        V4      p	\        T4      pT'       d	   T'       g   \        R4      # T'       g   \        R4      # T;'       g    RP                  4       ;'       g    \        T4      ;p'       g   \        R4      # RR	R
TRR.pT'       d%   \        Y4      R8w  d   TR\        T4      .,          pT;'       g    .  FD  pTR\        \        T\        \        34      '       d   T'       d
   T^ ,          MT4      .,          pKF  	   \        Y½YxY’R7      G Rj  x€L
 w  pppT^ 8w  d   \        TT4      MRpTe0   \         P#                  R4       \        Y½YxTR7      G Rj  x€L
 w  pppT^ 8w  d   \        R\-        TT4       24      # \/        T4      w  ppT'       d   \        RT 24      # RRRT/pT'       d   RTR&   T#   \         d   p
\        RT
 24      u Rp
?
# Rp
?
ii ; i LÎ Lˆ  \$        P&                   d    h \(         d+   p\        R\+        \        T4      4       24      u Rp?# Rp?ii ; i5i)zLOne-shot send without a live adapter (out-of-process ``deliver=buzz`` cron).r!   zBuzz standalone send: NzLBuzz standalone send: BUZZ_RELAY_URL and BUZZ_PRIVATE_KEY must be configuredz/Buzz standalone send: buzz CLI binary not foundr9   z?Buzz standalone send: no target channel (set BUZZ_HOME_CHANNEL)rh  r•  rg  r–  r—  r  r¥  r×  r  zQBuzz: retrying standalone message after unresolved presentation-mention preflight)r™   rt  rp  z+Buzz standalone send failed to launch CLI: zBuzz standalone send failed: r”  Tr�  Úmedia_delivered)r!  r+  rc  ro  r€   r   r7  rk   r1  r&  r5   rï   r¥   rw   r�  rN   r,  rP  rˆ   r?  rQ  r•  rœ  r¢  )Úpconfigrc  r~  r˜  rº  r»  r!   r¡   rt  rg  rR  r5  r¼  rs  rb  r"  r#  rS  rL   r®  r¡  r®  rŸ  s   &&&$$$                 r   Ú_standalone_sendrÀ  <  s^  é € ô
 �G˜W bÓ)×/Ð/¨R€EÜ˜eÓ$€EÜ& uÓ-€Kð:Ü$ UÓ+ˆô $ EÓ*€HßŸÜÐhÓiÐißÜÐKÓLÐLØ—}�} "×+Ñ+Ó-×PÐPÔ1IÈ%Ó1PÐPˆFÖPÜÐ[Ó\Ð\Ø˜ ¨V°[À#ÐF€Dç”^ GÓ3°uÔ<Ø�œs 9›~Ð.Õ.ˆØ×"Ð" Ò"ˆØ�œ3¬:°e¼dÄE¸]×+KÒ+K×PU˜u QžxÐ[`ÓaÐbÕbŠñ #ð
hÜ)¨(ÀEÐmuô   K÷  K‰ˆˆc�3ØKOÐSTÌ9Ô9¸'À3ÔGÐZ^ˆØÒÜ�K‰KÐkÔlä#-¨hÈÐszÔ#{×{‰NˆD�#�sð
 ˆq„yÜÐ9Ô:LÈSÐRVÓ:WÐ9XÐYÓZÐZÜ1°#Ó6Ñ€HˆmßÜÐ9¸-¸ÐIÓJÐJØ˜˜|¨XÐ6€FßØ$(ˆÐ Ñ!Ø€MøôE ô :ÜÐ2°3°%Ð8Ó9Õ9ûð:úñ  Kñ
 |øÜ×!Ñ!ô ØÜô hÜÐGÔH\Ô]`ÐabÓ]cÓHdÐGeÐfÓgÕgûðhüsÅ   ‚.I/±G8 ¼I/ÁI/Á*I/Á>I/ÂI/Â*I/Ã,I/Ã20I/Ä#I/Ä>H" ÅHÅAH" ÆH ÆH" Æ AI/Ç1I/Ç8HÈHÈHÈI/ÈHÈI/ÈH" È H" È"I,ÉI,ÉI'É!I,É"I/É'I,É,I/c                ó   € V ^8„  d   QhRR/# r\  r  )r6   s   "r   r7   r7   k  s   € ÷ ,Yñ ,Y˜4ñ ,Yr   c                 ó‚  aa€ ^ RI HoHp HpHoHpHpHpHp ^ RI	H
p R VV3R llpV! R4       S! R4      pV! RRR4      '       d   R# V! R	4       V! R
4       \        4        S! RT;'       g    RR7      p	V	'       g   V! R4       R# V! RV	P                  4       4       S! RRR7      p
V
'       d   V! RV
P                  4       4       M\        4       '       g	   V! R4       V! RR4      pV'       d   V! RVP                  RR4      4       V! RR4      pV'       d   V! RVP                  4       4       \        4        V! R4       V ! RR4      '       d   V! RR4       V! RR4       V! R4       M5V! RR 4       V! R!R4      pT! RV'       d   VP                  RR4      MR4       \        4        V! R"4       V! R#4       R# )$zbInteractive ``hermes gateway setup`` flow (lazy CLI imports keep the plugin importable elsewhere).)ÚpromptÚprompt_yes_noÚsave_env_valueÚget_env_valueÚprint_headerÚ
print_infoÚprint_warningÚprint_success)Údeclines_reconfigurec                ó<   € V ^8„  d   QhR\         R\         R\         /# )r0   r›  r|  r3   rT   )r6   s   "r   r7   Ú'interactive_setup.<locals>.__annotate__q  s!   € ÷ ?ñ ?”3ð ?œSð ?¤Sñ ?r   c                 ó8   <€ S! T S! V4      ;'       g    R R7      # )r9   ©r   r  )r›  r|  rÆ  rÃ  s   &&€€r   ÚaskÚinteractive_setup.<locals>.askq  s   ø€ Ù�e¡]°3Ó%7×%=Ð%=¸2Ô>Ð>r   r  r)  zReconfigure Buzz?NzNConnect Hermes to a Buzz community (Block's Nostr-based human+agent platform).zK   Requires the buzz CLI binary and a Nostr key that is a community member.z9Relay URL (e.g. https://mycommunity.communities.buzz.xyz)r9   rÏ  u-   Relay URL is required â€” skipping Buzz setupz<Nostr private key (nsec or hex; leave blank to keep current)T)r²  rb  uN   No private key configured â€” set BUZZ_PRIVATE_KEY before starting the gatewayzEChannel UUIDs to watch (comma-separated, empty = all joined channels)rÐ  r¦  z;Home channel UUID for cron/notification delivery (optional)r.  u7   ðŸ”’ Access control: restrict who can talk to the agentz1Allow all community members to talk to the agent?FÚBUZZ_ALLOW_ALL_USERSÚtruerÙ  uF   âš ï¸�  Open access â€” anyone in the community can command the agent.r  zLAllowed users (comma-separated npubs or hex pubkeys, empty to deny everyone)z*Buzz configuration saved to ~/.hermes/.envzFRestart the gateway for changes to take effect: hermes gateway restart)Úhermes_cli.setuprÃ  rÄ  rÅ  rÆ  rÇ  rÈ  rÉ  rÊ  Úhermes_cli.setup_platformsrË  Úprintrk   rc  rh   )rÄ  rÅ  rÇ  rÈ  rÉ  rÊ  rË  rÐ  Úexisting_relayr¡   r"   rÑ  rH  ÚallowedrÆ  rÃ  s                 @@r   Úinteractive_setuprÙ  k  s�  ù€ ÷÷ ó õ @÷?ñ ?ñ �ÔÙ"Ð#3Ó4€NÙ˜FÐ$7Ð9I×JÒJÙÙÐ_Ô`ÙÐ\Ô]Ü	„GÙÐNÐXf×XlÐXlÐjlÔm€EßÙÐEÔFÙÙÐ# U§[¡[£]Ô3Ù
ÐOÐZ^Ô
_€Cß
ÙÐ)¨3¯9©9«;Õ7Ü!×#Ò#ÙÐfÔgÙÐZÐ\kÓl€HßÙ�¨×(8Ñ(8¸¸bÓ(AÔBÙÐLÐNaÓb€DßÙÐ*¨D¯J©J«LÔ9Ü	„GÙÐHÔIÙÐHÈ%×PÒPÙÐ-¨vÔ6ÙÐ+¨RÔ0ÙÐ^Õ_áÐ-¨wÔ7ÙÐdÐfzÓ{ˆÙÐ+Ï¨W¯_©_¸SÀ"Ô-EÐVXÔYÜ	„GÙÐ>Ô?ÙÐWÖXr   c                ó
  € V P                   ! R%/ \        R4      P                  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\        bRRbR\        bRRbRRbRRbRRbRRbR R!bR"R#bB  R$# )&z7Plugin entry point: called by the Hermes plugin system.Úsend_targetsr   rB  r›  r  Úadapter_factoryc                 ó   € \        V 4      # r©   )rÉ  )rŸ  s   &r   rA   Úregister.<locals>.<lambda>ž  s	   € ¼{È3Ô?Or   Úcheck_fnr¦  r©  Úrequired_envr)  rb  Úinstall_hintzXRequires the buzz CLI binary (https://github.com/block/buzz) on PATH or at BUZZ_CLI_PATHÚsetup_fnÚenv_enablement_fnÚapply_yaml_config_fnÚcron_deliver_env_varr.  Ústandalone_sender_fnÚallowed_users_envrÙ  Úallow_all_envrÒ  rµ  u   ðŸ��Úpii_safeFÚallow_update_commandTÚplatform_hintzùYou are collaborating in a Buzz workspace (Block's Nostr-based human+agent platform). Markdown IS supported. Users address you by @-mentioning your name or npub in channels; direct messages reach you without a mention. Keep responses conversational.Údisplay_tierÚmediumNr  )
Úregister_platformrÇ   ÚSEND_ENTRY_KWARGSr£  r¦  r©  rÙ  r¹  r°  rÀ  )Úctxs   &r   Úregisterrñ  š  sö   € à×Òñ Ü
˜Ó
'×
9Ñ
9òáðá!ðâ3OðåZlðõ (ðõ 7Cðð ScÐdvÑQwðñ pð	õ
 #ðõ
 7Fðõ
 ]oðñ 1ðõ HXðñ /ðñ ?Uðñ ]cðñ ðñ "ðñJðñ" ô#r   r©   i  @)r9   )ÚnsecÚprivate_key_hexrt  ))r™   r)  r5   )r5  r4  r5   )r/  r.  r5   )r×  rÖ  r5   )rÓ  rÒ  r5   )rÑ  rÐ  Úcsv)rÚ  rÙ  rô  )rÜ  rÛ  rô  )Úallow_all_usersrÒ  r~   )rÕ  rÔ  r~   )r  r  r~   )r  r  r~   )šrŽ  rˆ   rŒ   r×  r\  Úloggingrm  r   rE   rF  ri  r  Úcollectionsr   r   Úpathlibr   Útypingr   r   r   r	   r
   Úurllib.parser   r   Úagent.secret_scoper   rN  Úgateway.platforms._sharedr   r®  r   r   r   r   r   r¸  r   r   r$   Ú	getLoggerrq  r,  rh  r%   r&   r'   r(   Úgateway.platforms.helpersr)   Úgateway.platforms.eventr*   r+   Úgateway.configr,   Ú#plugins.platforms.buzz.buzz_cursorsr-   r.   r  Ú	frozensetr"  rF   rC   r>   r  rN   r#  r=  ræ  rå  Ú_CLI_TIMEOUTrk  rw  r°  r´  rÏ  ro   ru   r…   r  r`  rM  r*  r+  rD  rO  Ú_MEDIA_URL_PATTERNrH   r­   r±   r�   r�   r–   r¢   r¶   r¾   rÇ   rÅ   rm  Úgateway.authz_mixinr×   rØ   rÙ   rÚ   rÛ   r  rë   rñ   rø   rý   r  r  rõ   r&  r+  r1  r7  r?  r6  rR  rU  rW  r_  rc  ro  r�  r”  r•  rœ  r¢  r™  r¨  r°  r½  rÃ  rM  ÚPHOTOÚAUDIOÚVIDEOrr  r  rþ  rÉ  r   r£  r¦  r©  r¯  r°  r¹  rÀ  rÙ  rñ  r  r   r   Ú<module>r	     sŽ  ðñó Û Û Û Û Û Û 	Û 	Û Û Û Ý #Ý Ý ß 3Õ 3ß -õ
 K÷ó õ 1ôHòð" 
×	Ò	˜8Ó	$€÷ó õ 2ß =Ý #ß Jð €
ñ ˜Z¨°Ð6Ó7€Ø!ŸzšzÐ*oÓpÐ Ø'/Ð $Ø�JŠJ�Ó'€	õ	&ð €ØÐ ØÐ ØÐ Ø€àÐ ØÐ àÐ Ø 0Ð Ø#Ð Ø!$Ð õ
2õð  Ð ð
 Ð Ø!Ð ØÐ Ø0Ð áÐ 0Ó1×<Ñ<Ó>Ð àlÐ Ø—Z’ZØ(Ð);Ð(<Ð<[Ð\Ð^`×^kÑ^kóÐ ð —’Ð.°·±Ó>€Ø—’ÐYÐ[]×[hÑ[hÓi€õõOõõõ2Nõ(õñ ˜LÓ)€÷õ õ

Jò;õlõ
;õ^õõ5õjõrõEõ
]õ
V÷7÷	ð 9€õ÷	÷E÷	_ðbØY[ðbà $ðbà7C÷bð: Ð ÷pð	eÐVZ÷ 	eõ"õ õ_õDõ)õ}ð Ð Ø  +×"3Ò"3Ð4°wÀ×@QÒ@QÐ6RÐU\Ð^i×^oÒ^oÐTpÐqÐ Ø! ;×#4Ò#4°g¸{×?PÒ?PÐRYÐ[f×[lÒ[lÐnxð  {F÷  {Oò  {Oð  PÐ ôaa�/Ð#6ô aaõL'4õ(	kõ
7õ#ð
€õ3õ0ð ,ØGKð,à'+ð,àDI÷,õ^,Yô^r   