
    FjJ0                       d Z ddlZddlZddlZddlZddlZddlZddlZddlm	Z	 ddl
mZ  ej        e          Z ej        d          Z ej        d          Z ej        d          Z ej        d          Z ej        d	          Z ej        d
          ZeZ eh d          Z ej        d          Zh dZh dZh dZddhZddhZ ej        dej                  Z  ej        dej                  Z!de"fdZ#de"de$fdZ%de&de'de(dz  fdZ)ddde'fd Z*d!d"d#d$d%d&gd'd(d$d)d*d$d+d*d,g d-d.Z+d/ Z,d0 Z-d1 Z.d2e"d3e"fd4Z/d5 Z0d6 Z1d2e"d7e"d8e"dz  fd9Z2ddd:d;d<Z3dUd=Z4d>e&de5fd?Z6dVd@Z7dA Z8dB Z9dWdCZ:dD Z;dE Z<dF Z=dXdGZ>dH Z?dI Z@dJ ZAdWdKZBdL ZCdXdMZDdN ZEdO ZFdWdPZGddQlHmIZImJZJ  eIjK        d!dRe+e,eEdST           dS )Ya$  Send Message Tool -- cross-channel messaging via platform APIs.

Sends a message to a user or channel on any connected messaging platform
(Telegram, Discord, Slack). Supports listing available targets and resolving
human-friendly channel names to IDs. Works in both CLI and gateway contexts.
    N)
