+
    kHàjÑE  ã                   ó  € R t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIHtHtHt ^ RI	H
t
HtHtHt  ^ RItRt^ RIHtHt ^ RIHtHt ^ RIHtHt ^ R	IHtHt ^ R
IHt ^ RIH t!H"t# ^ RI$H%t% ]PL                  ! ]'4      t( ! R R])4      t*Rt+Rt,Rt-Rt.. R0Ot/^Zt0Rt1R1t2R R lt3RR/R R llt4R R lt5R R lt6R R lt7R R  lt8R! R" lt9R# R$ lt: ! R% R&]4      t;R' R( lt<R)RR*RR+R/R, R- llt=R. R/ lt>R#   ] d    RtRt LËi ; i)2aø  ntfy platform adapter: HTTP-streaming subscription (``/json``, ``poll=false``) in, POST out.

config.yaml ``platforms.ntfy.extra``: ``server`` (default https://ntfy.sh), ``topic`` (required),
``publish_topic`` (defaults to topic), ``token`` (Bearer or ``user:pass`` Basic), ``markdown``
(default false). Env (read at construct time; ``extra`` wins over env): NTFY_TOPIC, NTFY_SERVER_URL,
NTFY_TOKEN, NTFY_PUBLISH_TOPIC, NTFY_MARKDOWN ("true"/"1"/"yes"), NTFY_ALLOWED_USERS (topic names),
NTFY_ALLOW_ALL_USERS (dev only), NTFY_HOME_CHANNEL, NTFY_HOME_CHANNEL_NAME.
Identity: ntfy has no authenticated user; ``title`` is publisher-controlled and NOT used for
authorization. Each topic is one trusted channel (``user_id`` == topic). Protect it with a read token.
N)ÚdatetimeÚtimezoneÚUTC)ÚAnyÚDictÚListÚOptionalTF)ÚPlatformÚPlatformConfig)ÚBasePlatformAdapterÚ
SendResult)ÚMessageEventÚMessageType)Úget_scoped_secretÚ
send_error)ÚMessageDeduplicator)Úextra_or_secretÚseed_extra_from_env)Úparse_nonemptyc                   ó   € ] tR t^(tRtRtR# )Ú_FatalStreamErrorz&Unrecoverable stream error (401, 404).© N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú__static_attributes__r   ó    ÚC/home/ubuntu/.hermes/hermes-agent/plugins/platforms/ntfy/adapter.pyr   r   (   s   † Ý0r   r   zhttps://ntfy.shi   é,  iè  zhermes-agentc                óR   € V ^8„  d   QhR\         R\        \         \         3,          /# )é   ÚtokenÚreturn©ÚstrÚdict)Úformats   "r   Ú__annotate__r)   6   s"   € ÷ 0ñ 0œcð 0¤d¬3´¨8¥nñ 0r   c                óÒ   € T ;'       g    RP                  4       p V '       g   / # RV 9   d7   ^ RIpRRVP                  V P                  4       4      P	                  4        2/# RRV  2/# )u×   ``Authorization`` header from an ntfy token; ``{}`` when unset.

Tokens are whitespace-stripped (pasted tokens often carry newlines that
would malform the header). ``user:pass`` â†’ Basic, anything else â†’ Bearer.
Ú Ú:NÚAuthorizationzBasic zBearer )ÚstripÚbase64Ú	b64encodeÚencodeÚdecode)r#   r/   s   & r   Ú_build_auth_headerr3   6   si   € ð �[ˆ[�b×ÑÓ!€EßØˆ	Ø
ˆe„|ÛØ 6¨&×*:Ñ*:¸5¿<¹<»>Ó*J×*QÑ*QÓ*SÐ)TÐ!UÐVÐVØ˜w u gÐ.Ð/Ð/r   Ú
auth_firstc          
      ój   € V ^8„  d   QhR\         R\        R\        R\        \         \         3,          /# )r"   r#   Úmarkdownr4   r$   )r&   Úboolr'   )r(   s   "r   r)   r)   E   s5   € ÷ 
ñ 
œCð 
¬4ð 
Äð 
ÔPTÔUXÔZ]ÐU]ÕP^ñ 
r   c               ór   € \        V 4      pRRR\        /pV'       d   / VCVCM/ VCVCpV'       d   RVR&   V# )z­Headers for a publish POST: auth (if any), plain-text body, echo tag, optional X-Markdown.