formatdate)redact_sensitive_textz^\s*(-?\d+)(?::(\d+))?\s*$zD^\s*((?:oc|ou|on|chat|open)_[-A-Za-z0-9]+)(?::([-A-Za-z0-9_]+))?\s*$z^\s*([CGDU][A-Z0-9]{8,})\s*$z%^\s*([CGD][A-Z0-9]{8,}):([^\s:]+)\s*$zS^\s*((?:wxid|gh|v\d+|wm|wb)_[A-Za-z0-9_-]+|[A-Za-z0-9._-]+@chatroom|filehelper)\s*$z ^\s*((?:group|direct):[^:]+)\s*$>   smssignalwhatsappz^\s*\+(\d{7,15})\s*$>   .gif.jpg.png.jpeg.webp>   .3gp.avi.mkv.mov.mp4>   .wav.flac.m4a.mp3.ogg.opusr   r   r   r   zP([?&](?:access_token|api[_-]?key|auth[_-]?token|token|signature|sig)=)([^&#\s]+)zJ\b(access_token|api[_-]?key|auth[_-]?token|signature|sig)\s*=\s*([^\s,;]+)returnc                     t          |           }t                              d |          }t                              d |          }|S )zCRedact secrets from error text before surfacing it to users/models.c                 2    |                      d           dS )N   z***groupms    6/usr/local/lib/hermes-agent/tools/send_message_tool.py<lambda>z&_sanitize_error_text.<locals>.<lambda>@   s    QWWQZZ2D2D2D     c                 2    |                      d           dS )Nr   z=***r   r   s    r    r!   z&_sanitize_error_text.<locals>.<lambda>A   s    !''!**7J7J7J r"   )r   _URL_SECRET_QUERY_REsub_GENERIC_SECRET_ASSIGN_RE)textredacteds     r    _sanitize_error_textr)   =   sF    $T**H#''(D(DhOOH(,,-J-JHUUHOr"   messagec                 $    dt          |           iS )z9Build a standardized error payload with redacted content.error)r)   )r*   s    r    _errorr-   E   s    )'2233r"   excattemptc                 R   t          | dd           }|6	 t          t          |          d          S # t          t          f$ r Y dS w xY wt          |                                           }d|v sd|v rd S d|v sd|v sd|v sd	|v sd
|v sd|v sd|v sd|v rt          d|z            S d S )Nretry_afterg        g      ?z	timed outtimeoutzbad gateway502ztoo many requests429zservice unavailable503zgateway timeout504   )getattrmaxfloat	TypeError
ValueErrorstrlower)r.   r/   r1   r'   s       r    _telegram_retry_delayr?   J   s    #}d33K	u[))3///:& 	 	 	33	 s88>>Ddi4//tD==$&&D== D((D==$$D==Q'\"""4s   2 AA   )attemptsrA   c                N  K   t          |          D ]}	  | j        di | d {V c S # t          $ rn}t          ||          }|	||dz
  k    r t                              d|dz   ||t          |                     t          j        |           d {V  Y d }~d }~ww xY wd S )Nr   zFTransient Telegram send failure (attempt %d/%d), retrying in %.1fs: %s )	rangesend_message	Exceptionr?   loggerwarningr)   asynciosleep)botrA   kwargsr/   r.   delays         r    !_send_telegram_message_with_retryrN   c   s     ?? ' '	'))33F33333333333 	' 	' 	')#w77E}8a< 7 7NNX!$S))   -&&&&&&&&&&&&&&	'' 's   *
B"A$BB"rE   a  Send a message to a connected messaging platform, or list available targets.

IMPORTANT: When the user asks to send to a specific channel or person (not just a bare platform name), call send_message(action='list') FIRST to see available targets, then send to the correct one.
If the user just says a platform name like 'send to telegram', send directly to the home channel without listing first.objectstringsendlistzAction to perform. 'send' (default) sends a message. 'list' returns all available channels/contacts across connected platforms.)typeenumdescriptiona  Delivery target. Format: 'platform' (uses home channel), 'platform:#channel-name', 'platform:chat_id', or 'platform:chat_id:thread_id' for Telegram topics and Discord threads. Examples: 'telegram', 'telegram:-1001234567890:17585', 'discord:999888777:555444333', 'discord:#bot-home', 'slack:#engineering', 'signal:+155****4567', 'matrix:!roomid:server.org', 'matrix:@user:server.org', 'yuanbao:direct:<account_id>' (DM), 'yuanbao:group:<group_code>' (group chat))rS   rU   u   The message text to send. To send an image or file, include MEDIA:<local_path> (e.g. 'MEDIA:/tmp/report.pdf') in the message — the platform will deliver it as a native media attachment.)actiontargetr*   )rS   
propertiesrequired)namerU   
parametersc                 t    |                      dd          }|dk    rt                      S t          |           S )z-Handle cross-channel send_message tool calls.rV   rQ   rR   )get_handle_list_handle_send)argskwrV   s      r    send_message_toolrb      s8    XXh''F~~r"   c                      	 ddl m}  t          j        d |             i          S # t          $ r.}t          j        t          d|                     cY d}~S d}~ww xY w)z5Return formatted list of available messaging targets.r   )format_directory_for_displaytargetsz"Failed to load channel directory: N)gateway.channel_directoryrd   jsondumpsrF   r-   )rd   es     r    r^   r^      s    LJJJJJJz9&B&B&D&DEFFF L L Lz&!Ia!I!IJJKKKKKKKKLs   #& 
A#AAAc                   ( |                      dd          }|                      dd          }|r|st          d          S |                    dd          }|d                                                                         }t          |          dk    r|d                                         nd}d}d}|rt          ||          \  }}}nd	}|rw|su	 dd
lm}	  |	||          }
|
rt          ||
          \  }}}nt          j
        dd| d| di          S n-# t          $ r  t          j
        dd| d| di          cY S w xY wddlm}  |            rt          d          S 	 ddlm}m}  |            }n;# t          $ r.}t          j
        t#          d|                     cY d}~S d}~ww xY w	  ||          }n)# t$          t&          f$ r t          d|           cY S w xY w|j                             |          }|r|j        s|dk    rt-          j        dd                                          }t-          j        dd                                          }|re|rcddlm}  |d||t-          j        dd                                          t-          j        dd                                          d          }n&t          d| d          S t          d| d          S dd lm} d!|v }|                    |          \  }}|                    |          }|                                pt;          |          }d	}|s|                    |          }|sC|dk    r=t-          j        d"d                                          }|rdd#lm}  |||d$%          }|r
|j         }d}n2t          j
        dd&| d'| d(|!                                 d)i          S tE          |||          }|rt          j
        |          S |d*k    r|r|#                    d+          rz	 ddl$((fd,} dd-l%m&}!  |! | |j'        |                    }"|"r|"}nt          j
        dd.| d/i          S n0# t          $ r#}t          j
        dd0| i          cY d}~S d}~ww xY w	 dd-l%m&}!  |!tQ          |||||||1                    }#|r6tS          |#tT                    r!|#                     d2          rd3| d4| d5|#d6<   tS          |#tT                    re|#                     d2          rP|rN	 dd7l+m,}$ dd8l-m.}%  |%d9d:          }& |%d;d          pd}' |$||||&||'<          rd|#d=<   n# t          $ r Y nw xY wtS          |#tT                    rd|#v rt_          |#d                   |#d<   t          j
        |#          S # t          $ r.}t          j
        t#          d>|                     cY d}~S d}~ww xY w)?z$Send a message to a platform target.rW    r*   z;Both 'target' and 'message' are required when action='send':r   r   NF)resolve_channel_namer,   zCould not resolve 'z' on z;. Use send_message(action='list') to see available targets.z). Try using a numeric channel ID instead.)is_interruptedInterrupted)load_gateway_configPlatformzFailed to load gateway config: zUnknown platform: weixinWEIXIN_TOKENWEIXIN_ACCOUNT_IDPlatformConfigTWEIXIN_BASE_URLWEIXIN_CDN_BASE_URL)
account_idbase_urlcdn_base_url)enabledtokenextraz
Platform 'zZ' is not configured. Set up credentials in ~/.hermes/config.yaml or environment variables.)BasePlatformAdapterz[[as_document]]WEIXIN_HOME_CHANNEL)HomeChannelzWeixin Home)platformchat_idrZ   zNo home channel set for zQ to determine where to send the message. Either specify a channel directly with 'z=:CHANNEL_NAME', or set a home channel via: hermes config set z_HOME_CHANNEL <channel_id>slackUc                 >  K   d}d|  dd}                                         d                    4 d {V }|                    ||d|gi	          4 d {V }|                                 d {V }|                    d
          r2|d         d         cd d d           d {V  cd d d           d {V  S 	 d d d           d {V  d d d           d {V  d S # 1 d {V swxY w Y   	 d d d           d {V  d S # 1 d {V swxY w Y   d S )Nz(https://slack.com/api/conversations.openBearer application/jsonAuthorizationzContent-Type
   totalr2   usersheadersrg   okchannelid)ClientSessionClientTimeoutpostrg   r]   )r}   user_idurlr   sessionrespdataaiohttps          r    _open_slack_dmz$_handle_send.<locals>._open_slack_dm  s     @,=e,=,=Oabb"009N9NUW9N9X9X0YY $ $ $ $ $ $ $]d&||CRYQZG[|\\ $ $ $ $ $ $ $`d%)YY[[00000088D>> 9#'	?4#8$ $ $ $ $ $ $ $ $ $ $ $ $$ $ $ $ $ $ $ $ $ $ $ $ $ $
  $	$ $ $ $ $ $ $ $ $ $ $ $$ $ $ $ $ $ $ $ $ $ $ $ $ $$ $ $ $ $ $ $ $ $ $ $ $ $ $ $$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $sA   "D =C'DC'D'
C1	1D4C1	5D
DD)
_run_asyncz"Could not open DM with Slack user z#. Check bot permissions (im:write).zFailed to open Slack DM: 	thread_idmedia_filesforce_documentsuccesszSent to z home channel (chat_id: )note)mirror_to_sessionget_session_envHERMES_SESSION_PLATFORMcliHERMES_SESSION_USER_ID)source_labelr   r   mirroredzSend failed: )0r]   
tool_errorsplitstripr>   len_parse_target_refrf   rm   rg   rh   rF   tools.interruptrn   gateway.configrp   rq   r-   r<   KeyError	platformsr|   osgetenvrv   gateway.platforms.baser   extract_mediafilter_media_delivery_paths_describe_media_for_mirrorget_home_channelr   r   upper_maybe_skip_cron_duplicate_send
startswithr   model_toolsr   r}   _send_to_platform
isinstancedictgateway.mirrorr   gateway.session_contextr   r)   ))r`   rW   r*   partsplatform_name
target_refr   r   is_explicitrm   resolved_rn   rp   rq   configri   r   pconfigwx_token
wx_accountrv   r   force_document_attachmentsr   cleaned_messagemirror_textused_home_channelhomewx_homer   duplicate_skipr   r   
dm_channelresultr   r   r   r   r   s)                                           @r    r_   r_      s   XXh##Fhhy"%%G Y YWXXXLLa  E!HNN$$**,,M%(ZZ!^^q!!!JGI *;M:*V*V'KK  + 	FFFFFF++M:FFH (9-(R(R%AAz Q: Q QM Q Q Q#    %&  	 	 	: ;z ; ; ; ; ;     	 /.....~ )-(((I@@@@@@@@$$&& I I Iz&!F1!F!FGGHHHHHHHHI
@8M**! @ @ @>}>>?????@ ""8,,G V'/ V H$$y44::<<H#6;;AACCJ ZJ Z999999(. "&0$&I.?$D$D$J$J$L$L(*	2G(L(L(R(R(T(T    "  #Y}  #Y  #Y  #Y  Z  Z  Z  U=  U  U  U  V  V  V:::::: "3g!=#6#D#DW#M#M K%AA+NNK!''))T-G-T-TK &&x00 	[11i 5r::@@BBG [666666"{HgMZZZ 	lG $: rM r r;Hr r@M@S@S@U@Ur r r    5]GYWWN *z.))) G0B0B30G0G	JNNN$ $ $ $ $ /.....#NN7='$J$JKKJ @$z7,}QX,},},}"~   	J 	J 	J:w(GA(G(GHIIIIIIII	J'7******#'9  

 

  	ZFD!9!9 	Zfjj>S>S 	ZYYYwYYYF6N fd## 	

9(=(= 	+ 	<<<<<<CCCCCC./H%PP)/*BBGGO4$$!!-'#   . *.F:&    fd## 	D6(9(926'?CCF7Oz&!!! 7 7 7z&!4!4!455666666667s   AD 'EE(E; ;
F3#F.(F3.F37G #G)(G)+AQ4 4
R!>RR!R!%B	W /<U, +W ,
U96W 8U99AW 
W9#W4.W94W9r   r   c                 L   | dk    rGt                               |          }|r+|                    d          |                    d          dfS | dk    rGt                              |          }|r+|                    d          |                    d          dfS | dk    rGt                              |          }|r+|                    d          |                    d          dfS | dk    rt
                              |          }|r+|                    d          |                    d          dfS t                              |          }|r$|                    d          }|d         d	v}|d
|fS | dk    rG|                                }|                    d          }|dk    r|d
|         ||dz   d
         dfS | dk    r4t                              |          }|r|                    d          d
dfS | dk    rvt                              |          }|r|                    d          d
dfS |                                                                rd|                                 d
dfS dS | t          v r3t                              |          }|r|                                d
dfS |                    d                                          r|d
dfS | dk    r/|                    d          s|                    d          r|d
dfS | dk    r	d|v r|d
dfS dS )zFParse a tool target into chat_id/thread_id and whether it is explicit.telegramr   r7   Tfeishudiscordr   r   >   r   WNmatrixz:$rr   yuanbaogroup:NNF-!@xmpp)_TELEGRAM_TOPIC_TARGET_RE	fullmatchr   _FEISHU_TARGET_RE_NUMERIC_TOPIC_RE_SLACK_THREAD_TARGET_RE_SLACK_TARGET_REr   rfind_WEIXIN_TARGET_RE_YUANBAO_TARGET_REisdigit_PHONE_PLATFORMS_E164_TARGET_RElstripr   )r   r   matchr   r   trimmed	split_idxs          r    r   r   V  sW   
"")33J?? 	8;;q>>5;;q>>477  !++J77 	8;;q>>5;;q>>477	!!!++J77 	8;;q>>5;;q>>477'11*== 	8;;q>>5;;q>>477 **:66 	.kk!nnG "!*J6KD+--  ""$$MM$''	q==:I:&	A(@$FF  !++J77 	.;;q>>4--	!!",,Z88 	.;;q>>4--%%'' 	=0J,,..00$<<  ((())*55 	2 ##%%tT11%%'' &4%%  j&;&;C&@&@ JDYDYZ]D^D^ 4%%3*#4#44%%r"   c                 :   | sdS t          |           dk    rr| d         \  }}t          j                            |          d                                         }|r|t
          v rdS |t          v rdS |t          v rdS |t          v rdS dS d	t          |            d
S )zJReturn a human-readable mirror summary when a message only contains media.rk   r   r   z[Sent voice message]z[Sent image attachment]z[Sent video attachment]z[Sent audio attachment]z[Sent document attachment]z[Sent z media attachments])	r   r   pathsplitextr>   _VOICE_EXTS_IMAGE_EXTS_VIDEO_EXTS_AUDIO_EXTS)r   
media_pathis_voiceexts       r    r   r     s     r
;1*1~
Hgz**1-3355 	*{**))+,,+,,+,,++9C$$9999r"   c                     ddl m}   | dd                                                                          } | dd                                          }|r|sdS  | dd                                          pd}|||dS )	zMReturn the cron scheduler's auto-delivery target for the current run, if any.r   r   !HERMES_CRON_AUTO_DELIVER_PLATFORMrk    HERMES_CRON_AUTO_DELIVER_CHAT_IDN"HERMES_CRON_AUTO_DELIVER_THREAD_ID)r   r   r   )r   r   r   r>   )r   r   r   r   s       r    _get_cron_auto_delivery_targetr    s    777777BBGGMMOOUUWWHo@"EEKKMMG 7 t DbIIOOQQYUYI  r"   r   r   c                     t                      }|sdS |d         | k    o>t          |d                   t          |          k    o|                    d          |k    }|sdS |  d| }||d| z  }ddd|d| d	d
S )zRSkip redundant cron send_message calls when the scheduler will auto-deliver there.Nr   r   r   rl   T#cron_auto_delivery_duplicate_targetzSkipped send_message to z. This cron job will already auto-deliver its final response to that same target. Put the intended user-facing content in your final response instead, or use a different target if you want an additional message.)r   skippedreasonrW   r   )r  r=   r]   )r   r   r   auto_targetsame_targettarget_labels         r    r   r     s    022K t 	J=0 	6I&''3w<<7	6OOK((I5 
  t#//g//LI' 7h| h h h
 
 
r"   Fr   c                  K   d}	 ddl m}  |            }n# t          $ r d}Y nw xY w|	 |j                            |           }	n# t          $ r d}	Y nw xY w|	r	 |rd|ind}
|	                    |||
           d{V }n-# t          j        $ r  t          $ r}dd| icY d}~S d}~ww xY w|j        r
d|j	        d	S dd
|j
         iS t          | d          r| j        nt          |           }d}	 ddlm} |                    |          }n# t          $ r d}Y nw xY w||j        	 |                    ||||||           d{V }nJ# t          j        $ r  t          $ r.}t"                              d|d           dd| icY d}~S d}~ww xY wt'          |t(                    r,|                    d          s|                    d          r|S dd| dt+          |          j         iS dd| diS )a  Send a message via a live gateway adapter, with a standalone fallback
    for out-of-process callers (e.g. cron running separately from the gateway).

    Order of attempts:
      1. Live in-process adapter via ``_gateway_runner_ref()`` (the path that
         existed before this change).
      2. The plugin's ``standalone_sender_fn`` registered on its
         ``PlatformEntry`` (used when the gateway is not in this process, so
         the runner weakref is ``None``).
      3. A descriptive error explaining both options.
    Nr   )_gateway_runner_refr   )r   contentmetadatar,   zPlugin platform send failed: T)r   
message_idzAdapter send failed: valueplatform_registryr   z$Plugin standalone send for %s raisedexc_infozPlugin standalone send failed: r   zPlugin standalone send for 'zR' returned an invalid result: expected a dict with 'success' or 'error' keys, got zNo live adapter for platform 'z'. Is the gateway running with this platform connected? For out-of-process delivery (e.g. cron in a separate process), the platform plugin must register a standalone_sender_fn on its PlatformEntry.)gateway.runr  rF   adaptersr]   rQ   rI   CancelledErrorr   r  r,   hasattrr  r=   gateway.platform_registryr  standalone_sender_fnrG   debugr   r   rS   __name__)r   r   r   chunkr   r   r   runnerr  adapterr  r   ri   r   entryr  s                   r    _send_via_adapterr$    si     * F333333$$&&    	o))(33GG 	 	 	GGG	F7@JK33d&||GUU]|^^^^^^^^)    F F F!D!D!DEEEEEEEF~ J#'v7HIIICV\CCDD&-h&@&@SHNNc(mmME??????!%%m44    U7C	D 55#'- 6        FF % 	 	 	 	D 	D 	DLL?Y]L^^^BqBBCCCCCCC	D fd## 	I)>)> 	&**WBUBU 	M5} 5 5!&\\25 5
 	
 	E] E E E sk    &&A AA&B B-B("B-(B-6D D! D!.!E F)#FFFc           
      ~  K   ddl m} ddlm}m}	 ddlm}
 	 ddlm} d}n# t          $ r d}Y nw xY w	 ddl
m} d}n# t          $ r d}Y nw xY w|pg }| |j        k    rZ|rX	 |
                    |
          }|                    |          }n,# t          $ r t                               d	d
           Y nw xY w|j        |r|j        nd|j        |
j        i}|r|j        ||j        <   | |vrI	 ddlm} |                    | j                  }|r|j        dk    r
|j        || <   n# t          $ r Y nw xY w|                    |           }|r(| |j        k    r|	nd}|                    |||          }n|g}| |j        k    rd}t7          t9          |di           o|j                            d                    }t=          |          D ]p\  }}|t?          |          dz
  k    }tA          |j!        |||r|ng |||           d{V }tE          |tF                    r|                    d          r|c S |}q|S | |j$        k    rtK          ||||           d{V S | |j&        k    rddlm} |                    d          }||j'        ddiS d}t=          |          D ]o\  }}|t?          |          dz
  k    }|'                    |||||r|ng            d{V }tE          |tF                    r|                    d          r|c S |}p|S | |j(        k    r|r}d}t=          |          D ]i\  }}|t?          |          dz
  k    }tS          ||||r|ng |           d{V }tE          |tF                    r|                    d          r|c S |}j|S | |j*        k    r|rd}t=          |          D ]m\  }}|t?          |          dz
  k    }tW          |j        |||r|ng            d{V }tE          |tF                    r|                    d          r|c S |}n|S | |j,        k    r}|r{d}t=          |          D ]g\  }}|t?          |          dz
  k    }t[          |||r|nd           d{V }tE          |tF                    r|                    d          r|c S |}h|S | |j        k    r|r}d}t=          |          D ]i\  }}|t?          |          dz
  k    }t]          ||||r|nd|           d{V }tE          |tF                    r|                    d          r|c S |}j|S |r!|/                                sdd| j         diS d}|rd| j         d}d}|D ][}| |j        k    rta          |j!        ||           d{V }n| |j1        k    rte          |j        ||           d{V }n| |j*        k    rtW          |j        ||           d{V }n| |j3        k    rti          |j        ||           d{V }n| |j5        k    rtm          |j7        ||           d{V }n[| |j(        k    r$tq          |j!        |j        ||           d{V }n,| |j9        k    r#tu          |j!        |j        ||           d{V }n| |j;        k    rty          |j        ||           d{V }n| |j        k    rt]          ||||           d{V }n| |j=        k    rt}          |j        ||           d{V }n| |j?        k    rt          |j        ||           d{V }na| |jA        k    rt          |||           d{V }n>| |j,        k    rt[          ||           d{V }nt          | ||||||           d{V }tE          |tF                    r|                    d          r|c S |}]|rgtE          |tF                    rR|                    d          r=t          |                    d g                     }|E                    |           ||d <   |S )!a  Route a message to the appropriate platform sender.

    Long messages are automatically chunked to fit within platform limits
    using the same smart-splitting algorithm as the gateway adapters
    (preserves code-block boundaries, adds part indicators).
    r   )rq   )r   	utf16_len)SlackAdapterTelegramAdapterTF)FeishuAdapterz<Failed to apply Slack mrkdwn formatting in _send_to_platformr  i   r  N)len_fnr~   disable_link_previewsr   )r   r   r,  r   r,   r   r   z=Discord plugin not registered or missing standalone_sender_fn)r   r   )r   r   zsend_message MEDIA delivery is currently only supported for telegram, discord, matrix, weixin, signal, yuanbao and feishu; target z had only media attachmentsz#MEDIA attachments were omitted for z; native send_message media delivery is currently only supported for telegram, discord, matrix, weixin, signal, yuanbao and feishu)r   r   r   warnings)Fr   rq   r   r   r&  gateway.platforms.slackr'  gateway.platforms.telegramr)  ImportErrorgateway.platforms.feishur*  SLACK__new__format_messagerF   rG   r  TELEGRAMMAX_MESSAGE_LENGTHFEISHUr  r  r]   r  max_message_lengthtruncate_messageboolr8   r~   	enumerater   _send_telegramr}   r   r   WEIXIN_send_weixinDISCORDr  MATRIX_send_matrix_via_adapterSIGNAL_send_signalYUANBAO_send_yuanbao_send_feishur   _send_slackWHATSAPP_send_whatsappEMAIL_send_emailSMS	_send_smsapi_key_send_matrixHOMEASSISTANT_send_homeassistantDINGTALK_send_dingtalkWECOM_send_wecomBLUEBUBBLES_send_bluebubblesQQBOT_send_qqbotr$  rR   append)r   r   r   r*   r   r   r   rq   r   r&  r'  r)  _telegram_availabler*  _feishu_availableslack_adapter_MAX_LENGTHSr  r#  max_len_len_fnchunkslast_resultr,  ir   is_lastr   rH   r.  s                                 r    r   r   -  s      ('''''EEEEEEEE444444$>>>>>>" $ $ $#$"::::::  " " "!" #K8>!!g!	h(00>>M#227;;GG 	h 	h 	hLLWbfLggggg	h 	AT^?==Z^7L  I(5(HX_% |##	CCCCCC%))(.99E B1A55).)AX& 	 	 	D	 x((G '8+<<<))$$55gww5WW 8$$$ $WWgr%B%B%qw}GXGXYpGqGq r r!&)) 	! 	!HAuCKK!O+G)+2:KK#&;-        F &$'' FJJw,?,?  KK 8?""!'7GUUUUUUUUUU 8###??????!%%i00=E6>\]]!&)) 	! 	!HAuCKK!O+G 55#+2:KK 6        F &$'' FJJw,?,?  KK 8?""{"!&)) 	! 	!HAuCKK!O+G3+2:KK#        F &$'' FJJw,?,?  KK 8?""{"!&)) 
	! 
	!HAuCKK!O+G'+2:KK	        F &$'' FJJw,?,?  KK 8####!&)) 		! 		!HAuCKK!O+G(+2<KK        F
 &$'' FJJw,?,?  KK 8?""{"!&)) 	! 	!HAuCKK!O+G'+2<KK#        F &$'' FJJw,?,?  KK  
7==?? 
F".F F F
 	
 G 
O(. O O O 	
 K * *x~%%&w}guEEEEEEEEFF***)'-%HHHHHHHHFF(('wFFFFFFFFFF''&w}guEEEEEEEEFF%%$W_guEEEEEEEEFF(('w}guUUUUUUUUFF///.w}gmWV[\\\\\\\\FF***)'-%HHHHHHHHFF(('%9UUUUUUUUUFF''&w}guEEEEEEEEFF---,W]GUKKKKKKKKFF''&w????????FF)))(%88888888FF -#'-        F fd## 	

7(;(; 	MMM +:k400 +[__Y5O5O +
B7788   "*Js?   ! 00= AA!*B &B54B5,7D$ $
D10D1r,   c                 H    dt          |                                           v S )zCheck if a Telegram error is a thread-not-found failure.

    Matches the gateway adapter's ``_is_thread_not_found_error`` for
    the standalone ``_send_telegram`` path (issue #27012).
    zthread not found)r=   r>   )r,   s    r    _is_telegram_thread_not_foundrg  #  s!     U!1!1!3!333r"   c           	      f  K   	 ddl m} ddlm} t	          t          j        d|                    }	|	r
|}
|j        }nK	 ddlm	} |
                    |          }|                    |          }
n# t          $ r |}
Y nw xY w|j        }	 ddlm}  |ddg	          }n# t          $ r d
}Y nw xY w|r	 ddlm} t$                              d|            ||  ||           ||                    }nJ# t          $ r1}t$                              d|            ||           }Y d
}~nd
}~ww xY w ||           }t+          |          }|pg }i }|e	 ddlm	} |                    t/          |                    }n4# t          $ r' t/          |          dk    rd
nt+          |          }Y nw xY w|||d<   t1          |          }|rd|d<   d
}g }|
                                rs	 t5          |f||
|d| d
{V }nY# t          $ rK}t7          |          r^|r\t$                              d|                    d                     |                    dd
           t5          |f||
|d| d
{V }ndt/          |                                          v sFdt/          |                                          v s#dt/          |                                          v rjt$                              d|t?          |                     |	s%	 ddlm }  ||
          }n# t          $ r |}Y nw xY w|}t5          |f||d
d| d
{V }n Y d
}~nd
}~ww xY w|D ]\  }}tB          j"        #                    |          s5d| }t$                              |           |$                    |           ZtB          j"        %                    |          d                                         }	 tM          |d          5 } t1          |          }!	 |tN          v r|s |j(        d/|| d|! d
{V }nx|tR          v r |j*        d/|| d |! d
{V }nX|tV          v r|r |j,        d/|| d!|! d
{V }n6|tZ          v r |j.        d/|| d"|! d
{V }n |j/        d/|| d#|! d
{V }n$# t          $ r}"t7          |"          r|!                    d          rt$                              d$|!d                    | 0                    d           |!                    dd
           |tN          v r|s |j(        d/|| d|! d
{V }nz|tR          v r |j*        d/|| d |! d
{V }nZ|tV          v r|r |j,        d/|| d!|! d
{V }n8|tZ          v r |j.        d/|| d"|! d
{V }n |j/        d/|| d#|! d
{V }n Y d
}"~"nd
}"~"ww xY wd
d
d
           n# 1 swxY w Y   # t          $ rO}#t?          d%| d&|#           }t$          1                    |           |$                    |           Y d
}#~#d
}#~#ww xY w|d'}$|r|$|d(S d)|$iS dd*|t/          |j2                  d+}%|r||%d,<   |%S # tf          $ r d)d-icY S t          $ r}#ti          d.|#           cY d
}#~#S d
}#~#ww xY w)0uD  Send via Telegram Bot API (one-shot, no polling needed).

    Applies markdown→MarkdownV2 formatting (same as the gateway adapter)
    so that bold, links, and headers render correctly.  If the message
    already contains HTML tags, it is sent with ``parse_mode='HTML'``
    instead, bypassing MarkdownV2 conversion.
    r   )Bot)	ParseModez<[a-zA-Z/][^>]*>r(  )resolve_proxy_urlTELEGRAM_PROXYzapi.telegram.org)target_hostsN)HTTPXRequestz>send_message: standalone Telegram send routed through proxy %s)proxy)r}   requestget_updates_requestzUsend_message: failed to attach Telegram proxy (%s), falling back to direct connection)r}   1message_thread_idTdisable_web_page_preview)r   r'   
parse_modezIThread %s not found in _send_telegram, retrying without message_thread_idparsemarkdownhtmlzFParse mode %s failed in _send_telegram, falling back to plain text: %s)_strip_mdv2z Media file not found, skipping: r   rb)r   photo)r   video)r   voice)r   audio)r   documentzFThread %s not found for media send, retrying without message_thread_idzFailed to send media : ANo deliverable text or media remained after processing MEDIA tags)r,   r.  r,   r   r   r   r   r  r.  zGpython-telegram-bot not installed. Run: pip install python-telegram-botzTelegram send failed: rC   )5r   ri  telegram.constantsrj  r;  researchHTMLr0  r)  r4  r5  rF   MARKDOWN_V2r   rk  telegram.requestrn  rG   inforH   int_message_thread_id_for_sendr=   r   r   rN   rg  r]   popr>   r)   ry  r   r   existsr[  r   openr   
send_photor   
send_videor   
send_voice_TELEGRAM_SEND_AUDIO_EXTS
send_audiosend_documentseekr,   r  r1  r-   )&r}   r   r*   r   r   r,  r   ri  rj  	_has_html	formattedsend_parse_moder)  _adapterrk  	_tg_proxyrn  rK   
_proxy_errint_chat_idthread_kwargseffective_thread_idtext_kwargslast_msgr.  md_errorry  plainr   r   rH   r  fmedia_kwargs	media_errri   r,   r   s&                                         r    r=  r=  ,  s     U4      000000 #6@@AA	 	4I'nOO$FFFFFF*22?CC$33G<<		 $ $ $#			$ (3O	@@@@@@))*:J\I]^^^II 	 	 	III	 	#
'999999\^ghhhc(Ly999(49(E(E(E  
  ' ' 'v  yC  D  D  Dc&&&' #E"""C'll!'R 
FFFFFF&5&Q&Q	NN' '##      	NNc11DDs9~~ $## #.5H12 =))  	;6:K23?? *	)!B"'i." " 3>" "      
  # # # 1:: } NNc%))*=>>    OO$7>>>%F& +)#2& & 7B& &            HH
 H 3 3 5 555s8}}GZGZG\G\9\9\`fjmnvjwjwj}j}jj``NN`',X66  
 % (,NNNNNN$/K	$:$:EE( , , ,$+EEE, !(%F& +%#'& & ,7& &            HH G#J %0 D	) D	) J7>>*-- IZIIw'''((('"":..q17799C<)*d++ 7"q#'#6#6L5"+--n--;S^ .(31. .@L. . ( ( ( ( ( (HH !K//-;S^ .(31. .@L. . ( ( ( ( ( (HH !K//H/-;S^ .(31. .@L. . ( ( ( ( ( (HH !$===-;S^ .(31. .@L. . ( ( ( ( ( (HH .?S-> .(3a. .CO. . ( ( ( ( ( (H %  "  "  "8CC "HXHXYlHmHm " #NN h ,-@ A  
 FF1III(,,-@$GGG"k11.11? 2",7q2" 2"DP2" 2" ," ," ," ," ," ," "%!3!31? 2",7q2" 2"DP2" 2" ," ," ," ," ," ," "%!3!3!31? 2",7q2" 2"DP2" 2" ," ," ," ," ," ," "%(A!A!A1? 2",7q2" 2"DP2" 2" ," ," ," ," ," ," 2C1B 2",7!2" 2"GS2" 2" ," ," ," ," ," ," "A "/7" 7" 7" 7" 7" 7" 7" 7" 7" 7" 7" 7" 7" 7" 7"p  ) ) )./Xz/X/XUV/X/XYYW%%%(((((((()
 WE >!&H===U## "h122	
 
  	*!)F: d d dbcccc 4 4 42q22333333334s  :Y; 0A0 /Y; 0A?<Y; >A??
Y; 
B Y; B.+Y; -B..Y; 4AC8 7Y; 8
D3'D.)Y; .D33&Y; (F Y; .F41Y; 3F449Y; .H Y; MDML&%M&L52M4L55MY; MBY; 4W.W!BR1/W!1W<DWW!WW!W.!W%	%W.(W%	)W.,Y; .
Y8AY<Y; YY; Y; !Y; ;Z0	Z0Z+%Z0+Z0c           	      P  K   	 ddl }n# t          $ r ddicY S w xY w	 ddlm}m}  |            } ||          \  }}d}	d|  dd	}
 |j        dd
|                    d          i|4 d{V }||dd} |j        |	f|
|d|4 d{V }|                                 d{V }|	                    d          r>dd||	                    d          dcddd          d{V  cddd          d{V  S t          d|	                    dd                     cddd          d{V  cddd          d{V  S # 1 d{V swxY w Y   	 ddd          d{V  dS # 1 d{V swxY w Y   dS # t          $ r}t          d|           cY d}~S d}~ww xY w)zSend via Slack Web API.r   Nr,   /aiohttp not installed. Run: pip install aiohttprk  proxy_kwargs_for_aiohttpz&https://slack.com/api/chat.postMessager   r   r   r2      r   T)r   r'   mrkdwnr   r   r   tsr  zSlack API error: unknownzSlack send failed: rC   )r   r1  r   rk  r  r   r   r   rg   r]   r-   rF   )r}   r   r*   r   rk  r  _proxy_sess_kw_req_kwr   r   r   payloadr   r   ri   s                   r    rH  rH    sk     L L L LJKKKKL1VVVVVVVV""$$44V<<'6$5e$5$5GYZZ(7(]]1F1FR1F1P1P]T\]] 	R 	R 	R 	R 	R 	R 	Rah")7dKKG#w|CRwRR'RR R R R R R R RVZ!YY[[((((((88D>> t'+Wdhdldlmqdrdrss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 P$((7I2N2NPPQQ	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 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 	R 	R 	R 	R 	R 	R 	R 	R 	R 	R 	R 	R 	R 	R 	R 	R  1 1 1/A//000000001s   	 AE? 1E,A	EE,*E? =%E"E,4E? 
E	E,E	E,E? ,
E66E? 9E6:E? ?
F%	F F% F%c                 L  K   	 ddl }n# t          $ r ddicY S w xY w	 |                     dd          }|                                4 d{V }|                    d| d||d	|                    d
                    4 d{V 	 }|j        dk    rX|                                 d{V }dd||                    d          dcddd          d{V  cddd          d{V  S |                                 d{V }t          d|j         d|           cddd          d{V  cddd          d{V  S # 1 d{V swxY w Y   	 ddd          d{V  dS # 1 d{V swxY w Y   dS # t          $ r}	t          d|	           cY d}	~	S d}	~	ww xY w)z,Send via the local WhatsApp bridge HTTP API.r   Nr,   r  bridge_porti  zhttp://localhost:z/send)chatIdr*   r  r   )rg   r2      Tr   	messageIdr  zWhatsApp bridge error (): zWhatsApp send failed: )r   r1  r]   r   r   r   statusrg   r'   r-   rF   )
r~   r   r*   r   r  r   r   r   bodyri   s
             r    rJ  rJ  #  s?     L L L LJKKKKL4iit44((** 	P 	P 	P 	P 	P 	P 	Pg||6K666 'G<<--B-77 $   P P P P P P P P ;#%%!%,,,,,,D#'$.#*&*hh{&;&;	 P P P P P P P P P P P P P	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P "YY[[((((((NNNNNOOP P P P P P P P P P P P P	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	PP P P P P P P P P P P P P P P	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P 	P   4 4 42q22333333334s   	 0E= :E*	?EE*E= -3E E*2E= 
E	E*E	E*E= *
E44E= 7E48E= =
F#FF#F#c                 Z
   !"#$%K   	 ddl %n# t          $ r ddicY S w xY wddlm}m m}m}m}m}m	!m
}	 	 |                     dd                              d          $|                     d	d
          ""sddiS |pg }
g #|
D ]U\  }}t          j                            |          r#                    |           :t"                              d|           V#r, #fdt'          dt)          #                     D             }ng g}!"$%fd}dt*          ddf"$%fd} |	            }t"                              d|                                t)          #          t)          |                     g }t1          |          D ]\  }}t)          |          }|dk    rO|                    |          }||k    r4 |d ||           d|dz    dt)          |           d           d{V  |dk    r|nd
}t'          d|dz             D ]}	 |                    |           d{V  t7          j                    } |||           d{V }t7          j                    |z
  }d|vr|                    ||           d{V   n|d         } ||          s,t=          d|dz    dt)          |           d|           c c S  ||          }|                    ||           ||k    rP|                    |dz              t"                               d|dz   t)          |          ||r|ddnd            nt"                              d|dz   t)          |          |||r|ddnd           l# tB          $ r}||k    rY|                    |dz              t"                               d|dz   t)          |          |t+          |                     Y d}~ nJt"                              d|dz   t)          |          ||t+          |                     Y d}~d}~ww xY wg }t)          #          t)          |
          k     r|                    d            |rF|                    d!t)          |           d"d#"                    d$ |D                        d%           |r@t)          |          t)          |          k    r t=          d&t)          |           d'          S d(d)d*}|r||d+<   |S # tB          $ r}t=          d,|           cY d}~S d}~ww xY w)-u  Send via signal-cli JSON-RPC API.

    Supports both text-only and text-with-attachments (images/audio/documents).
    Multi-attachment sends are chunked into batches of
    SIGNAL_MAX_ATTACHMENTS_PER_MSG and metered by the process-wide
    SignalAttachmentScheduler — same bucket the gateway adapter uses, so
    sends from this tool and inbound-driven replies share rate-limit state.
    r   Nr,   httpx not installed)$SIGNAL_BATCH_PACING_NOTICE_THRESHOLDSIGNAL_MAX_ATTACHMENTS_PER_MSGSIGNAL_RATE_LIMIT_MAX_ATTEMPTS_extract_retry_after_seconds_format_wait_is_signal_rate_limit_error_signal_send_timeoutget_schedulerhttp_urlzhttp://127.0.0.1:8080/accountrk   zSignal account not configuredz)Signal media file not found, skipping: %sc                 *    g | ]}||z            S rC   rC   ).0rd  r  attachment_pathss     r    