``auth_first`` pins the header order each call site has always sent on the wire.
zContent-Typeztext/plain; charset=utf-8zX-TagsÚtruez
X-Markdown)r3   Ú	_ECHO_TAG)r#   r6   r4   ÚauthÚbaseÚheaderss   &&$   r   Ú_publish_headersr>   E   sN   € ô
 ˜eÓ$€DØÐ7¸Ä9ÐM€Dß",Ð�Ð˜ÑÐ2B°TÐ2B¸TÐ2B€GßØ &ˆ�ÑØ€Nr   c                ó<   € V ^8„  d   QhR\         R\         R\        /# )r"   ÚmessageÚcontextr$   )r&   Úbytes)r(   s   "r   r)   r)   R   s!   € ÷ 8ñ 8œCð 8¬Sð 8´Uñ 8r   c               ó¤   € \        V 4      \        8”  d&   \        P                  RV\        V 4      \        4       V R\         P	                  R4      # )zUApply the ntfy 4096-char limit, logging a warning (tagged ``context``) on truncation.z7%s: truncating message from %d to %d chars (ntfy limit)Núutf-8)ÚlenÚMAX_MESSAGE_LENGTHÚloggerÚwarningr1   )r@   rA   s   &$r   Ú_truncate_bodyrI   R   sF   € ä
ˆ7ƒ|Ô(Ô(Ü�‰ØEØ”S˜“\Ô#5ô	7ð Ð&Ô&Ð'×.Ñ.¨wÓ7Ð7r   c                ó$   € V ^8„  d   QhR\         /# ©r"   r$   )r&   )r(   s   "r   r)   r)   [   s   € ÷ %ñ %¤#ñ %r   c                ó  €  V P                  4       P                  R4      ;'       g'    \        P                  ! 4       P                  R,          #   \
         d*    \        P                  ! 4       P                  R,          u # i ; i)z8ntfy's returned message id, or a random 12-hex fallback.Úid:Né   N)ÚjsonÚgetÚuuidÚuuid4ÚhexÚ	Exception)Úresps   &r   Ú_response_message_idrV   [   s[   € ð%Ø�y‰y‹{�‰˜tÓ$×=Ð=¬¯
ª
«×(8Ñ(8¸Õ(=Ð=øÜô %Ü�zŠz‹|×Ñ Õ$Ò$ð%ús   ‚%A ¨&A Á1BÂBc                óR   € V ^8„  d   QhR\         \        \        3,          R\        /# )r"   Úextrar$   ©r'   r&   r   )r(   s   "r   r)   r)   c   s&   € ÷ \ñ \”tœC¤˜H•~ð \¬#ñ \r   c                 óD   € \        V R R\        4      P                  R4      # )ÚserverÚNTFY_SERVER_URLÚ/)Ú_extra_or_secretÚDEFAULT_SERVERÚrstrip)rX   s   &r   Ú_server_urlra   c   s    € Ü˜E 8Ð->ÄÓO×VÑVÐWZÓ[Ð[r   c                ó$   € V ^8„  d   QhR\         /# rK   ©r7   )r(   s   "r   r)   r)   g   s   € ÷ Rñ RœDñ Rr   c                 ód   € \         ;'       d$    \        \        RR4      P                  4       4      # )uY   Installable and minimally configured (reads NTFY_TOPIC directly â€” no full config load).Ú
NTFY_TOPICr+   )ÚHTTPX_AVAILABLEr7   Ú_get_scoped_secretr.   r   r   r   Úcheck_requirementsrh   g   s&   € ä×QÐQœtÔ$6°|ÀRÓ$H×$NÑ$NÓ$PÓQÐQr   c                ó$   € V ^8„  d   QhR\         /# rK   rc   )r(   s   "r   r)   r)   l   s   € ÷ ]ñ ]œtñ ]r   c           	     óX   € \        \        \        V R/ 4      ;'       g    / RR4      4      # )z?True when a topic is configured (config.yaml ``extra`` or env).rX   Útopicre   )r7   r^   Úgetattr©Úconfigs   &r   Úvalidate_configro   l   s(   € äÔ ¤¨°¸"Ó!=×!CÐ!CÀÀWÈlÓ[Ó\Ð\r   c                ó$   € V ^8„  d   QhR\         /# rK   rc   )r(   s   "r   r)   r)   q   s   € ÷ kñ kœDñ kr   c                óˆ   € \        \        R4      ;'       g(    \        V R/ 4      ;'       g    / P                  RR4      4      # )z6Check whether ntfy is configured (env or config.yaml).re   rX   rk   r+   )r7   rg   rl   rP   rm   s   &r   Úis_connectedrr   q   s<   € äÔ" <Ó0×iÐi´W¸VÀWÈbÓ5Q×5WÐ5WÐUW×4\Ñ4\Ð]dÐfhÓ4iÓjÐjr   c                   óø   a a€ ] tR t^vt oRt]tRtV3R lV 3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V3R lR ltRV3R lR lltV3R lR ltV3R lR ltRtVtV ;t# )ÚNtfyAdapterzDntfy adapter: HTTP-streaming subscription in, HTTP POST publish out.Tc                ó    <€ V ^8„  d   QhRS[ /# )r"   rn   )r
   )r(   Ú__classdict__s   "€r   r)   ÚNtfyAdapter.__annotate__|   s   ø€ ÷ 	eñ 	e™~ñ 	er   c                ól  <€ \         SV `  V\        R 4      R7       VP                  ;'       g    / p\	        V4      V n        \        VRR4      V n        \        VRR4      ;'       g    V P                  V n        \        VRR4      V n	        RV n
        RV n        \        \        \        R	7      V n        R# )
Úntfy)rn   Úplatformrk   re   Úpublish_topicÚNTFY_PUBLISH_TOPICr#   Ú
NTFY_TOKENN)Úmax_sizeÚttl_seconds)ÚsuperÚ__init__r	   rX   ra   Ú_serverr^   Ú_topicÚ_publish_topicÚ_tokenÚ_stream_taskÚ_http_clientr   ÚDEDUP_MAX_SIZEÚDEDUP_WINDOW_SECONDSÚ_dedup)Úselfrn   rX   Ú	__class__s   && €r   r�   ÚNtfyAdapter.__init__|   s—   ø€ Ü‰Ñ ´¸&Ó1AÐÔBØ—‘×"Ð" ˆÜ'¨Ó.ˆŒÜ+¨E°7¸LÓIˆŒÜ#3°E¸?ÐL`Ó#a×#pÐ#pÐei×epÑepˆÔÜ+¨E°7¸LÓIˆŒØ48ˆÔØ9=ˆÔÜ)´>ÔOcÔdˆŽr   Úis_reconnectFc                ó&   <€ V ^8„  d   QhRS[ RS[ /# )r"   rŽ   r$   rc   )r(   rv   s   "€r   r)   rw   ‰   s   ø€ ÷ ñ ©Tð ¹dñ r   c             ƒ  ó€  "  € \         '       g#   \        P                  RV P                  4       R# V P                  '       g#   \        P                  RV P                  4       R#  \
        P                  ! RR7      V n        \        P                  ! V P                  4       4      V n        V P                  4        \        P                  RV P                  V P                  V P                  4       V P                  R4       R#   \          d-   p\        P#                  RT P                  T4        Rp?R# Rp?ii ; i5i)	z<Connect to ntfy by starting the streaming subscription task.z0[%s] httpx not installed. Run: pip install httpxFz[%s] NTFY_TOPIC not configuredN©Útimeoutu'   [%s] Connected â€” subscribing to %s/%sTz[%s] Failed to connect: %s)rf   rG   rH   Únamerƒ   ÚhttpxÚAsyncClientr‡   ÚasyncioÚcreate_taskÚ_run_streamr†   Ú_mark_connectedÚinfor‚   Ú_wire_plugin_handlersrT   Úerror)r‹   rŽ   Úes   &$ r   ÚconnectÚNtfyAdapter.connect‰   sÙ   é € ç‹Ü�N‰NÐMÈtÏyÉyÔYÙØ�{�{ˆ{Ü�N‰NÐ;¸T¿Y¹YÔGÙð		Ü %× 1Ò 1¸$Ô ?ˆDÔÜ '× 3Ò 3°D×4DÑ4DÓ4FÓ GˆDÔØ× Ñ Ô"Ü�K‰KÐAÀ4Ç9Á9ÈdÏlÉlÐ\`×\gÑ\gÔhØ×&Ñ& tÔ,ÙøÜô 	Ü�L‰LÐ5°t·y±yÀ!ÔDÝûð	üs7   ‚A D>Á"D>Á&BD ÄD>ÄD;Ä!D6Ä0D>Ä6D;Ä;D>c                ó   <€ V ^8„  d   QhRR/# ©r"   r$   Nr   )r(   rv   s   "€r   r)   rw   œ   s   ø€ ÷ ñ  4ñ r   c              ƒ  óŽ  "  € ^ pRpV P                    RV P                   R2pV P                  4       pV P                  '       dþ    \        P                  RV P                  V4       \        P                  ! 4       pV P                  W44      G Rj  x€L
  T P                  '       g   R# \        P                  ! 4       T,
          R8¼  d   ^ p\        \!        T\#        \        4      ^,
          4      ,          p\        P%                  R	T P                  T4       \        P&                  ! T4      G Rj  x€L
  T^,          pEK  R#  L³  \        P                   d     R# \         d    RT n         R# \         dE   pT P                  '       g    Rp?R# \        P                  RT P                  T4        Rp?EL&Rp?ii ; i L‘5i)
z8Subscribe to the ntfy topic with automatic reconnection.g        r]   z/jsonz[%s] Opening stream to %sNFz[%s] Stream error: %sg      N@z[%s] Reconnecting in %ds...)r‚   rƒ   Ú_auth_headersÚ_runningrG   Údebugr“   ÚtimeÚ	monotonicÚ_consume_streamr–   ÚCancelledErrorr   rT   rH   ÚRECONNECT_BACKOFFÚminrE   rš   Úsleep)r‹   Úbackoff_idxÚstream_startÚurlr=   r�   Údelays   &      r   r˜   ÚNtfyAdapter._run_streamœ   sX  é € àˆØ!ˆØ—‘�˜a §¡˜}¨EÐ2ˆØ×$Ñ$Ó&ˆØ�m�mˆmðFÜ—‘Ð8¸$¿)¹)ÀSÔIÜ#Ÿ~š~Ó/�Ø×*Ñ*¨3Ó8×8Ð8ð —=—=�=Ùä�~Š~Ó ,Õ.°$Ô6Ø�Ü%¤c¨+´sÔ;LÓ7MÐPQÕ7QÓ&RÕSˆEÜ�K‰KÐ5°t·y±yÀ%ÔHÜ—-’- Ó&×&Ð&Ø˜1Õ‹Kñ- ñ 9øÜ×)Ñ)ô ÚÜ$ô Ø %�”ÚÜô FØ—}—}�}ÝÜ—‘Ð6¸¿	¹	À1×EÒEûðFúñ 'ùs†   ‚AGÁA
E ÂEÂE ÂGÂ'B
GÄ1GÄ2GÅE ÅG ÅGÅG Å'G Å/GÅ2G Å;G Å<F;ÆGÆ!F;Æ5GÆ;G Ç Gc                ó$   <€ V ^8„  d   QhRS[ RR/# )r"   Ústatus_coder$   N)Úint)r(   rv   s   "€r   r)   rw   º   s   ø€ ÷ (ñ (©ð (°ñ (r   c                ó(  € VR8X  d'   \         P                  RV P                  4       RRr2RpMHVR8X  d@   \         P                  RV P                  V P                  4       RR	V P                   R
2r2RpMR# V P	                  W#RR7       \        V4      h)zT401/404 are unrecoverable: log, set the fatal state and raise ``_FatalStreamError``.i‘  uO   [%s] Authentication failed (401) â€” stopping reconnect loop. Check NTFY_TOKEN.Úntfy_unauthorizedz2ntfy server rejected auth (401). Check NTFY_TOKEN.z401 Unauthorizedi”  u;   [%s] Topic not found (404): %s â€” stopping reconnect loop.Úntfy_topic_not_foundzntfy topic 'z!' returned 404. Check NTFY_TOPIC.z404 Not FoundNF)Ú	retryable)rG   rœ   r“   rƒ   Ú_set_fatal_errorr   )r‹   r³   ÚcodeÚdetailÚreasons   &&   r   Ú_fatal_statusÚNtfyAdapter._fatal_statusº   s’   € à˜#ÔÜ�L‰LØaÐcg×clÑclônà.Ð0d�&Ø'‰FØ˜CÔÜ�L‰LÐVÐX\×XaÑXaÐcg×cnÑcnÔoØ1°\À$Ç+Á+ÀÐNoÐ3p�&Ø$‰FáØ×Ñ˜d°eÐÔ<Ü Ó'Ð'r   c                ó@   <€ V ^8„  d   QhRS[ RS[S[ S[ 3,          RR/# )r"   r¯   r=   r$   Nr%   )r(   rv   s   "€r   r)   rw   Ê   s*   ø€ ÷ 2ñ 2©ð 2±t¹CÁ¸Hµ~ð 2È$ñ 2r   c              ƒ  óì  "  € V P                   P                  RWRR/\        P                  ! R\        RRR7      R7      ;_uu_4       GRj  x€L
 pV P                  VP                  4       VP                  4        VP                  4         Rj  x€L
  pV P                  '       g    RRR4      GRj  x€L
  R# VP                  4       pV'       g   KI   \        P                  ! V4      pTP                  R4      R	8X  g   Kx  T P                  T4      G Rj  x€L
  K“   LÒ L� Ln  \        P                   d     K±  i ; i L(D±RRR4      GRj  x€L 
  R#   + GRj  x€L 
 '       g   i     R# ; i5i)
z6Open an HTTP streaming connection and dispatch events.ÚGETÚpollÚfalseç      .@)rž   ÚreadÚwriteÚpool)r=   Úparamsr’   NÚeventr@   )r‡   Ústreamr”   ÚTimeoutÚSTREAM_TIMEOUT_SECONDSr½   r³   Úraise_for_statusÚaiter_linesr¤   r.   rO   ÚloadsÚJSONDecodeErrorrP   Ú_on_message)r‹   r¯   r=   ÚresponseÚlinerÉ   s   &&&   r   r¨   ÚNtfyAdapter._consume_streamÊ   sA  é € ð ×$Ñ$×+Ñ+Ø�3°¸Ð0AÜ—M’M¨$Ô5KÐSWÐ^bÔcð ,÷ 
÷ 
ô 
ð Ø×Ñ˜x×3Ñ3Ô4Ø×%Ñ%Ô'Ø&×2Ñ2Ô4÷ 2ð 2�dØ—}—}�}Ø÷
÷ 
ñ 
ð —z‘z“|�ßÙðÜ ŸJšJ tÓ,�Eð —9‘9˜WÓ%¨Ö2Ø×*Ñ*¨5Ó1×1Ò1ñ#
ñ2ñ
øô ×+Ñ+ô Úðúñ 2ð 5÷
÷ 
÷ 
÷ 
÷ 
ô 
üsÌ   ‚A
E4ÁDÁE4Á<EÂEÂD!
ÂEÂEÂ)E4Â4D#Â5E4Â;EÃEÃD%Ã,EÄEÄE
ÄEÄE4Ä!EÄ#E4Ä%D>	Ä:EÄ=D>	Ä>EÅEÅE4ÅEÅE4ÅE1	ÅE Å
E1	Å)E1	Å+	E4c                ó   <€ V ^8„  d   QhRR/# r¡   r   )r(   rv   s   "€r   r)   rw   à   s   ø€ ÷ 4ñ 4 $ñ 4r   c              ƒ  óô  "  € RV n         V P                  4        V P                  '       d7   V P                  P                  4         V P                  G Rj  x€L
  RV n        V P                  '       d*   V P                  P                  4       G Rj  x€L
  RV n        V P                  P                  4        \        P                  RV P                  4       R#  L‚  \        P
                   d     L—i ; i Ld5i)zDisconnect from ntfy.FNz[%s] Disconnected)r¤   Ú_mark_disconnectedr†   Úcancelr–   r©   r‡   ÚacloserŠ   ÚclearrG   rš   r“   ©r‹   s   &r   Ú