<listcomp>z _send_signal.<locals>.<listcomp>j  s9        !1'E#E!EF  r"   c                   K   |d}	                     d          r	dd          |d<   n	g|d<   | r| |d<   dd|d	t          t          j                    d
z             d} | rt          |           nd          }                    |          4 d {V }|                    
 d|           d {V }|                                 |                                cd d d           d {V  S # 1 d {V swxY w Y   d S )Nr  r*   r      groupId	recipientattachments2.0rQ   send_  jsonrpcmethodparamsr   r   r   /api/v1/rpcrg   )r   r  timer   AsyncClientr   raise_for_statusrg   )batch_attachmentsbatch_messager  r  r2   clientr   r  r  r   r  httpxs          r    _postz_send_signal.<locals>._postq  s     !(]CCF!!(++ 0$+ABBKy!!'.i{#  :(9}% !  7c$)++"45577	 G +*EV+]3/@+A+A+A\]^^G(((99 # # # # # # #V#[[H)A)A)A[PPPPPPPP%%'''yy{{# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #s   AC77
DDr'   r   c                   K   | d}                     d          rdd         |d<   ng|d<   	                     d          4 d{V }|                     d	d
d|dt          t	          j                    dz             d           d{V  ddd          d{V  dS # 1 d{V swxY w Y   dS # t
          $ r&}t                              d|           Y d}~dS d}~ww xY w)z9Best-effort one-shot RPC for a user-facing pacing notice.r  r   r  Nr  r        >@r   r  r  rQ   notice_r  r  r  z Signal: inline notice failed: %s)r   r  r   r  r  rF   rG   rH   )r'   notice_params_client_er  r   r  r  s       r    _send_inline_noticez)_send_signal.<locals>._send_inline_notice  s     (/DAAM!!(++ 7+2122;i((.5Yk*G ,,T,:: 	 	 	 	 	 	 	g!,,#000',&,&3"EC	d0B,C,C"E"E	  '         	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	  G G GA2FFFFFFFFFGs<   B? A
B,B? ,
B66B? 9B6:B? ?
C/	C**C/zIsend_message Signal: scheduler state=%s, %d attachment(s) in %d batch(es)u!   (More images coming — pausing ~z for Signal rate limit, batch r   z.)zSignal RPC error on batch r  z`Signal: rate-limit retries exhausted on batch %d/%d (%d attachments lost, server retry_after=%s)z.0fsr  ziSignal: rate-limited on batch %d/%d (attempt %d/%d, server retry_after=%s); scheduler will pace the retryz7Signal: send error on batch %d/%d after %d attempts: %szFSignal: transient error on batch %d/%d (attempt %d/%d): %s; will retryz1Some media files were skipped (not found on disk)zSignal rate-limited z batch(es) (#z, #c              3   4   K   | ]}t          |          V  d S N)r=   )r  bs     r    	<genexpr>z_send_signal.<locals>.<genexpr>  s(      ??1A??????r"   r   zSignal: every batch (z*) hit rate limit; no attachments deliveredTr   r   r   r   r.  zSignal send failed: )#r  r1  #gateway.platforms.signal_rate_limitr  r  r  r  r  r  r  r  r]   rstripr   r   r  r[  rG   rH   rD   r   r=   r  stater<  estimate_waitacquirer  	monotonicreport_rpc_durationr-   feedbackr,   rF   join)&r~   r   r*   r   r  r  r  r  r  r  valid_mediar   	_is_voiceatt_batchesr  r  	schedulerfailed_batchesidx	att_batchn	estimatedr  r/   _rpc_t0r   _rpc_durationerrserver_retry_afterri   r.  r   r  r  r  r  r  r  s&    `                              @@@@@@r    rD  rD  ?  s     0 0 0 0.////0	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	Y299Z)@AAHHMM))Ir** 	><==!'R%0 	X 	X!J	w~~j)) X ''
3333JJWWWW
  	    q#&6"7"79WXX  KK
 $K	# 	# 	# 	# 	# 	# 	# 	# 	#*	GC 	GD 	G 	G 	G 	G 	G 	G 	G 	G 	G* "MOO	WOOs#344c+6F6F	
 	
 	
 %''44 :	 :	NCIA1uu%33A66	 DDD--WLL<S<S W W8;aW WBEkBRBRW W W        
 (+axxGGRM $BQ$FGG . .-#++A........."n..G!&y-!@!@@@@@@@D$(N$4$4w$>Md**';;M1MMMMMMMMMw-C66s;; h%&f37&f&fSQ\M]M]&f&fad&f&fggggggg)E)Ec)J)J&&&'91==="@@@&--cAg666K!GS%5%5q<N]188888T]	   NN8 a[!1!1!?8JY-44444PY    !   "@@@&--cAg666U!GS%5%5wA   NN`a[!1!17<Z\_`a\b\b          3{#3#333OOOPPP 	OOCs>':': C CZZ???????C C C  
  	c.11S5E5EEE,K(8(8 , , ,  
 "xGLL 	*!)F: 2 2 20Q00111111112s    !!AT >FT A6M?T :M?
T A5M?T 7M?=T ?
P/	AP*"T (<P*$T *P//CT 5T 
T*T%T*%T*c                 H  K   ddl }ddlm} |                     d          pt	          j        dd          }t	          j        dd          }|                     d          pt	          j        d	d          }	 t          t	          j        d
d                    }n# t          t          f$ r d}Y nw xY wt          |||g          sddiS 	  ||dd          }	||	d<   ||	d<   d|	d<   t          d          |	d<   |                    ||          }
|
                    t          j                               |
                    ||           |
                    |	           |
                                 dd|dS # t$          $ r}t'          d|           cY d}~S d}~ww xY w)z:Send via SMTP (one-shot, no persistent connection needed).r   N)MIMETextaddressEMAIL_ADDRESSrk   EMAIL_PASSWORD	smtp_hostEMAIL_SMTP_HOSTEMAIL_SMTP_PORT587iK  r,   zNEmail not configured (EMAIL_ADDRESS, EMAIL_PASSWORD, EMAIL_SMTP_HOST required)r  zutf-8FromTozHermes AgentSubjectT)	localtimeDate)contextemailr  zEmail send failed: )smtplibemail.mime.textr  r]   r   r   r  r<   r;   allr   SMTPstarttlssslcreate_default_contextloginrE   quitrF   r-   )r~   r   r*   r  r  r  passwordr
  	smtp_portmsgserverri   s               r    rL  rL    s     NNN((((((ii	""Dbi&D&DGy)2..H		+&&J")4Er*J*JI	"3U;;<<			"   			 9-.. kijj1hw11FD	'I 4000Fi33 : < <===Wh'''C   WIII 1 1 1/A//000000001s1   7"B B0/B0
B0E; ;
F!FF!F!c                 6  K   	 ddl }n# t          $ r ddicY S w xY wddl}t          j        dd          }t          j        dd          }|r| r|sddiS t          j        d	d
|t
          j                  }t          j        dd
|t
          j                  }t          j        dd
|t
          j                  }t          j        dd
|t
          j                  }t          j        dd|          }t          j        dd