disconnectÚNtfyAdapter.disconnectà   sÅ   é € àˆŒØ×ÑÔ!Ø××ÐØ×Ñ×$Ñ$Ô&ðØ×'Ñ'×'Ð'ð !%ˆDÔØ××ÐØ×#Ñ#×*Ñ*Ó,×,Ð,Ø $ˆDÔØ�‰×ÑÔÜ�‰Ð'¨¯©Ö3ñ (øÜ×)Ñ)ô Ùðúñ -ùsO   ‚AC8ÁC ÁCÁC ÁC8Á4C8ÂC6ÂAC8ÃC ÃC3Ã0C8Ã2C3Ã3C8c                ó:   <€ V ^8„  d   QhRS[ S[S[3,          RR/# )r"   rÉ   r$   NrY   )r(   rv   s   "€r   r)   rw   ó   s#   ø€ ÷ 1ñ 1¡t©C±¨H¥~ð 1¸$ñ 1r   c           	   ƒ  óZ  "  € VP                  R4      ;'       g     \        P                  ! 4       P                  pV P                  P                  V4      '       d$   \        P                  RV P                  V4       R# \        VP                  R4      ;'       g    . 9   d#   \        P                  RV P                  4       R# VP                  R4      ;'       g    RP                  4       pV'       g#   \        P                  RV P                  4       R# VP                  R	4      ;'       g    V P                  pV P                  WDR
WDVR7      pVP                  R4      \        P                  ! \        R7      rv V'       d&   \        P                   ! \#        V4      \        R7      MTp\+        V\,        P.                  WRWR7      p\        P                  RV P                  WCR,          4       V P1                  V4      G Rj  x€L
  R#   \$        \&        \(        3 d     Lxi ; i L"5i)z'Process an incoming ntfy message event.rM   z#[%s] Duplicate message %s, skippingNÚtagsz$[%s] Skipping own message (echo tag)r@   r+   z![%s] Empty message body, skippingrk   Údm)Úchat_idÚ	chat_nameÚ	chat_typeÚuser_idÚ	user_nameÚ