|          }t          j        dd|t
          j                  }t          j        dd
|          }t          j        dd|          }|	                                }	 ddl
m}m}  |            }	 ||	          \  }
}| d|  }|                    |                    d                                        d          }d| d}dd| i} |j        d,d|                    d          i|
4 d{V }|                                }|                    d|           |                    d |           |                    d!|            |j        |f||d"|4 d{V }|                                 d{V }|j        d#k    ra|                    d$t1          |                    }t3          d%|j         d&|           cddd          d{V  cddd          d{V  S |                    d'd          }d(d)||d*cddd          d{V  cddd          d{V  S # 1 d{V swxY w Y   	 ddd          d{V  dS # 1 d{V swxY w Y   dS # t4          $ r}t3          d+|           cY d}~S d}~ww xY w)-zSend a single SMS via Twilio REST API.

    Uses HTTP Basic auth (Account SID : Auth Token) and form-encoded POST.
    Chunking is handled by _send_to_platform() before this is called.
    r   Nr,   r  TWILIO_ACCOUNT_SIDrk   TWILIO_PHONE_NUMBERzXSMS not configured (TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_PHONE_NUMBER required)z\*\*(.+?)\*\*z\1)flagsz	\*(.+?)\*z	__(.+?)__z_(.+?)_z```[a-z]*\n?z`(.+?)`z
^#{1,6}\s+z\[([^\]]+)\]\([^\)]+\)z\n{3,}z

r  rl   asciiz+https://api.twilio.com/2010-04-01/Accounts/z/Messages.jsonr   zBasic r2   r  r   r  r  Body)r   r   i  r*   zTwilio API error (r  sidTr   r  zSMS send failed: rC   )r   r1  base64r   r   r  r%   DOTALL	MULTILINEr   r   rk  r  	b64encodeencodedecoder   r   FormData	add_fieldr   rg   r  r]   r=   r-   rF   )
auth_tokenr   r*   r   r)  account_sidfrom_numberrk  r  r  r  r  credsencodedr   r   r   	form_datar   r  	error_msgmsg_sidri   s                          r    rN  rN    s=     L L L LJKKKKL MMM)0"55K)1266K uj u ustt f%ugRYGGGGf\5'CCCGf\5'CCCGfZryAAAGf_b'22GfZ00Gf]Br|DDDGf.w??GfY00GmmooG/VVVVVVVV""$$44V<<'----""5<<#8#899@@IIWKWWW"$6W$6$67(7(]]1F1FR1F1P1P]T\]] 	g 	g 	g 	g 	g 	g 	gah((**I444g...000#w|CTiTTGTT g g g g g g gX\!YY[[((((((;#%% $CII > >I!"Rt{"R"Ry"R"RSS	g g g g g g g g g g g g g	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g ((5"--#'Uw^effg g g g g g g g g g g g g	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	gg g g g g g g g g g g g g g g	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g 	g  / / /-!--......../s   	 ,BM2 A.M2A"L:M&M2 9L:M'M2 :
M	MM	MM2 
M))M2 ,M)-M2 2
N<NNNc                 (  K   	 ddl }n# t          $ r ddicY S w xY w	 |                    d          pt          j        dd                              d          }| pt          j        d	d          } |r| sdd
iS dt          t          j                    dz             dt          j        d          	                                 }ddl
m}  ||d          }| d| d| }	d|  dd}
d|d}	 ddl}|                    |ddg          }t          j        dd|          }d|d<   ||d<   n# t          $ r Y nw xY w|                    |                    d !          "          4 d{V }|                    |	|
|#          4 d{V }|j        d$vrX|                                 d{V }t)          d%|j         d&|           cddd          d{V  cddd          d{V  S |                                 d{V }ddd          d{V  n# 1 d{V swxY w Y   ddd          d{V  n# 1 d{V swxY w Y   d'd(||                    d)          d*S # t,          $ r}t)          d+|           cY d}~S d}~ww xY w),zSend via Matrix Client-Server API.

    Converts markdown to HTML for rich rendering in Matrix clients.
    Falls back to plain text if the ``markdown`` library is not installed.
    r   Nr,   r  
homeserverMATRIX_HOMESERVERrk   r  MATRIX_ACCESS_TOKENzGMatrix not configured (MATRIX_HOMESERVER, MATRIX_ACCESS_TOKEN required)hermes_r  r      )quote)safez/_matrix/client/v3/rooms/z/send/m.room.message/r   r   r   zm.text)msgtyper  fenced_codetables)
extensionsz<h[1-6]>(.*?)</h[1-6]>z<strong>\1</strong>zorg.matrix.custom.htmlformatformatted_bodyr  r   r   r      r     zMatrix API error (r  Tr   event_idr  Matrix send failed: )r   r1  r]   r   r   r  r  r  urandomhexurllib.parser?  rw  r  r%   r   r   putr  r'   r-   rg   rF   )r}   r~   r   r*   r   r:  txn_idr?  encoded_roomr   r   r  _mdrx  r   r   r  r   ri   s                      r    rP  rP  M  s     L L L LJKKKKL2ii--S;NPR1S1S[[\_``
=#8"== 	h 	hfggJ3ty{{T122JJRZ]]5F5F5H5HJJ&&&&&&uW2...aalaaY_aa$5e$5$5GYZZ '88	""""<<]H4M<NND635KTRRD 8GH(,G$%% 	 	 	D	 ((1F1FR1F1P1P(QQ 	) 	) 	) 	) 	) 	) 	)U\{{3g{FF ) ) ) ) ) ) )$;j00!%,,,,,,D!"Mt{"M"Mt"M"MNN) ) ) ) ) ) ) ) ) ) ) ) )	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	)
 "YY[[((((((	) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) )	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	)  X'Y]YaYablYmYmnnn 2 2 20Q00111111112s   	 AI+ :A7I+ 2=D0 /I+ 0
D=:I+ <D==3I+ 0I =HI I+ 1HI 
H'	'I *H'	+I .I+  
I

I+ I
I+ +
J5JJJc                 @  K   	 ddl m} n# t          $ r ddicY S w xY w|pg }	  ||           }|                                 d{V }|s:t	          d          	 |                                 d{V  S # t          $ r Y S w xY w|rd|ind}d}	|                                rg|                    |||           d{V }	|	j	        sBt	          d	|	j
                   	 |                                 d{V  S # t          $ r Y S w xY w|D ]\  }
}t          j                            |
          s?t	          d
|
           c 	 |                                 d{V  S # t          $ r Y S w xY wt          j                            |
          d                                         }|t           v r|                    ||
|           d{V }	n|t$          v r|                    ||
|           d{V }	np|t(          v r!|r|                    ||
|           d{V }	nF|t,          v r|                    ||
|           d{V }	n|                    ||
|           d{V }	|	j	        sDt	          d|	j
                   c 	 |                                 d{V  S # t          $ r Y S w xY w|	/ddi	 |                                 d{V  S # t          $ r Y S w xY wdd||	j        d	 |                                 d{V  S # t          $ r Y S w xY w# t          $ rG}t	          d	|           cY d}~	 |                                 d{V  S # t          $ r Y S w xY wd}~ww xY w# 	 |                                 d{V  w # t          $ r Y w w xY wxY w)zISend via the Matrix adapter so native Matrix media uploads are preserved.r   )MatrixAdapterr,   zIMatrix dependencies not installed. Run: pip install 'mautrix[encryption]'NzMatrix connect failedr   r  rJ  Media file not found: r   zMatrix media send failed: r  Tr   r  )gateway.platforms.matrixrS  r1  connectr-   
disconnectrF   r   rQ   r   r,   r   r   r  r   r>   r   send_image_filer   r  r   r  r   r  r  )r   r   r*   r   r   rS  r"  	connectedr  rc  r   r   r  ri   s                 r    rB  rB  y  s     f::::::: f f fdeeeef #K0-((!//++++++++	 	3122R	$$&&&&&&&&&& 	 	 	D	S 09BK++d==?? 	J 'Wg Q QQQQQQQK& JH[5FHHIIB	$$&&&&&&&&&& 	 	 	D	C %0 	P 	P J7>>*-- ECzCCDDDD:	$$&&&&&&&&&& 	 	 	D	; '"":..q17799Ck!!$+$;$;GZZb$;$c$ccccccc##$+$6$6w
U]$6$^$^^^^^^^###$+$6$6w
U]$6$^$^^^^^^^##$+$6$6w
U]$6$^$^^^^^^^$+$9$9':X`$9$a$aaaaaaa& PN;;LNNOOOO	$$&&&&&&&&&& 	 	 	D	#P `a	$$&&&&&&&&&& 	 	 	D	  %0	
 
	$$&&&&&&&&&& 	 	 	D	  2 2 20Q001111111	$$&&&&&&&&&& 	 	 	D	2	$$&&&&&&&&&& 	 	 	D	s    5L A55