message_idr¦   )Útz)ÚtextÚmessage_typeÚsourcerç   Úraw_messageÚ	timestampz[%s] Message on topic %s: %s:NéP   N)rP   rQ   rR   rS   rŠ   Úis_duplicaterG   r¥   r“   r:   r.   rƒ   Úbuild_sourcer   Únowr   Úfromtimestampr´   Ú
ValueErrorÚOSErrorÚ	TypeErrorr   r   ÚTEXTÚhandle_message)	r‹   rÉ   Úmsg_idré   rk   rë   Úunix_tsrí   Úmessage_events	   &&       r   rÑ   ÚNtfyAdapter._on_messageó   sš  é € à—‘˜4“×4Ð4¤D§J¢J£L×$4Ñ$4ˆØ�;‰;×#Ñ# F×+Ò+Ü�L‰LÐ>ÀÇ	Á	È6ÔRÙÜ˜Ÿ™ 6Ó*×0Ð0¨bÔ1Ü�L‰LÐ?ÀÇÁÔKÙØ—	‘	˜)Ó$×*Ð*¨×1Ñ1Ó3ˆßÜ�L‰LÐ<¸d¿i¹iÔHÙð —	‘	˜'Ó"×1Ð1 d§k¡kˆØ×"Ñ"Ø°dÀEÐgmð #ó oˆà"ŸY™Y vÓ.´·²ÄÔ0D�ð	ßHOœ×.Ò.¬s°7«|ÄÕDÐU^ˆIô %Ø¤K×$4Ñ$4¸VØô4ˆô 	�‰Ð3°T·Y±YÀÈCÅyÔQØ×!Ñ! -Ó0×0Ò0øô œG¤YÐ/ô 	Ùð	úñ 	1ùsW   ‚AH+Á?H+ÂA H+ÃH+Ã69H+Ä0AH+Å>/H Æ-AH+ÈH)ÈH+ÈH&È#H+È%H&È&H+c                ón   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          RS[S[S[ S[3,          ,          RS[/# )r"   râ   ÚcontentÚreply_toÚmetadatar$   )r&   r   r'   r   r   )r(   rv   s   "€r   r)   rw     sK   ø€ ÷ ;ñ ;Ùð;Ù%(ð;Ù4<¹SµMð;ÙT\Ñ]aÑbeÑgjÐbjÕ]kÕTlð;á	ñ;r   c           	   ƒ  ó–  "  € T;'       g    / P                  R4      ;'       g    V P                  ;'       g    TpV P                  '       g   \        RRR7      # \	        V P
                  \        V P                  P                  ;'       g    / P                  RR4      4      4      p\        V4      V P                  8”  d6   \        P                  RV P                  \        V4      V P                  4       VRV P                   P                  R4      p V P                  P                  V P                    R	V 2WvR