BBAL C::
DD
:L E  
E-,E-0DL J""
J/.J/2L :K
K"!K"%L 1L
LL
M-&M(7M-8M0 =M
M%$M%(M--M0 0N2NN
NNNNc                 b  K   	 ddl }n# t          $ r ddicY S w xY w	 |                    d          pt          j        dd                              d          }| pt          j        d	d          } |r| sdd
iS | d}d|  dd}|                    |                    d                    4 d{V }|                    ||||d          4 d{V }	|	j	        dvrX|	
                                 d{V }
t          d|	j	         d|
           cddd          d{V  cddd          d{V  S 	 ddd          d{V  n# 1 d{V swxY w Y   ddd          d{V  n# 1 d{V swxY w Y   dd|dS # t          $ r}t          d|           cY d}~S d}~ww xY w)z'Send via Home Assistant notify service.r   Nr,   r  r   HASS_URLrk   r  
HASS_TOKENz=Home Assistant not configured (HASS_URL, HASS_TOKEN required)z/api/services/notify/notifyr   r   r   r  r   r   )r*   rW   r   rG  zHome Assistant API error (r  Thomeassistantr  zHome Assistant send failed: )r   r1  r]   r   r   r  r   r   r   r  r'   r-   rF   )r}   r~   r   r*   r   hass_urlr   r   r   r   r  ri   s               r    rR  rR    s     L L L LJKKKKL:IIe$$A	*b(A(AII#NN4<44 	^u 	^\]]666$5e$5$5GYZZ((1F1FR1F1P1P(QQ 	W 	W 	W 	W 	W 	W 	WU\||C7^e?f?f|gg W W W W W W Wko;j00!%,,,,,,D!"Ut{"U"Ut"U"UVVW W W W W W W W W W W W W	W 	W 	W 	W 	W 	W 	W 	W 	W 	W 	W 	W 	W 	W0W W W W W W W W W W W W W W W W W W W W W W W W W W W	W 	W 	W 	W 	W 	W 	W 	W 	W 	W 	W 	W 	W 	W 	W 	W 	W 	W 	W 	W 	W 	W 	W 	W 	W 	W 	W
  _QQQ : : :8Q8899999999:s   	 AF :=F 7"E1=EE1(F <E1
E	E1E	E1F 1
E;;F >E;?F 
F.F)#F.)F.c                   K   	 ddl }n# t          $ r ddicY S w xY w	 |                     d          pt          j        dd          }|sddiS |                    d	
          4 d{V }|                    |dd|id           d{V }|                                 |                                }|                    dd          dk    r8t          d|                    dd                     cddd          d{V  S 	 ddd          d{V  n# 1 d{V swxY w Y   dd|dS # t          $ r}t          d|           cY d}~S d}~ww xY w)aq  Send via DingTalk robot webhook.

    Note: The gateway's DingTalk adapter uses per-session webhook URLs from
    incoming messages (dingtalk-stream SDK).  For cross-platform send_message
    delivery we use a static robot webhook URL instead, which must be
    configured via ``DINGTALK_WEBHOOK_URL`` env var or ``webhook_url`` in the
    platform's extra config.
    r   Nr,   r  webhook_urlDINGTALK_WEBHOOK_URLrk   zkDingTalk not configured. Set DINGTALK_WEBHOOK_URL env var or webhook_url in dingtalk platform extra config.r  r   r'   r  )rA  r'   r  errcodezDingTalk API error: errmsgr  Tdingtalkr  zDingTalk send failed: )r  r1  r]   r   r   r  r   r  rg   r-   rF   )	r~   r   r*   r  ra  r  r   r   ri   s	            r    rT  rT    s     0 0 0 0.////04ii..W")<RTV2W2W 	L  K  L  L$$T$22 	V 	V 	V 	V 	V 	V 	Vf!')W1EFF %        D !!###99;;Dxx	1%%**TTXXh	5R5RTTUU	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V +	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V 	V  ZGLLL 4 4 42q22333333334sZ   	 /D1 D1 *B
D4D1 D1 
D$$D1 'D$(D1 1
E;EEEc                   K   	 ddl m}m}  |            sddiS n# t          $ r ddicY S w xY w	 ddlm}  ||           } ||          }|                                 d{V }|st          d	|j        pd
           S 	 |	                    ||           d{V }	|	j
        s1t          d|	j                   |                                 d{V  S dd||	j        d|                                 d{V  S # |                                 d{V  w xY w# t          $ r}
t          d|
           cY d}
~
S d}
~
ww xY w)z;Send via WeCom using the adapter's WebSocket send pipeline.r   )WeComAdaptercheck_wecom_requirementsr,   z?WeCom requirements not met. Need aiohttp + WECOM_BOT_ID/SECRET.zWeCom adapter not available.ru   r~   NzWeCom: failed to connect - zunknown errorzWeCom send failed: Twecomr  )gateway.platforms.wecomrg  rh  r1  r   rv   rW  r-   fatal_error_messagerQ   r   r,   rX  r  rF   )r~   r   r*   rg  rh  rv   r   r"  rZ  r   ri   s              r    rV  rV    s     9RRRRRRRR'')) 	`^__	` 9 9 97888891111111 .u---,w''!//++++++++	 	jh8S8fWfhhiii	'"<<99999999F> DBFLBBCC $$&&&&&&&&&&  $W\b\mnn$$&&&&&&&&&&'$$&&&&&&&&&& 1 1 1/A//000000001sN    ,,AD 9C= <D C= "D =DD 
E&D=7E=Ec                    K   	 ddl m}m}  |            sddiS n# t          $ r ddicY S w xY w	  || j        | j        |||           d{V S # t          $ r}t          d|           cY d}~S d}~ww xY w)	z6Send via Weixin iLink using the native adapter helper.r   )check_weixin_requirementssend_weixin_directr,   z9Weixin requirements not met. Need aiohttp + cryptography.zWeixin adapter not available.)r~   r}   r   r*   r   NzWeixin send failed: )gateway.platforms.weixinrn  ro  r1  r~   r}   rF   r-   )r   r   r*   r   rn  ro  ri   s          r    r?  r?    s     :ZZZZZZZZ((** 	ZXYY	Z : : :89999:	2''--#
 
 
 
 
 
 
 
 
 	
  2 2 20Q00111111112s)    ,,A 
A6A1+A61A6c                 v  K   	 ddl m}m}  |            sddiS n# t          $ r ddicY S w xY w	 ddlm}  ||           } ||          }|                                 d{V }|st          d	          S 	 |                    ||           d{V }	|	j	        s1t          d
|	j
                   |                                 d{V  S dd||	j        d|                                 d{V  S # |                                 d{V  w xY w# t          $ r}
t          d
|
           cY d}
~
S d}
~
ww xY w)zBSend via BlueBubbles iMessage server using the adapter's REST API.r   )BlueBubblesAdaptercheck_bluebubbles_requirementsr,   z8BlueBubbles requirements not met (need aiohttp + httpx).z"BlueBubbles adapter not available.ru   ri  Nz(BlueBubbles: failed to connect to serverzBlueBubbles send failed: Tbluebubblesr  )gateway.platforms.bluebubblesrr  rs  r1  r   rv   rW  r-   rQ   r   r,   rX  r  rF   )r~   r   r*   rr  rs  rv   r   r"  rZ  r   ri   s              r    rX  rX    s     ?dddddddd--// 	YWXX	Y ? ? ?=>>>>?7111111 .u---$$W--!//++++++++	 	FDEEE	'"<<99999999F> JH&,HHII $$&&&&&&&&&&  $7bhbstt$$&&&&&&&&&&'$$&&&&&&&&&& 7 7 75!55666666667sN    ,,AD 99C3 2D C3 D 3DD 
D8D3-D83D8c                   K   	 ddl m}m} |sddiS ddl m}m} n# t
          $ r ddicY S w xY w|pg }	  ||           }	t          |	dd          }