R7      G Rj  x€L
 pVP"                  R8  d   \        R\%        V4      R7      # VP&                  p	\        P                  RV P                  VP"                  V	R,          4       \        RRVP"                   RV	R,           2R7      #  LŽ  \(        P*                   d    \        RRR7      u # \,         dB   p
\        P/                  RT P                  T
4       \        R\1        T
4      R7      u Rp
?
# Rp
?
ii ; i5i)z2Publish a message to the configured publish topic.r{   FzHTTP client not initialized)Úsuccessrœ   r6   z7[%s] Message truncated from %d to %d chars (ntfy limit)NrD   r]   rÄ   )rý   r=   r’   r    T)r  rç   z[%s] Send failed HTTP %d: %sºNéÈ   NzHTTP ú: zTimeout publishing to ntfyz[%s] Send error: %s)rP   r„   r‡   r   r>   r…   r7   rn   rX   rE   rF   rG   rH   r“   r1   Úpostr‚   r³   rV   ré   r”   ÚTimeoutExceptionrT   rœ   r&   )r‹   râ   rý   rþ   rÿ   r{   r=   ÚbodyrU   Ú	body_textr�   s   &&&&&      r   ÚsendÚNtfyAdapter.send  sé  é € ð "Ÿ˜ R×,Ñ,¨_Ó=×_Ð_À×ATÑAT×_Ð_ÐX_ˆØ× × Ð Ü eÐ3PÔQÐQÜ" 4§;¡;´°d·k±k×6GÑ6G×6MÐ6MÈ2×5RÑ5RÐS]Ð_dÓ5eÓ0fÓgˆÜˆw‹<˜$×1Ñ1Ô1Ü�N‰NØIØ—	‘	œ3˜w›<¨×)@Ñ)@ôBð Ð/˜×/Ñ/Ð0×7Ñ7¸Ó@ˆð	;Ø×*Ñ*×/Ñ/Ø—<‘<�.  - Ð1¸4ÐZ^ð 0ó `÷ `ˆDà×Ñ #Ô%Ü!¨$Ô;OÐPTÓ;UÔVÐVØŸ	™	ˆIÜ�N‰NÐ9¸4¿9¹9Àd×FVÑFVÐXaÐbfÕXgÔhÜ e°U¸4×;KÑ;KÐ:LÈBÈyÐY]ÍÐN_Ð3`ÔaÐañ`øô ×%Ñ%ô 	QÜ eÐ3OÔPÒPÜô 	;Ü�L‰LÐ.°·	±	¸1Ô=Ü e´3°q³6Ô:Õ:ûð	;üs}   ‚"I	¥I	¹I	Á>I	ÂBI	Ä0G ÅGÅ*G Å1I	Å2A"G ÇI	ÇG Ç"IÇ9I	Ç;IÈIÈ6IÈ;IÈ<I	ÉIÉI	c                ó<   <€ V ^8„  d   QhRS[ RS[S[ S[3,          /# )r"   râ   r$   )r&   r'   r   )r(   rv   s   "€r   r)   rw   -  s#   ø€ ÷ /ñ /©3ð /±4¹¹S¸µ>ñ /r   c              ƒ  ó   "  € R VRR/# 5i)r“   Útyperá   r   )r‹   râ   s   &&r   Úget_chat_infoÚNtfyAdapter.get_chat_info-  s   é € Ø˜ ¨Ð.Ð.ùs   ‚	c                ó6   <€ V ^8„  d   QhRS[ S[S[3,          /# rK   )r'   r&   )r(   rv   s   "€r   r)   rw   0  s   ø€ ÷ /ñ /™t¡C© H�~ñ /r   c                ó,   € \        V P                  4      # ©N)r3   r…   rÛ   s   &r   r£   ÚNtfyAdapter._auth_headers0  s   € Ü! $§+¡+Ó.Ð.r   )rŠ   r‡   r„   r¤   r‚   r†   r…   rƒ   )NN)r   r   r   r   r   rF   Úserial_receive_loopr�   rž   r˜   r½   r¨   rÜ   rÑ   r	  r  r£   r   Ú__classdictcell__Ú__classcell__)rŒ   rv   s   @@r   rt   rt   v   s†   ù‡ € ÙNà+ÐØÐ÷	eó 	eð°E÷ ò ÷&ð ÷<(ð (÷ 2ð 2÷,4ð 4÷&1ð 1÷>;ò ;÷6/ð /÷/÷ /ð /r   rt   c                ó2   € V ^8„  d   QhR\         R,          /# r¡   )r'   )r(   s   "r   r)   r)   7  s   € ÷ 
Rñ 
Rœ �ñ 
Rr   c                 ó¶   € \        RR4      P                  4       p V '       g   R# \        RRR 3RRRRR	 33R
V R7      pRV RVP                  R\        4      /VC# )z�``env_enablement_fn``: seed ``PlatformConfig.extra`` from the profile's env before adapter
construction; ``None`` when ``NTFY_TOPIC`` is unset.re   r+   Nr\   r[   c                 ó$   € V P                  R 4      # )r]   )r`   ©Úvs   &r   Ú<lambda>Ú!_env_enablement.<locals>.<lambda>>  s   € °·±¸´r   ÚNTFY_MARKDOWNr6   c                 ó0   € V P                  4       \        9   # r  )ÚlowerÚ_MARKDOWN_TRUTHYr  s   &r   r  r  ?  s   € ÈqÏwÉwËyÔ\lÒOlr   ÚNTFY_HOME_CHANNEL)Úhome_envÚhome_defaultrk   )r|   r{   N)r}   r#   N)rg   r.   Ú_seed_extra_from_envÚpopr_   )rk   Úseeds     r   Ú_env_enablementr(  7  sq   € ô ˜|¨RÓ0×6Ñ6Ó8€EßÙÜØ	˜HÑ&=Ð>Ð@mØ%¨¸ÑElÐ'mð!ð $°%ô9€Dð �U˜H d§h¡h¨x¼Ó&HÐQÈDÐQÐQr   Ú	thread_idÚmedia_filesÚforce_documentc                óÄ   € V ^8„  d   QhR\         R\         R\        \         ,          R\        \        \         ,          ,          R\        R\        \         \
        3,          /# )r"   râ   r@   r)  r*  r+  r$   )r&   r   Úlistr7   r'   r   )r(   s   "r   r)   r)   E  sS   € ÷ ?ñ ?Üð?Ü$'ð?äœ�}ð?ä2:¼4Ä½9Õ2Eð?ä^bð?ô 
Œ#Œsˆ(…^ñ?r   c          
   ƒ  óh  "  € \         '       g   \        R4      # \        V R/ 4      ;'       g    / p\        V4      pT;'       go    VP	                  R4      ;'       gV    \        RR4      P                  4       ;'       g4    VP	                  R4      ;'       g    \        RR4      P                  4       pV'       g   \        R4      # \        VR	R
4      p	\        RR4      P                  4       P                  4       p
\        VP	                  R4      4      ;'       g
    V
\        9   p\        W›RR7      p\        VRR7      p \        P                  ! RR7      ;_uu_4       GRj  x€L
 pVP                  V RV 2WÜR7      G Rj  x€L
 pRRR4      GRj  x€L
  XP                   R8¼  d-   \        RVP                    RVP"                  R,           24      # RRRRRVR\%        V4      /#  L„ Lf LX  + GRj  x€L 
 '       g   i     Lo; i  \&         d   p\        R T 24      u Rp?# Rp?ii ; i5i)!a  Out-of-process publish for cron / send_message_tool when no gateway adapter is live.

``thread_id``/``media_files`` are signature parity only (ntfy has no thread
or attachment primitive). Markdown is honored if ``NTFY_MARKDOWN`` is set
OR ``pconfig.extra["markdown"]`` is True.
z)ntfy standalone send: httpx not installedrX   r{   r|   r+   rk   re   z/ntfy standalone send: NTFY_TOPIC not configuredr#   r}   r  r6   F)r4   zntfy standalone)rA   rÄ   r‘   Nr]   )rý   r=   r    z
ntfy HTTP r  r  r  Trz   ry   râ   rç   zntfy standalone send failed: )rf   r   rl   ra   rP   rg   r.   r^   r   r7   r!  r>   rI   r”   r•   r  r³   ré   rV   rT   )Úpconfigrâ   r@   r)  r*  r+  rX   r[   r{   r#   Úmarkdown_envr6   r=   r  ÚclientrU   r�   s   &&&$$$           r   Ú_standalone_sendr2  E  s÷  é € ÷ ‹?ÜÐEÓFÐFÜ�G˜W bÓ)×/Ð/¨R€EÜ˜Ó€Fà÷ 	Nð 	N�5—9‘9˜_Ó-÷ 	Nð 	NÔ1CÐDXÐZ\Ó1]×1cÑ1cÓ1e÷ 	Nð 	NØ�9‰9�WÓ÷	Nð 	NÜ!3°LÀ"Ó!E×!KÑ!KÓ!Mð ÷ ÜÐKÓLÐLÜ˜U G¨\Ó:€EÜ% o°rÓ:×@Ñ@ÓB×HÑHÓJ€LÜ�E—I‘I˜jÓ)Ó*×NÐN¨lÔ>NÑ.N€HÜ˜u¸5ÔA€GÜ˜'Ð+<Ô=€Dð?Ü×$Ò$¨T×2×2Õ2°fØŸ™¨ x¨q°°Ð%@È$˜Ó`×`ˆD÷ 3×2à×Ñ˜sÔ"Ü 
¨4×+;Ñ+;Ð*<¸B¸t¿y¹yÈ½Ð>OÐPÓQÐQØ˜4 ¨V°YÀÈ|Ô]qÐrvÓ]wÐxÐxñ	 3Ù`÷ 3×2×2Ò2ûô
 ô ?ÜÐ9¸!¸Ð=Ó>Õ>ûð?üsÆ   ‚+H2®H2ÁH2Á!H2Â H2Â"H2Â<BH2Å#H Å%G*Å&H Å)G0ÆG,ÆG0Æ
H ÆG.ÆA H ÇH2ÇH Ç)H2Ç*H Ç,G0Ç.H Ç0H		Ç6G9Ç7
H		ÈH		ÈH ÈH/ÈH*È$H/È%H2È*H/È/H2c                ó   € V ^8„  d   QhRR/# r¡   r   )r(   s   "r   r)   r)   g  s   € ÷ ñ �Tñ r   c                óŽ   € V P                  \        RRR RR\        \        \        R.R\
        R\        RR	\        R
RRRR7       R# )uE   Plugin entry point â€” called by the Hermes plugin system at startup.ry   c                 ó   € \        V 4      # r  )rt   )Úcfgs   &r   r  Úregister.<locals>.<lambda>k  s	   € ¼{È3Ô?Or   z@Chat with Hermes over ntfy push topics (ntfy.sh or self-hosted).zDhttps://hermes-agent.nousresearch.com/docs/user-guide/messaging/ntfyre   z1pip install httpx   # already a Hermes dependencyr"  ÚNTFY_ALLOWED_USERSÚNTFY_ALLOW_ALL_USERSu   ðŸ””Tu  You are communicating via ntfy push notifications. Use plain text by default â€” ntfy supports optional markdown (set markdown: true in config or NTFY_MARKDOWN=true). Keep responses concise; ntfy is a push notification service with a 4096-character per-message limit.)Útarget_ref_syntax_fnr“   ÚlabelÚadapter_factoryÚdashboard_descriptionÚdocs_urlÚcheck_fnro   rr   Úrequired_envÚinstall_hintÚenv_enablement_fnÚcron_deliver_env_varÚstandalone_sender_fnÚallowed_users_envÚallow_all_envÚmax_message_lengthÚemojiÚpii_safeÚallow_update_commandÚplatform_hintN)Úregister_platformr   rh   ro   rr   r(  r2  rF   )Úctxs   &r   ÚregisterrN  g  sU   € à×ÑÜ+Ø˜6Ñ3OØ`ØWÜ#´_ÔS_Ø"�^Ð2eÜ)Ø0Ü-Ø.Ð>TÜ-°VØØ!ð7ð ö r   )r"   é   é
   é   é<   )Ú1r9   Úyes)?r   r–   rO   Úloggingr¦   rQ   r   r   r   Útypingr   r   r   r   r”   rf   ÚImportErrorÚgateway.configr	   r
   Úgateway.platforms.baser   r   Úgateway.platforms.eventr   r   Úgateway.platforms._sharedr   rg   r   Úgateway.platforms.helpersr   r   r^   r   r%  Úgateway.platforms.send_targetsr   Ú	getLoggerr   rG   rT   r   r_   rF   r‰   rˆ   rª   rÌ   r:   r!  r3   r>   rI   rV   ra   rh   ro   rr   rt   r(  r2  rN  r   r   r   Ú<module>r_     s"  ðñ	ó Û Û Û Û ß ,Ñ ,ß ,Ó ,ðÛØ€O÷
 4ß Bß =ß YÝ 9÷õ :à	×	Ò	˜8Ó	$€ô1˜	ô 1ð #€ØÐ ØÐ Ø€Ú&Ð ØÐ Ø€	Ø'Ð õ0ð
Àt÷ 
õ8õ%õ\õRõ
]õ
kô
{/Ð%ô {/õB
Rð?à#ð?àHLð?àej÷?÷Døða
 ô Ø€OØ‚Eðús   ®C2 Ã2D Ã?D 