|
dk    r|n|}|	                    |          |	_        |rd	|ind
}d
}|	                                r<|	
                    |||           d
{V }|j        st          d|j                   S |D ]P\  }}t          j                            |          st          d|           c S t          j                            |          d                                         }|t&          v r|	                    |||           d
{V }n|t*          v r|	                    |||           d
{V }np|t.          v r!|r|	                    |||           d
{V }nF|t2          v r|	                    |||           d
{V }n|	                    |||           d
{V }|j        st          d|j                   c S R|ddiS dd||j        dS # t8          $ r}t          d|           cY d
}~S d
}~ww xY w)z7Send via Feishu/Lark using the adapter's send pipeline.r   )r*  FEISHU_AVAILABLEr,   zJFeishu dependencies not installed. Run: pip install 'hermes-agent[feishu]')FEISHU_DOMAINLARK_DOMAIN_domain_namer   larkr   NrT  zFeishu send failed: rU  r   zFeishu media send failed: r  Tr  )r2  r*  rw  rx  ry  r1  r8   _build_lark_clientr  r   rQ   r   r-   r,   r   r   r  r   r>   r   rY  r   r  r   r  r   r  r  rF   )r   r   r*   r   r   r*  rw  rx  ry  r"  domain_namedomainr  rc  r   r   r  ri   s                     r    rG  rG  6  s     gLLLLLLLL 	kijjGGGGGGGGG g g geffffg #K*2-((g~x@@"-"7"7[!44V<</8BK++d==?? 	J 'Wg Q QQQQQQQK& JH[5FHHIII$/ 	P 	P J7>>*-- ECzCCDDDDD'"":..q17799Ck!!$+$;$;GZZb$;$c$ccccccc##$+$6$6w
U]$6$^$^^^^^^^###$+$6$6w
U]$6$^$^^^^^^^##$+$6$6w
U]$6$^$^^^^^^^$+$9$9':X`$9$a$aaaaaaa& PN;;LNNOOOOOP `aa  %0	
 
 	
  2 2 20Q00111111112sG     ,,BH4 :H4 	DH4  H4 (H4 4
I>IIIc                      t           j                            d          rdS ddlm}   | dd          }|r|dk    rdS 	 ddlm}  |            S # t          $ r Y d	S w xY w)
u  Gate send_message on gateway running (always available on messaging platforms).

    Also passes for kanban workers — the dispatcher sets ``HERMES_KANBAN_TASK``
    on every spawned worker, but those workers run with the assignee profile's
    ``HERMES_HOME`` which has no ``gateway.pid``, so the gateway-running check
    would fail even though the parent gateway is alive. Honoring the env var
    lets workers call ``send_message`` to deliver rich content directly to the
    originating chat (paired with ``kanban_complete`` for the short notifier
    summary), which is the canonical pattern for any worker that needs to
    reply with more than the ~200-char first-line truncation the kanban
    notifier applies.
    HERMES_KANBAN_TASKTr   r   r   rk   local)is_gateway_runningF)r   environr]   r   r   gateway.statusr  rF   )r   r   r  s      r    _check_send_messager  o  s     
z~~*++ t7777778"==H H''t555555!!###   uus   A 
AAc           	        K   	 ddl }n# t          $ r t          d          cY S w xY w| j        pi }|                    d          pt          j        dd          }| j        p)|                    d          pt          j        dd          }|r|st          d	          S 	 |                    d
          4 d{V }|	                    dt          |          t          |          d           d{V }|j        dk    r)t          d|j                   cddd          d{V  S |                                }	|	                    d          }
|
s!t          d          cddd          d{V  S d|
 dd}|dd         dd}d| d}|	                    |||           d{V }|j        dv r@|                                }dd||                    d          dcddd          d{V  S d | d}|	                    |||           d{V }|j        dv r@|                                }dd||                    d          dcddd          d{V  S d!| d}|	                    |||           d{V }|j        dv r@|                                }dd||                    d          dcddd          d{V  S t          d"|j         d#|j         d$|j                   cddd          d{V  S # 1 d{V swxY w Y   dS # t          $ r}t          d%|           cY d}~S d}~ww xY w)&a  Send via QQBot using the REST API directly (no WebSocket needed).

    Uses the QQ Bot Open Platform REST endpoints to get an access token
    and post a message. Supports guild channels, C2C (private) chats,
    and group chats by trying the appropriate endpoints.
    r   Nz8QQBot direct send requires httpx. Run: pip install httpxapp_id	QQ_APP_IDrk   client_secretQQ_CLIENT_SECRETz3QQBot: QQ_APP_ID / QQ_CLIENT_SECRET not configured.   r   z)https://bots.qq.com/app/getAppAccessToken)appIdclientSecretr  r  zQQBot token request failed: access_tokenz"QQBot: no access_token in responsezQQBot r   r   i  )r  msg_typez#https://api.sgroup.qq.com/channels/z	/messages)rg   r   rG  Tqqbotr   r  z#https://api.sgroup.qq.com/v2/users/z$https://api.sgroup.qq.com/v2/groups/zQQBot send failed: channel=z c2c=z group=zQQBot send failed: )r  r1  r-   r~   r]   r   r   r}   r  r   r=   status_coderg   rF   )r   r   r*   r  r~   appidsecretr  
token_resp
token_datar  r   r  r   r   r   url_c2cresp_c2c	url_group
resp_groupri   s                        r    rZ  rZ    sK     R R R RPQQQQQR MREIIh=29["#=#=Em 3uyy99 3-r22  M MKLLL21$$R$00 /	F /	F /	F /	F /	F /	F /	FF%{{;"5zz3v;;GG  +          J %,,UZ=SUUVV/	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F $**J%>>.99L ECDD/	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F" "9,!8!8 2 G #*%4%.a@@G KJJJCSwHHHHHHHHD:--yy{{#'W&*hhtnn6 67/	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F> OGNNNG#[[w[PPPPPPPPH#z11}}#'W&*hhtnn6 6G/	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	FN RwQQQI%{{97G{TTTTTTTTJ%33!((#'W&*hhtnn6 6W/	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F^   E8H  E  ExOc  E  Elv  mC  E  E  F  F_/	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F /	F`  1 1 1/A//000000001s   	 %% L <ALL +9L$L 7A/L&L 9ALL &AL L &L9L 
LL LL 
M)M :M Mc                   K   	 ddl m}m} n# t          $ r t	          d          cY S w xY w |            }|t	          d          S 	  ||| ||           d{V S # t
          $ r}t	          d|           cY d}~S d}~ww xY w)u  Send via Yuanbao using the running gateway adapter's WebSocket connection.

    Yuanbao uses a persistent WebSocket — unlike HTTP-based platforms, we
    cannot create a throwaway client.  We obtain the running singleton from
    the adapter module itself (``get_active_adapter``).

    chat_id format:
      - Group: "group:<group_code>"
      - DM:    "direct:<account_id>" or just "<account_id>"
    r   )get_active_adaptersend_yuanbao_directz%Yuanbao adapter module not available.NzVYuanbao adapter is not running. Start the gateway with yuanbao platform enabled first.r-  zYuanbao send failed: )gateway.platforms.yuanbaor  r  r1  r-   rF   )r   r*   r   r  r  r"  ri   s          r    rF  rF    s      ?UUUUUUUUU ? ? ?=>>>>>? ! ""GE
 
 	

3(('7P[\\\\\\\\\\ 3 3 31a11222222223s*    ))A 
B'A>8B>B)registryr   	messagingu   📨)rZ   toolsetschemahandlercheck_fnemojir   )NNFFr  )NN)L__doc__rI   rg   loggingr   r  r  r  email.utilsr   agent.redactr   	getLoggerr  rG   compiler   r   r   r   r   r   r   	frozensetr   r   r   r   r   r   r  
IGNORECASEr$   r&   r=   r)   r   r-   rF   r  r:   r?   rN   SEND_MESSAGE_SCHEMArb   r^   r_   r   r   r  r   r$  r   r;  rg  r=  rH  rJ  rD  rL  rN  rP  rB  rR  rT  rV  r?  rX  rG  r  rZ  rF  tools.registryr  r   registerrC   r"   r    <module>r     s=       				 				 



  " " " " " " . . . . . .		8	$	$&BJ'DEE BJfgg  2:=>> $"*%MNN BJuvv RZ CDD -  9:::;; "*455888666@@@w $V, !rzWM   'BJQM  #    4C 4D 4 4 4 4
y 3 54<    2 EF ' ' 'c ' ' ' '& 	5  !(  a  !  o 
 !  ] 
 
 #   @  L L Lk7 k7 k7\:S :c : : : :z: : :&  3  QTW[Q[    J V V V V Vrs s s sl4 4t 4 4 4 4]4 ]4 ]4 ]4@1 1 1.4 4 48r2 r2 r2 r2j1 1 1B5/ 5/ 5/p)2 )2 )2X9 9 9 9x: : :.4 4 4>1 1 162 2 2 2*7 7 7662 62 62 62r  4E1 E1 E1P3 3 3 3< 0 / / / / / / /  	 
     r"   